| Index: runtime/vm/stub_code_ia32.cc
|
| diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
|
| index 4434d4c142fec8b83ed93dc8c39df4ea46b46d37..e6f881841c5525a92c5cab00332077337d5cb1f7 100644
|
| --- a/runtime/vm/stub_code_ia32.cc
|
| +++ b/runtime/vm/stub_code_ia32.cc
|
| @@ -29,6 +29,7 @@ DEFINE_FLAG(bool, use_slow_path, false,
|
| DECLARE_FLAG(bool, trace_optimized_ic_calls);
|
| DECLARE_FLAG(int, optimization_counter_threshold);
|
| DECLARE_FLAG(bool, support_debugger);
|
| +DECLARE_FLAG(bool, lazy_dispatchers);
|
|
|
| #define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))
|
|
|
| @@ -505,6 +506,36 @@ void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
|
| }
|
|
|
|
|
| +static void GenerateDispatcherCode(Assembler* assembler,
|
| + Label* call_target_function) {
|
| + __ Comment("NoSuchMethodDispatch");
|
| + // When lazily generated invocation dispatchers are disabled, the
|
| + // miss-handler may return null.
|
| + const Immediate& raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + __ cmpl(EAX, raw_null);
|
| + __ j(NOT_EQUAL, call_target_function);
|
| + __ EnterStubFrame();
|
| + // Load the receiver.
|
| + __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
|
| + __ movl(EAX, Address(
|
| + EBP, EDI, TIMES_HALF_WORD_SIZE, kParamEndSlotFromFp * kWordSize));
|
| + __ pushl(raw_null); // Setup space on stack for result.
|
| + __ pushl(EAX); // Receiver.
|
| + __ pushl(ECX);
|
| + __ pushl(EDX); // Arguments descriptor array.
|
| + __ movl(EDX, EDI);
|
| + // EDX: Smi-tagged arguments array length.
|
| + PushArgumentsArray(assembler);
|
| + const intptr_t kNumArgs = 4;
|
| + __ CallRuntime(kInvokeNoSuchMethodDispatcherRuntimeEntry, kNumArgs);
|
| + __ Drop(4);
|
| + __ popl(EAX); // Return value.
|
| + __ LeaveFrame();
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
|
| __ EnterStubFrame();
|
| // Load the receiver into EAX. The argument count in the arguments
|
| @@ -533,6 +564,12 @@ void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
|
| __ popl(ECX); // Restore IC data.
|
| __ LeaveFrame();
|
|
|
| + if (!FLAG_lazy_dispatchers) {
|
| + Label call_target_function;
|
| + GenerateDispatcherCode(assembler, &call_target_function);
|
| + __ Bind(&call_target_function);
|
| + }
|
| +
|
| __ movl(EBX, FieldAddress(EAX, Function::instructions_offset()));
|
| __ addl(EBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
| __ jmp(EBX);
|
| @@ -1370,7 +1407,7 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
| __ j(NOT_EQUAL, &update); // Continue.
|
| } else {
|
| // Last check, all checks before matched.
|
| - __ j(EQUAL, &found, Assembler::kNearJump); // Break.
|
| + __ j(EQUAL, &found); // Break.
|
| }
|
| }
|
| __ Bind(&update);
|
| @@ -1418,7 +1455,11 @@ void StubCode::GenerateNArgsCheckInlineCacheStub(
|
| __ popl(EDX); // Restore arguments descriptor array.
|
| __ LeaveFrame();
|
| Label call_target_function;
|
| - __ jmp(&call_target_function);
|
| + if (!FLAG_lazy_dispatchers) {
|
| + GenerateDispatcherCode(assembler, &call_target_function);
|
| + } else {
|
| + __ jmp(&call_target_function);
|
| + }
|
|
|
| __ Bind(&found);
|
|
|
|
|