diff options
Diffstat (limited to 'js/src/jit/shared/BaselineCompiler-shared.cpp')
-rw-r--r-- | js/src/jit/shared/BaselineCompiler-shared.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/js/src/jit/shared/BaselineCompiler-shared.cpp b/js/src/jit/shared/BaselineCompiler-shared.cpp new file mode 100644 index 000000000..5342eeb3f --- /dev/null +++ b/js/src/jit/shared/BaselineCompiler-shared.cpp @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jit/shared/BaselineCompiler-shared.h" + +#include "jit/BaselineIC.h" +#include "jit/VMFunctions.h" + +#include "jsscriptinlines.h" +#include "jit/MacroAssembler-inl.h" + +using namespace js; +using namespace js::jit; + +BaselineCompilerShared::BaselineCompilerShared(JSContext* cx, TempAllocator& alloc, JSScript* script) + : cx(cx), + script(script), + pc(script->code()), + ionCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, false)), + ionOSRCompileable_(jit::IsIonEnabled(cx) && CanIonCompileScript(cx, script, true)), + compileDebugInstrumentation_(script->isDebuggee()), + alloc_(alloc), + analysis_(alloc, script), + frame(script, masm), + stubSpace_(), + icEntries_(), + pcMappingEntries_(), + icLoadLabels_(), + pushedBeforeCall_(0), +#ifdef DEBUG + inCall_(false), +#endif + spsPushToggleOffset_(), + profilerEnterFrameToggleOffset_(), + profilerExitFrameToggleOffset_(), + traceLoggerToggleOffsets_(cx), + traceLoggerScriptTextIdOffset_() +{ } + +void +BaselineCompilerShared::prepareVMCall() +{ + pushedBeforeCall_ = masm.framePushed(); +#ifdef DEBUG + inCall_ = true; +#endif + + // Ensure everything is synced. + frame.syncStack(0); + + // Save the frame pointer. + masm.Push(BaselineFrameReg); +} + +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; + + // 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); +} |