summaryrefslogtreecommitdiffstats
path: root/js/src/jit/shared/BaselineCompiler-shared.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/shared/BaselineCompiler-shared.cpp')
-rw-r--r--js/src/jit/shared/BaselineCompiler-shared.cpp146
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);
+}