Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/. */
6 :
7 : #include "jit/BaselineFrame-inl.h"
8 :
9 : #include "jit/BaselineJIT.h"
10 : #include "jit/Ion.h"
11 : #include "vm/Debugger.h"
12 : #include "vm/EnvironmentObject.h"
13 :
14 : #include "jit/JitFrames-inl.h"
15 : #include "vm/Stack-inl.h"
16 :
17 : using namespace js;
18 : using namespace js::jit;
19 :
20 : static void
21 39 : TraceLocals(BaselineFrame* frame, JSTracer* trc, unsigned start, unsigned end)
22 : {
23 39 : if (start < end) {
24 : // Stack grows down.
25 38 : Value* last = frame->valueSlot(end - 1);
26 38 : TraceRootRange(trc, end - start, last, "baseline-stack");
27 : }
28 39 : }
29 :
30 : void
31 27 : BaselineFrame::trace(JSTracer* trc, JitFrameIterator& frameIterator)
32 : {
33 27 : replaceCalleeToken(TraceCalleeToken(trc, calleeToken()));
34 :
35 : // Trace |this|, actual and formal args.
36 27 : if (isFunctionFrame()) {
37 27 : TraceRoot(trc, &thisArgument(), "baseline-this");
38 :
39 27 : unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
40 27 : TraceRootRange(trc, numArgs + isConstructing(), argv(), "baseline-args");
41 : }
42 :
43 : // Trace environment chain, if it exists.
44 27 : if (envChain_)
45 27 : TraceRoot(trc, &envChain_, "baseline-envchain");
46 :
47 : // Trace return value.
48 27 : if (hasReturnValue())
49 1 : TraceRoot(trc, returnValue().address(), "baseline-rval");
50 :
51 27 : if (isEvalFrame() && script()->isDirectEvalInFunction())
52 0 : TraceRoot(trc, evalNewTargetAddress(), "baseline-evalNewTarget");
53 :
54 27 : if (hasArgsObj())
55 0 : TraceRoot(trc, &argsObj_, "baseline-args-obj");
56 :
57 : // Trace locals and stack values.
58 27 : JSScript* script = this->script();
59 27 : size_t nfixed = script->nfixed();
60 : jsbytecode* pc;
61 27 : frameIterator.baselineScriptAndPc(nullptr, &pc);
62 27 : size_t nlivefixed = script->calculateLiveFixed(pc);
63 :
64 : // NB: It is possible that numValueSlots() could be zero, even if nfixed is
65 : // nonzero. This is the case if the function has an early stack check.
66 27 : if (numValueSlots() == 0)
67 0 : return;
68 :
69 27 : MOZ_ASSERT(nfixed <= numValueSlots());
70 :
71 27 : if (nfixed == nlivefixed) {
72 : // All locals are live.
73 15 : TraceLocals(this, trc, 0, numValueSlots());
74 : } else {
75 : // Trace operand stack.
76 12 : TraceLocals(this, trc, nfixed, numValueSlots());
77 :
78 : // Clear dead block-scoped locals.
79 38 : while (nfixed > nlivefixed)
80 13 : unaliasedLocal(--nfixed).setUndefined();
81 :
82 : // Trace live locals.
83 12 : TraceLocals(this, trc, 0, nlivefixed);
84 : }
85 :
86 27 : if (script->compartment()->debugEnvs)
87 0 : script->compartment()->debugEnvs->traceLiveFrame(trc, this);
88 : }
89 :
90 : bool
91 0 : BaselineFrame::isNonGlobalEvalFrame() const
92 : {
93 0 : return isEvalFrame() && script()->enclosingScope()->as<EvalScope>().isNonGlobal();
94 : }
95 :
96 : bool
97 3124 : BaselineFrame::initFunctionEnvironmentObjects(JSContext* cx)
98 : {
99 3124 : return js::InitFunctionEnvironmentObjects(cx, this);
100 : }
101 :
102 : bool
103 9 : BaselineFrame::pushVarEnvironment(JSContext* cx, HandleScope scope)
104 : {
105 9 : return js::PushVarEnvironmentObject(cx, scope, this);
106 : }
107 :
108 : bool
109 141 : BaselineFrame::initForOsr(InterpreterFrame* fp, uint32_t numStackValues)
110 : {
111 141 : mozilla::PodZero(this);
112 :
113 141 : envChain_ = fp->environmentChain();
114 :
115 141 : if (fp->hasInitialEnvironmentUnchecked())
116 33 : flags_ |= BaselineFrame::HAS_INITIAL_ENV;
117 :
118 141 : if (fp->script()->needsArgsObj() && fp->hasArgsObj()) {
119 0 : flags_ |= BaselineFrame::HAS_ARGS_OBJ;
120 0 : argsObj_ = &fp->argsObj();
121 : }
122 :
123 141 : if (fp->hasReturnValue())
124 1 : setReturnValue(fp->returnValue());
125 :
126 141 : frameSize_ = BaselineFrame::FramePointerOffset +
127 282 : BaselineFrame::Size() +
128 141 : numStackValues * sizeof(Value);
129 :
130 141 : MOZ_ASSERT(numValueSlots() == numStackValues);
131 :
132 1040 : for (uint32_t i = 0; i < numStackValues; i++)
133 899 : *valueSlot(i) = fp->slots()[i];
134 :
135 141 : if (fp->isDebuggee()) {
136 0 : JSContext* cx = TlsContext.get();
137 :
138 : // For debuggee frames, update any Debugger.Frame objects for the
139 : // InterpreterFrame to point to the BaselineFrame.
140 :
141 : // The caller pushed a fake return address. ScriptFrameIter, used by the
142 : // debugger, wants a valid return address, but it's okay to just pick one.
143 : // In debug mode there's always at least 1 ICEntry (since there are always
144 : // debug prologue/epilogue calls).
145 0 : JitFrameIterator iter(cx);
146 0 : MOZ_ASSERT(iter.returnAddress() == nullptr);
147 0 : BaselineScript* baseline = fp->script()->baselineScript();
148 0 : iter.current()->setReturnAddress(baseline->returnAddressForIC(baseline->icEntry(0)));
149 :
150 0 : if (!Debugger::handleBaselineOsr(cx, fp, this))
151 0 : return false;
152 :
153 0 : setIsDebuggee();
154 : }
155 :
156 141 : return true;
157 9 : }
|