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)); |