Index: runtime/vm/code_generator.cc |
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
index 4485c5805227d4a233ff785db0b9a708b42021e8..dcc3ea9799abdc8f8d5616f56411197c820f9ee2 100644 |
--- a/runtime/vm/code_generator.cc |
+++ b/runtime/vm/code_generator.cc |
@@ -69,6 +69,7 @@ DEFINE_FLAG(int, deoptimize_every, 0, |
"Deoptimize on every N stack overflow checks"); |
DEFINE_FLAG(charp, deoptimize_filter, NULL, |
"Deoptimize in named function on stack overflow checks"); |
+DEFINE_FLAG(bool, lazy_dispatchers, true, "Lazily generate dispatchers"); |
#ifdef DEBUG |
DEFINE_FLAG(charp, gc_at_instance_allocation, NULL, |
@@ -776,6 +777,9 @@ RawFunction* InlineCacheMissHelper( |
target_name, |
args_descriptor, |
&result)) { |
+ if (!FLAG_lazy_dispatchers) { |
+ return result.raw(); // Return null. |
+ } |
ArgumentsDescriptor desc(args_descriptor); |
const Function& target_function = |
Function::Handle(receiver_class.GetInvocationDispatcher( |
@@ -811,7 +815,10 @@ static RawFunction* InlineCacheMissHandler( |
} |
target_function = InlineCacheMissHelper(receiver, ic_data); |
} |
- ASSERT(!target_function.IsNull()); |
+ if (target_function.IsNull()) { |
+ ASSERT(!FLAG_lazy_dispatchers); |
+ return target_function.raw(); |
+ } |
if (args.length() == 1) { |
ic_data.AddReceiverCheck(args[0]->GetClassId(), target_function); |
} else { |
@@ -1012,8 +1019,11 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
if (target_function.IsNull()) { |
target_function = InlineCacheMissHelper(receiver, ic_data); |
} |
- |
- ASSERT(!target_function.IsNull()); |
+ if (target_function.IsNull()) { |
+ ASSERT(!FLAG_lazy_dispatchers); |
+ 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())); |
@@ -1022,6 +1032,30 @@ DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) { |
} |
+// Invoke appropriate noSuchMethod or closure from getter. |
+// Arg0: receiver |
+// Arg1: IC data |
+// Arg2: arguments descriptor array |
+// Arg3: arguments array |
+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 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()); |
+ // Handle noSuchMethod invocation. |
+ const Object& result = Object::Handle( |
+ DartEntry::InvokeNoSuchMethod(receiver, |
+ target_name, |
+ orig_arguments, |
+ orig_arguments_desc)); |
+ CheckResultError(result); |
+ arguments.SetReturn(result); |
+} |
+ |
+ |
+ |
// Invoke appropriate noSuchMethod function. |
// Arg0: receiver (closure object) |
// Arg1: arguments descriptor array. |