Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
| index bc33bca5998156f222e6cc78b0f023b858511200..e7c4225461e45dee005ea8fd4ab38bf8022105b1 100644 |
| --- a/runtime/vm/code_generator.cc |
| +++ b/runtime/vm/code_generator.cc |
| @@ -61,6 +61,7 @@ DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); |
| DECLARE_FLAG(int, deoptimization_counter_threshold); |
| DECLARE_FLAG(bool, trace_compiler); |
| DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
| +DECLARE_FLAG(int, max_polymorphic_checks); |
| DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement."); |
| DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); |
| @@ -779,11 +780,9 @@ static bool ResolveCallThroughGetter(const Instance& receiver, |
| // Handle other invocations (implicit closures, noSuchMethod). |
| RawFunction* InlineCacheMissHelper( |
| const Instance& receiver, |
| - const ICData& ic_data) { |
| - const Array& args_descriptor = Array::Handle(ic_data.arguments_descriptor()); |
| - |
| + const Array& args_descriptor, |
| + const String& target_name) { |
| const Class& receiver_class = Class::Handle(receiver.clazz()); |
| - const String& target_name = String::Handle(ic_data.target_name()); |
| Function& result = Function::Handle(); |
| if (!ResolveCallThroughGetter(receiver, |
| @@ -828,7 +827,12 @@ static RawFunction* InlineCacheMissHandler( |
| String::Handle(ic_data.target_name()).ToCString(), |
| receiver.ToCString()); |
| } |
| - target_function = InlineCacheMissHelper(receiver, ic_data); |
| + const Array& args_descriptor = |
| + Array::Handle(ic_data.arguments_descriptor()); |
| + const String& target_name = String::Handle(ic_data.target_name()); |
| + target_function = InlineCacheMissHelper(receiver, |
| + args_descriptor, |
| + target_name); |
| } |
| if (target_function.IsNull()) { |
| ASSERT(!FLAG_lazy_dispatchers); |
| @@ -1014,11 +1018,15 @@ DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs, 3) { |
| // Returns: target function to call. |
| DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
| const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
| - const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
| + const Object& ic_data_or_cache = Object::Handle(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( |
| - MegamorphicCacheTable::Lookup(isolate, name, descriptor)); |
| + String& name = String::Handle(); |
|
srdjan
2015/11/03 22:30:49
zone is already defined here, please use it for ha
rmacnak
2015/11/03 23:54:29
Done
|
| + if (ic_data_or_cache.IsICData()) { |
| + name = ICData::Cast(ic_data_or_cache).target_name(); |
| + } else { |
| + ASSERT(ic_data_or_cache.IsMegamorphicCache()); |
| + name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); |
| + } |
| Class& cls = Class::Handle(receiver.clazz()); |
| ASSERT(!cls.IsNull()); |
| if (FLAG_trace_ic || FLAG_trace_ic_miss_in_optimized) { |
| @@ -1032,17 +1040,41 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
| name, |
| args_desc)); |
| if (target_function.IsNull()) { |
| - target_function = InlineCacheMissHelper(receiver, ic_data); |
| + target_function = InlineCacheMissHelper(receiver, descriptor, name); |
| } |
| if (target_function.IsNull()) { |
| ASSERT(!FLAG_lazy_dispatchers); |
| + // TODO(rmacnak): Consider inserting null into the cache. |
| arguments.SetReturn(target_function); |
| return; |
| } |
| - // Insert function found into cache and return it. |
| - cache.EnsureCapacity(); |
| - const Smi& class_id = Smi::Handle(Smi::New(cls.id())); |
| - cache.Insert(class_id, target_function); |
| + |
| + if (ic_data_or_cache.IsICData()) { |
| + const ICData& ic_data = ICData::Cast(ic_data_or_cache); |
| + if (ic_data.NumberOfChecks() == FLAG_max_polymorphic_checks) { |
|
srdjan
2015/11/03 22:30:49
Use '>=', it is more reliable than '=='
rmacnak
2015/11/03 23:54:29
Done.
|
| + // Switch |
| + const MegamorphicCache& cache = MegamorphicCache::Handle( |
| + MegamorphicCacheTable::Lookup(isolate, name, descriptor)); |
| + DartFrameIterator iterator; |
| + StackFrame* miss_function_frame = iterator.NextFrame(); |
| + ASSERT(miss_function_frame->IsDartFrame()); |
| + StackFrame* caller_frame = iterator.NextFrame(); |
| + ASSERT(caller_frame->IsDartFrame()); |
| + const Code& code = Code::Handle(caller_frame->LookupDartCode()); |
| + const Code& stub = |
| + Code::Handle(StubCode::MegamorphicLookup_entry()->code()); |
| + CodePatcher::PatchSwitchableCallAt(caller_frame->pc(), |
| + code, ic_data, cache, stub); |
| + } else { |
| + ic_data.AddReceiverCheck(receiver.GetClassId(), target_function); |
| + } |
| + } else { |
| + const MegamorphicCache& cache = MegamorphicCache::Cast(ic_data_or_cache); |
| + // Insert function found into cache and return it. |
| + cache.EnsureCapacity(); |
| + const Smi& class_id = Smi::Handle(Smi::New(cls.id())); |
| + cache.Insert(class_id, target_function); |
| + } |
| arguments.SetReturn(target_function); |
| } |
| @@ -1055,10 +1087,16 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
| DEFINE_RUNTIME_ENTRY(InvokeNoSuchMethodDispatcher, 4) { |
| ASSERT(!FLAG_lazy_dispatchers); |
| const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0)); |
| - const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1)); |
| + const Object& ic_data_or_cache = Object::Handle(arguments.ArgAt(1)); |
| const Array& orig_arguments_desc = Array::CheckedHandle(arguments.ArgAt(2)); |
| const Array& orig_arguments = Array::CheckedHandle(arguments.ArgAt(3)); |
| - const String& target_name = String::Handle(ic_data.target_name()); |
| + String& target_name = String::Handle(); |
| + if (ic_data_or_cache.IsICData()) { |
| + target_name = ICData::Cast(ic_data_or_cache).target_name(); |
| + } else { |
| + ASSERT(ic_data_or_cache.IsMegamorphicCache()); |
| + target_name = MegamorphicCache::Cast(ic_data_or_cache).target_name(); |
| + } |
| Class& cls = Class::Handle(receiver.clazz()); |
| Function& function = Function::Handle(); |