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

Unified Diff: runtime/vm/code_generator.cc

Issue 154393003: Implement eager instantiation and canonicalization of type arguments at run (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 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
Index: runtime/vm/code_generator.cc
===================================================================
--- runtime/vm/code_generator.cc (revision 32446)
+++ runtime/vm/code_generator.cc (working copy)
@@ -91,8 +91,8 @@
const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0));
const Array& array = Array::Handle(Array::New(length.Value()));
arguments.SetReturn(array);
- AbstractTypeArguments& element_type =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+ TypeArguments& element_type =
+ TypeArguments::CheckedHandle(arguments.ArgAt(1));
// An Array is raw or takes one type argument. However, its type argument
// vector may be longer than 1 due to a type optimization reusing the type
// argument vector of the instantiator.
@@ -102,6 +102,15 @@
}
+// Helper returning the token position of the Dart caller.
+static intptr_t GetCallerLocation() {
+ DartFrameIterator iterator;
+ StackFrame* caller_frame = iterator.NextFrame();
+ ASSERT(caller_frame != NULL);
+ return caller_frame->GetTokenPos();
+}
+
+
// Allocate a new object.
// Arg0: class of the object that needs to be allocated.
// Arg1: type arguments of the object that needs to be allocated.
@@ -116,8 +125,8 @@
ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull());
return;
}
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+ TypeArguments& type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(1));
// If no instantiator is provided, set the type arguments and return.
if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
@@ -134,61 +143,17 @@
// A still uninstantiated type argument vector must have the correct length.
ASSERT(!type_arguments.IsInstantiated() &&
(type_arguments.Length() == cls.NumTypeArguments()));
- const AbstractTypeArguments& instantiator =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
+ const TypeArguments& instantiator =
+ TypeArguments::CheckedHandle(arguments.ArgAt(2));
ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
// Code inlined in the caller should have optimized the case where the
// instantiator can be reused as type argument vector.
ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
- type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator);
- instance.SetTypeArguments(type_arguments);
-}
-
-
-// Helper returning the token position of the Dart caller.
-static intptr_t GetCallerLocation() {
- DartFrameIterator iterator;
- StackFrame* caller_frame = iterator.NextFrame();
- ASSERT(caller_frame != NULL);
- return caller_frame->GetTokenPos();
-}
-
-
-// Allocate a new object of a generic type and check that the instantiated type
-// arguments are within the declared bounds or throw a dynamic type error.
-// Arg0: class of the object that needs to be allocated.
-// Arg1: type arguments of the object that needs to be allocated.
-// Arg2: type arguments of the instantiator or kNoInstantiator.
-// Return value: newly allocated object.
-DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 3) {
- ASSERT(FLAG_enable_type_checks);
- const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
- const Instance& instance = Instance::Handle(Instance::New(cls));
- arguments.SetReturn(instance);
- ASSERT(cls.NumTypeArguments() > 0);
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
- if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
- ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
- StubCode::kNoInstantiator);
- // Unless null (for a raw type), the type argument vector may be longer than
- // necessary due to a type optimization reusing the type argument vector of
- // the instantiator.
- ASSERT(type_arguments.IsNull() ||
- (type_arguments.IsInstantiated() &&
- (type_arguments.Length() >= cls.NumTypeArguments())));
- } else {
- // A still uninstantiated type argument vector must have the correct length.
- ASSERT(!type_arguments.IsInstantiated() &&
- (type_arguments.Length() == cls.NumTypeArguments()));
- const AbstractTypeArguments& instantiator =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
- ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
+ if (FLAG_enable_type_checks) {
Error& bound_error = Error::Handle();
- // Code inlined in the caller should have optimized the case where the
- // instantiator can be reused as type argument vector.
- ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
- type_arguments = type_arguments.InstantiateFrom(instantiator, &bound_error);
+ type_arguments =
+ type_arguments.InstantiateAndCanonicalizeFrom(instantiator,
+ &bound_error);
if (!bound_error.IsNull()) {
// Throw a dynamic type error.
const intptr_t location = GetCallerLocation();
@@ -199,6 +164,9 @@
Symbols::Empty(), bound_error_message);
UNREACHABLE();
}
+ } else {
+ type_arguments =
+ type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
}
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
instance.SetTypeArguments(type_arguments);
@@ -211,8 +179,8 @@
// Return value: instantiated type.
DEFINE_RUNTIME_ENTRY(InstantiateType, 2) {
AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(0));
- const AbstractTypeArguments& instantiator =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+ const TypeArguments& instantiator =
+ TypeArguments::CheckedHandle(arguments.ArgAt(1));
ASSERT(!type.IsNull() && !type.IsInstantiated());
ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
Error& bound_error = Error::Handle();
@@ -242,16 +210,17 @@
// Arg1: instantiator type arguments.
// Return value: instantiated type arguments.
DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(0));
- const AbstractTypeArguments& instantiator =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+ TypeArguments& type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(0));
+ const TypeArguments& instantiator =
+ TypeArguments::CheckedHandle(arguments.ArgAt(1));
ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
// Code inlined in the caller should have optimized the case where the
// instantiator can be reused as type argument vector.
ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
- type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator);
+ type_arguments =
+ type_arguments.InstantiateAndCanonicalizeFrom(instantiator, NULL);
ASSERT(type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
}
@@ -268,8 +237,8 @@
DEFINE_RUNTIME_ENTRY(AllocateClosure, 2) {
const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
ASSERT(function.IsClosureFunction() && !function.IsImplicitClosureFunction());
- const AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
+ const TypeArguments& type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(1));
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
// The current context was saved in the Isolate structure when entering the
// runtime.
@@ -290,8 +259,8 @@
const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
ASSERT(function.IsImplicitInstanceClosureFunction());
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(1));
- const AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
+ const TypeArguments& type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(2));
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
Context& context = Context::Handle();
context = Context::New(1);
@@ -331,7 +300,7 @@
const char* message,
const Instance& instance,
const AbstractType& type,
- const AbstractTypeArguments& instantiator_type_arguments,
+ const TypeArguments& instantiator_type_arguments,
const Bool& result) {
DartFrameIterator iterator;
StackFrame* caller_frame = iterator.NextFrame();
@@ -370,51 +339,6 @@
}
-// Converts InstantiatedTypeArguments to TypeArguments and stores it
-// into the instance. The assembly code can handle only type arguments of
-// class TypeArguments. Because of the overhead, do it only when needed.
-// Return true if type arguments have been replaced, false otherwise.
-static bool OptimizeTypeArguments(const Instance& instance) {
- const Class& type_class = Class::ZoneHandle(instance.clazz());
- if (type_class.NumTypeArguments() == 0) {
- return false;
- }
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::Handle(instance.GetTypeArguments());
- if (type_arguments.IsNull()) {
- return false;
- }
- bool replaced = false;
- if (type_arguments.IsInstantiatedTypeArguments()) {
- AbstractTypeArguments& uninstantiated = AbstractTypeArguments::Handle();
- AbstractTypeArguments& instantiator = AbstractTypeArguments::Handle();
- do {
- const InstantiatedTypeArguments& instantiated_type_arguments =
- InstantiatedTypeArguments::Cast(type_arguments);
- uninstantiated =
- instantiated_type_arguments.uninstantiated_type_arguments();
- instantiator = instantiated_type_arguments.instantiator_type_arguments();
- Error& bound_error = Error::Handle();
- type_arguments = uninstantiated.InstantiateFrom(instantiator,
- &bound_error);
- ASSERT(bound_error.IsNull()); // Malbounded types are not optimized.
- } while (type_arguments.IsInstantiatedTypeArguments());
- AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
- new_type_arguments = type_arguments.Canonicalize();
- instance.SetTypeArguments(new_type_arguments);
- replaced = true;
- } else if (!type_arguments.IsCanonical()) {
- AbstractTypeArguments& new_type_arguments = AbstractTypeArguments::Handle();
- new_type_arguments = type_arguments.Canonicalize();
- instance.SetTypeArguments(new_type_arguments);
- replaced = true;
- }
- ASSERT(AbstractTypeArguments::Handle(
- instance.GetTypeArguments()).IsTypeArguments());
- return replaced;
-}
-
-
// This updates the type test cache, an array containing 4-value elements
// (instance class, instance type arguments, instantiator type arguments and
// test_result). It can be applied to classes with type arguments in which
@@ -426,7 +350,7 @@
const Instance& instance,
const AbstractType& type,
const Instance& instantiator,
- const AbstractTypeArguments& incoming_instantiator_type_arguments,
+ const TypeArguments& instantiator_type_arguments,
const Bool& result,
const SubtypeTestCache& new_cache) {
// Since the test is expensive, don't do it unless necessary.
@@ -438,37 +362,35 @@
}
return;
}
- // Instantiator type arguments may be canonicalized later.
- AbstractTypeArguments& instantiator_type_arguments =
- AbstractTypeArguments::Handle(incoming_instantiator_type_arguments.raw());
- AbstractTypeArguments& instance_type_arguments =
- AbstractTypeArguments::Handle();
+ if (instance.IsSmi()) {
+ if (FLAG_trace_type_checks) {
+ OS::Print("UpdateTypeTestCache: instance is Smi\n");
+ }
+ return;
+ }
+ TypeArguments& instance_type_arguments =
+ TypeArguments::Handle();
srdjan 2014/02/07 21:59:47 This should fit on one line.
const Class& instance_class = Class::Handle(instance.clazz());
- // Canonicalize type arguments.
- bool type_arguments_replaced = false;
if (instance_class.NumTypeArguments() > 0) {
- // Canonicalize type arguments.
- type_arguments_replaced = OptimizeTypeArguments(instance);
instance_type_arguments = instance.GetTypeArguments();
}
- if (!instantiator.IsNull()) {
- if (OptimizeTypeArguments(instantiator)) {
- type_arguments_replaced = true;
- }
- instantiator_type_arguments = instantiator.GetTypeArguments();
- }
- intptr_t last_instance_class_id = -1;
- AbstractTypeArguments& last_instance_type_arguments =
- AbstractTypeArguments::Handle();
- AbstractTypeArguments& last_instantiator_type_arguments =
- AbstractTypeArguments::Handle();
- Bool& last_result = Bool::Handle();
const intptr_t len = new_cache.NumberOfChecks();
if (len >= FLAG_max_subtype_cache_entries) {
return;
}
+#if defined(DEBUG)
+ ASSERT(instance_type_arguments.IsNull() ||
+ instance_type_arguments.IsCanonical());
+ ASSERT(instantiator_type_arguments.IsNull() ||
+ instantiator_type_arguments.IsCanonical());
+ intptr_t last_instance_class_id = -1;
+ TypeArguments& last_instance_type_arguments =
+ TypeArguments::Handle();
+ TypeArguments& last_instantiator_type_arguments =
+ TypeArguments::Handle();
+ Bool& last_result = Bool::Handle();
for (intptr_t i = 0; i < len; ++i) {
new_cache.GetCheck(
i,
@@ -480,28 +402,18 @@
(last_instance_type_arguments.raw() == instance_type_arguments.raw()) &&
(last_instantiator_type_arguments.raw() ==
instantiator_type_arguments.raw())) {
- if (FLAG_trace_type_checks) {
- OS::PrintErr("%" Pd " ", i);
- if (type_arguments_replaced) {
- PrintTypeCheck("Duplicate cache entry (canonical.)", instance, type,
- instantiator_type_arguments, result);
- } else {
- PrintTypeCheck("WARNING Duplicate cache entry", instance, type,
- instantiator_type_arguments, result);
- }
- }
- // Can occur if we have canonicalized arguments.
- // TODO(srdjan): Investigate why this assert can fail.
- // ASSERT(type_arguments_replaced);
+ OS::PrintErr(" Error in test cache %p ix: %" Pd ",", new_cache.raw(), i);
+ PrintTypeCheck(" duplicate cache entry", instance, type,
+ instantiator_type_arguments, result);
+ UNREACHABLE();
return;
}
}
- if (!instantiator_type_arguments.IsInstantiatedTypeArguments()) {
- new_cache.AddCheck(instance_class.id(),
- instance_type_arguments,
- instantiator_type_arguments,
- result);
- }
+#endif
+ new_cache.AddCheck(instance_class.id(),
+ instance_type_arguments,
+ instantiator_type_arguments,
+ result);
if (FLAG_trace_type_checks) {
AbstractType& test_type = AbstractType::Handle(type.raw());
if (!test_type.IsInstantiated()) {
@@ -550,8 +462,8 @@
const Instance& instance = Instance::CheckedHandle(arguments.ArgAt(0));
const AbstractType& type = AbstractType::CheckedHandle(arguments.ArgAt(1));
const Instance& instantiator = Instance::CheckedHandle(arguments.ArgAt(2));
- const AbstractTypeArguments& instantiator_type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3));
+ const TypeArguments& instantiator_type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(3));
const SubtypeTestCache& cache =
SubtypeTestCache::CheckedHandle(arguments.ArgAt(4));
ASSERT(type.IsFinalized());
@@ -598,8 +510,8 @@
AbstractType::CheckedHandle(arguments.ArgAt(1));
const Instance& dst_instantiator =
Instance::CheckedHandle(arguments.ArgAt(2));
- const AbstractTypeArguments& instantiator_type_arguments =
- AbstractTypeArguments::CheckedHandle(arguments.ArgAt(3));
+ const TypeArguments& instantiator_type_arguments =
+ TypeArguments::CheckedHandle(arguments.ArgAt(3));
const String& dst_name = String::CheckedHandle(arguments.ArgAt(4));
const SubtypeTestCache& cache =
SubtypeTestCache::CheckedHandle(arguments.ArgAt(5));

Powered by Google App Engine
This is Rietveld 408576698