| Index: runtime/vm/stub_code_ia32.cc
|
| diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
|
| index 669c874e84a8440199346363763185cceac8d31b..cfaab2842ab6bb1db93240ce201c2ce2cdac9964 100644
|
| --- a/runtime/vm/stub_code_ia32.cc
|
| +++ b/runtime/vm/stub_code_ia32.cc
|
| @@ -80,7 +80,8 @@ void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
|
| // There are no runtime calls to closures, so we do not need to set the tag
|
| // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
|
| __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments.
|
| - __ leal(EAX, Address(EBP, EDX, TIMES_4, 1 * kWordSize)); // Compute argv.
|
| + // Compute argv.
|
| + __ leal(EAX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize));
|
| __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments.
|
| __ addl(EAX, Immediate(1 * kWordSize)); // Retval is next to 1st argument.
|
| __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
|
| @@ -369,11 +370,13 @@ static void PushArgumentsArray(Assembler* assembler) {
|
| // +------------------+
|
| // | return-address | (deoptimization point)
|
| // +------------------+
|
| +// | Saved CODE_REG |
|
| +// +------------------+
|
| // | ... | <- SP of optimized frame
|
| //
|
| // Parts of the code cannot GC, part of the code can GC.
|
| static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| - bool preserve_result) {
|
| + DeoptStubKind kind) {
|
| // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
|
| __ EnterDartFrame(0);
|
| // The code in this frame may not cause GC. kDeoptimizeCopyFrameRuntimeEntry
|
| @@ -385,7 +388,13 @@ static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| // Push registers in their enumeration order: lowest register number at
|
| // lowest address.
|
| for (intptr_t i = kNumberOfCpuRegisters - 1; i >= 0; i--) {
|
| - __ pushl(static_cast<Register>(i));
|
| + if (i == CODE_REG) {
|
| + // Save the original value of CODE_REG pushed before invoking this stub
|
| + // instead of the value used to call this stub.
|
| + __ pushl(Address(EBP, 2 * kWordSize));
|
| + } else {
|
| + __ pushl(static_cast<Register>(i));
|
| + }
|
| }
|
| __ subl(ESP, Immediate(kNumberOfXmmRegisters * kFpuRegisterSize));
|
| intptr_t offset = 0;
|
| @@ -396,11 +405,13 @@ static void GenerateDeoptimizationSequence(Assembler* assembler,
|
| }
|
|
|
| __ movl(ECX, ESP); // Preserve saved registers block.
|
| - __ ReserveAlignedFrameSpace(1 * kWordSize);
|
| - __ movl(Address(ESP, 0), ECX); // Start of register block.
|
| - __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 1);
|
| + __ ReserveAlignedFrameSpace(2 * kWordSize);
|
| + __ movl(Address(ESP, 0 * kWordSize), ECX); // Start of register block.
|
| + __ movl(Address(ESP, 1 * kWordSize), Immediate(kind == kLazyDeopt ? 1 : 0));
|
| + __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
|
| // Result (EAX) is stack-size (FP - SP) in bytes.
|
|
|
| + const bool preserve_result = (kind == kLazyDeopt);
|
| if (preserve_result) {
|
| // Restore result into EBX temporarily.
|
| __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize));
|
| @@ -460,12 +471,12 @@ void StubCode::GenerateDeoptimizeLazyStub(Assembler* assembler) {
|
| __ popl(EBX);
|
| __ subl(EBX, Immediate(CallPattern::pattern_length_in_bytes()));
|
| __ pushl(EBX);
|
| - GenerateDeoptimizationSequence(assembler, true); // Preserve EAX.
|
| + GenerateDeoptimizationSequence(assembler, kLazyDeopt);
|
| }
|
|
|
|
|
| void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
|
| - GenerateDeoptimizationSequence(assembler, false); // Don't preserve EAX.
|
| + GenerateDeoptimizationSequence(assembler, kEagerDeopt);
|
| }
|
|
|
|
|
| @@ -684,13 +695,13 @@ void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
|
| // Called when invoking dart code from C++ (VM code).
|
| // Input parameters:
|
| // ESP : points to return address.
|
| -// ESP + 4 : entrypoint of the dart function to call.
|
| +// ESP + 4 : code object of the dart function to call.
|
| // ESP + 8 : arguments descriptor array.
|
| // ESP + 12 : arguments array.
|
| // ESP + 16 : current thread.
|
| // Uses EAX, EDX, ECX, EDI as temporary registers.
|
| void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| - const intptr_t kEntryPointOffset = 2 * kWordSize;
|
| + const intptr_t kTargetCodeOffset = 2 * kWordSize;
|
| const intptr_t kArgumentsDescOffset = 3 * kWordSize;
|
| const intptr_t kArgumentsOffset = 4 * kWordSize;
|
| const intptr_t kThreadOffset = 5 * kWordSize;
|
| @@ -698,13 +709,17 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| // Save frame pointer coming in.
|
| __ EnterFrame(0);
|
|
|
| + // Push code object to PC marker slot.
|
| + __ movl(EAX, Address(EBP, kThreadOffset));
|
| + __ pushl(Address(EAX, Thread::invoke_dart_code_stub_offset()));
|
| +
|
| // Save C++ ABI callee-saved registers.
|
| __ pushl(EBX);
|
| __ pushl(ESI);
|
| __ pushl(EDI);
|
|
|
| // Set up THR, which caches the current thread in Dart code.
|
| - __ movl(THR, Address(EBP, kThreadOffset));
|
| + __ movl(THR, EAX);
|
| __ LoadIsolate(EDI);
|
|
|
| // Save the current VMTag on the stack.
|
| @@ -722,7 +737,7 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| __ movl(Address(THR, Thread::top_resource_offset()), Immediate(0));
|
| // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
|
| // code below.
|
| - ASSERT(kExitLinkSlotFromEntryFp == -6);
|
| + ASSERT(kExitLinkSlotFromEntryFp == -7);
|
| __ movl(EDX, Address(THR, Thread::top_exit_frame_info_offset()));
|
| __ pushl(EDX);
|
| __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
|
| @@ -756,7 +771,9 @@ void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
|
| __ Bind(&done_push_arguments);
|
|
|
| // Call the dart code entrypoint.
|
| - __ call(Address(EBP, kEntryPointOffset));
|
| + __ movl(EAX, Address(EBP, kTargetCodeOffset));
|
| + __ movl(EAX, Address(EAX, VMHandles::kOffsetOfRawPtrInHandle));
|
| + __ call(FieldAddress(EAX, Code::entry_point_offset()));
|
|
|
| // Reread the arguments descriptor array to obtain the number of passed
|
| // arguments.
|
| @@ -1001,9 +1018,7 @@ void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
|
| // Returns patch_code_pc offset where patching code for disabling the stub
|
| // has been generated (similar to regularly generated Dart code).
|
| void StubCode::GenerateAllocationStubForClass(
|
| - Assembler* assembler, const Class& cls,
|
| - uword* entry_patch_offset, uword* patch_code_pc_offset) {
|
| - *entry_patch_offset = assembler->CodeSize();
|
| + Assembler* assembler, const Class& cls) {
|
| const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
|
| const Immediate& raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| @@ -1125,10 +1140,6 @@ void StubCode::GenerateAllocationStubForClass(
|
| // Restore the frame pointer.
|
| __ LeaveFrame();
|
| __ ret();
|
| - // Emit function patching code. This will be swapped with the first 5 bytes
|
| - // at entry point.
|
| - *patch_code_pc_offset = assembler->CodeSize();
|
| - __ Jmp(*StubCode::FixAllocationStubTarget_entry());
|
| }
|
|
|
|
|
| @@ -1168,7 +1179,7 @@ void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
|
| // function and not the top-scope function.
|
| void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
|
| Register ic_reg = ECX;
|
| - Register func_reg = EDI;
|
| + Register func_reg = EBX;
|
| if (FLAG_trace_optimized_ic_calls) {
|
| __ EnterStubFrame();
|
| __ pushl(func_reg); // Preserve
|
| @@ -1704,10 +1715,12 @@ void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| __ pushl(raw_null); // Room for result.
|
| __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
|
| - __ popl(EAX); // Address of original stub.
|
| + __ popl(EAX); // Code of original stub.
|
| __ popl(ECX); // Restore IC data.
|
| __ LeaveFrame();
|
| - __ jmp(EAX); // Jump to original stub.
|
| + // Jump to original stub.
|
| + __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
|
| + __ jmp(EAX);
|
| }
|
|
|
|
|
| @@ -1719,9 +1732,11 @@ void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| __ pushl(raw_null); // Room for result.
|
| __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
|
| - __ popl(EAX); // Address of original stub.
|
| + __ popl(EAX); // Code of the original stub
|
| __ LeaveFrame();
|
| - __ jmp(EAX); // Jump to original stub.
|
| + // Jump to original stub.
|
| + __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
|
| + __ jmp(EAX);
|
| }
|
|
|
|
|
| @@ -1893,7 +1908,7 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|
|
|
|
| // Calls to the runtime to optimize the given function.
|
| -// EDI: function to be reoptimized.
|
| +// EBX: function to be reoptimized.
|
| // EDX: argument descriptor (preserved).
|
| void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
|
| const Immediate& raw_null =
|
| @@ -1901,7 +1916,7 @@ void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
|
| __ EnterStubFrame();
|
| __ pushl(EDX);
|
| __ pushl(raw_null); // Setup space on stack for return value.
|
| - __ pushl(EDI);
|
| + __ pushl(EBX);
|
| __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry, 1);
|
| __ popl(EAX); // Discard argument.
|
| __ popl(EAX); // Get Code object
|
| @@ -2068,12 +2083,12 @@ void StubCode::EmitMegamorphicLookup(
|
|
|
|
|
| // Called from megamorphic calls.
|
| -// EDI: receiver.
|
| +// ECX: receiver.
|
| // EBX: lookup cache.
|
| // Result:
|
| // EBX: entry point.
|
| void StubCode::GenerateMegamorphicLookupStub(Assembler* assembler) {
|
| - EmitMegamorphicLookup(assembler, EDI, EBX, EBX);
|
| + EmitMegamorphicLookup(assembler, ECX, EBX, EBX);
|
| __ ret();
|
| }
|
|
|
|
|