[vm] Remove irregular type arguments parameter from factories

In the VM, factory constructors always had an extra "type arguments"
parameter, even if class is not generic. Factory constructor bodies
were using class type parameters instead of function type parameters.

This results in extra code when calling non-generic factories
which is slightly inefficient in terms of code size and performance.
Also, it creates an additional complexity throughout the system as
factories should be special cased in many places.

This change removes artificial "type arguments" parameter, treating
factory constructors basically as static methods. This matches
kernel AST representation.

TEST=ci

Change-Id: I957583cb2ce9a3c408699880a04036e06b01dd31
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/501762
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Alexander Markov
2026-05-12 06:11:15 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 66b54232ee
commit 6195ea86bc
39 changed files with 310 additions and 539 deletions
+1 -1
View File
@@ -173,7 +173,7 @@ namespace bin {
V(Socket_SetSocketId, 3) \
V(Socket_WriteList, 4) \
V(Socket_HasPendingWrite, 1) \
V(SocketControlMessage_fromHandles, 2) \
V(SocketControlMessage_fromHandles, 1) \
V(SocketControlMessageImpl_extractHandles, 1) \
V(Stdin_ReadByte, 1) \
V(Stdin_GetEchoMode, 1) \
+1 -2
View File
@@ -1525,8 +1525,7 @@ void FUNCTION_NAME(SocketControlMessage_fromHandles)(
DartUtils::NewDartUnsupportedError(
"This is not supported on this operating system"));
#else
ASSERT(Dart_IsNull(Dart_GetNativeArgument(args, 0)));
Dart_Handle handles_dart = Dart_GetNativeArgument(args, 1);
Dart_Handle handles_dart = Dart_GetNativeArgument(args, 0);
if (Dart_IsNull(handles_dart)) {
Dart_ThrowException(
DartUtils::NewDartArgumentError("handles list can't be null"));
+5 -6
View File
@@ -10,7 +10,7 @@
namespace dart {
DEFINE_NATIVE_ENTRY(List_allocate, 0, 2) {
DEFINE_NATIVE_ENTRY(List_allocate, 1, 1) {
// Implemented in FlowGraphBuilder::VisitNativeBody.
UNREACHABLE();
return Object::null();
@@ -55,12 +55,11 @@ DEFINE_NATIVE_ENTRY(List_slice, 0, 4) {
}
// Private factory, expects correct arguments.
DEFINE_NATIVE_ENTRY(ImmutableList_from, 0, 4) {
// Ignore first argument of this factory (type argument).
DEFINE_NATIVE_ENTRY(ImmutableList_from, 1, 3) {
const Array& from_array =
Array::CheckedHandle(zone, arguments->NativeArgAt(1));
const Smi& smi_offset = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
const Smi& smi_length = Smi::CheckedHandle(zone, arguments->NativeArgAt(3));
Array::CheckedHandle(zone, arguments->NativeArgAt(0));
const Smi& smi_offset = Smi::CheckedHandle(zone, arguments->NativeArgAt(1));
const Smi& smi_length = Smi::CheckedHandle(zone, arguments->NativeArgAt(2));
const intptr_t length = smi_length.Value();
const intptr_t offset = smi_offset.Value();
const Array& result = Array::Handle(Array::New(length));
+5 -5
View File
@@ -16,9 +16,9 @@
namespace dart {
DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
GET_NATIVE_ARGUMENT(Bool, default_value, arguments->NativeArgAt(2));
DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(Bool, default_value, arguments->NativeArgAt(1));
// Call the embedder to supply us with the environment.
const String& env_value =
String::Handle(Api::GetEnvironmentValue(thread, name));
@@ -33,8 +33,8 @@ DEFINE_NATIVE_ENTRY(Bool_fromEnvironment, 0, 3) {
return default_value.ptr();
}
DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
// Call the embedder to supply us with the environment.
const String& env_value =
String::Handle(Api::GetEnvironmentValue(thread, name));
+2 -4
View File
@@ -18,10 +18,8 @@
namespace dart {
DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 0, 2) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Double_doubleFromInteger, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Integer, value, arguments->NativeArgAt(0));
if (FLAG_trace_intrinsified_natives) {
OS::PrintErr("Double_doubleFromInteger %s\n", value.ToCString());
}
+3 -3
View File
@@ -12,10 +12,10 @@
namespace dart {
DEFINE_NATIVE_ENTRY(GrowableList_allocate, 0, 2) {
DEFINE_NATIVE_ENTRY(GrowableList_allocate, 1, 1) {
const TypeArguments& type_arguments =
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
TypeArguments::CheckedHandle(zone, arguments->NativeTypeArgs());
GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(0));
if (data.Length() < 0) {
Exceptions::ThrowRangeError("length",
Integer::Handle(Integer::New(data.Length())),
+3 -3
View File
@@ -185,9 +185,9 @@ DEFINE_NATIVE_ENTRY(Integer_parse, 0, 1) {
return ParseInteger(value);
}
DEFINE_NATIVE_ENTRY(Integer_fromEnvironment, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
GET_NATIVE_ARGUMENT(Integer, default_value, arguments->NativeArgAt(2));
DEFINE_NATIVE_ENTRY(Integer_fromEnvironment, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(Integer, default_value, arguments->NativeArgAt(1));
// Call the embedder to supply us with the environment.
const String& env_value =
String::Handle(Api::GetEnvironmentValue(thread, name));
+5 -12
View File
@@ -31,9 +31,7 @@
namespace dart {
DEFINE_NATIVE_ENTRY(Capability_factory, 0, 1) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
DEFINE_NATIVE_ENTRY(Capability_factory, 0, 0) {
// Keep capability IDs less than 2^53 so web clients of the service
// protocol can process it properly.
//
@@ -57,10 +55,8 @@ DEFINE_NATIVE_ENTRY(Capability_get_hashcode, 0, 1) {
return Smi::New(hash);
}
DEFINE_NATIVE_ENTRY(RawReceivePort_factory, 0, 2) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, debug_name, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(RawReceivePort_factory, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, debug_name, arguments->NativeArgAt(0));
if (isolate == nullptr) {
ThrowCantRunWithoutIsolateError();
UNREACHABLE();
@@ -1363,12 +1359,9 @@ static intptr_t GetTypedDataSizeOrThrow(const Instance& instance) {
Exceptions::ThrowArgumentError(instance);
}
DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 2) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
DEFINE_NATIVE_ENTRY(TransferableTypedData_factory, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Instance, array_instance,
arguments->NativeArgAt(1));
arguments->NativeArgAt(0));
Array& array = Array::Handle();
intptr_t array_length;
+38 -20
View File
@@ -1405,19 +1405,32 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
}
ASSERT(!type.IsNull());
TypeArguments& type_arguments = TypeArguments::Handle();
if (!type.IsInstantiated()) {
// Must have been a declaration type.
const Type& rare_type = Type::Handle(klass.RareType());
ASSERT(rare_type.IsInstantiated());
type_arguments = rare_type.GetInstanceTypeArguments(thread);
} else {
type_arguments = type.GetInstanceTypeArguments(thread);
type = klass.RareType();
ASSERT(type.IsInstantiated());
}
const bool is_generic_factory =
lookup_constructor.IsFactory() && lookup_constructor.IsGeneric();
intptr_t type_args_len = 0;
TypeArguments& instantiator_type_arguments = TypeArguments::Handle();
TypeArguments& function_type_arguments = TypeArguments::Handle();
if (lookup_constructor.IsGenerativeConstructor()) {
instantiator_type_arguments = type.GetInstanceTypeArguments(thread);
} else if (is_generic_factory) {
function_type_arguments = type.arguments();
type_args_len = lookup_constructor.NumTypeParameters();
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.Length() == type_args_len);
}
Class& redirected_klass = Class::Handle(klass.ptr());
const intptr_t num_explicit_args = explicit_args.Length();
const intptr_t num_implicit_args = 1;
const intptr_t num_implicit_positional_args =
lookup_constructor.IsGenerativeConstructor() ? 1 : 0;
const intptr_t num_implicit_args =
((type_args_len > 0) ? 1 : 0) + num_implicit_positional_args;
const Array& args =
Array::Handle(Array::New(num_implicit_args + num_explicit_args));
@@ -1427,10 +1440,14 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
explicit_argument = explicit_args.At(i);
args.SetAt(i + num_implicit_args, explicit_argument);
}
if (is_generic_factory) {
args.SetAt(0, function_type_arguments);
}
const int kTypeArgsLen = 0;
const Array& args_descriptor_array = Array::Handle(
ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length(), arg_names));
const Array& args_descriptor_array =
Array::Handle(ArgumentsDescriptor::NewBoxed(
type_args_len, num_implicit_positional_args + num_explicit_args,
arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
if (!lookup_constructor.AreValidArguments(args_descriptor, nullptr)) {
@@ -1442,14 +1459,18 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
UNREACHABLE();
}
#if defined(DEBUG)
// Make sure the receiver is the null value, so that DoArgumentTypesMatch does
// not attempt to retrieve the instantiator type arguments from the receiver.
explicit_argument = args.At(args_descriptor.FirstArgIndex());
ASSERT(explicit_argument.IsNull());
if (lookup_constructor.IsGenerativeConstructor()) {
// Make sure the receiver is the null value, so that DoArgumentTypesMatch
// does not attempt to retrieve the instantiator type arguments from
// the receiver.
explicit_argument = args.At(args_descriptor.FirstArgIndex());
ASSERT(explicit_argument.IsNull());
}
#endif
const Object& type_error =
Object::Handle(lookup_constructor.DoArgumentTypesMatch(
args, args_descriptor, type_arguments));
args, args_descriptor, instantiator_type_arguments,
function_type_arguments));
if (!type_error.IsNull()) {
Exceptions::PropagateError(Error::Cast(type_error));
UNREACHABLE();
@@ -1461,16 +1482,13 @@ DEFINE_NATIVE_ENTRY(ClassMirror_invokeConstructor, 0, 5) {
// Note we have delayed allocation until after the function
// type and argument matching checks.
new_object = Instance::New(redirected_klass);
if (!type_arguments.IsNull()) {
if (!instantiator_type_arguments.IsNull()) {
// The type arguments will be null if the class has no type parameters, in
// which case the following call would fail because there is no slot
// reserved in the object for the type vector.
new_object.SetTypeArguments(type_arguments);
new_object.SetTypeArguments(instantiator_type_arguments);
}
args.SetAt(0, new_object);
} else {
// Factories get type arguments.
args.SetAt(0, type_arguments);
}
// Invoke the constructor and return the new object.
+2 -4
View File
@@ -15,10 +15,8 @@ namespace dart {
// Native implementations of the profiler parts of the dart:developer library.
DEFINE_NATIVE_ENTRY(UserTag_new, 0, 2) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, tag_label, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(UserTag_new, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, tag_label, arguments->NativeArgAt(0));
return UserTag::New(thread, tag_label);
}
+6 -8
View File
@@ -17,15 +17,13 @@
namespace dart {
DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 6) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(RegExp_factory, 0, 5) {
GET_NON_NULL_NATIVE_ARGUMENT(String, pattern, arguments->NativeArgAt(0));
bool multi_line = arguments->NativeArgAt(2) == Bool::True().ptr();
bool ignore_case = arguments->NativeArgAt(3) != Bool::True().ptr();
bool unicode = arguments->NativeArgAt(4) == Bool::True().ptr();
bool dot_all = arguments->NativeArgAt(5) == Bool::True().ptr();
bool multi_line = arguments->NativeArgAt(1) == Bool::True().ptr();
bool ignore_case = arguments->NativeArgAt(2) != Bool::True().ptr();
bool unicode = arguments->NativeArgAt(3) == Bool::True().ptr();
bool dot_all = arguments->NativeArgAt(4) == Bool::True().ptr();
RegExpFlags flags;
flags |= RegExpFlag::kGlobal; // All dart regexps are global.
+10 -16
View File
@@ -36,19 +36,17 @@ DEFINE_NATIVE_ENTRY(Float32x4_splat, 0, 1) {
return Float32x4::New(_v, _v, _v, _v);
}
DEFINE_NATIVE_ENTRY(Float32x4_zero, 0, 1) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
DEFINE_NATIVE_ENTRY(Float32x4_zero, 0, 0) {
return Float32x4::New(0.0f, 0.0f, 0.0f, 0.0f);
}
DEFINE_NATIVE_ENTRY(Float32x4_fromInt32x4Bits, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, v, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Float32x4_fromInt32x4Bits, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Int32x4, v, arguments->NativeArgAt(0));
return Float32x4::New(v.value());
}
DEFINE_NATIVE_ENTRY(Float32x4_fromFloat64x2, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, v, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Float32x4_fromFloat64x2, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Float64x2, v, arguments->NativeArgAt(0));
float _x = static_cast<float>(v.x());
float _y = static_cast<float>(v.y());
return Float32x4::New(_x, _y, 0.0f, 0.0f);
@@ -433,8 +431,8 @@ DEFINE_NATIVE_ENTRY(Int32x4_fromBools, 0, 4) {
return Int32x4::New(_x, _y, _z, _w);
}
DEFINE_NATIVE_ENTRY(Int32x4_fromFloat32x4Bits, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Int32x4_fromFloat32x4Bits, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0));
return Int32x4::New(v.value());
}
@@ -693,16 +691,12 @@ DEFINE_NATIVE_ENTRY(Float64x2_splat, 0, 1) {
return Float64x2::New(v.value(), v.value());
}
DEFINE_NATIVE_ENTRY(Float64x2_zero, 0, 1) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
DEFINE_NATIVE_ENTRY(Float64x2_zero, 0, 0) {
return Float64x2::New(0.0, 0.0);
}
DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 0, 2) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(1));
DEFINE_NATIVE_ENTRY(Float64x2_fromFloat32x4, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Float32x4, v, arguments->NativeArgAt(0));
double _x = v.x();
double _y = v.y();
return Float64x2::New(_x, _y);
+3 -3
View File
@@ -16,9 +16,9 @@
namespace dart {
DEFINE_NATIVE_ENTRY(String_fromEnvironment, 0, 3) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(2));
DEFINE_NATIVE_ENTRY(String_fromEnvironment, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(0));
GET_NATIVE_ARGUMENT(String, default_value, arguments->NativeArgAt(1));
// Call the embedder to supply us with the environment.
const String& env_value =
String::Handle(Api::GetEnvironmentValue(thread, name));
+5 -2
View File
@@ -59,8 +59,11 @@ Dart_NativeFunction BootstrapNatives::Lookup(Dart_Handle name,
int num_entries = sizeof(BootStrapEntries) / sizeof(struct NativeEntries);
for (int i = 0; i < num_entries; i++) {
const struct NativeEntries* entry = &(BootStrapEntries[i]);
if ((strcmp(function_name, entry->name_) == 0) &&
(entry->argument_count_ == argument_count)) {
if (strcmp(function_name, entry->name_) == 0) {
if (entry->argument_count_ != argument_count) {
FATAL("Wrong number of arguments of %s (expected %d, actual %d)",
function_name, argument_count, entry->argument_count_);
}
return reinterpret_cast<Dart_NativeFunction>(entry->function_);
}
}
+19 -19
View File
@@ -45,18 +45,18 @@ namespace dart {
V(Integer_moduloFromInteger, 2) \
V(Integer_greaterThanFromInteger, 2) \
V(Integer_equalToInteger, 2) \
V(Integer_fromEnvironment, 3) \
V(Integer_fromEnvironment, 2) \
V(Integer_parse, 1) \
V(Integer_shlFromInteger, 2) \
V(Integer_shrFromInteger, 2) \
V(Integer_ushrFromInteger, 2) \
V(Bool_fromEnvironment, 3) \
V(Bool_hasEnvironment, 2) \
V(Capability_factory, 1) \
V(Bool_fromEnvironment, 2) \
V(Bool_hasEnvironment, 1) \
V(Capability_factory, 0) \
V(Capability_equals, 2) \
V(Capability_get_hashcode, 1) \
V(createConstMapFromMapOfDeeplyImmutables, 1) \
V(RawReceivePort_factory, 2) \
V(RawReceivePort_factory, 1) \
V(RawReceivePort_get_id, 1) \
V(RawReceivePort_closeInternal, 1) \
V(RawReceivePort_setActive, 2) \
@@ -99,14 +99,14 @@ namespace dart {
V(Double_equalToInteger, 2) \
V(Double_greaterThan, 2) \
V(Double_equal, 2) \
V(Double_doubleFromInteger, 2) \
V(Double_doubleFromInteger, 1) \
V(Double_parse, 3) \
V(Double_toString, 1) \
V(Double_toStringAsFixed, 2) \
V(Double_toStringAsExponential, 2) \
V(Double_toStringAsPrecision, 2) \
V(Double_flipSignBit, 1) \
V(RegExp_factory, 6) \
V(RegExp_factory, 5) \
V(RegExp_getPattern, 1) \
V(RegExp_getIsMultiLine, 1) \
V(RegExp_getIsCaseSensitive, 1) \
@@ -116,11 +116,11 @@ namespace dart {
V(RegExp_getGroupNameMap, 1) \
V(RegExp_ExecuteMatch, 3) \
V(RegExp_ExecuteMatchSticky, 3) \
V(List_allocate, 2) \
V(List_allocate, 1) \
V(List_setIndexed, 3) \
V(List_getLength, 1) \
V(List_slice, 4) \
V(ImmutableList_from, 4) \
V(ImmutableList_from, 3) \
V(StringBase_createFromCodePoints, 3) \
V(StringBase_substringUnchecked, 3) \
V(StringBase_joinReplaceAllResult, 4) \
@@ -133,7 +133,7 @@ namespace dart {
V(String_getLength, 1) \
V(String_charAt, 2) \
V(String_concat, 2) \
V(String_fromEnvironment, 3) \
V(String_fromEnvironment, 2) \
V(String_toLowerCase, 1) \
V(String_toUpperCase, 1) \
V(String_concatRange, 3) \
@@ -172,9 +172,9 @@ namespace dart {
V(TypedDataView_typedData, 1) \
V(Float32x4_fromDoubles, 4) \
V(Float32x4_splat, 1) \
V(Float32x4_fromInt32x4Bits, 2) \
V(Float32x4_fromFloat64x2, 2) \
V(Float32x4_zero, 1) \
V(Float32x4_fromInt32x4Bits, 1) \
V(Float32x4_fromFloat64x2, 1) \
V(Float32x4_zero, 0) \
V(Float32x4_add, 2) \
V(Float32x4_negate, 1) \
V(Float32x4_sub, 2) \
@@ -207,8 +207,8 @@ namespace dart {
V(Float32x4_reciprocalSqrt, 1) \
V(Float64x2_fromDoubles, 2) \
V(Float64x2_splat, 1) \
V(Float64x2_zero, 1) \
V(Float64x2_fromFloat32x4, 2) \
V(Float64x2_zero, 0) \
V(Float64x2_fromFloat32x4, 1) \
V(Float64x2_add, 2) \
V(Float64x2_negate, 1) \
V(Float64x2_sub, 2) \
@@ -227,7 +227,7 @@ namespace dart {
V(Float64x2_sqrt, 1) \
V(Int32x4_fromInts, 4) \
V(Int32x4_fromBools, 4) \
V(Int32x4_fromFloat32x4Bits, 2) \
V(Int32x4_fromFloat32x4Bits, 1) \
V(Int32x4_or, 2) \
V(Int32x4_and, 2) \
V(Int32x4_xor, 2) \
@@ -260,7 +260,7 @@ namespace dart {
V(Isolate_sendOOB, 2) \
V(Isolate_spawnFunction, 10) \
V(Isolate_spawnUri, 12) \
V(GrowableList_allocate, 2) \
V(GrowableList_allocate, 1) \
V(GrowableList_setIndexed, 3) \
V(GrowableList_getLength, 1) \
V(GrowableList_getCapacity, 1) \
@@ -290,7 +290,7 @@ namespace dart {
V(ThreadLocal_hasValue, 1) \
V(ThreadLocal_setValue, 2) \
V(Uri_isWindowsPlatform, 0) \
V(UserTag_new, 2) \
V(UserTag_new, 1) \
V(UserTag_label, 1) \
V(UserTag_makeCurrent, 1) \
V(VMService_SendIsolateServiceMessage, 2) \
@@ -322,7 +322,7 @@ namespace dart {
V(DartApiDLMajorVersion, 0) \
V(DartApiDLMinorVersion, 0) \
V(DartNativeApiFunctionPointer, 1) \
V(TransferableTypedData_factory, 2) \
V(TransferableTypedData_factory, 1) \
V(TransferableTypedData_materialize, 1) \
V(Timer_postTimerEvent, 1)
+3 -17
View File
@@ -1528,16 +1528,8 @@ ObjectPtr BytecodeReaderHelper::ReadType(intptr_t tag,
type =
Class::Cast(parent).TypeParameterAt(index_in_parent, nullability);
} else if (parent.IsFunction()) {
if (Function::Cast(parent).IsFactory()) {
// For factory constructors VM uses type parameters of a class
// instead of constructor's type parameters.
parent = Function::Cast(parent).Owner();
type =
Class::Cast(parent).TypeParameterAt(index_in_parent, nullability);
} else {
type = Function::Cast(parent).TypeParameterAt(index_in_parent,
nullability);
}
type = Function::Cast(parent).TypeParameterAt(index_in_parent,
nullability);
} else if (parent.IsNull()) {
ASSERT(!enclosing_function_types_.is_empty());
for (intptr_t i = enclosing_function_types_.length() - 1; i >= 0; --i) {
@@ -2124,7 +2116,6 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
intptr_t flags = reader_.ReadUInt();
const bool is_static = (flags & kIsStaticFlag) != 0;
const bool is_factory = (flags & kIsFactoryFlag) != 0;
const bool is_native = (flags & kIsNativeFlag) != 0;
const bool has_pragma = (flags & kHasPragmaFlag) != 0;
const bool is_extension_member = (flags & kIsExtensionMemberFlag) != 0;
@@ -2204,7 +2195,7 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
ReadTypeParametersDeclaration(Class::Handle(Z), signature);
}
const intptr_t num_implicit_params = (!is_static || is_factory) ? 1 : 0;
const intptr_t num_implicit_params = (!is_static) ? 1 : 0;
const intptr_t num_params = num_implicit_params + reader_.ReadUInt();
const bool has_optional_named_params =
((flags & kHasOptionalNamedParamsFlag) != 0);
@@ -2241,11 +2232,6 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) {
NOT_IN_PRECOMPILED(
function.SetParameterNameAt(param_index, Symbols::This()));
++param_index;
} else if (is_factory) {
signature.SetParameterTypeAt(param_index, AbstractType::dynamic_type());
NOT_IN_PRECOMPILED(function.SetParameterNameAt(
param_index, Symbols::TypeArgumentsParameter()));
++param_index;
}
for (; param_index < num_params; ++param_index) {
+1 -2
View File
@@ -1477,8 +1477,7 @@ intptr_t FlowGraph::ComputeLocationsOfFixedParameters(
compiler::ParameterInfoArray* parameter_info /* = nullptr */) {
return compiler::ComputeCallingConvention(
zone, function, function.num_fixed_parameters(),
[&](intptr_t i) {
const intptr_t index = (function.IsFactory() ? (i - 1) : i);
[&](intptr_t index) {
return index >= 0 ? ParameterRepresentationAt(function, index)
: kTagged;
},
+15 -24
View File
@@ -2852,22 +2852,21 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
// argument passed to the constructor.
if (call->is_known_list_constructor() &&
IsFixedLengthArrayCid(call->Type()->ToCid())) {
return call->ArgumentAt(1);
return call->ArgumentAt(call->FirstArgIndex());
} else if (call->function().recognized_kind() ==
MethodRecognizer::kByteDataFactory) {
// Similarly, we check for the ByteData constructor and forward its
// explicit length argument appropriately.
return call->ArgumentAt(1);
return call->ArgumentAt(call->FirstArgIndex());
} else if (IsTypedDataViewFactory(call->function())) {
// Typed data view factories all take three arguments (after
// the implicit type arguments parameter):
// Typed data view factories all take three arguments:
//
// 1) _TypedList buffer -- the underlying data for the view
// 2) int offsetInBytes -- the offset into the buffer to start viewing
// 3) int length -- the number of elements in the view
//
// Here, we forward the third.
return call->ArgumentAt(3);
return call->ArgumentAt(call->FirstArgIndex() + 2);
}
} else if (LoadFieldInstr* load_array = orig_instance->AsLoadField()) {
// For arrays with guarded lengths, replace the length load
@@ -2901,7 +2900,7 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
if (IsTypedDataViewFactory(call->function()) ||
IsUnmodifiableTypedDataViewFactory(call->function())) {
return call->ArgumentAt(1);
return call->ArgumentAt(call->FirstArgIndex());
}
}
break;
@@ -2911,7 +2910,7 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
ASSERT(!calls_initializer());
if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
if (IsTypedDataViewFactory(call->function())) {
return call->ArgumentAt(2);
return call->ArgumentAt(call->FirstArgIndex() + 1);
} else if (call->function().recognized_kind() ==
MethodRecognizer::kByteDataFactory) {
// A _ByteDataView returned from the ByteData constructor always
@@ -2944,7 +2943,8 @@ Definition* LoadFieldInstr::Canonicalize(FlowGraph* flow_graph) {
}
if (StaticCallInstr* call = orig_instance->AsStaticCall()) {
if (call->is_known_list_constructor()) {
return call->ArgumentAt(0);
return (call->type_args_len() > 0) ? call->ArgumentAt(0)
: flow_graph->constant_null();
} else if (IsTypedDataViewFactory(call->function()) ||
IsUnmodifiableTypedDataViewFactory(call->function())) {
return flow_graph->constant_null();
@@ -3942,12 +3942,12 @@ Instruction* GuardFieldLengthInstr::Canonicalize(FlowGraph* flow_graph) {
ConstantInstr* length = nullptr;
if (call->is_known_list_constructor() &&
LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
length = call->ArgumentAt(1)->AsConstant();
length = call->ArgumentAt(call->FirstArgIndex())->AsConstant();
} else if (call->function().recognized_kind() ==
MethodRecognizer::kByteDataFactory) {
length = call->ArgumentAt(1)->AsConstant();
length = call->ArgumentAt(call->FirstArgIndex())->AsConstant();
} else if (LoadFieldInstr::IsTypedDataViewFactory(call->function())) {
length = call->ArgumentAt(3)->AsConstant();
length = call->ArgumentAt(call->FirstArgIndex() + 2)->AsConstant();
}
if ((length != nullptr) && length->value().IsSmi() &&
Smi::Cast(length->value()).Value() == expected_length) {
@@ -5471,7 +5471,7 @@ Representation StaticCallInstr::RequiredInputRepresentation(
intptr_t idx) const {
// The first input is the array of types
// for generic functions
if (type_args_len() > 0 || function().IsFactory()) {
if (type_args_len() > 0) {
if (idx == 0) {
return kTagged;
}
@@ -5954,14 +5954,6 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
compiler->GenerateStaticCall(deopt_id(), source(), function(), args_info,
locs(), *call_ic_data, rebind_rule_,
entry_kind());
if (function().IsFactory()) {
TypeUsageInfo* type_usage_info = compiler->thread()->type_usage_info();
if (type_usage_info != nullptr) {
const Class& klass = Class::Handle(function().Owner());
RegisterTypeArgumentsUse(compiler->function(), type_usage_info, klass,
ArgumentAt(0));
}
}
}
CachableIdempotentCallInstr::CachableIdempotentCallInstr(
@@ -5997,7 +5989,7 @@ CachableIdempotentCallInstr::CachableIdempotentCallInstr(
Representation CachableIdempotentCallInstr::RequiredInputRepresentation(
intptr_t idx) const {
// The first input is the array of types for generic functions.
if (type_args_len() > 0 || function().IsFactory()) {
if (type_args_len() > 0) {
if (idx == 0) {
return kTagged;
}
@@ -8684,11 +8676,10 @@ SimdOpInstr* SimdOpInstr::CreateFromFactoryCall(Zone* zone,
Instruction* call) {
SimdOpInstr* op =
new (zone) SimdOpInstr(KindForMethod(kind), call->deopt_id());
ASSERT(call->ArgumentCount() == op->InputCount());
for (intptr_t i = 0; i < op->InputCount(); i++) {
// Note: ArgumentAt(0) is type arguments which we don't need.
op->SetInputAt(i, call->ArgumentValueAt(i + 1)->CopyWithType(zone));
op->SetInputAt(i, call->ArgumentValueAt(i)->CopyWithType(zone));
}
ASSERT(call->ArgumentCount() == (op->InputCount() + 1));
return op;
}
@@ -1507,13 +1507,14 @@ static CompileType ComputeListFactoryType(CompileType* inferred_type,
ASSERT(cid != kDynamicCid);
if ((cid == kGrowableObjectArrayCid || cid == kArrayCid ||
cid == kImmutableArrayCid) &&
type_args_value->BindsToConstant()) {
((type_args_value == nullptr) || type_args_value->BindsToConstant())) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Class& cls =
Class::Handle(zone, thread->isolate_group()->class_table()->At(cid));
auto& type_args = TypeArguments::Handle(zone);
if (!type_args_value->BoundConstant().IsNull()) {
if (type_args_value != nullptr &&
!type_args_value->BoundConstant().IsNull()) {
type_args ^= type_args_value->BoundConstant().ptr();
ASSERT(type_args.Length() >= cls.NumTypeArguments());
type_args = type_args.FromInstanceTypeArguments(thread, cls);
@@ -1533,7 +1534,8 @@ CompileType StaticCallInstr::ComputeType() const {
// (in optimized mode) and avoid keeping separate result_type.
CompileType* const inferred_type = result_type();
if (is_known_list_constructor()) {
return ComputeListFactoryType(inferred_type, ArgumentValueAt(0));
Value* type_args_value = type_args_len() > 0 ? ArgumentValueAt(0) : nullptr;
return ComputeListFactoryType(inferred_type, type_args_value);
}
intptr_t inferred_cid = kDynamicCid;
+10 -17
View File
@@ -1325,14 +1325,14 @@ void CallSpecializer::VisitStaticCall(StaticCallInstr* call) {
if (call->HasICData() && targets.IsMonomorphic() &&
(call->FirstArgIndex() == 0)) {
if (binary_feedback.ArgumentIs(kSmiCid)) {
Definition* arg = call->ArgumentAt(1);
Definition* arg = call->ArgumentAt(0);
AddCheckSmi(arg, call->deopt_id(), call->env(), call);
ReplaceCall(call, new (Z) SmiToDoubleInstr(new (Z) Value(arg),
call->source()));
return;
} else if (binary_feedback.ArgumentIs(kMintCid) &&
CanConvertInt64ToDouble()) {
Definition* arg = call->ArgumentAt(1);
Definition* arg = call->ArgumentAt(0);
ReplaceCall(call, new (Z) Int64ToDoubleInstr(new (Z) Value(arg),
call->deopt_id()));
return;
@@ -2688,24 +2688,24 @@ class SimdLowering : public ValueObject {
// Mixed
case MethodRecognizer::kFloat32x4ToFloat64x2: {
UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
Float32x4ToFloat64x2();
BoxVector(kUnboxedDouble, 2);
return true;
}
case MethodRecognizer::kFloat64x2ToFloat32x4: {
UnboxVector(0, kUnboxedDouble, kDoubleCid, 2, 1);
UnboxVector(0, kUnboxedDouble, kDoubleCid, 2);
Float64x2ToFloat32x4();
BoxVector(kUnboxedFloat, 4);
return true;
}
case MethodRecognizer::kInt32x4ToFloat32x4:
UnboxVector(0, kUnboxedInt32, kMintCid, 4, 1);
UnboxVector(0, kUnboxedInt32, kMintCid, 4);
Int32x4ToFloat32x4();
BoxVector(kUnboxedFloat, 4);
return true;
case MethodRecognizer::kFloat32x4ToInt32x4:
UnboxVector(0, kUnboxedFloat, kDoubleCid, 4, 1);
UnboxVector(0, kUnboxedFloat, kDoubleCid, 4);
Float32x4ToInt32x4();
BoxVector(kUnboxedInt32, 4);
return true;
@@ -2744,12 +2744,8 @@ class SimdLowering : public ValueObject {
BoxVector(kUnboxedDouble, 2);
}
void UnboxVector(intptr_t i,
Representation rep,
intptr_t cid,
intptr_t n,
intptr_t type_args = 0) {
Definition* arg = call_->ArgumentAt(i + type_args);
void UnboxVector(intptr_t i, Representation rep, intptr_t cid, intptr_t n) {
Definition* arg = call_->ArgumentAt(i);
if (CompilerState::Current().is_aot()) {
// Add null-checks in case of the arguments are known to be compatible
// but they are possibly nullable.
@@ -2765,11 +2761,8 @@ class SimdLowering : public ValueObject {
}
}
void UnboxScalar(intptr_t i,
Representation rep,
intptr_t n,
intptr_t type_args = 0) {
Definition* arg = call_->ArgumentAt(i + type_args);
void UnboxScalar(intptr_t i, Representation rep, intptr_t n) {
Definition* arg = call_->ArgumentAt(i);
if (CompilerState::Current().is_aot()) {
// Add null-checks in case of the arguments are known to be compatible
// but they are possibly nullable.
@@ -3415,12 +3415,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
return instructions;
}
const Class& klass = Class::ZoneHandle(Z, target.Owner());
if (target.IsGenerativeConstructor() || target.IsFactory()) {
// The VM requires a TypeArguments object as first parameter for
// every factory constructor.
++argument_count;
}
ASSERT(!target.IsGenerativeConstructor());
if (target.IsCachableIdempotent()) {
return BuildCachableIdempotentCall(position, target);
@@ -3469,7 +3464,7 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
}
Fragment instructions;
LocalVariable* instance_variable = nullptr;
const Class& klass = Class::ZoneHandle(Z, target.Owner());
const bool special_case_unchecked_cast =
klass.IsTopLevel() && (klass.library() == Library::InternalLibrary()) &&
@@ -3482,38 +3477,8 @@ Fragment StreamingFlowGraphBuilder::BuildStaticInvocation(TokenPosition* p) {
const bool special_case =
special_case_identical || special_case_unchecked_cast;
// If we cross the Kernel -> VM core library boundary, a [StaticInvocation]
// can appear, but the thing we're calling is not a static method, but a
// factory constructor.
// The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the
// forwarded constructor.
// In that case we'll make an instance and pass it as first argument.
//
// TODO(27590): Get rid of this after we're using core libraries compiled
// into Kernel.
intptr_t type_args_len = 0;
if (target.IsGenerativeConstructor()) {
if (klass.NumTypeArguments() > 0) {
const TypeArguments& type_arguments =
PeekArgumentsInstantiatedType(klass);
instructions += TranslateInstantiatedTypeArguments(type_arguments);
instructions += AllocateObject(position, klass, 1);
} else {
instructions += AllocateObject(position, klass, 0);
}
instance_variable = MakeTemporary();
instructions += LoadLocal(instance_variable);
} else if (target.IsFactory()) {
// The VM requires currently a TypeArguments object as first parameter for
// every factory constructor :-/ !
//
// TODO(27590): Get rid of this after we're using core libraries compiled
// into Kernel.
const TypeArguments& type_arguments = PeekArgumentsInstantiatedType(klass);
instructions += TranslateInstantiatedTypeArguments(type_arguments);
} else if (!special_case) {
if (!special_case) {
AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
@@ -4161,7 +4126,10 @@ Fragment StreamingFlowGraphBuilder::BuildListLiteral(TokenPosition* p) {
Symbols::_GrowableListLiteralFactory()));
ASSERT(!factory_method.IsNull());
instructions += StaticCall(position, factory_method, 2, ICData::kStatic);
instructions += StaticCall(position, factory_method,
/*argument_count=*/1, Array::null_array(),
ICData::kStatic, /*result_type=*/nullptr,
/*type_args_len=*/1);
instructions += DropTempsPreserveTop(1); // Instantiated type_arguments.
return instructions;
}
@@ -4211,8 +4179,10 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(TokenPosition* p) {
Library::PrivateCoreLibName(Symbols::MapLiteralFactory()));
}
return instructions +
StaticCall(position, factory_method, 2, ICData::kStatic);
return instructions + StaticCall(position, factory_method,
/*argument_count=*/1, Array::null_array(),
ICData::kStatic, /*result_type=*/nullptr,
/*type_args_len=*/2);
}
Fragment StreamingFlowGraphBuilder::BuildRecordLiteral(TokenPosition* p) {
+16 -37
View File
@@ -164,18 +164,8 @@ Fragment FlowGraphBuilder::PopContext() {
Fragment FlowGraphBuilder::LoadInstantiatorTypeArguments() {
// TODO(27590): We could use `active_class_->IsGeneric()`.
Fragment instructions;
if (scopes_ != nullptr && scopes_->type_arguments_variable != nullptr) {
#ifdef DEBUG
Function& function =
Function::Handle(Z, parsed_function_->function().ptr());
while (function.IsClosureFunction()) {
function = function.parent_function();
}
ASSERT(function.IsFactory());
#endif
instructions += LoadLocal(scopes_->type_arguments_variable);
} else if (parsed_function_->has_receiver_var() &&
active_class_.ClassNumTypeArguments() > 0) {
if (parsed_function_->has_receiver_var() &&
active_class_.ClassNumTypeArguments() > 0) {
ASSERT(!parsed_function_->function().IsFactory());
instructions += LoadLocal(parsed_function_->receiver_var());
instructions += LoadNativeField(
@@ -1466,14 +1456,14 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
break;
case MethodRecognizer::kGrowableArrayAllocateWithData: {
ASSERT(function.IsFactory());
ASSERT_EQUAL(function.NumParameters(), 2);
ASSERT_EQUAL(function.NumParameters(), 1);
const Class& cls =
Class::ZoneHandle(Z, compiler::GrowableObjectArrayClass().ptr());
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += LoadLocal(parsed_function_->function_type_arguments());
body += AllocateObject(TokenPosition::kNoSource, cls, 1);
LocalVariable* object = MakeTemporary();
body += LoadLocal(object);
body += LoadLocal(parsed_function_->RawParameterVariable(1));
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += StoreNativeField(Slot::GrowableObjectArray_data(),
StoreFieldInstr::Kind::kInitializing,
kNoStoreBarrier);
@@ -1494,9 +1484,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
body += Constant(Object::mutable_empty_array());
break;
case MethodRecognizer::kObjectArrayAllocate:
ASSERT(function.IsFactory() && (function.NumParameters() == 2));
ASSERT(function.IsFactory() && (function.NumParameters() == 1));
body += LoadLocal(parsed_function_->function_type_arguments());
body += LoadLocal(parsed_function_->RawParameterVariable(0));
body += LoadLocal(parsed_function_->RawParameterVariable(1));
body += CreateArray();
break;
case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString:
@@ -1693,7 +1683,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
const auto& type_arguments = TypeArguments::ZoneHandle(
Z, IG->object_store()->type_argument_never());
ASSERT(function.NumTypeParameters() == 1);
ASSERT_EQUAL(function.NumParameters(), 1);
body += Constant(type_arguments);
body += AllocateObject(TokenPosition::kNoSource, pointer_class, 1);
@@ -2013,10 +2002,10 @@ Fragment FlowGraphBuilder::BuildTypedDataViewFactoryConstructor(
ASSERT(class_table->HasValidClassAt(cid));
const auto& view_class = Class::ZoneHandle(H.zone(), class_table->At(cid));
ASSERT(function.IsFactory() && (function.NumParameters() == 4));
LocalVariable* typed_data = parsed_function_->RawParameterVariable(1);
LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(2);
LocalVariable* length = parsed_function_->RawParameterVariable(3);
ASSERT(function.IsFactory() && (function.NumParameters() == 3));
LocalVariable* typed_data = parsed_function_->RawParameterVariable(0);
LocalVariable* offset_in_bytes = parsed_function_->RawParameterVariable(1);
LocalVariable* length = parsed_function_->RawParameterVariable(2);
Fragment body;
@@ -2265,8 +2254,8 @@ Fragment FlowGraphBuilder::BuildTypedDataFactoryConstructor(
ASSERT(
Thread::Current()->isolate_group()->class_table()->HasValidClassAt(cid));
ASSERT(function.IsFactory() && (function.NumParameters() == 2));
LocalVariable* length = parsed_function_->RawParameterVariable(1);
ASSERT(function.IsFactory() && (function.NumParameters() == 1));
LocalVariable* length = parsed_function_->RawParameterVariable(0);
Fragment instructions;
instructions += LoadLocal(length);
@@ -2423,12 +2412,8 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode,
ASSERT(!forwarding_target->IsNull());
}
TypeParameters& type_parameters = TypeParameters::Handle(Z);
if (dart_function.IsFactory()) {
type_parameters = Class::Handle(Z, dart_function.Owner()).type_parameters();
} else {
type_parameters = dart_function.type_parameters();
}
TypeParameters& type_parameters =
TypeParameters::Handle(Z, dart_function.type_parameters());
const intptr_t num_type_params = type_parameters.Length();
if (num_type_params == 0) return;
// Check type parameter bounds against forwarding stub target, if any.
@@ -2471,8 +2456,6 @@ void FlowGraphBuilder::BuildTypeArgumentTypeChecks(TypeChecksToBuild mode,
if (forwarding_target != nullptr) {
type_param = forwarding_target->TypeParameterAt(i);
} else if (dart_function.IsFactory()) {
type_param = Class::Handle(Z, dart_function.Owner()).TypeParameterAt(i);
} else {
type_param = dart_function.TypeParameterAt(i);
}
@@ -4351,7 +4334,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
intptr_t type_args_len = 0;
if (function.IsGeneric()) {
if (target.IsConstructor()) {
if (target.IsGenerativeConstructor()) {
const auto& result_type = AbstractType::Handle(Z, function.result_type());
ASSERT(result_type.IsFinalized());
// Instantiate a flattened type arguments vector which
@@ -4368,10 +4351,6 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
ASSERT(parsed_function_->function_type_arguments() != nullptr);
closure += LoadLocal(parsed_function_->function_type_arguments());
}
} else if (target.IsFactory()) {
// Factories always take an extra implicit argument for
// type arguments even if their classes don't have type parameters.
closure += NullConstant();
}
// Push receiver.
@@ -3204,9 +3204,7 @@ TypedDataViewPtr KernelReaderHelper::GetConstantCoverageFor(intptr_t index) {
intptr_t ActiveClass::MemberTypeParameterCount(Zone* zone) {
ASSERT(member != nullptr);
if (member->IsFactory()) {
return klass->NumTypeParameters();
} else if (member->IsMethodExtractor()) {
if (member->IsMethodExtractor()) {
Function& extracted =
Function::Handle(zone, member->extracted_method_closure());
return extracted.NumTypeParameters();
@@ -3601,35 +3599,8 @@ void TypeTranslator::BuildTypeParameterType() {
parameter_index -= class_type_parameter_count;
if (active_class_->HasMember()) {
if (active_class_->MemberIsFactoryProcedure()) {
//
// WARNING: This is a little hackish:
//
// We have a static factory constructor. The kernel IR gives the factory
// constructor function its own type parameters (which are equal in name
// and number to the ones of the enclosing class). I.e.,
//
// class A<T> {
// factory A.x() { return new B<T>(); }
// }
//
// is basically translated to this:
//
// class A<T> {
// static A.x<T'>() { return new B<T'>(); }
// }
//
if (class_type_parameter_count > parameter_index) {
result_ = active_class_->klass->TypeParameterAt(parameter_index,
nullability);
return;
}
parameter_index -= class_type_parameter_count;
}
// Factory function should not be considered as procedure.
const intptr_t procedure_type_parameter_count =
(active_class_->MemberIsProcedure() &&
!active_class_->MemberIsFactoryProcedure())
active_class_->MemberIsProcedure()
? active_class_->MemberTypeParameterCount(Z)
: 0;
if (procedure_type_parameter_count > 0) {
@@ -3937,26 +3908,20 @@ void TypeTranslator::SetupFunctionParameters(
bool is_closure,
FunctionNodeHelper* function_node_helper) {
ASSERT(!(is_method && is_closure));
bool is_factory = function.IsFactory();
intptr_t extra_parameters = (is_method || is_closure || is_factory) ? 1 : 0;
intptr_t extra_parameters = (is_method || is_closure) ? 1 : 0;
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
ASSERT(!signature.IsNull());
intptr_t type_parameter_count = 0;
if (!is_factory) {
type_parameter_count = helper_->ReadListLength();
LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
signature, type_parameter_count);
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
}
intptr_t type_parameter_count = helper_->ReadListLength();
LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
signature, type_parameter_count);
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
if (!is_factory) {
LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature,
type_parameter_count);
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
}
LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature,
type_parameter_count);
function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
function_node_helper->ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
@@ -3996,13 +3961,9 @@ void TypeTranslator::SetupFunctionParameters(
signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
function.SetParameterNameAt(pos, Symbols::ClosureParameter());
pos++;
} else if (is_factory) {
signature.SetParameterTypeAt(pos, AbstractType::dynamic_type());
function.SetParameterNameAt(pos, Symbols::TypeArgumentsParameter());
pos++;
}
} else {
ASSERT(!is_method && !is_closure && !is_factory);
ASSERT(!is_method && !is_closure);
}
const Library& lib = Library::Handle(Z, active_class_->klass->library());
@@ -1429,11 +1429,6 @@ class ActiveClass {
member->IsFactory();
}
bool MemberIsFactoryProcedure() {
ASSERT(member != nullptr);
return member->IsFactory();
}
intptr_t MemberTypeParameterCount(Zone* zone);
intptr_t ClassNumTypeArguments() {
+7 -21
View File
@@ -224,12 +224,6 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
}
}
}
} else if (function.IsFactory()) {
LocalVariable* variable = MakeVariable(
TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
scope_->InsertParameterAt(pos++, variable);
result_->type_arguments_variable = variable;
}
ParameterTypeCheckMode type_check_mode =
@@ -1570,21 +1564,13 @@ void ScopeBuilder::VisitTypeParameterType() {
function = function.parent_function();
}
if (function.IsFactory()) {
// The type argument vector is passed as the very first argument to the
// factory constructor function.
HandleSpecialLoad(&result_->type_arguments_variable,
Symbols::TypeArgumentsParameter(),
LocalVariable::kNoKernelOffset);
} else {
// If the type parameter is a parameter to this or an enclosing function,
// we can read it directly from the function type arguments vector later.
// Otherwise, the type arguments vector we need is stored on the instance
// object, so we need to capture 'this'.
Class& parent_class = Class::Handle(Z, function.Owner());
if (index < parent_class.NumTypeParameters()) {
HandleLoadReceiver();
}
// If the type parameter is a parameter to this or an enclosing function,
// we can read it directly from the function type arguments vector later.
// Otherwise, the type arguments vector we need is stored on the instance
// object, so we need to capture 'this'.
Class& parent_class = Class::Handle(Z, function.Owner());
if (index < parent_class.NumTypeParameters()) {
HandleLoadReceiver();
}
}
}
+1 -5
View File
@@ -181,8 +181,7 @@ struct FunctionScope {
class ScopeBuildingResult : public ZoneObject {
public:
ScopeBuildingResult()
: type_arguments_variable(nullptr),
switch_variable(nullptr),
: switch_variable(nullptr),
finally_return_variable(nullptr),
setter_value(nullptr),
raw_variable_counter_(0) {}
@@ -200,9 +199,6 @@ class ScopeBuildingResult : public ZoneObject {
IntMap<LocalScope*> scopes;
GrowableArray<FunctionScope> function_scopes;
// Only non-null for factory constructor functions.
LocalVariable* type_arguments_variable;
// Non-nullptr when the function contains a switch statement.
LocalVariable* switch_variable;
+1
View File
@@ -15,6 +15,7 @@ intptr_t MethodRecognizer::NumArgsCheckedForStaticCall(
const Function& function) {
switch (function.recognized_kind()) {
case MethodRecognizer::kDoubleFromInteger:
return 1;
case MethodRecognizer::kMathMin:
case MethodRecognizer::kMathMax:
return 2;
+36 -23
View File
@@ -3205,11 +3205,14 @@ DART_EXPORT Dart_Handle Dart_NewMap(Dart_Handle keys_type,
Function& factory_method = Function::ZoneHandle(Z);
factory_method = map_class.LookupFactoryAllowPrivate(
Library::PrivateCoreLibName(Symbols::MapKeyValuesFactory()));
const Array& arguments_descriptor =
Array::Handle(Z, ArgumentsDescriptor::NewBoxed(2, 2));
const Array& args = Array::Handle(Z, Array::New(3));
args.SetAt(0, type_arguments);
args.SetAt(1, keys_obj);
args.SetAt(2, values_obj);
return Api::NewHandle(T, DartEntry::InvokeFunction(factory_method, args));
return Api::NewHandle(
T, DartEntry::InvokeFunction(factory_method, args, arguments_descriptor));
}
DART_EXPORT Dart_Handle Dart_NewListOfTypeFilled(Dart_Handle element_type,
@@ -3427,7 +3430,7 @@ DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
static ObjectPtr ResolveConstructor(const char* current_func,
const Class& cls,
const String& class_name,
const String& dotted_name,
const String& constr_name,
int num_args);
static ObjectPtr ThrowArgumentError(const char* exception_message) {
@@ -4079,13 +4082,12 @@ DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
ASSERT(result.IsFunction());
const Function& factory = Function::Cast(result);
ASSERT(!factory.IsGenerativeConstructor());
ASSERT(factory.NumParameters() == 1);
// Create the argument list.
const Array& args = Array::Handle(Z, Array::New(2));
// Factories get type arguments.
args.SetAt(0, Object::null_type_arguments());
const Array& args = Array::Handle(Z, Array::New(1));
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data));
args.SetAt(1, obj);
args.SetAt(0, obj);
// Invoke the factory constructor and return the new object.
result = DartEntry::InvokeFunction(factory, args);
@@ -4297,10 +4299,11 @@ static ObjectPtr ResolveConstructor(const char* current_func,
return ApiError::New(message);
}
}
const int kTypeArgsLen = 0;
const int extra_args = 1;
const int type_args_len =
constructor.IsGenerativeConstructor() ? 0 : cls.NumTypeParameters();
const int extra_args = constructor.IsGenerativeConstructor() ? 1 : 0;
String& error_message = String::Handle();
if (!constructor.AreValidArgumentCounts(kTypeArgsLen, num_args + extra_args,
if (!constructor.AreValidArgumentCounts(type_args_len, num_args + extra_args,
0, &error_message)) {
const String& message = String::Handle(String::NewFormatted(
"%s: wrong argument count for "
@@ -4344,9 +4347,6 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
Class& cls = Class::Handle(Z, type_obj.type_class());
CHECK_ERROR_HANDLE(cls.EnsureIsAllocateFinalized(T));
TypeArguments& type_arguments =
TypeArguments::Handle(Z, type_obj.GetInstanceTypeArguments(T));
const String& base_constructor_name = String::Handle(Z, cls.Name());
// And get the name of the constructor to invoke.
@@ -4388,22 +4388,33 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
}
// Create the argument list.
const intptr_t type_args_len =
constructor.IsGenerativeConstructor() ? 0 : cls.NumTypeParameters();
const intptr_t num_implicit_positional_args =
constructor.IsGenerativeConstructor() ? 1 : 0;
intptr_t arg_index = 0;
int extra_args = 1;
const Array& args =
Array::Handle(Z, Array::New(number_of_arguments + extra_args));
Array& args = Array::Handle(Z);
TypeArguments& instantiator_type_arguments = TypeArguments::Handle(Z);
TypeArguments& function_type_arguments = TypeArguments::Handle(Z);
if (constructor.IsGenerativeConstructor()) {
// Constructors get the uninitialized object.
if (!type_arguments.IsNull()) {
args = Array::New(number_of_arguments + num_implicit_positional_args);
instantiator_type_arguments = type_obj.GetInstanceTypeArguments(T);
if (!instantiator_type_arguments.IsNull()) {
// The type arguments will be null if the class has no type parameters, in
// which case the following call would fail because there is no slot
// reserved in the object for the type vector.
new_object.SetTypeArguments(type_arguments);
new_object.SetTypeArguments(instantiator_type_arguments);
}
args.SetAt(arg_index++, new_object);
} else {
// Factories get type arguments.
args.SetAt(arg_index++, type_arguments);
args = Array::New(number_of_arguments + ((type_args_len > 0) ? 1 : 0));
if (type_args_len > 0) {
function_type_arguments = type_obj.arguments();
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.Length() == type_args_len);
args.SetAt(arg_index++, function_type_arguments);
}
}
Object& argument = Object::Handle(Z);
for (int i = 0; i < number_of_arguments; i++) {
@@ -4420,19 +4431,21 @@ DART_EXPORT Dart_Handle Dart_New(Dart_Handle type,
args.SetAt(arg_index++, argument);
}
const int kTypeArgsLen = 0;
Array& args_descriptor_array = Array::Handle(
Z, ArgumentsDescriptor::NewBoxed(kTypeArgsLen, args.Length()));
Z,
ArgumentsDescriptor::NewBoxed(
type_args_len, number_of_arguments + num_implicit_positional_args));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
ObjectPtr type_error = constructor.DoArgumentTypesMatch(
args, args_descriptor, type_arguments, Object::empty_type_arguments());
args, args_descriptor, instantiator_type_arguments,
function_type_arguments);
if (type_error != Error::null()) {
return Api::NewHandle(T, type_error);
}
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(constructor, args);
result = DartEntry::InvokeFunction(constructor, args, args_descriptor_array);
if (result.IsError()) {
return Api::NewHandle(T, result.ptr());
}
+9 -13
View File
@@ -9713,10 +9713,6 @@ bool Function::CanBeInlined() const {
intptr_t Function::NumImplicitParameters() const {
const UntaggedFunction::Kind k = kind();
if (k == UntaggedFunction::kConstructor) {
// Type arguments for factory; instance for generative constructor.
return 1;
}
if ((k == UntaggedFunction::kClosureFunction) ||
(k == UntaggedFunction::kImplicitClosureFunction) ||
(k == UntaggedFunction::kFfiTrampoline)) {
@@ -10910,7 +10906,7 @@ FunctionPtr Function::ImplicitClosureFunction() const {
}
const intptr_t num_type_params =
IsConstructor() ? cls.NumTypeParameters() : NumTypeParameters();
IsGenerativeConstructor() ? cls.NumTypeParameters() : NumTypeParameters();
TypeArguments& instantiator_type_arguments = TypeArguments::Handle(zone);
TypeArguments& function_type_arguments = TypeArguments::Handle(zone);
@@ -10922,7 +10918,7 @@ FunctionPtr Function::ImplicitClosureFunction() const {
auto transform_type = [&](AbstractType& type) {
if (num_type_params > 0) {
if (IsConstructor()) {
if (IsGenerativeConstructor()) {
type = type.UpdateFunctionTypes(num_type_params, kAllFree, Heap::kOld,
nullptr);
if (!type.IsInstantiated(kCurrentClass)) {
@@ -10940,7 +10936,7 @@ FunctionPtr Function::ImplicitClosureFunction() const {
auto transform_type_args = [&](TypeArguments& type_args) {
ASSERT(num_type_params > 0);
if (!type_args.IsNull()) {
if (IsConstructor()) {
if (IsGenerativeConstructor()) {
type_args = type_args.UpdateFunctionTypes(num_type_params, kAllFree,
Heap::kOld, nullptr);
if (!type_args.IsInstantiated(kCurrentClass)) {
@@ -10958,7 +10954,8 @@ FunctionPtr Function::ImplicitClosureFunction() const {
// Set closure function's type parameters.
if (num_type_params > 0) {
const TypeParameters& old_type_params = TypeParameters::Handle(
zone, IsConstructor() ? cls.type_parameters() : type_parameters());
zone,
IsGenerativeConstructor() ? cls.type_parameters() : type_parameters());
const TypeParameters& new_type_params =
TypeParameters::Handle(zone, TypeParameters::New());
// No need to set names that are ignored in a signature, however, the
@@ -10977,7 +10974,7 @@ FunctionPtr Function::ImplicitClosureFunction() const {
type_args.SetTypeAt(i, type_param);
}
if (IsConstructor()) {
if (IsGenerativeConstructor()) {
instantiator_type_arguments =
type_args.ToInstantiatorTypeArguments(thread, cls);
} else {
@@ -10996,7 +10993,7 @@ FunctionPtr Function::ImplicitClosureFunction() const {
// Set closure function's result type.
AbstractType& result_type = AbstractType::Handle(zone);
if (IsConstructor()) {
if (IsGenerativeConstructor()) {
result_type = cls.DeclarationType();
} else {
result_type = this->result_type();
@@ -18123,14 +18120,13 @@ ICDataPtr ICData::NewForStaticCall(const Function& owner,
intptr_t num_args_tested,
RebindRule rebind_rule) {
// See `MethodRecognizer::NumArgsCheckedForStaticCall`.
ASSERT(num_args_tested == 0 || num_args_tested == 2);
ASSERT(num_args_tested == 0 || num_args_tested == 1 || num_args_tested == 2);
ASSERT(!target.IsNull());
Zone* zone = Thread::Current()->zone();
const auto& target_name = String::Handle(zone, target.name());
GrowableArray<intptr_t> cids(num_args_tested);
if (num_args_tested == 2) {
cids.Add(kObjectCid);
for (intptr_t i = 0; i < num_args_tested; ++i) {
cids.Add(kObjectCid);
}
return ICData::NewWithCheck(owner, target_name, arguments_descriptor,
+3 -8
View File
@@ -1064,13 +1064,8 @@ DEFINE_RUNTIME_ENTRY(AdjustArgumentsDesciptorForImplicitClosure, 3) {
intptr_t num_arguments = args_desc.Count();
if (target.is_static()) {
if (target.IsFactory()) {
// Factory always takes type arguments via a positional parameter.
type_args_len = 0;
} else {
// Drop closure receiver.
--num_arguments;
}
// Drop closure receiver.
--num_arguments;
} else {
if (target.IsGenerativeConstructor()) {
// Type arguments are not passed to a generative constructor.
@@ -2496,7 +2491,7 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) {
const Instance& arg = Instance::CheckedHandle(zone, arguments.ArgAt(0));
const ICData& ic_data = ICData::CheckedHandle(zone, arguments.ArgAt(1));
// IC data for static call is prepopulated with the statically known target.
ASSERT(ic_data.NumberOfChecksIs(1));
ASSERT(!ic_data.NumberOfChecksIs(0));
const Function& target = Function::Handle(zone, ic_data.GetTargetAt(0));
target.EnsureHasCode();
ASSERT(!target.IsNull() && target.HasCode());