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/RematerializedFrame.h"
12 #include "jit/Bailouts.h"
13 #include "jit/JSJitFrameIter.h"
14 #include "js/friend/DumpFunctions.h" // js::DumpValue
15 #include "vm/ArgumentsObject.h"
17 #include "vm/EnvironmentObject-inl.h"
18 #include "vm/JSScript-inl.h"
23 struct CopyValueToRematerializedFrame
{
26 explicit CopyValueToRematerializedFrame(Value
* slots
) : slots(slots
) {}
28 void operator()(const Value
& v
) { *slots
++ = v
; }
31 RematerializedFrame::RematerializedFrame(JSContext
* cx
, uint8_t* top
,
32 unsigned numActualArgs
,
33 InlineFrameIterator
& iter
,
34 MaybeReadFallback
& fallback
)
35 : prevUpToDate_(false),
36 isDebuggee_(iter
.script()->isDebuggee()),
37 hasInitialEnv_(false),
38 isConstructing_(iter
.isConstructing()),
39 hasCachedSavedFrame_(false),
42 frameNo_(iter
.frameNo()),
43 numActualArgs_(numActualArgs
),
44 script_(iter
.script()),
47 if (iter
.isFunctionFrame()) {
48 callee_
= iter
.callee(fallback
);
53 CopyValueToRematerializedFrame
op(slots_
);
54 iter
.readFrameArgsAndLocals(
55 cx
, op
, op
, &envChain_
, &hasInitialEnv_
, &returnValue_
, &argsObj_
,
56 &thisArgument_
, ReadFrameArgsBehavior::ActualsAndFormals
, fallback
);
60 RematerializedFrame
* RematerializedFrame::New(JSContext
* cx
, uint8_t* top
,
61 InlineFrameIterator
& iter
,
62 MaybeReadFallback
& fallback
) {
64 iter
.isFunctionFrame() ? iter
.calleeTemplate()->nargs() : 0;
65 unsigned argSlots
= std::max(numFormals
, iter
.numActualArgs());
66 unsigned extraSlots
= argSlots
+ iter
.script()->nfixed();
68 // One Value slot is included in sizeof(RematerializedFrame), so we can
69 // reduce the extra slot count by one. However, if there are zero slot
70 // allocations total, then reducing the slots by one will lead to
71 // the memory allocation being smaller than sizeof(RematerializedFrame).
76 RematerializedFrame
* buf
=
77 cx
->pod_calloc_with_extra
<RematerializedFrame
, Value
>(extraSlots
);
83 RematerializedFrame(cx
, top
, iter
.numActualArgs(), iter
, fallback
);
87 bool RematerializedFrame::RematerializeInlineFrames(
88 JSContext
* cx
, uint8_t* top
, InlineFrameIterator
& iter
,
89 MaybeReadFallback
& fallback
, RematerializedFrameVector
& frames
) {
90 Rooted
<RematerializedFrameVector
> tempFrames(cx
,
91 RematerializedFrameVector(cx
));
92 if (!tempFrames
.resize(iter
.frameCount())) {
97 size_t frameNo
= iter
.frameNo();
98 tempFrames
[frameNo
].reset(
99 RematerializedFrame::New(cx
, top
, iter
, fallback
));
100 if (!tempFrames
[frameNo
]) {
103 if (tempFrames
[frameNo
]->environmentChain()) {
104 if (!EnsureHasEnvironmentObjects(cx
, tempFrames
[frameNo
].get().get())) {
115 frames
= std::move(tempFrames
.get());
119 CallObject
& RematerializedFrame::callObj() const {
120 MOZ_ASSERT(hasInitialEnvironment());
121 MOZ_ASSERT(callee()->needsCallObject());
123 JSObject
* env
= environmentChain();
124 while (!env
->is
<CallObject
>()) {
125 env
= env
->enclosingEnvironment();
127 return env
->as
<CallObject
>();
130 bool RematerializedFrame::initFunctionEnvironmentObjects(JSContext
* cx
) {
131 return js::InitFunctionEnvironmentObjects(cx
, this);
134 bool RematerializedFrame::pushVarEnvironment(JSContext
* cx
,
135 Handle
<Scope
*> scope
) {
136 return js::PushVarEnvironmentObject(cx
, scope
, this);
139 void RematerializedFrame::trace(JSTracer
* trc
) {
140 TraceRoot(trc
, &script_
, "remat ion frame script");
141 TraceRoot(trc
, &envChain_
, "remat ion frame env chain");
143 TraceRoot(trc
, &callee_
, "remat ion frame callee");
146 TraceRoot(trc
, &argsObj_
, "remat ion frame argsobj");
148 TraceRoot(trc
, &returnValue_
, "remat ion frame return value");
149 TraceRoot(trc
, &thisArgument_
, "remat ion frame this");
150 TraceRootRange(trc
, numArgSlots() + script_
->nfixed(), slots_
,
151 "remat ion frame stack");
154 void RematerializedFrame::dump() {
155 fprintf(stderr
, " Rematerialized Ion Frame%s\n",
156 inlined() ? " (inlined)" : "");
157 if (isFunctionFrame()) {
158 fprintf(stderr
, " callee fun: ");
160 DumpValue(ObjectValue(*callee()));
162 fprintf(stderr
, "?\n");
165 fprintf(stderr
, " global frame, no callee\n");
168 fprintf(stderr
, " file %s line %u offset %zu\n", script()->filename(),
169 script()->lineno(), script()->pcToOffset(pc()));
171 fprintf(stderr
, " script = %p\n", (void*)script());
173 if (isFunctionFrame()) {
174 fprintf(stderr
, " env chain: ");
176 DumpValue(ObjectValue(*environmentChain()));
178 fprintf(stderr
, "?\n");
182 fprintf(stderr
, " args obj: ");
184 DumpValue(ObjectValue(argsObj()));
186 fprintf(stderr
, "?\n");
190 fprintf(stderr
, " this: ");
192 DumpValue(thisArgument());
194 fprintf(stderr
, "?\n");
197 for (unsigned i
= 0; i
< numActualArgs(); i
++) {
198 if (i
< numFormalArgs()) {
199 fprintf(stderr
, " formal (arg %u): ", i
);
201 fprintf(stderr
, " overflown (arg %u): ", i
);
204 DumpValue(argv()[i
]);
206 fprintf(stderr
, "?\n");
210 for (unsigned i
= 0; i
< script()->nfixed(); i
++) {
211 fprintf(stderr
, " local %u: ", i
);
213 DumpValue(locals()[i
]);
215 fprintf(stderr
, "?\n");