| Index: runtime/vm/code_generator.cc
|
| diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
|
| index 0ab08196e3c6d85af24574f3d2e2be5d1cd50ea1..66ea220d56b0908c970e9e3f325dbdae3d306f28 100644
|
| --- a/runtime/vm/code_generator.cc
|
| +++ b/runtime/vm/code_generator.cc
|
| @@ -1025,6 +1025,64 @@ DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 5) {
|
| }
|
|
|
|
|
| +// Handle a miss of a megamorphic cache.
|
| +// Arg0: Receiver.
|
| +// Arg1: ICData object.
|
| +// Arg2: Arguments descriptor array.
|
| +
|
| +// Returns: target instructions to call or null if the
|
| +// InstanceFunctionLookup stub should be used (e.g., to invoke no such
|
| +// method and implicit closures)..
|
| +DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
|
| + ASSERT(arguments.ArgCount() ==
|
| + kMegamorphicCacheMissHandlerRuntimeEntry.argument_count());
|
| + const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
|
| + const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
|
| + const Array& descriptor = Array::CheckedHandle(arguments.ArgAt(2));
|
| + const String& name = String::Handle(ic_data.target_name());
|
| + const MegamorphicCache& cache = MegamorphicCache::Handle(
|
| + isolate->megamorphic_cache_table()->Lookup(name, descriptor));
|
| + Class& cls = Class::Handle(receiver.clazz());
|
| + // For lookups treat null as an instance of class Object.
|
| + if (cls.IsNullClass()) {
|
| + cls = isolate->object_store()->object_class();
|
| + }
|
| + ASSERT(!cls.IsNull());
|
| + if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) {
|
| + OS::Print("Megamorphic IC miss, class=%s, function=%s\n",
|
| + cls.ToCString(), name.ToCString());
|
| + }
|
| +
|
| + intptr_t arg_count =
|
| + Smi::Cast(Object::Handle(descriptor.At(0))).Value();
|
| + intptr_t named_arg_count =
|
| + arg_count - Smi::Cast(Object::Handle(descriptor.At(1))).Value();
|
| + const Function& target = Function::Handle(
|
| + Resolver::ResolveDynamicForReceiverClass(cls,
|
| + name,
|
| + arg_count,
|
| + named_arg_count));
|
| +
|
| + Instructions& instructions = Instructions::Handle();
|
| + if (!target.IsNull()) {
|
| + if (!target.HasCode()) {
|
| + const Error& error =
|
| + Error::Handle(Compiler::CompileFunction(target));
|
| + if (!error.IsNull()) Exceptions::PropagateError(error);
|
| + }
|
| + ASSERT(target.HasCode());
|
| + instructions = Code::Handle(target.CurrentCode()).instructions();
|
| + }
|
| + arguments.SetReturn(instructions);
|
| + if (instructions.IsNull()) return;
|
| +
|
| + cache.EnsureCapacity();
|
| + const Smi& class_id = Smi::Handle(Smi::New(cls.id()));
|
| + cache.Insert(class_id, target);
|
| + return;
|
| +}
|
| +
|
| +
|
| // Updates IC data for two arguments. Used by the equality operation when
|
| // the control flow bypasses regular inline cache (null arguments).
|
| // Arg0: Receiver object.
|
|
|