Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| =================================================================== |
| --- runtime/vm/code_generator.cc (revision 7209) |
| +++ runtime/vm/code_generator.cc (working copy) |
| @@ -188,6 +188,78 @@ |
| } |
| +// 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: index of the token of the instance creation (source location). |
| +// Arg1: class of the object that needs to be allocated. |
| +// Arg2: type arguments of the object that needs to be allocated. |
| +// Arg3: type arguments of the instantiator or kNoInstantiator. |
| +// Return value: newly allocated object. |
|
srdjan
2012/05/01 23:30:51
Can you measure if there is any performance impact
regis
2012/05/02 01:34:16
Yes, I will measure (I'll check with you for the p
|
| +DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 4) { |
| + ASSERT(FLAG_enable_type_checks); |
| + ASSERT(arguments.Count() == |
| + kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count()); |
| + const Class& cls = Class::CheckedHandle(arguments.At(1)); |
| + const Instance& instance = Instance::Handle(Instance::New(cls)); |
| + arguments.SetReturn(instance); |
| + ASSERT(cls.HasTypeArguments()); |
| + AbstractTypeArguments& type_arguments = |
| + AbstractTypeArguments::CheckedHandle(arguments.At(2)); |
| + ASSERT(type_arguments.IsNull() || |
| + (type_arguments.Length() == cls.NumTypeArguments())); |
| + AbstractTypeArguments& bounds_instantiator = AbstractTypeArguments::Handle(); |
| + if (Object::Handle(arguments.At(3)).IsSmi()) { |
| + ASSERT(Smi::CheckedHandle(arguments.At(3)).Value() == |
| + StubCode::kNoInstantiator); |
| + } else { |
| + ASSERT(!type_arguments.IsInstantiated()); |
| + const AbstractTypeArguments& instantiator = |
| + AbstractTypeArguments::CheckedHandle(arguments.At(3)); |
| + ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); |
| + if (instantiator.IsNull()) { |
| + type_arguments = |
| + InstantiatedTypeArguments::New(type_arguments, instantiator); |
| + } else if (instantiator.IsTypeArguments()) { |
| + // Code inlined in the caller should have optimized the case where the |
| + // instantiator is a TypeArguments and can be used as type argument |
| + // vector. |
| + ASSERT(!type_arguments.IsUninstantiatedIdentity() || |
| + (instantiator.Length() != type_arguments.Length())); |
| + type_arguments = |
| + InstantiatedTypeArguments::New(type_arguments, instantiator); |
| + } else { |
| + // If possible, use the instantiator as the type argument vector. |
| + if (type_arguments.IsUninstantiatedIdentity() && |
| + (instantiator.Length() == type_arguments.Length())) { |
| + type_arguments = instantiator.raw(); |
| + } else { |
| + type_arguments = |
| + InstantiatedTypeArguments::New(type_arguments, instantiator); |
| + } |
| + } |
| + bounds_instantiator = instantiator.raw(); |
| + } |
| + if (!type_arguments.IsNull()) { |
| + ASSERT(type_arguments.IsInstantiated()); |
| + Error& malformed_error = Error::Handle(); |
| + if (!type_arguments.IsWithinBoundsOf(cls, |
| + bounds_instantiator, |
| + &malformed_error)) { |
| + ASSERT(!malformed_error.IsNull()); |
| + // Throw a dynamic type error. |
| + intptr_t location = Smi::CheckedHandle(arguments.At(0)).Value(); |
| + String& malformed_error_message = String::Handle( |
| + String::New(malformed_error.ToErrorCString())); |
| + const String& no_name = String::Handle(String::NewSymbol("")); |
| + Exceptions::CreateAndThrowTypeError( |
| + location, no_name, no_name, no_name, malformed_error_message); |
| + UNREACHABLE(); |
| + } |
| + } |
| + instance.SetTypeArguments(type_arguments); |
| +} |
| + |
| + |
| // Instantiate type arguments. |
| // Arg0: uninstantiated type arguments. |
| // Arg1: instantiator type arguments. |