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"
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"
19 using namespace js::jit
;
21 static void TraceLocals(BaselineFrame
* frame
, JSTracer
* trc
, unsigned start
,
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.
43 TraceRoot(trc
, &envChain_
, "baseline-envchain");
46 // Trace return value.
47 if (hasReturnValue()) {
48 TraceRoot(trc
, returnValue().address(), "baseline-rval");
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();
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
);
78 // Trace operand stack.
79 TraceLocals(this, trc
, nfixed
, numValueSlots
);
81 // Clear dead block-scoped locals.
82 while (nfixed
> nlivefixed
) {
83 unaliasedLocal(--nfixed
).setUndefined();
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
;
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);
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
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();
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
);
162 debugFrameSize_
= frameSizeForNumValueSlots(numStackValues
);
163 MOZ_ASSERT(debugNumValueSlots() == numStackValues
);
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)) {