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/RematerializedFrame.h"
8 :
9 : #include "mozilla/SizePrintfMacros.h"
10 :
11 : #include "jit/JitFrames.h"
12 : #include "vm/ArgumentsObject.h"
13 : #include "vm/Debugger.h"
14 :
15 : #include "jsscriptinlines.h"
16 : #include "jit/JitFrames-inl.h"
17 : #include "vm/EnvironmentObject-inl.h"
18 :
19 : using namespace js;
20 : using namespace jit;
21 :
22 : struct CopyValueToRematerializedFrame
23 : {
24 : Value* slots;
25 :
26 0 : explicit CopyValueToRematerializedFrame(Value* slots)
27 0 : : slots(slots)
28 0 : { }
29 :
30 0 : void operator()(const Value& v) {
31 0 : *slots++ = v;
32 0 : }
33 : };
34 :
35 0 : RematerializedFrame::RematerializedFrame(JSContext* cx, uint8_t* top, unsigned numActualArgs,
36 0 : InlineFrameIterator& iter, MaybeReadFallback& fallback)
37 : : prevUpToDate_(false),
38 0 : isDebuggee_(iter.script()->isDebuggee()),
39 0 : isConstructing_(iter.isConstructing()),
40 : hasCachedSavedFrame_(false),
41 : top_(top),
42 0 : pc_(iter.pc()),
43 0 : frameNo_(iter.frameNo()),
44 : numActualArgs_(numActualArgs),
45 0 : script_(iter.script())
46 : {
47 0 : if (iter.isFunctionFrame())
48 0 : callee_ = iter.callee(fallback);
49 : else
50 0 : callee_ = nullptr;
51 :
52 0 : CopyValueToRematerializedFrame op(slots_);
53 0 : iter.readFrameArgsAndLocals(cx, op, op, &envChain_, &hasInitialEnv_, &returnValue_,
54 : &argsObj_, &thisArgument_, &newTarget_, ReadFrame_Actuals,
55 0 : fallback);
56 0 : }
57 :
58 : /* static */ RematerializedFrame*
59 0 : RematerializedFrame::New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter,
60 : MaybeReadFallback& fallback)
61 : {
62 0 : unsigned numFormals = iter.isFunctionFrame() ? iter.calleeTemplate()->nargs() : 0;
63 0 : unsigned argSlots = Max(numFormals, iter.numActualArgs());
64 0 : size_t numBytes = sizeof(RematerializedFrame) +
65 0 : (argSlots + iter.script()->nfixed()) * sizeof(Value) -
66 0 : sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
67 :
68 0 : void* buf = cx->pod_calloc<uint8_t>(numBytes);
69 0 : if (!buf)
70 0 : return nullptr;
71 :
72 0 : return new (buf) RematerializedFrame(cx, top, iter.numActualArgs(), iter, fallback);
73 : }
74 :
75 : /* static */ bool
76 0 : RematerializedFrame::RematerializeInlineFrames(JSContext* cx, uint8_t* top,
77 : InlineFrameIterator& iter,
78 : MaybeReadFallback& fallback,
79 : GCVector<RematerializedFrame*>& frames)
80 : {
81 0 : Rooted<GCVector<RematerializedFrame*>> tempFrames(cx, GCVector<RematerializedFrame*>(cx));
82 0 : if (!tempFrames.resize(iter.frameCount()))
83 0 : return false;
84 :
85 : while (true) {
86 0 : size_t frameNo = iter.frameNo();
87 0 : tempFrames[frameNo].set(RematerializedFrame::New(cx, top, iter, fallback));
88 0 : if (!tempFrames[frameNo])
89 0 : return false;
90 0 : if (tempFrames[frameNo]->environmentChain()) {
91 0 : if (!EnsureHasEnvironmentObjects(cx, tempFrames[frameNo].get()))
92 0 : return false;
93 : }
94 :
95 0 : if (!iter.more())
96 0 : break;
97 0 : ++iter;
98 0 : }
99 :
100 0 : frames = Move(tempFrames.get());
101 0 : return true;
102 : }
103 :
104 : /* static */ void
105 0 : RematerializedFrame::FreeInVector(GCVector<RematerializedFrame*>& frames)
106 : {
107 0 : for (size_t i = 0; i < frames.length(); i++) {
108 0 : RematerializedFrame* f = frames[i];
109 0 : MOZ_ASSERT(!Debugger::inFrameMaps(f));
110 : f->RematerializedFrame::~RematerializedFrame();
111 0 : js_free(f);
112 : }
113 0 : frames.clear();
114 0 : }
115 :
116 : CallObject&
117 0 : RematerializedFrame::callObj() const
118 : {
119 0 : MOZ_ASSERT(hasInitialEnvironment());
120 :
121 0 : JSObject* env = environmentChain();
122 0 : while (!env->is<CallObject>())
123 0 : env = env->enclosingEnvironment();
124 0 : return env->as<CallObject>();
125 : }
126 :
127 : bool
128 0 : RematerializedFrame::initFunctionEnvironmentObjects(JSContext* cx)
129 : {
130 0 : return js::InitFunctionEnvironmentObjects(cx, this);
131 : }
132 :
133 : bool
134 0 : RematerializedFrame::pushVarEnvironment(JSContext* cx, HandleScope scope)
135 : {
136 0 : return js::PushVarEnvironmentObject(cx, scope, this);
137 : }
138 :
139 : void
140 0 : RematerializedFrame::trace(JSTracer* trc)
141 : {
142 0 : TraceRoot(trc, &script_, "remat ion frame script");
143 0 : TraceRoot(trc, &envChain_, "remat ion frame env chain");
144 0 : if (callee_)
145 0 : TraceRoot(trc, &callee_, "remat ion frame callee");
146 0 : if (argsObj_)
147 0 : TraceRoot(trc, &argsObj_, "remat ion frame argsobj");
148 0 : TraceRoot(trc, &returnValue_, "remat ion frame return value");
149 0 : TraceRoot(trc, &thisArgument_, "remat ion frame this");
150 0 : TraceRoot(trc, &newTarget_, "remat ion frame newTarget");
151 0 : TraceRootRange(trc, numArgSlots() + script_->nfixed(), slots_, "remat ion frame stack");
152 0 : }
153 :
154 : void
155 0 : RematerializedFrame::dump()
156 : {
157 0 : fprintf(stderr, " Rematerialized Ion Frame%s\n", inlined() ? " (inlined)" : "");
158 0 : if (isFunctionFrame()) {
159 0 : fprintf(stderr, " callee fun: ");
160 : #ifdef DEBUG
161 0 : DumpValue(ObjectValue(*callee()));
162 : #else
163 : fprintf(stderr, "?\n");
164 : #endif
165 : } else {
166 0 : fprintf(stderr, " global frame, no callee\n");
167 : }
168 :
169 0 : fprintf(stderr, " file %s line %" PRIuSIZE " offset %" PRIuSIZE "\n",
170 : script()->filename(), script()->lineno(),
171 0 : script()->pcToOffset(pc()));
172 :
173 0 : fprintf(stderr, " script = %p\n", (void*) script());
174 :
175 0 : if (isFunctionFrame()) {
176 0 : fprintf(stderr, " env chain: ");
177 : #ifdef DEBUG
178 0 : DumpValue(ObjectValue(*environmentChain()));
179 : #else
180 : fprintf(stderr, "?\n");
181 : #endif
182 :
183 0 : if (hasArgsObj()) {
184 0 : fprintf(stderr, " args obj: ");
185 : #ifdef DEBUG
186 0 : DumpValue(ObjectValue(argsObj()));
187 : #else
188 : fprintf(stderr, "?\n");
189 : #endif
190 : }
191 :
192 0 : fprintf(stderr, " this: ");
193 : #ifdef DEBUG
194 0 : DumpValue(thisArgument());
195 : #else
196 : fprintf(stderr, "?\n");
197 : #endif
198 :
199 0 : for (unsigned i = 0; i < numActualArgs(); i++) {
200 0 : if (i < numFormalArgs())
201 0 : fprintf(stderr, " formal (arg %d): ", i);
202 : else
203 0 : fprintf(stderr, " overflown (arg %d): ", i);
204 : #ifdef DEBUG
205 0 : DumpValue(argv()[i]);
206 : #else
207 : fprintf(stderr, "?\n");
208 : #endif
209 : }
210 :
211 0 : for (unsigned i = 0; i < script()->nfixed(); i++) {
212 0 : fprintf(stderr, " local %d: ", i);
213 : #ifdef DEBUG
214 0 : DumpValue(locals()[i]);
215 : #else
216 : fprintf(stderr, "?\n");
217 : #endif
218 : }
219 : }
220 :
221 0 : fputc('\n', stderr);
222 0 : }
|