Chromium Code Reviews| 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)); |