[vm] Use the cached number of parent type args in FunctionType.
Also ensure the number of parent type arguments is appropriately
adjusted in the returned FunctionType when partially instantiating
a FunctionType, and that free parent type arguments are _not_
included in types built while reading constants.
Since the number of parent type arguments is now cached there, we
no longer need to also cache them in ClosureData. We can also remove
the parent walking in Function::NumParentTypeArguments().
Previously, a FunctionType where the component types did not use
parent type parameters was considered instantiated. This CL changes
it so that FunctionType with free parent type parameters are never
considered instantiated. This is necessary because otherwise,
when instantiating the parent type parameters, a FunctionType that
does not use its parent type parameters will be used unchanged
instead of creating a copy with fewer parent type parameters.
Because of this, places where IsInstantiated was used to simply
check for generic parent functions (namely, for implicit closure
creation) has been appropriately weakened to check
!HasGenericParent() instead.
TEST=Existing tests on CI.
Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-nnbd-linux-release-x64-try
Change-Id: Ifb4a0a1273d8d01908cdf4ffc3c4c28a1c33ffa0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190021
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Régis Crelier <regis@google.com>
Commit-Queue: Tess Strickland <sstrickl@google.com>
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d390576..ef653b0 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1069,7 +1069,6 @@
s->Push(data->untag()->parent_function_);
s->Push(data->untag()->closure_);
s->Push(data->untag()->default_type_arguments_);
- s->Push(data->untag()->default_type_arguments_info_);
}
void WriteAlloc(Serializer* s) {
@@ -1093,7 +1092,8 @@
WriteField(data, parent_function_);
WriteField(data, closure_);
WriteField(data, default_type_arguments_);
- WriteField(data, default_type_arguments_info_);
+ s->WriteUnsigned(
+ static_cast<intptr_t>(data->untag()->default_type_arguments_kind_));
}
}
@@ -1134,8 +1134,8 @@
data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
data->untag()->default_type_arguments_ =
static_cast<TypeArgumentsPtr>(d->ReadRef());
- data->untag()->default_type_arguments_info_ =
- static_cast<SmiPtr>(d->ReadRef());
+ data->untag()->default_type_arguments_kind_ =
+ static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
}
}
};
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2821fad..8aa57f7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2768,7 +2768,7 @@
case Slot::Kind::kClosure_instantiator_type_arguments:
case Slot::Kind::kClosure_hash:
case Slot::Kind::kClosureData_default_type_arguments:
- case Slot::Kind::kClosureData_default_type_arguments_info:
+ case Slot::Kind::kClosureData_default_type_arguments_kind:
case Slot::Kind::kCapturedVariable:
case Slot::Kind::kDartField:
case Slot::Kind::kFunction_data:
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index cac72cc..e39dff8 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2742,8 +2742,9 @@
switch (r) {
case kTagged:
return RangeBoundary::kRangeBoundarySmi;
+ case kUnboxedUint8: // Overapproximate Uint8 as Int16.
+ return RangeBoundary::kRangeBoundaryInt16;
case kUnboxedInt32:
- case kUnboxedUint8: // Overapproximate Uint8 as Int32.
return RangeBoundary::kRangeBoundaryInt32;
case kUnboxedInt64:
case kUnboxedUint32: // Overapproximate Uint32 as Int64.
@@ -2821,6 +2822,7 @@
UNREACHABLE();
break;
+ case Slot::Kind::kClosureData_default_type_arguments_kind:
case Slot::Kind::kFunction_kind_tag:
case Slot::Kind::kFunction_packed_fields:
case Slot::Kind::kTypeParameter_flags:
@@ -2841,9 +2843,6 @@
case Slot::Kind::kArgumentsDescriptor_size:
*range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
break;
-
- case Slot::Kind::kClosureData_default_type_arguments_info:
- *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
}
}
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index ab21d74..b0037f4 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -32,6 +32,7 @@
enum RangeSize {
kRangeBoundarySmi,
+ kRangeBoundaryInt16,
kRangeBoundaryInt32,
kRangeBoundaryInt64,
};
@@ -97,6 +98,8 @@
switch (size) {
case kRangeBoundarySmi:
return FromConstant(compiler::target::kSmiMin);
+ case kRangeBoundaryInt16:
+ return FromConstant(kMinInt16);
case kRangeBoundaryInt32:
return FromConstant(kMinInt32);
case kRangeBoundaryInt64:
@@ -110,6 +113,8 @@
switch (size) {
case kRangeBoundarySmi:
return FromConstant(compiler::target::kSmiMax);
+ case kRangeBoundaryInt16:
+ return FromConstant(kMaxInt16);
case kRangeBoundaryInt32:
return FromConstant(kMaxInt32);
case kRangeBoundaryInt64:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 3a2a1cd..8096b2d 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -83,7 +83,6 @@
V(Closure, UntaggedClosure, function, Function, FINAL) \
V(Closure, UntaggedClosure, context, Context, FINAL) \
V(Closure, UntaggedClosure, hash, Context, VAR) \
- V(ClosureData, UntaggedClosureData, default_type_arguments_info, Smi, FINAL) \
V(Function, UntaggedFunction, data, Dynamic, FINAL) \
V(FunctionType, UntaggedFunctionType, parameter_names, Array, FINAL) \
V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL) \
@@ -125,6 +124,8 @@
//
// Note: As the underlying field is unboxed, these slots cannot be nullable.
#define UNBOXED_NATIVE_SLOTS_LIST(V) \
+ V(ClosureData, UntaggedClosureData, default_type_arguments_kind, Uint8, \
+ FINAL) \
V(Function, UntaggedFunction, kind_tag, Uint32, FINAL) \
V(Function, UntaggedFunction, packed_fields, Uint32, FINAL) \
V(FunctionType, UntaggedFunctionType, packed_fields, Uint32, FINAL) \
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index 7c0d3ad..215ced2 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -122,6 +122,9 @@
KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
reader.ReadUInt(); // skip variable-sized int for adjusted constant offset
reader.SetOffset(reader.ReaderOffset() + constant_offset);
+ // No function types returned as part of any types built should reference
+ // free parent type args, ensured by clearing the enclosing function type.
+ ActiveEnclosingFunctionScope scope(active_class_, nullptr);
// Construct constant from raw bytes.
Instance& instance = Instance::Handle(Z);
const intptr_t constant_tag = reader.ReadByte();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index db41553..7437768 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1598,9 +1598,8 @@
StoreInstanceFieldInstr::Kind::kInitializing);
}
- // The function signature cannot have uninstantiated function type parameters,
- // because the function cannot be local and have parent generic functions.
- ASSERT(target.HasInstantiatedSignature(kFunctions));
+ // The function cannot be local and have parent generic functions.
+ ASSERT(!target.HasGenericParent());
// Allocate a context that closes over `this`.
// Note: this must be kept in sync with ScopeBuilder::BuildScopes.
@@ -2095,8 +2094,6 @@
LocalVariable* parameter_names = nullptr;
LocalVariable* parameter_types = nullptr;
LocalVariable* type_parameters = nullptr;
- LocalVariable* closure_data = nullptr;
- LocalVariable* default_tav_info = nullptr;
LocalVariable* instantiator_type_args = nullptr;
LocalVariable* parent_function_type_args = nullptr;
};
@@ -2216,38 +2213,40 @@
// Load the defaults, instantiating or replacing them with the other type
// arguments as appropriate.
Fragment store_default;
- store_default += LoadLocal(info.default_tav_info);
- static_assert(
- Function::DefaultTypeArgumentsKindField::shift() == 0,
- "Need to generate shift for DefaultTypeArgumentsKindField bit field");
- store_default += IntConstant(Function::DefaultTypeArgumentsKindField::mask());
- store_default += SmiBinaryOp(Token::kBIT_AND);
+ store_default += LoadLocal(info.closure);
+ store_default += LoadNativeField(Slot::Closure_function());
+ store_default += LoadNativeField(Slot::Function_data());
+ LocalVariable* closure_data = MakeTemporary("closure_data");
+
+ store_default += LoadLocal(closure_data);
+ const auto& slot = Slot::ClosureData_default_type_arguments_kind();
+ store_default += LoadNativeField(slot);
+ store_default += Box(slot.representation());
LocalVariable* default_tav_kind = MakeTemporary("default_tav_kind");
- // One read-only stack values (default_tav_kind) that must be dropped after
- // rejoining at done.
+ // Two locals to drop after join, closure_data and default_tav_kind.
JoinEntryInstr* done = BuildJoinEntry();
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *is_instantiated, *is_not_instantiated;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kIsInstantiated));
+ ClosureData::DefaultTypeArgumentsKind::kIsInstantiated));
store_default += BranchIfEqual(&is_instantiated, &is_not_instantiated);
store_default.current = is_not_instantiated; // Check next case.
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *needs_instantiation, *can_share;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kNeedsInstantiation));
+ ClosureData::DefaultTypeArgumentsKind::kNeedsInstantiation));
store_default += BranchIfEqual(&needs_instantiation, &can_share);
store_default.current = can_share; // Check next case.
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *can_share_instantiator, *can_share_function;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
+ ClosureData::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
store_default += BranchIfEqual(&can_share_instantiator, &can_share_function);
Fragment instantiated(is_instantiated);
- instantiated += LoadLocal(info.closure_data);
+ instantiated += LoadLocal(closure_data);
instantiated += LoadNativeField(Slot::ClosureData_default_type_arguments());
instantiated += StoreLocal(info.vars->function_type_args);
instantiated += Drop();
@@ -2260,7 +2259,7 @@
// can be used within the defaults).
do_instantiation += LoadLocal(info.parent_function_type_args);
// Load the default type arguments to instantiate.
- do_instantiation += LoadLocal(info.closure_data);
+ do_instantiation += LoadLocal(closure_data);
do_instantiation +=
LoadNativeField(Slot::ClosureData_default_type_arguments());
do_instantiation += InstantiateDynamicTypeArguments();
@@ -2284,6 +2283,7 @@
store_default.current = done; // Return here after branching.
store_default += DropTemporary(&default_tav_kind);
+ store_default += DropTemporary(&closure_data);
Fragment store_delayed;
store_delayed += LoadLocal(info.closure);
@@ -2723,13 +2723,6 @@
// full set of function type arguments, then check the local function type
// arguments against the closure function's type parameter bounds.
Fragment generic;
- generic += LoadLocal(info.closure);
- generic += LoadNativeField(Slot::Closure_function());
- generic += LoadNativeField(Slot::Function_data());
- info.closure_data = MakeTemporary("closure_data");
- generic += LoadLocal(info.closure_data);
- generic += LoadNativeField(Slot::ClosureData_default_type_arguments_info());
- info.default_tav_info = MakeTemporary("default_tav_info");
// Calculate the local function type arguments and store them in
// info.vars->function_type_args.
generic += BuildClosureCallDefaultTypeHandling(info);
@@ -2738,13 +2731,10 @@
// Load the parent function type args.
generic += LoadLocal(info.parent_function_type_args);
// Load the number of parent type parameters.
- generic += LoadLocal(info.default_tav_info);
- static_assert(Function::NumParentTypeParametersField::shift() > 0,
- "No need to shift for NumParentTypeParametersField bit field");
- generic += IntConstant(Function::NumParentTypeParametersField::shift());
- generic += SmiBinaryOp(Token::kSHR);
- generic += IntConstant(Function::NumParentTypeParametersField::mask());
- generic += SmiBinaryOp(Token::kBIT_AND);
+ generic += LoadLocal(info.signature);
+ generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
+ UntaggedFunctionType::PackedNumParentTypeArguments>(
+ Slot::FunctionType_packed_fields());
// Load the number of total type parameters.
LocalVariable* num_parents = MakeTemporary();
generic += LoadLocal(info.type_parameters);
@@ -2757,8 +2747,6 @@
PrependTypeArgumentsFunction(), 4, ICData::kStatic);
generic += StoreLocal(info.vars->function_type_args);
generic += Drop();
- generic += DropTemporary(&info.default_tav_info);
- generic += DropTemporary(&info.closure_data);
// Now that we have the full set of function type arguments, check them
// against the type parameter bounds. However, if the local function type
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 3c934f6..7f0425a 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1276,7 +1276,7 @@
class ClosureData : public AllStatic {
public:
static word default_type_arguments_offset();
- static word default_type_arguments_info_offset();
+ static word default_type_arguments_kind_offset();
static word InstanceSize();
static word NextFieldOffset();
};
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index efd12ee..70016d86 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -113,7 +113,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -647,7 +647,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -1186,7 +1186,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -1717,7 +1717,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -2257,7 +2257,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -2796,7 +2796,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -3336,7 +3336,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -3864,7 +3864,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -4397,7 +4397,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -4922,7 +4922,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -5456,7 +5456,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -5989,7 +5989,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -6530,7 +6530,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 20;
+ AOT_ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 24;
@@ -7125,7 +7125,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -7726,7 +7726,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -8325,7 +8325,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -8923,7 +8923,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -9521,7 +9521,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 20;
+ AOT_ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 24;
@@ -10109,7 +10109,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -10703,7 +10703,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -11295,7 +11295,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -11886,7 +11886,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index e708265..d2dac49 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -89,7 +89,7 @@
FIELD(Closure, hash_offset) \
FIELD(Closure, instantiator_type_arguments_offset) \
FIELD(ClosureData, default_type_arguments_offset) \
- FIELD(ClosureData, default_type_arguments_info_offset) \
+ FIELD(ClosureData, default_type_arguments_kind_offset) \
FIELD(Code, object_pool_offset) \
FIELD(Code, saved_instructions_offset) \
FIELD(Code, owner_offset) \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4d07a98..945516b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7057,18 +7057,16 @@
}
FunctionPtr Function::parent_function() const {
- if (IsClosureFunction()) {
- const Object& obj = Object::Handle(untag()->data());
- ASSERT(!obj.IsNull());
- return ClosureData::Cast(obj).parent_function();
- }
- return Function::null();
+ if (!IsClosureFunction()) return Function::null();
+ const Object& obj = Object::Handle(untag()->data());
+ ASSERT(!obj.IsNull());
+ return ClosureData::Cast(obj).parent_function();
}
void Function::set_parent_function(const Function& value) const {
+ ASSERT(IsClosureFunction());
const Object& obj = Object::Handle(untag()->data());
ASSERT(!obj.IsNull());
- ASSERT(IsClosureFunction());
ClosureData::Cast(obj).set_parent_function(value);
}
@@ -7150,8 +7148,7 @@
ClosureData::Handle(ClosureData::RawCast(untag()->data()));
ASSERT(!closure_data.IsNull());
if (kind_out != nullptr) {
- *kind_out = DefaultTypeArgumentsKindField::decode(
- closure_data.default_type_arguments_info());
+ *kind_out = closure_data.default_type_arguments_kind();
}
return closure_data.default_type_arguments();
}
@@ -7163,13 +7160,9 @@
const auto& closure_data =
ClosureData::Handle(ClosureData::RawCast(untag()->data()));
ASSERT(!closure_data.IsNull());
- intptr_t updated_info = closure_data.default_type_arguments_info();
auto kind = DefaultTypeArgumentsKindFor(value);
ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
- updated_info = DefaultTypeArgumentsKindField::update(kind, updated_info);
- updated_info = NumParentTypeParametersField::update(NumParentTypeArguments(),
- updated_info);
- closure_data.set_default_type_arguments_info(updated_info);
+ closure_data.set_default_type_arguments_kind(kind);
// We could just store null for the ksharesFunction/kSharesInstantiator cases,
// assuming all clients retrieve the DefaultTypeArgumentsKind to distinguish.
closure_data.set_default_type_arguments(value);
@@ -7204,22 +7197,6 @@
return function.ptr();
}
-bool Function::HasGenericParent() const {
- if (IsImplicitClosureFunction()) {
- // The parent function of an implicit closure function is not the enclosing
- // function we are asking about here.
- return false;
- }
- Function& parent = Function::Handle(parent_function());
- while (!parent.IsNull()) {
- if (parent.IsGeneric()) {
- return true;
- }
- parent = parent.parent_function();
- }
- return false;
-}
-
FunctionPtr Function::implicit_closure_function() const {
if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
IsFieldInitializer() || IsFfiTrampoline()) {
@@ -7721,17 +7698,9 @@
}
intptr_t Function::NumParentTypeArguments() const {
- if (IsImplicitClosureFunction()) {
- return 0;
- }
- Function& parent = Function::Handle(parent_function());
- intptr_t num_parent_type_args = 0;
- while (!parent.IsNull()) {
- num_parent_type_args += parent.NumTypeParameters();
- if (parent.IsImplicitClosureFunction()) break;
- parent = parent.parent_function();
- }
- return num_parent_type_args;
+ // Don't allocate handle in cases where we know it is 0.
+ if (!IsClosureFunction()) return 0;
+ return FunctionType::Handle(signature()).NumParentTypeArguments();
}
TypeParameterPtr Function::LookupTypeParameter(const String& type_name,
@@ -8420,32 +8389,30 @@
Heap::Space space,
TrailPtr trail) const {
ASSERT(IsFinalized() || IsBeingFinalized());
- // A FunctionType cannot be part of a cycle (self-referencing typedefs are not
- // allowed), therefore, the passed in trail does not need to be propagated to
- // calls instantiating types of the signature.
Zone* zone = Thread::Current()->zone();
- // See the comment on kCurrentAndEnclosingFree to understand why we don't
- // adjust 'num_free_fun_type_params' downward in this case.
const intptr_t num_parent_type_args = NumParentTypeArguments();
bool delete_type_parameters = false;
if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
+ // See the comment on kCurrentAndEnclosingFree to understand why we don't
+ // adjust 'num_free_fun_type_params' downward in this case.
num_free_fun_type_params = kAllFree;
delete_type_parameters = true;
} else {
ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
- if (IsGeneric() || HasGenericParent()) {
- // We only consider the function type parameters declared by the parents
- // of this signature function as free.
- if (num_parent_type_args < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_args;
- }
+ // We only consider the function type parameters declared by the parents
+ // of this signature function as free.
+ if (num_parent_type_args < num_free_fun_type_params) {
+ num_free_fun_type_params = num_parent_type_args;
}
}
- // TODO(regis): Is this correct to use num_parent_type_args here?
- // Or should it be 0 after instantiation?
+ // The number of parent type parameters that remain uninstantiated.
+ const intptr_t remaining_parent_type_params =
+ num_free_fun_type_params < num_parent_type_args
+ ? num_parent_type_args - num_free_fun_type_params
+ : 0;
FunctionType& sig = FunctionType::Handle(
- FunctionType::New(num_parent_type_args, nullability(), space));
+ FunctionType::New(remaining_parent_type_params, nullability(), space));
AbstractType& type = AbstractType::Handle(zone);
// Copy the type parameters and instantiate their bounds (if necessary).
@@ -8463,7 +8430,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code
// that must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -8498,7 +8465,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -8517,7 +8484,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -9090,7 +9057,7 @@
if (!HasInstantiatedSignature(kCurrentClass)) {
instantiator_type_arguments = receiver.GetTypeArguments();
}
- ASSERT(HasInstantiatedSignature(kFunctions)); // No generic parent function.
+ ASSERT(!HasGenericParent()); // No generic parent function.
return Closure::New(instantiator_type_arguments,
Object::null_type_arguments(), *this, context);
}
@@ -9188,13 +9155,18 @@
if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
num_free_fun_type_params = kAllFree;
} else if (genericity != kCurrentClass) {
- if (IsGeneric() || HasGenericParent()) {
- // We only consider the function type parameters declared by the parents
- // of this signature function as free.
- const int num_parent_type_args = NumParentTypeArguments();
- if (num_parent_type_args < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_args;
- }
+ const intptr_t num_parent_type_args = NumParentTypeArguments();
+ if (num_parent_type_args > 0 && num_free_fun_type_params > 0) {
+ // The number of parent type arguments is cached in the FunctionType, so
+ // we can't consider any FunctionType with free parent type arguments as
+ // fully instantiated. Instead, the FunctionType must be instantiated to
+ // reduce the number of parent type arguments, even if they're unused in
+ // its component types.
+ return false;
+ }
+ // Don't consider local function type parameters as free.
+ if (num_free_fun_type_params > num_parent_type_args) {
+ num_free_fun_type_params = num_parent_type_args;
}
}
AbstractType& type = AbstractType::Handle(result_type());
@@ -9924,20 +9896,14 @@
untag()->set_default_type_arguments(value.ptr());
}
-intptr_t ClosureData::default_type_arguments_info() const {
- const SmiPtr value = untag()->default_type_arguments_info();
- if (value == Smi::null()) {
- static_assert(Function::DefaultTypeArgumentsKindField::decode(0) ==
- Function::DefaultTypeArgumentsKind::kInvalid,
- "Returning valid value for null Smi");
- return 0;
- }
- return Smi::Value(untag()->default_type_arguments_info());
+ClosureData::DefaultTypeArgumentsKind ClosureData::default_type_arguments_kind()
+ const {
+ return LoadNonPointer(&untag()->default_type_arguments_kind_);
}
-void ClosureData::set_default_type_arguments_info(intptr_t value) const {
- ASSERT(Smi::IsValid(value));
- untag()->set_default_type_arguments_info(Smi::New(value));
+void ClosureData::set_default_type_arguments_kind(
+ DefaultTypeArgumentsKind value) const {
+ StoreNonPointer(&untag()->default_type_arguments_kind_, value);
}
ClosureDataPtr ClosureData::New() {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 535c62e..a360e94 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2599,7 +2599,7 @@
// Generic dispatchers only set the number without actual type parameters.
bool IsGeneric() const { return NumTypeParameters() > 0; }
// Return true if any parent function of this function is generic.
- bool HasGenericParent() const;
+ bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
// Not thread-safe; must be called in the main thread.
// Sets function's code and code's function.
@@ -2677,41 +2677,8 @@
// Enclosing function of this local function.
FunctionPtr parent_function() const;
- enum class DefaultTypeArgumentsKind : uint8_t {
- // Only here to make sure it's explicitly set appropriately.
- kInvalid = 0,
- // Must instantiate the default type arguments before use.
- kNeedsInstantiation,
- // The default type arguments are already instantiated.
- kIsInstantiated,
- // Use the instantiator type arguments that would be used to instantiate
- // the default type arguments, as instantiating produces the same result.
- kSharesInstantiatorTypeArguments,
- // Use the function type arguments that would be used to instantiate
- // the default type arguments, as instantiating produces the same result.
- kSharesFunctionTypeArguments,
- };
- static constexpr intptr_t kDefaultTypeArgumentsKindFieldSize = 3;
- static_assert(static_cast<uint8_t>(
- DefaultTypeArgumentsKind::kSharesFunctionTypeArguments) <
- (1 << kDefaultTypeArgumentsKindFieldSize),
- "Wrong bit size chosen for default TAV kind field");
-
- // Fields encoded in an integer stored alongside a default TAV. The size of
- // the integer should be <= the size of a target Smi.
- using DefaultTypeArgumentsKindField =
- BitField<intptr_t,
- DefaultTypeArgumentsKind,
- 0,
- kDefaultTypeArgumentsKindFieldSize>;
- // TODO(regis): Rename to NumParentTypeArgumentsField.
- // Just use the rest of the space for the number of parent type parameters.
- using NumParentTypeParametersField =
- BitField<intptr_t,
- intptr_t,
- DefaultTypeArgumentsKindField::kNextBit,
- compiler::target::kSmiBits -
- DefaultTypeArgumentsKindField::kNextBit>;
+ using DefaultTypeArgumentsKind =
+ UntaggedClosureData::DefaultTypeArgumentsKind;
// Returns a canonicalized vector of the type parameters instantiated
// to bounds. If non-generic, the empty type arguments vector is returned.
@@ -3763,10 +3730,13 @@
static intptr_t default_type_arguments_offset() {
return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
}
- static intptr_t default_type_arguments_info_offset() {
- return OFFSET_OF(UntaggedClosureData, default_type_arguments_info_);
+ static intptr_t default_type_arguments_kind_offset() {
+ return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
}
+ using DefaultTypeArgumentsKind =
+ UntaggedClosureData::DefaultTypeArgumentsKind;
+
private:
ContextScopePtr context_scope() const { return untag()->context_scope_; }
void set_context_scope(const ContextScope& value) const;
@@ -3785,8 +3755,8 @@
}
void set_default_type_arguments(const TypeArguments& value) const;
- intptr_t default_type_arguments_info() const;
- void set_default_type_arguments_info(intptr_t value) const;
+ DefaultTypeArgumentsKind default_type_arguments_kind() const;
+ void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
static ClosureDataPtr New();
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5bf6bc9..adc346f 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1216,9 +1216,29 @@
closure) // Closure object for static implicit closures.
// Instantiate-to-bounds TAV for use when no TAV is provided.
POINTER_FIELD(TypeArgumentsPtr, default_type_arguments)
- // Additional information about the instantiate-to-bounds TAV.
- POINTER_FIELD(SmiPtr, default_type_arguments_info)
- VISIT_TO(ObjectPtr, default_type_arguments_info)
+ VISIT_TO(ObjectPtr, default_type_arguments)
+
+ enum class DefaultTypeArgumentsKind : uint8_t {
+ // Only here to make sure it's explicitly set appropriately.
+ kInvalid = 0,
+ // Must instantiate the default type arguments before use.
+ kNeedsInstantiation,
+ // The default type arguments are already instantiated.
+ kIsInstantiated,
+ // Use the instantiator type arguments that would be used to instantiate
+ // the default type arguments, as instantiating produces the same result.
+ kSharesInstantiatorTypeArguments,
+ // Use the function type arguments that would be used to instantiate
+ // the default type arguments, as instantiating produces the same result.
+ kSharesFunctionTypeArguments,
+ };
+
+ // kernel_to_il.cc assumes we can load the untagged value and box it in a Smi.
+ static_assert(sizeof(DefaultTypeArgumentsKind) * kBitsPerByte <=
+ compiler::target::kSmiBits,
+ "Default type arguments kind must fit in a Smi");
+
+ DefaultTypeArgumentsKind default_type_arguments_kind_;
friend class Function;
};
@@ -2348,6 +2368,8 @@
static constexpr intptr_t kMaxOptionalParametersBits =
UntaggedFunction::kMaxOptionalParametersBits;
+ // The bit fields are public for use in kernel_to_il.cc.
+ public:
typedef BitField<uint32_t, uint8_t, 0, kMaxParentTypeArgumentsBits>
PackedNumParentTypeArguments;
typedef BitField<uint32_t,
@@ -2378,6 +2400,7 @@
"In-place mask for number of optional parameters cannot fit in "
"a Smi on the target architecture");
+ private:
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Function;