| 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.
|
|
|