js/src/jit/CompileInfo.h

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:81f44811a22b
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 #ifndef jit_CompileInfo_h
8 #define jit_CompileInfo_h
9
10 #include "jsfun.h"
11
12 #include "jit/Registers.h"
13 #include "vm/ScopeObject.h"
14
15 namespace js {
16 namespace jit {
17
18 inline unsigned
19 StartArgSlot(JSScript *script)
20 {
21 // Reserved slots:
22 // Slot 0: Scope chain.
23 // Slot 1: Return value.
24
25 // When needed:
26 // Slot 2: Argumentsobject.
27
28 // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
29 return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
30 }
31
32 inline unsigned
33 CountArgSlots(JSScript *script, JSFunction *fun)
34 {
35 // Slot x + 0: This value.
36 // Slot x + 1: Argument 1.
37 // ...
38 // Slot x + n: Argument n.
39
40 // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
41 return StartArgSlot(script) + (fun ? fun->nargs() + 1 : 0);
42 }
43
44 // Contains information about the compilation source for IR being generated.
45 class CompileInfo
46 {
47 public:
48 CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
49 ExecutionMode executionMode, bool scriptNeedsArgsObj)
50 : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
51 executionMode_(executionMode), scriptNeedsArgsObj_(scriptNeedsArgsObj)
52 {
53 JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
54
55 // The function here can flow in from anywhere so look up the canonical
56 // function to ensure that we do not try to embed a nursery pointer in
57 // jit-code. Precisely because it can flow in from anywhere, it's not
58 // guaranteed to be non-lazy. Hence, don't access its script!
59 if (fun_) {
60 fun_ = fun_->nonLazyScript()->functionNonDelazifying();
61 JS_ASSERT(fun_->isTenured());
62 }
63
64 osrStaticScope_ = osrPc ? script->getStaticScope(osrPc) : nullptr;
65
66 nimplicit_ = StartArgSlot(script) /* scope chain and argument obj */
67 + (fun ? 1 : 0); /* this */
68 nargs_ = fun ? fun->nargs() : 0;
69 nfixedvars_ = script->nfixedvars();
70 nlocals_ = script->nfixed();
71 nstack_ = script->nslots() - script->nfixed();
72 nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
73 }
74
75 CompileInfo(unsigned nlocals, ExecutionMode executionMode)
76 : script_(nullptr), fun_(nullptr), osrPc_(nullptr), osrStaticScope_(nullptr),
77 constructing_(false), executionMode_(executionMode), scriptNeedsArgsObj_(false)
78 {
79 nimplicit_ = 0;
80 nargs_ = 0;
81 nfixedvars_ = 0;
82 nlocals_ = nlocals;
83 nstack_ = 1; /* For FunctionCompiler::pushPhiInput/popPhiOutput */
84 nslots_ = nlocals_ + nstack_;
85 }
86
87 JSScript *script() const {
88 return script_;
89 }
90 JSFunction *funMaybeLazy() const {
91 return fun_;
92 }
93 bool constructing() const {
94 return constructing_;
95 }
96 jsbytecode *osrPc() {
97 return osrPc_;
98 }
99 NestedScopeObject *osrStaticScope() const {
100 return osrStaticScope_;
101 }
102
103 bool hasOsrAt(jsbytecode *pc) {
104 JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
105 return pc == osrPc();
106 }
107
108 jsbytecode *startPC() const {
109 return script_->code();
110 }
111 jsbytecode *limitPC() const {
112 return script_->codeEnd();
113 }
114
115 const char *filename() const {
116 return script_->filename();
117 }
118
119 unsigned lineno() const {
120 return script_->lineno();
121 }
122 unsigned lineno(jsbytecode *pc) const {
123 return PCToLineNumber(script_, pc);
124 }
125
126 // Script accessors based on PC.
127
128 JSAtom *getAtom(jsbytecode *pc) const {
129 return script_->getAtom(GET_UINT32_INDEX(pc));
130 }
131
132 PropertyName *getName(jsbytecode *pc) const {
133 return script_->getName(GET_UINT32_INDEX(pc));
134 }
135
136 inline RegExpObject *getRegExp(jsbytecode *pc) const;
137
138 JSObject *getObject(jsbytecode *pc) const {
139 return script_->getObject(GET_UINT32_INDEX(pc));
140 }
141
142 inline JSFunction *getFunction(jsbytecode *pc) const;
143
144 const Value &getConst(jsbytecode *pc) const {
145 return script_->getConst(GET_UINT32_INDEX(pc));
146 }
147
148 jssrcnote *getNote(GSNCache &gsn, jsbytecode *pc) const {
149 return GetSrcNote(gsn, script(), pc);
150 }
151
152 // Total number of slots: args, locals, and stack.
153 unsigned nslots() const {
154 return nslots_;
155 }
156
157 // Number of slots needed for Scope chain, return value,
158 // maybe argumentsobject and this value.
159 unsigned nimplicit() const {
160 return nimplicit_;
161 }
162 // Number of arguments (without counting this value).
163 unsigned nargs() const {
164 return nargs_;
165 }
166 // Number of slots needed for "fixed vars". Note that this is only non-zero
167 // for function code.
168 unsigned nfixedvars() const {
169 return nfixedvars_;
170 }
171 // Number of slots needed for all local variables. This includes "fixed
172 // vars" (see above) and also block-scoped locals.
173 unsigned nlocals() const {
174 return nlocals_;
175 }
176 unsigned ninvoke() const {
177 return nslots_ - nstack_;
178 }
179
180 uint32_t scopeChainSlot() const {
181 JS_ASSERT(script());
182 return 0;
183 }
184 uint32_t returnValueSlot() const {
185 JS_ASSERT(script());
186 return 1;
187 }
188 uint32_t argsObjSlot() const {
189 JS_ASSERT(hasArguments());
190 return 2;
191 }
192 uint32_t thisSlot() const {
193 JS_ASSERT(funMaybeLazy());
194 JS_ASSERT(nimplicit_ > 0);
195 return nimplicit_ - 1;
196 }
197 uint32_t firstArgSlot() const {
198 return nimplicit_;
199 }
200 uint32_t argSlotUnchecked(uint32_t i) const {
201 // During initialization, some routines need to get at arg
202 // slots regardless of how regular argument access is done.
203 JS_ASSERT(i < nargs_);
204 return nimplicit_ + i;
205 }
206 uint32_t argSlot(uint32_t i) const {
207 // This should only be accessed when compiling functions for
208 // which argument accesses don't need to go through the
209 // argument object.
210 JS_ASSERT(!argsObjAliasesFormals());
211 return argSlotUnchecked(i);
212 }
213 uint32_t firstLocalSlot() const {
214 return nimplicit_ + nargs_;
215 }
216 uint32_t localSlot(uint32_t i) const {
217 return firstLocalSlot() + i;
218 }
219 uint32_t firstStackSlot() const {
220 return firstLocalSlot() + nlocals();
221 }
222 uint32_t stackSlot(uint32_t i) const {
223 return firstStackSlot() + i;
224 }
225
226 uint32_t startArgSlot() const {
227 JS_ASSERT(script());
228 return StartArgSlot(script());
229 }
230 uint32_t endArgSlot() const {
231 JS_ASSERT(script());
232 return CountArgSlots(script(), funMaybeLazy());
233 }
234
235 uint32_t totalSlots() const {
236 JS_ASSERT(script() && funMaybeLazy());
237 return nimplicit() + nargs() + nlocals();
238 }
239
240 bool isSlotAliased(uint32_t index, NestedScopeObject *staticScope) const {
241 JS_ASSERT(index >= startArgSlot());
242
243 if (funMaybeLazy() && index == thisSlot())
244 return false;
245
246 uint32_t arg = index - firstArgSlot();
247 if (arg < nargs())
248 return script()->formalIsAliased(arg);
249
250 uint32_t local = index - firstLocalSlot();
251 if (local < nlocals()) {
252 // First, check if this local is a var.
253 if (local < nfixedvars())
254 return script()->varIsAliased(local);
255
256 // Otherwise, it might be part of a block scope.
257 for (; staticScope; staticScope = staticScope->enclosingNestedScope()) {
258 if (!staticScope->is<StaticBlockObject>())
259 continue;
260 StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>();
261 if (blockObj.localOffset() < local) {
262 if (local - blockObj.localOffset() < blockObj.numVariables())
263 return blockObj.isAliased(local - blockObj.localOffset());
264 return false;
265 }
266 }
267
268 // In this static scope, this var is dead.
269 return false;
270 }
271
272 JS_ASSERT(index >= firstStackSlot());
273 return false;
274 }
275
276 bool isSlotAliasedAtEntry(uint32_t index) const {
277 return isSlotAliased(index, nullptr);
278 }
279 bool isSlotAliasedAtOsr(uint32_t index) const {
280 return isSlotAliased(index, osrStaticScope());
281 }
282
283 bool hasArguments() const {
284 return script()->argumentsHasVarBinding();
285 }
286 bool argumentsAliasesFormals() const {
287 return script()->argumentsAliasesFormals();
288 }
289 bool needsArgsObj() const {
290 return scriptNeedsArgsObj_;
291 }
292 bool argsObjAliasesFormals() const {
293 return scriptNeedsArgsObj_ && !script()->strict();
294 }
295
296 ExecutionMode executionMode() const {
297 return executionMode_;
298 }
299
300 bool executionModeIsAnalysis() const {
301 return executionMode_ == DefinitePropertiesAnalysis || executionMode_ == ArgumentsUsageAnalysis;
302 }
303
304 bool isParallelExecution() const {
305 return executionMode_ == ParallelExecution;
306 }
307
308 bool canOptimizeOutSlot(uint32_t i) const {
309 if (script()->strict())
310 return true;
311
312 // Function.arguments can be used to access all arguments in
313 // non-strict scripts, so we can't optimize out any arguments.
314 return !(firstArgSlot() <= i && i - firstArgSlot() < nargs());
315 }
316
317 private:
318 unsigned nimplicit_;
319 unsigned nargs_;
320 unsigned nfixedvars_;
321 unsigned nlocals_;
322 unsigned nstack_;
323 unsigned nslots_;
324 JSScript *script_;
325 JSFunction *fun_;
326 jsbytecode *osrPc_;
327 NestedScopeObject *osrStaticScope_;
328 bool constructing_;
329 ExecutionMode executionMode_;
330
331 // Whether a script needs an arguments object is unstable over compilation
332 // since the arguments optimization could be marked as failed on the main
333 // thread, so cache a value here and use it throughout for consistency.
334 bool scriptNeedsArgsObj_;
335 };
336
337 } // namespace jit
338 } // namespace js
339
340 #endif /* jit_CompileInfo_h */

mercurial