Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Unified Diff: runtime/vm/code_generator.cc

Issue 2799373002: Pass a second type argument vector to all type instantiation calls in the VM. (Closed)
Patch Set: addressed comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | runtime/vm/constant_propagator.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index de63989ec9f953e6121c4bfaf8ca5e0a55a69f02..4e6a05ca231d28c7c5e9bd6c057c4069415130f3 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -234,16 +234,23 @@ DEFINE_RUNTIME_ENTRY(AllocateObject, 2) {
// Instantiate type.
// Arg0: uninstantiated type.
// Arg1: instantiator type arguments.
+// Arg2: function type arguments.
// Return value: instantiated type.
-DEFINE_RUNTIME_ENTRY(InstantiateType, 2) {
+DEFINE_RUNTIME_ENTRY(InstantiateType, 3) {
AbstractType& type = AbstractType::CheckedHandle(zone, arguments.ArgAt(0));
- const TypeArguments& instantiator =
+ const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
+ const TypeArguments& function_type_arguments =
+ TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
ASSERT(!type.IsNull() && !type.IsInstantiated());
- ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
+ ASSERT(instantiator_type_arguments.IsNull() ||
+ instantiator_type_arguments.IsInstantiated());
+ ASSERT(function_type_arguments.IsNull() ||
+ function_type_arguments.IsInstantiated());
Error& bound_error = Error::Handle(zone);
type =
- type.InstantiateFrom(instantiator, &bound_error, NULL, NULL, Heap::kOld);
+ type.InstantiateFrom(instantiator_type_arguments, function_type_arguments,
+ &bound_error, NULL, NULL, Heap::kOld);
if (!bound_error.IsNull()) {
// Throw a dynamic type error.
const TokenPosition location = GetCallerLocation();
@@ -267,21 +274,27 @@ DEFINE_RUNTIME_ENTRY(InstantiateType, 2) {
// Instantiate type arguments.
// Arg0: uninstantiated type arguments.
// Arg1: instantiator type arguments.
+// Arg2: function type arguments.
// Return value: instantiated type arguments.
-DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
+DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 3) {
TypeArguments& type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(0));
- const TypeArguments& instantiator =
+ const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(1));
+ const TypeArguments& function_type_arguments =
+ TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
- ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
+ ASSERT(instantiator_type_arguments.IsNull() ||
+ instantiator_type_arguments.IsInstantiated());
+ ASSERT(function_type_arguments.IsNull() ||
+ function_type_arguments.IsInstantiated());
// Code inlined in the caller should have optimized the case where the
// instantiator can be reused as type argument vector.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
if (isolate->type_checks()) {
Error& bound_error = Error::Handle(zone);
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
- instantiator, &bound_error);
+ instantiator_type_arguments, function_type_arguments, &bound_error);
if (!bound_error.IsNull()) {
// Throw a dynamic type error.
const TokenPosition location = GetCallerLocation();
@@ -293,8 +306,8 @@ DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
UNREACHABLE();
}
} else {
- type_arguments =
- type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
+ type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
+ instantiator_type_arguments, function_type_arguments, NULL);
}
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
@@ -333,6 +346,7 @@ static void PrintTypeCheck(const char* message,
const Instance& instance,
const AbstractType& type,
const TypeArguments& instantiator_type_arguments,
+ const TypeArguments& function_type_arguments,
const Bool& result) {
DartFrameIterator iterator;
StackFrame* caller_frame = iterator.NextFrame();
@@ -353,7 +367,8 @@ static void PrintTypeCheck(const char* message,
Error& bound_error = Error::Handle();
const AbstractType& instantiated_type =
AbstractType::Handle(type.InstantiateFrom(
- instantiator_type_arguments, &bound_error, NULL, NULL, Heap::kOld));
+ instantiator_type_arguments, function_type_arguments, &bound_error,
+ NULL, NULL, Heap::kOld));
OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
message, String::Handle(instance_type.Name()).ToCString(),
(result.raw() == Bool::True().raw()) ? "is" : "is !",
@@ -369,16 +384,18 @@ static void PrintTypeCheck(const char* message,
}
-// This updates the type test cache, an array containing 4-value elements
+// This updates the type test cache, an array containing 5-value elements
// (instance class (or function if the instance is a closure), instance type
-// arguments, instantiator type arguments and test_result). It can be applied to
-// classes with type arguments in which case it contains just the result of the
-// class subtype test, not including the evaluation of type arguments.
+// arguments, instantiator type arguments, function type arguments,
+// and test_result). It can be applied to classes with type arguments in which
+// case it contains just the result of the class subtype test, not including the
+// evaluation of type arguments.
// This operation is currently very slow (lookup of code is not efficient yet).
static void UpdateTypeTestCache(
const Instance& instance,
const AbstractType& type,
const TypeArguments& instantiator_type_arguments,
+ const TypeArguments& function_type_arguments,
const Bool& result,
const SubtypeTestCache& new_cache) {
// Since the test is expensive, don't do it unless necessary.
@@ -396,6 +413,17 @@ static void UpdateTypeTestCache(
}
return;
}
+ // If the type is uninstantiated and refers to parent function type
+ // parameters, the context is required in the type test and the cache
+ // therefore cannot be used.
+ if (!type.IsInstantiated(kParentFunctions)) {
+ if (FLAG_trace_type_checks) {
+ OS::Print(
+ "UpdateTypeTestCache: type refers to parent function's type "
+ "parameters\n");
+ }
+ return;
+ }
const Class& instance_class = Class::Handle(instance.clazz());
Object& instance_class_id_or_function = Object::Handle();
TypeArguments& instance_type_arguments = TypeArguments::Handle();
@@ -417,48 +445,61 @@ static void UpdateTypeTestCache(
instance_type_arguments.IsCanonical());
ASSERT(instantiator_type_arguments.IsNull() ||
instantiator_type_arguments.IsCanonical());
+ ASSERT(function_type_arguments.IsNull() ||
+ function_type_arguments.IsCanonical());
Object& last_instance_class_id_or_function = Object::Handle();
TypeArguments& last_instance_type_arguments = TypeArguments::Handle();
TypeArguments& last_instantiator_type_arguments = TypeArguments::Handle();
+ TypeArguments& last_function_type_arguments = TypeArguments::Handle();
Bool& last_result = Bool::Handle();
for (intptr_t i = 0; i < len; ++i) {
new_cache.GetCheck(i, &last_instance_class_id_or_function,
&last_instance_type_arguments,
- &last_instantiator_type_arguments, &last_result);
+ &last_instantiator_type_arguments,
+ &last_function_type_arguments, &last_result);
if ((last_instance_class_id_or_function.raw() ==
instance_class_id_or_function.raw()) &&
(last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
(last_instantiator_type_arguments.raw() ==
- instantiator_type_arguments.raw())) {
+ instantiator_type_arguments.raw()) &&
+ (last_function_type_arguments.raw() ==
+ last_function_type_arguments.raw())) {
OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
PrintTypeCheck(" duplicate cache entry", instance, type,
- instantiator_type_arguments, result);
+ instantiator_type_arguments, function_type_arguments,
+ result);
UNREACHABLE();
return;
}
}
#endif
new_cache.AddCheck(instance_class_id_or_function, instance_type_arguments,
- instantiator_type_arguments, result);
+ instantiator_type_arguments, function_type_arguments,
+ result);
if (FLAG_trace_type_checks) {
AbstractType& test_type = AbstractType::Handle(type.raw());
if (!test_type.IsInstantiated()) {
Error& bound_error = Error::Handle();
test_type = type.InstantiateFrom(instantiator_type_arguments,
- &bound_error, NULL, NULL, Heap::kNew);
+ function_type_arguments, &bound_error,
+ NULL, NULL, Heap::kNew);
ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
}
OS::PrintErr(
" Updated test cache %p ix: %" Pd
" with "
- "(cid-or-fun: %p, type-args: %p, instantiator: %p, result: %s)\n"
+ "(cid-or-fun: %p, type-args: %p, i-type-args: %p, f-type-args: %p, "
+ "result: %s)\n"
" instance [class: (%p '%s' cid: %" Pd
"), type-args: %p %s]\n"
- " test-type [class: (%p '%s' cid: %" Pd "), in-type-args: %p %s]\n",
+ " test-type [class: (%p '%s' cid: %" Pd
+ "), i-type-args: %p %s, "
+ ", f-type-args: %p %s]\n",
new_cache.raw(), len,
instance_class_id_or_function.raw(), instance_type_arguments.raw(),
- instantiator_type_arguments.raw(), result.ToCString(),
+ instantiator_type_arguments.raw(), instantiator_type_arguments.raw(),
+ result.ToCString(),
instance_class.raw(), String::Handle(instance_class.Name()).ToCString(),
instance_class.id(), instance_type_arguments.raw(),
@@ -469,6 +510,8 @@ static void UpdateTypeTestCache(
.ToCString(),
Class::Handle(test_type.type_class()).id(),
instantiator_type_arguments.raw(),
+ instantiator_type_arguments.ToCString(),
+ instantiator_type_arguments.raw(),
instantiator_type_arguments.ToCString());
}
}
@@ -479,26 +522,30 @@ static void UpdateTypeTestCache(
// Arg0: instance being checked.
// Arg1: type.
// Arg2: type arguments of the instantiator of the type.
-// Arg3: SubtypeTestCache.
+// Arg3: type arguments of the function of the type.
+// Arg4: SubtypeTestCache.
// Return value: true or false, or may throw a type error in checked mode.
-DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
+DEFINE_RUNTIME_ENTRY(Instanceof, 5) {
const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0));
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments.ArgAt(1));
const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
+ const TypeArguments& function_type_arguments =
+ TypeArguments::CheckedHandle(zone, arguments.ArgAt(3));
const SubtypeTestCache& cache =
- SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(3));
+ SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4));
ASSERT(type.IsFinalized());
ASSERT(!type.IsMalformed()); // Already checked in code generator.
ASSERT(!type.IsMalbounded()); // Already checked in code generator.
ASSERT(!type.IsDynamicType()); // No need to check assignment.
Error& bound_error = Error::Handle(zone);
- const Bool& result = Bool::Get(
- instance.IsInstanceOf(type, instantiator_type_arguments, &bound_error));
+ const Bool& result =
+ Bool::Get(instance.IsInstanceOf(type, instantiator_type_arguments,
+ function_type_arguments, &bound_error));
if (FLAG_trace_type_checks) {
PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments,
- result);
+ function_type_arguments, result);
}
if (!result.value() && !bound_error.IsNull()) {
// Throw a dynamic type error only if the instanceof test fails.
@@ -510,8 +557,8 @@ DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
- UpdateTypeTestCache(instance, type, instantiator_type_arguments, result,
- cache);
+ UpdateTypeTestCache(instance, type, instantiator_type_arguments,
+ function_type_arguments, result, cache);
arguments.SetReturn(result);
}
@@ -521,31 +568,36 @@ DEFINE_RUNTIME_ENTRY(Instanceof, 4) {
// Arg0: instance being assigned.
// Arg1: type being assigned to.
// Arg2: type arguments of the instantiator of the type being assigned to.
-// Arg3: name of variable being assigned to.
-// Arg4: SubtypeTestCache.
+// Arg3: type arguments of the function of the type being assigned to.
+// Arg4: name of variable being assigned to.
+// Arg5: SubtypeTestCache.
// Return value: instance if a subtype, otherwise throw a TypeError.
-DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
+DEFINE_RUNTIME_ENTRY(TypeCheck, 6) {
const Instance& src_instance =
Instance::CheckedHandle(zone, arguments.ArgAt(0));
AbstractType& dst_type =
AbstractType::CheckedHandle(zone, arguments.ArgAt(1));
const TypeArguments& instantiator_type_arguments =
TypeArguments::CheckedHandle(zone, arguments.ArgAt(2));
- const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(3));
+ const TypeArguments& function_type_arguments =
+ TypeArguments::CheckedHandle(zone, arguments.ArgAt(3));
+ const String& dst_name = String::CheckedHandle(zone, arguments.ArgAt(4));
const SubtypeTestCache& cache =
- SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(4));
+ SubtypeTestCache::CheckedHandle(zone, arguments.ArgAt(5));
ASSERT(!dst_type.IsMalformed()); // Already checked in code generator.
ASSERT(!dst_type.IsMalbounded()); // Already checked in code generator.
ASSERT(!dst_type.IsDynamicType()); // No need to check assignment.
ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
Error& bound_error = Error::Handle(zone);
- const bool is_instance_of = src_instance.IsInstanceOf(
- dst_type, instantiator_type_arguments, &bound_error);
+ const bool is_instance_of =
+ src_instance.IsInstanceOf(dst_type, instantiator_type_arguments,
+ function_type_arguments, &bound_error);
if (FLAG_trace_type_checks) {
PrintTypeCheck("TypeCheck", src_instance, dst_type,
- instantiator_type_arguments, Bool::Get(is_instance_of));
+ instantiator_type_arguments, function_type_arguments,
+ Bool::Get(is_instance_of));
}
if (!is_instance_of) {
// Throw a dynamic type error.
@@ -554,8 +606,9 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
if (!dst_type.IsInstantiated()) {
// Instantiate dst_type before reporting the error.
- dst_type = dst_type.InstantiateFrom(instantiator_type_arguments, NULL,
- NULL, NULL, Heap::kNew);
+ dst_type = dst_type.InstantiateFrom(instantiator_type_arguments,
+ function_type_arguments, NULL, NULL,
+ NULL, Heap::kNew);
// Note that instantiated dst_type may be malbounded.
}
String& bound_error_message = String::Handle(zone);
@@ -568,7 +621,7 @@ DEFINE_RUNTIME_ENTRY(TypeCheck, 5) {
UNREACHABLE();
}
UpdateTypeTestCache(src_instance, dst_type, instantiator_type_arguments,
- Bool::True(), cache);
+ function_type_arguments, Bool::True(), cache);
arguments.SetReturn(src_instance);
}
@@ -806,8 +859,8 @@ static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
const AbstractType& type,
const ArgumentsDescriptor& desc) {
Error& error = Error::Handle();
- bool result =
- receiver.IsInstanceOf(type, Object::null_type_arguments(), &error);
+ bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(),
+ Object::null_type_arguments(), &error);
ASSERT(error.IsNull());
ObjectStore* store = Isolate::Current()->object_store();
const Function& target =
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | runtime/vm/constant_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698