bool BaselineCompilerShared::callVM(const VMFunction &fun, bool preInitialize) { IonCode *code = cx->runtime()->jitRuntime()->getVMWrapper(fun); if (!code) return false; #ifdef DEBUG // Assert prepareVMCall() has been called. JS_ASSERT(inCall_); inCall_ = false; #endif // Compute argument size. Note that this include the size of the frame pointer // pushed by prepareVMCall. uint32_t argSize = fun.explicitStackSlots() * sizeof(void *) + sizeof(void *); // Assert all arguments were pushed. JS_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize); uint32_t frameVals = preInitialize ? 0 : frame.nlocals() + frame.stackDepth(); uint32_t frameSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size() + (frameVals * sizeof(Value)); masm.store32(Imm32(frameSize), Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize())); uint32_t descriptor = MakeFrameDescriptor(frameSize + argSize, IonFrame_BaselineJS); masm.push(Imm32(descriptor)); // Perform the call. masm.call(code); uint32_t callOffset = masm.currentOffset(); masm.pop(BaselineFrameReg); // Add a fake ICEntry (without stubs), so that the return offset to // pc mapping works. ICEntry entry(pc - script->code, false); entry.setReturnOffset(callOffset); return icEntries_.append(entry); }
bool BaselineCompilerShared::callVM(const VMFunction &fun, CallVMPhase phase) { JitCode *code = cx->runtime()->jitRuntime()->getVMWrapper(fun); if (!code) return false; #ifdef DEBUG // Assert prepareVMCall() has been called. MOZ_ASSERT(inCall_); inCall_ = false; #endif // Compute argument size. Note that this include the size of the frame pointer // pushed by prepareVMCall. uint32_t argSize = fun.explicitStackSlots() * sizeof(void *) + sizeof(void *); // Assert all arguments were pushed. MOZ_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize); Address frameSizeAddress(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()); uint32_t frameVals = frame.nlocals() + frame.stackDepth(); uint32_t frameBaseSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size(); uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value)); if (phase == POST_INITIALIZE) { masm.store32(Imm32(frameFullSize), frameSizeAddress); uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, JitFrame_BaselineJS); masm.push(Imm32(descriptor)); } else if (phase == PRE_INITIALIZE) { masm.store32(Imm32(frameBaseSize), frameSizeAddress); uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, JitFrame_BaselineJS); masm.push(Imm32(descriptor)); } else { MOZ_ASSERT(phase == CHECK_OVER_RECURSED); Label afterWrite; Label writePostInitialize; // If OVER_RECURSED is set, then frame locals haven't been pushed yet. masm.branchTest32(Assembler::Zero, frame.addressOfFlags(), Imm32(BaselineFrame::OVER_RECURSED), &writePostInitialize); masm.move32(Imm32(frameBaseSize), BaselineTailCallReg); masm.jump(&afterWrite); masm.bind(&writePostInitialize); masm.move32(Imm32(frameFullSize), BaselineTailCallReg); masm.bind(&afterWrite); masm.store32(BaselineTailCallReg, frameSizeAddress); masm.add32(Imm32(argSize), BaselineTailCallReg); masm.makeFrameDescriptor(BaselineTailCallReg, JitFrame_BaselineJS); masm.push(BaselineTailCallReg); } // Perform the call. masm.call(code); uint32_t callOffset = masm.currentOffset(); masm.pop(BaselineFrameReg); // Add a fake ICEntry (without stubs), so that the return offset to // pc mapping works. ICEntry entry(script->pcToOffset(pc), ICEntry::Kind_CallVM); entry.setReturnOffset(CodeOffsetLabel(callOffset)); return icEntries_.append(entry); }
bool BaselineCompilerShared::callVM(const VMFunction& fun, CallVMPhase phase) { JitCode* code = cx->runtime()->jitRuntime()->getVMWrapper(fun); if (!code) return false; #ifdef DEBUG // Assert prepareVMCall() has been called. MOZ_ASSERT(inCall_); inCall_ = false; #endif #ifdef DEBUG // Assert the frame does not have an override pc when we're executing JIT code. { Label ok; masm.branchTest32(Assembler::Zero, frame.addressOfFlags(), Imm32(BaselineFrame::HAS_OVERRIDE_PC), &ok); masm.assumeUnreachable("BaselineFrame shouldn't override pc when executing JIT code"); masm.bind(&ok); } #endif // Compute argument size. Note that this include the size of the frame pointer // pushed by prepareVMCall. uint32_t argSize = fun.explicitStackSlots() * sizeof(void*) + sizeof(void*); // Assert all arguments were pushed. MOZ_ASSERT(masm.framePushed() - pushedBeforeCall_ == argSize); Address frameSizeAddress(BaselineFrameReg, BaselineFrame::reverseOffsetOfFrameSize()); uint32_t frameVals = frame.nlocals() + frame.stackDepth(); uint32_t frameBaseSize = BaselineFrame::FramePointerOffset + BaselineFrame::Size(); uint32_t frameFullSize = frameBaseSize + (frameVals * sizeof(Value)); if (phase == POST_INITIALIZE) { masm.store32(Imm32(frameFullSize), frameSizeAddress); uint32_t descriptor = MakeFrameDescriptor(frameFullSize + argSize, JitFrame_BaselineJS, ExitFrameLayout::Size()); masm.push(Imm32(descriptor)); } else if (phase == PRE_INITIALIZE) { masm.store32(Imm32(frameBaseSize), frameSizeAddress); uint32_t descriptor = MakeFrameDescriptor(frameBaseSize + argSize, JitFrame_BaselineJS, ExitFrameLayout::Size()); masm.push(Imm32(descriptor)); } else { MOZ_ASSERT(phase == CHECK_OVER_RECURSED); Label afterWrite; Label writePostInitialize; // If OVER_RECURSED is set, then frame locals haven't been pushed yet. masm.branchTest32(Assembler::Zero, frame.addressOfFlags(), Imm32(BaselineFrame::OVER_RECURSED), &writePostInitialize); masm.move32(Imm32(frameBaseSize), ICTailCallReg); masm.jump(&afterWrite); masm.bind(&writePostInitialize); masm.move32(Imm32(frameFullSize), ICTailCallReg); masm.bind(&afterWrite); masm.store32(ICTailCallReg, frameSizeAddress); masm.add32(Imm32(argSize), ICTailCallReg); masm.makeFrameDescriptor(ICTailCallReg, JitFrame_BaselineJS, ExitFrameLayout::Size()); masm.push(ICTailCallReg); } MOZ_ASSERT(fun.expectTailCall == NonTailCall); // Perform the call. masm.call(code); uint32_t callOffset = masm.currentOffset(); masm.pop(BaselineFrameReg); #ifdef DEBUG // Assert the frame does not have an override pc when we're executing JIT code. { Label ok; masm.branchTest32(Assembler::Zero, frame.addressOfFlags(), Imm32(BaselineFrame::HAS_OVERRIDE_PC), &ok); masm.assumeUnreachable("BaselineFrame shouldn't override pc after VM call"); masm.bind(&ok); } #endif // Add a fake ICEntry (without stubs), so that the return offset to // pc mapping works. return appendICEntry(ICEntry::Kind_CallVM, callOffset); }