| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index 728e2ffe6446a8833d056194b9aef8d727408440..7a41f2d6dc53f95e5b907579b8a8ee9036cd77bb 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -2673,6 +2673,14 @@ RawFunction* Class::CreateInvocationDispatcher(const String& target_name,
|
| false, // Not native.
|
| *this, TokenPosition::kMinSource));
|
| ArgumentsDescriptor desc(args_desc);
|
| + if (desc.TypeArgsLen() > 0) {
|
| + // Make dispatcher function generic, since type arguments are passed.
|
| + const TypeArguments& type_params =
|
| + TypeArguments::Handle(zone, TypeArguments::New(desc.TypeArgsLen()));
|
| + // TODO(regis): Can we leave the array uninitialized to save memory?
|
| + invocation.set_type_parameters(type_params);
|
| + }
|
| +
|
| invocation.set_num_fixed_parameters(desc.PositionalCount());
|
| invocation.SetNumOptionalParameters(desc.NamedCount(),
|
| false); // Not positional.
|
| @@ -4835,6 +4843,9 @@ void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
|
|
|
|
|
| bool TypeArguments::IsResolved() const {
|
| + if (IsCanonical()) {
|
| + return true;
|
| + }
|
| AbstractType& type = AbstractType::Handle();
|
| const intptr_t num_types = Length();
|
| for (intptr_t i = 0; i < num_types; i++) {
|
| @@ -13093,9 +13104,11 @@ const char* ICData::ToCString() const {
|
| const String& name = String::Handle(target_name());
|
| const intptr_t num_args = NumArgsTested();
|
| const intptr_t num_checks = NumberOfChecks();
|
| + const intptr_t type_args_len = TypeArgsLen();
|
| return OS::SCreate(Thread::Current()->zone(),
|
| - "ICData target:'%s' num-args: %" Pd " num-checks: %" Pd "",
|
| - name.ToCString(), num_args, num_checks);
|
| + "ICData target:'%s' num-args: %" Pd " num-checks: %" Pd
|
| + " type-args-len: %" Pd "",
|
| + name.ToCString(), num_args, num_checks, type_args_len);
|
| }
|
|
|
|
|
| @@ -13178,6 +13191,12 @@ intptr_t ICData::NumArgsTested() const {
|
| }
|
|
|
|
|
| +intptr_t ICData::TypeArgsLen() const {
|
| + ArgumentsDescriptor args_desc(Array::Handle(arguments_descriptor()));
|
| + return args_desc.TypeArgsLen();
|
| +}
|
| +
|
| +
|
| void ICData::SetNumArgsTested(intptr_t value) const {
|
| ASSERT(Utils::IsUint(2, value));
|
| StoreNonPointer(&raw_ptr()->state_bits_,
|
| @@ -14717,7 +14736,10 @@ const char* Code::Name() const {
|
| if (obj.IsNull()) {
|
| // Regular stub.
|
| const char* name = StubCode::NameOfStub(UncheckedEntryPoint());
|
| - ASSERT(name != NULL);
|
| + if (name == NULL) {
|
| + ASSERT(!StubCode::HasBeenInitialized());
|
| + return zone->PrintToString("[this stub]"); // Not yet recorded.
|
| + }
|
| return zone->PrintToString("[Stub] %s", name);
|
| } else if (obj.IsClass()) {
|
| // Allocation stub.
|
| @@ -16001,6 +16023,11 @@ bool Instance::IsInstanceOf(
|
| return true;
|
| }
|
| if (!sig_fun.HasInstantiatedSignature()) {
|
| + // The following signature instantiation of sig_fun with its own type
|
| + // parameters only works if sig_fun has no generic parent, which is
|
| + // guaranteed to be the case, since the looked up call() function
|
| + // cannot be nested. It is most probably not even generic.
|
| + ASSERT(!sig_fun.HasGenericParent());
|
| const TypeArguments& function_type_arguments =
|
| TypeArguments::Handle(zone, sig_fun.type_parameters());
|
| // No bound error possible, since the instance exists.
|
|
|