summaryrefslogtreecommitdiffstats
path: root/js/src/jit/BaselineFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/BaselineFrame.cpp')
-rw-r--r--js/src/jit/BaselineFrame.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/js/src/jit/BaselineFrame.cpp b/js/src/jit/BaselineFrame.cpp
new file mode 100644
index 000000000..6c9864ece
--- /dev/null
+++ b/js/src/jit/BaselineFrame.cpp
@@ -0,0 +1,157 @@
+/* -*- 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/BaselineFrame-inl.h"
+
+#include "jit/BaselineJIT.h"
+#include "jit/Ion.h"
+#include "vm/Debugger.h"
+#include "vm/EnvironmentObject.h"
+
+#include "jit/JitFrames-inl.h"
+#include "vm/Stack-inl.h"
+
+using namespace js;
+using namespace js::jit;
+
+static void
+MarkLocals(BaselineFrame* frame, JSTracer* trc, unsigned start, unsigned end)
+{
+ if (start < end) {
+ // Stack grows down.
+ Value* last = frame->valueSlot(end - 1);
+ TraceRootRange(trc, end - start, last, "baseline-stack");
+ }
+}
+
+void
+BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator)
+{
+ replaceCalleeToken(MarkCalleeToken(trc, calleeToken()));
+
+ // Mark |this|, actual and formal args.
+ if (isFunctionFrame()) {
+ TraceRoot(trc, &thisArgument(), "baseline-this");
+
+ unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
+ TraceRootRange(trc, numArgs + isConstructing(), argv(), "baseline-args");
+ }
+
+ // Mark environment chain, if it exists.
+ if (envChain_)
+ TraceRoot(trc, &envChain_, "baseline-envchain");
+
+ // Mark return value.
+ if (hasReturnValue())
+ TraceRoot(trc, returnValue().address(), "baseline-rval");
+
+ if (isEvalFrame() && script()->isDirectEvalInFunction())
+ TraceRoot(trc, evalNewTargetAddress(), "baseline-evalNewTarget");
+
+ if (hasArgsObj())
+ TraceRoot(trc, &argsObj_, "baseline-args-obj");
+
+ // Mark locals and stack values.
+ JSScript* script = this->script();
+ size_t nfixed = script->nfixed();
+ jsbytecode* pc;
+ frameIterator.baselineScriptAndPc(nullptr, &pc);
+ size_t nlivefixed = script->calculateLiveFixed(pc);
+
+ // NB: It is possible that numValueSlots() could be zero, even if nfixed is
+ // nonzero. This is the case if the function has an early stack check.
+ if (numValueSlots() == 0)
+ return;
+
+ MOZ_ASSERT(nfixed <= numValueSlots());
+
+ if (nfixed == nlivefixed) {
+ // All locals are live.
+ MarkLocals(this, trc, 0, numValueSlots());
+ } else {
+ // Mark operand stack.
+ MarkLocals(this, trc, nfixed, numValueSlots());
+
+ // Clear dead block-scoped locals.
+ while (nfixed > nlivefixed)
+ unaliasedLocal(--nfixed).setUndefined();
+
+ // Mark live locals.
+ MarkLocals(this, trc, 0, nlivefixed);
+ }
+
+ if (script->compartment()->debugEnvs)
+ script->compartment()->debugEnvs->markLiveFrame(trc, this);
+}
+
+bool
+BaselineFrame::isNonGlobalEvalFrame() const
+{
+ return isEvalFrame() && script()->enclosingScope()->as<EvalScope>().isNonGlobal();
+}
+
+bool
+BaselineFrame::initFunctionEnvironmentObjects(JSContext* cx)
+{
+ return js::InitFunctionEnvironmentObjects(cx, this);
+}
+
+bool
+BaselineFrame::pushVarEnvironment(JSContext* cx, HandleScope scope)
+{
+ return js::PushVarEnvironmentObject(cx, scope, this);
+}
+
+bool
+BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues)
+{
+ mozilla::PodZero(this);
+
+ envChain_ = fp->environmentChain();
+
+ if (fp->hasInitialEnvironmentUnchecked())
+ flags_ |= BaselineFrame::HAS_INITIAL_ENV;
+
+ if (fp->script()->needsArgsObj() && fp->hasArgsObj()) {
+ flags_ |= BaselineFrame::HAS_ARGS_OBJ;
+ argsObj_ = &fp->argsObj();
+ }
+
+ if (fp->hasReturnValue())
+ setReturnValue(fp->returnValue());
+
+ frameSize_ = BaselineFrame::FramePointerOffset +
+ BaselineFrame::Size() +
+ numStackValues * sizeof(Value);
+
+ MOZ_ASSERT(numValueSlots() == numStackValues);
+
+ for (uint32_t i = 0; i < numStackValues; i++)
+ *valueSlot(i) = fp->slots()[i];
+
+ if (fp->isDebuggee()) {
+ JSContext* cx = GetJSContextFromMainThread();
+
+ // For debuggee frames, update any Debugger.Frame objects for the
+ // InterpreterFrame to point to the BaselineFrame.
+
+ // The caller pushed a fake return address. ScriptFrameIter, used by the
+ // debugger, wants a valid return address, but it's okay to just pick one.
+ // In debug mode there's always at least 1 ICEntry (since there are always
+ // debug prologue/epilogue calls).
+ JitFrameIterator iter(cx);
+ MOZ_ASSERT(iter.returnAddress() == nullptr);
+ BaselineScript* baseline = fp->script()->baselineScript();
+ iter.current()->setReturnAddress(baseline->returnAddressForIC(baseline->icEntry(0)));
+
+ if (!Debugger::handleBaselineOsr(cx, fp, this))
+ return false;
+
+ setIsDebuggee();
+ }
+
+ return true;
+}