Bug 1885489 - Part 5: Add SnapshotIterator::readInt32(). r=iain
[gecko.git] / js / src / jit / BaselineFrame.cpp
blob49c70c373586934d7854ba84e2438db0c270b7da
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "jit/BaselineFrame-inl.h"
9 #include <algorithm>
11 #include "debugger/DebugAPI.h"
12 #include "vm/EnvironmentObject.h"
13 #include "vm/JSContext.h"
15 #include "jit/JSJitFrameIter-inl.h"
16 #include "vm/Stack-inl.h"
18 using namespace js;
19 using namespace js::jit;
21 static void TraceLocals(BaselineFrame* frame, JSTracer* trc, unsigned start,
22 unsigned end) {
23 if (start < end) {
24 // Stack grows down.
25 Value* last = frame->valueSlot(end - 1);
26 TraceRootRange(trc, end - start, last, "baseline-stack");
30 void BaselineFrame::trace(JSTracer* trc, const JSJitFrameIter& frameIterator) {
31 replaceCalleeToken(TraceCalleeToken(trc, calleeToken()));
33 // Trace |this|, actual and formal args.
34 if (isFunctionFrame()) {
35 TraceRoot(trc, &thisArgument(), "baseline-this");
37 unsigned numArgs = std::max(numActualArgs(), numFormalArgs());
38 TraceRootRange(trc, numArgs + isConstructing(), argv(), "baseline-args");
41 // Trace environment chain, if it exists.
42 if (envChain_) {
43 TraceRoot(trc, &envChain_, "baseline-envchain");
46 // Trace return value.
47 if (hasReturnValue()) {
48 TraceRoot(trc, returnValue().address(), "baseline-rval");
51 if (hasArgsObj()) {
52 TraceRoot(trc, &argsObj_, "baseline-args-obj");
55 if (runningInInterpreter()) {
56 TraceRoot(trc, &interpreterScript_, "baseline-interpreterScript");
59 // Trace locals and stack values.
60 JSScript* script = this->script();
61 size_t nfixed = script->nfixed();
62 jsbytecode* pc;
63 frameIterator.baselineScriptAndPc(nullptr, &pc);
64 size_t nlivefixed = script->calculateLiveFixed(pc);
66 uint32_t numValueSlots = frameIterator.baselineFrameNumValueSlots();
68 // NB: It is possible that numValueSlots could be zero, even if nfixed is
69 // nonzero. This is the case when we're initializing the environment chain or
70 // failed the prologue stack check.
71 if (numValueSlots > 0) {
72 MOZ_ASSERT(nfixed <= numValueSlots);
74 if (nfixed == nlivefixed) {
75 // All locals are live.
76 TraceLocals(this, trc, 0, numValueSlots);
77 } else {
78 // Trace operand stack.
79 TraceLocals(this, trc, nfixed, numValueSlots);
81 // Clear dead block-scoped locals.
82 while (nfixed > nlivefixed) {
83 unaliasedLocal(--nfixed).setUndefined();
86 // Trace live locals.
87 TraceLocals(this, trc, 0, nlivefixed);
91 if (auto* debugEnvs = script->realm()->debugEnvs()) {
92 debugEnvs->traceLiveFrame(trc, this);
96 bool BaselineFrame::uninlineIsProfilerSamplingEnabled(JSContext* cx) {
97 return cx->isProfilerSamplingEnabled();
100 bool BaselineFrame::initFunctionEnvironmentObjects(JSContext* cx) {
101 return js::InitFunctionEnvironmentObjects(cx, this);
104 bool BaselineFrame::pushVarEnvironment(JSContext* cx, Handle<Scope*> scope) {
105 return js::PushVarEnvironmentObject(cx, scope, this);
108 void BaselineFrame::setInterpreterFields(JSScript* script, jsbytecode* pc) {
109 uint32_t pcOffset = script->pcToOffset(pc);
110 interpreterScript_ = script;
111 interpreterPC_ = pc;
112 MOZ_ASSERT(icScript_);
113 interpreterICEntry_ = icScript_->interpreterICEntryFromPCOffset(pcOffset);
116 void BaselineFrame::setInterpreterFieldsForPrologue(JSScript* script) {
117 interpreterScript_ = script;
118 interpreterPC_ = script->code();
119 if (icScript_->numICEntries() > 0) {
120 interpreterICEntry_ = &icScript_->icEntry(0);
121 } else {
122 // If the script does not have any ICEntries (possible for non-function
123 // scripts) the interpreterICEntry_ field won't be used. Just set it to
124 // nullptr.
125 interpreterICEntry_ = nullptr;
129 bool BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues) {
130 mozilla::PodZero(this);
132 envChain_ = fp->environmentChain();
134 if (fp->hasInitialEnvironmentUnchecked()) {
135 flags_ |= BaselineFrame::HAS_INITIAL_ENV;
138 if (fp->script()->needsArgsObj() && fp->hasArgsObj()) {
139 flags_ |= BaselineFrame::HAS_ARGS_OBJ;
140 argsObj_ = &fp->argsObj();
143 if (fp->hasReturnValue()) {
144 setReturnValue(fp->returnValue());
147 icScript_ = fp->script()->jitScript()->icScript();
149 JSContext* cx =
150 fp->script()->runtimeFromMainThread()->mainContextFromOwnThread();
152 Activation* interpActivation = cx->activation()->prev();
153 jsbytecode* pc = interpActivation->asInterpreter()->regs().pc;
154 MOZ_ASSERT(fp->script()->containsPC(pc));
156 // We are doing OSR into the Baseline Interpreter. We can get the pc from the
157 // C++ interpreter's activation, we just have to skip the JitActivation.
158 flags_ |= BaselineFrame::RUNNING_IN_INTERPRETER;
159 setInterpreterFields(pc);
161 #ifdef DEBUG
162 debugFrameSize_ = frameSizeForNumValueSlots(numStackValues);
163 MOZ_ASSERT(debugNumValueSlots() == numStackValues);
164 #endif
166 for (uint32_t i = 0; i < numStackValues; i++) {
167 *valueSlot(i) = fp->slots()[i];
170 if (fp->isDebuggee()) {
171 // For debuggee frames, update any Debugger.Frame objects for the
172 // InterpreterFrame to point to the BaselineFrame.
173 if (!DebugAPI::handleBaselineOsr(cx, fp, this)) {
174 return false;
176 setIsDebuggee();
179 return true;