1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=4 sw=4 et tw=79 ft=cpp:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is SpiderMonkey JavaScript engine.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Mozilla Corporation.
21 : * Portions created by the Initial Developer are Copyright (C) 2009
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Luke Wagner <luke@mozilla.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #ifndef Stack_inl_h__
42 : #define Stack_inl_h__
43 :
44 : #include "jscntxt.h"
45 : #include "jscompartment.h"
46 :
47 : #include "methodjit/MethodJIT.h"
48 : #include "vm/Stack.h"
49 :
50 : #include "jsscriptinlines.h"
51 :
52 : #include "ArgumentsObject-inl.h"
53 : #include "ScopeObject-inl.h"
54 :
55 :
56 : namespace js {
57 :
58 : /*
59 : * We cache name lookup results only for the global object or for native
60 : * non-global objects without prototype or with prototype that never mutates,
61 : * see bug 462734 and bug 487039.
62 : */
63 : static inline bool
64 683963 : IsCacheableNonGlobalScope(JSObject *obj)
65 : {
66 683963 : bool cacheable = (obj->isCall() || obj->isBlock() || obj->isDeclEnv());
67 :
68 683963 : JS_ASSERT_IF(cacheable, !obj->getOps()->lookupProperty);
69 683963 : return cacheable;
70 : }
71 :
72 : inline JSObject &
73 1030221999 : StackFrame::scopeChain() const
74 : {
75 1030221999 : JS_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame());
76 1030221999 : if (!(flags_ & HAS_SCOPECHAIN)) {
77 2981792 : scopeChain_ = callee().toFunction()->environment();
78 2981792 : flags_ |= HAS_SCOPECHAIN;
79 : }
80 1030221999 : return *scopeChain_;
81 : }
82 :
83 : inline JSObject &
84 142185 : StackFrame::varObj()
85 : {
86 142185 : JSObject *obj = &scopeChain();
87 285090 : while (!obj->isVarObj())
88 720 : obj = obj->enclosingScope();
89 142185 : return *obj;
90 : }
91 :
92 : inline JSCompartment *
93 : StackFrame::compartment() const
94 : {
95 : JS_ASSERT_IF(isScriptFrame(), scopeChain().compartment() == script()->compartment());
96 : return scopeChain().compartment();
97 : }
98 :
99 : inline void
100 22102279 : StackFrame::initPrev(JSContext *cx)
101 : {
102 22102279 : JS_ASSERT(flags_ & HAS_PREVPC);
103 22102279 : if (FrameRegs *regs = cx->maybeRegs()) {
104 22083255 : prev_ = regs->fp();
105 22083255 : prevpc_ = regs->pc;
106 22083255 : prevInline_ = regs->inlined();
107 66187111 : JS_ASSERT_IF(!prev_->isDummyFrame(),
108 66187111 : uint32_t(prevpc_ - prev_->script()->code) < prev_->script()->length);
109 : } else {
110 19024 : prev_ = NULL;
111 : #ifdef DEBUG
112 19024 : prevpc_ = (jsbytecode *)0xbadc;
113 19024 : prevInline_ = (JSInlinedSite *)0xbadc;
114 : #endif
115 : }
116 22102279 : }
117 :
118 : inline void
119 19103 : StackFrame::resetGeneratorPrev(JSContext *cx)
120 : {
121 19103 : flags_ |= HAS_PREVPC;
122 19103 : initPrev(cx);
123 19103 : }
124 :
125 : inline void
126 140 : StackFrame::initInlineFrame(JSFunction *fun, StackFrame *prevfp, jsbytecode *prevpc)
127 : {
128 : /*
129 : * Note: no need to ensure the scopeChain is instantiated for inline
130 : * frames. Functions which use the scope chain are never inlined.
131 : */
132 140 : flags_ = StackFrame::FUNCTION;
133 140 : exec.fun = fun;
134 140 : resetInlinePrev(prevfp, prevpc);
135 140 : }
136 :
137 : inline void
138 195 : StackFrame::resetInlinePrev(StackFrame *prevfp, jsbytecode *prevpc)
139 : {
140 195 : JS_ASSERT_IF(flags_ & StackFrame::HAS_PREVPC, prevInline_);
141 195 : flags_ |= StackFrame::HAS_PREVPC;
142 195 : prev_ = prevfp;
143 195 : prevpc_ = prevpc;
144 195 : prevInline_ = NULL;
145 195 : }
146 :
147 : inline void
148 21873172 : StackFrame::initCallFrame(JSContext *cx, JSFunction &callee,
149 : JSScript *script, uint32_t nactual, StackFrame::Flags flagsArg)
150 : {
151 0 : JS_ASSERT((flagsArg & ~(CONSTRUCTING |
152 : LOWERED_CALL_APPLY |
153 : OVERFLOW_ARGS |
154 21873172 : UNDERFLOW_ARGS)) == 0);
155 21873172 : JS_ASSERT(script == callee.script());
156 :
157 : /* Initialize stack frame members. */
158 21873172 : flags_ = FUNCTION | HAS_PREVPC | HAS_SCOPECHAIN | HAS_BLOCKCHAIN | flagsArg;
159 21873172 : exec.fun = &callee;
160 21873172 : u.nactual = nactual;
161 21873172 : scopeChain_ = callee.environment();
162 21873172 : ncode_ = NULL;
163 21873172 : initPrev(cx);
164 21873172 : blockChain_= NULL;
165 21873172 : JS_ASSERT(!hasBlockChain());
166 21873172 : JS_ASSERT(!hasHookData());
167 21873172 : JS_ASSERT(annotation() == NULL);
168 21873172 : JS_ASSERT(!hasCallObj());
169 :
170 21873172 : SetValueRangeToUndefined(slots(), script->nfixed);
171 21873172 : }
172 :
173 : /*
174 : * Reinitialize the StackFrame fields that have been initialized up to the
175 : * point of FixupArity in the function prologue.
176 : */
177 : inline void
178 935048 : StackFrame::initFixupFrame(StackFrame *prev, StackFrame::Flags flags, void *ncode, unsigned nactual)
179 : {
180 0 : JS_ASSERT((flags & ~(CONSTRUCTING |
181 : LOWERED_CALL_APPLY |
182 : FUNCTION |
183 : OVERFLOW_ARGS |
184 935048 : UNDERFLOW_ARGS)) == 0);
185 :
186 935048 : flags_ = FUNCTION | flags;
187 935048 : prev_ = prev;
188 935048 : ncode_ = ncode;
189 935048 : u.nactual = nactual;
190 935048 : }
191 :
192 : inline Value &
193 210579 : StackFrame::canonicalActualArg(unsigned i) const
194 : {
195 210579 : if (i < numFormalArgs())
196 11580 : return formalArg(i);
197 198999 : JS_ASSERT(i < numActualArgs());
198 198999 : return actualArgs()[i];
199 : }
200 :
201 : template <class Op>
202 : inline bool
203 6551417 : StackFrame::forEachCanonicalActualArg(Op op, unsigned start /* = 0 */, unsigned count /* = unsigned(-1) */)
204 : {
205 6764264 : unsigned nformal = fun()->nargs;
206 6764264 : JS_ASSERT(start <= nformal);
207 :
208 6764264 : Value *formals = formalArgsEnd() - nformal;
209 6764264 : unsigned nactual = numActualArgs();
210 6764264 : if (count == unsigned(-1))
211 6551417 : count = nactual - start;
212 :
213 6764264 : unsigned end = start + count;
214 6764264 : JS_ASSERT(end >= start);
215 6764264 : JS_ASSERT(end <= nactual);
216 :
217 6764264 : if (end <= nformal) {
218 4881697 : Value *p = formals + start;
219 5933435 : for (; start < end; ++p, ++start) {
220 1051738 : if (!op(start, p))
221 0 : return false;
222 : }
223 : } else {
224 2165774 : for (Value *p = formals + start; start < nformal; ++p, ++start) {
225 283207 : if (!op(start, p))
226 0 : return false;
227 : }
228 1882567 : JS_ASSERT(start >= nformal);
229 1882567 : Value *actuals = formals - (nactual + 2) + start;
230 8988466 : for (Value *p = actuals; start < end; ++p, ++start) {
231 7105899 : if (!op(start, p))
232 0 : return false;
233 : }
234 : }
235 6764264 : return true;
236 : }
237 :
238 : template <class Op>
239 : inline bool
240 : StackFrame::forEachFormalArg(Op op)
241 : {
242 : Value *formals = formalArgsEnd() - fun()->nargs;
243 : Value *formalsEnd = formalArgsEnd();
244 : unsigned i = 0;
245 : for (Value *p = formals; p != formalsEnd; ++p, ++i) {
246 : if (!op(i, p))
247 : return false;
248 : }
249 : return true;
250 : }
251 :
252 : struct CopyTo
253 : {
254 : Value *dst;
255 425289 : CopyTo(Value *dst) : dst(dst) {}
256 1040540 : bool operator()(unsigned, Value *src) {
257 1040540 : *dst++ = *src;
258 1040540 : return true;
259 : }
260 : };
261 :
262 : inline unsigned
263 18616370 : StackFrame::numActualArgs() const
264 : {
265 : /*
266 : * u.nactual is always coherent, except for method JIT frames where the
267 : * callee does not access its arguments and the number of actual arguments
268 : * matches the number of formal arguments. The JIT requires that all frames
269 : * which do not have an arguments object and use their arguments have a
270 : * coherent u.nactual (even though the below code may not use it), as
271 : * JIT code may access the field directly.
272 : */
273 18616370 : JS_ASSERT(hasArgs());
274 18616370 : if (JS_UNLIKELY(flags_ & (OVERFLOW_ARGS | UNDERFLOW_ARGS)))
275 4181585 : return u.nactual;
276 14434785 : return numFormalArgs();
277 : }
278 :
279 : inline Value *
280 11653680 : StackFrame::actualArgs() const
281 : {
282 11653680 : JS_ASSERT(hasArgs());
283 11653680 : Value *argv = formalArgs();
284 11653680 : if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
285 1523941 : return argv - (2 + u.nactual);
286 10129739 : return argv;
287 : }
288 :
289 : inline Value *
290 5767206 : StackFrame::actualArgsEnd() const
291 : {
292 5767206 : JS_ASSERT(hasArgs());
293 5767206 : if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
294 1078934 : return formalArgs() - 2;
295 4688272 : return formalArgs() + numActualArgs();
296 : }
297 :
298 : inline void
299 217422 : StackFrame::setScopeChainNoCallObj(JSObject &obj)
300 : {
301 : #ifdef DEBUG
302 217422 : JS_ASSERT(&obj != NULL);
303 217422 : if (&obj != sInvalidScopeChain) {
304 217422 : if (hasCallObj()) {
305 4250 : JSObject *pobj = &obj;
306 8599 : while (pobj && pobj->getPrivate() != this)
307 99 : pobj = pobj->enclosingScope();
308 4250 : JS_ASSERT(pobj);
309 : } else {
310 215062 : for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
311 1890 : JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
312 : }
313 : }
314 : #endif
315 217422 : scopeChain_ = &obj;
316 217422 : flags_ |= HAS_SCOPECHAIN;
317 217422 : }
318 :
319 : inline void
320 745077 : StackFrame::setScopeChainWithOwnCallObj(CallObject &obj)
321 : {
322 745077 : JS_ASSERT(&obj != NULL);
323 745077 : JS_ASSERT(!hasCallObj() && obj.maybeStackFrame() == this);
324 745077 : scopeChain_ = &obj;
325 745077 : flags_ |= HAS_SCOPECHAIN | HAS_CALL_OBJ;
326 745077 : }
327 :
328 : inline CallObject &
329 1159593 : StackFrame::callObj() const
330 : {
331 1159593 : JS_ASSERT_IF(isNonEvalFunctionFrame() || isStrictEvalFrame(), hasCallObj());
332 :
333 1159593 : JSObject *pobj = &scopeChain();
334 2319303 : while (JS_UNLIKELY(!pobj->isCall()))
335 117 : pobj = pobj->enclosingScope();
336 1159593 : return pobj->asCall();
337 : }
338 :
339 : inline bool
340 15365746 : StackFrame::maintainNestingState() const
341 : {
342 : /*
343 : * Whether to invoke the nesting epilogue/prologue to maintain active
344 : * frame counts and check for reentrant outer functions.
345 : */
346 15365746 : return isNonEvalFunctionFrame() && !isGeneratorFrame() && script()->nesting();
347 : }
348 :
349 : inline bool
350 22242544 : StackFrame::functionPrologue(JSContext *cx)
351 : {
352 22242544 : JS_ASSERT(isNonEvalFunctionFrame());
353 22242544 : JS_ASSERT(!isGeneratorFrame());
354 :
355 22242544 : JSFunction *fun = this->fun();
356 22242544 : JSScript *script = fun->script();
357 :
358 22242544 : if (script->needsArgsObj() && !ArgumentsObject::create(cx, this))
359 0 : return false;
360 :
361 22242544 : if (fun->isHeavyweight()) {
362 742143 : if (!CallObject::createForFunction(cx, this))
363 0 : return false;
364 : } else {
365 : /* Force instantiation of the scope chain, for JIT frames. */
366 21500401 : scopeChain();
367 : }
368 :
369 22242544 : if (script->nesting()) {
370 796707 : JS_ASSERT(maintainNestingState());
371 796707 : types::NestingPrologue(cx, this);
372 : }
373 :
374 22242544 : return true;
375 : }
376 :
377 : inline void
378 13451255 : StackFrame::functionEpilogue()
379 : {
380 13451255 : JS_ASSERT(isNonEvalFunctionFrame());
381 :
382 13451255 : if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
383 1073348 : if (hasCallObj())
384 742692 : js_PutCallObject(this);
385 1073348 : if (hasArgsObj())
386 361711 : js_PutArgsObject(this);
387 : }
388 :
389 13451255 : if (maintainNestingState())
390 681430 : types::NestingEpilogue(this);
391 13451255 : }
392 :
393 : inline void
394 1117784 : StackFrame::updateEpilogueFlags()
395 : {
396 1117784 : if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
397 14321 : if (hasArgsObj() && !argsObj().maybeStackFrame())
398 8516 : flags_ &= ~HAS_ARGS_OBJ;
399 14321 : if (hasCallObj() && !callObj().maybeStackFrame()) {
400 : /*
401 : * For function frames, the call object may or may not have have an
402 : * enclosing DeclEnv object, so we use the callee's parent, since
403 : * it was the initial scope chain. For global (strict) eval frames,
404 : * there is no callee, but the call object's parent is the initial
405 : * scope chain.
406 : */
407 5943 : scopeChain_ = isFunctionFrame()
408 5943 : ? callee().toFunction()->environment()
409 11886 : : &scopeChain_->asScope().enclosingScope();
410 5943 : flags_ &= ~HAS_CALL_OBJ;
411 : }
412 : }
413 :
414 : /*
415 : * For outer/inner function frames, undo the active frame balancing so that
416 : * when we redo it in the epilogue we get the right final value. The other
417 : * nesting epilogue changes (update active args/vars) are idempotent.
418 : */
419 1117784 : if (maintainNestingState())
420 153241 : script()->nesting()->activeFrames++;
421 1117784 : }
422 :
423 : /*****************************************************************************/
424 :
425 : STATIC_POSTCONDITION(!return || ubound(from) >= nvals)
426 : JS_ALWAYS_INLINE bool
427 26521929 : StackSpace::ensureSpace(JSContext *cx, MaybeReportError report, Value *from, ptrdiff_t nvals,
428 : JSCompartment *dest) const
429 : {
430 26521929 : assertInvariants();
431 26521929 : JS_ASSERT(from >= firstUnused());
432 : #ifdef XP_WIN
433 : JS_ASSERT(from <= commitEnd_);
434 : #endif
435 26521929 : if (JS_UNLIKELY(conservativeEnd_ - from < nvals))
436 231 : return ensureSpaceSlow(cx, report, from, nvals, dest);
437 26521698 : return true;
438 : }
439 :
440 : inline Value *
441 1189214 : StackSpace::getStackLimit(JSContext *cx, MaybeReportError report)
442 : {
443 1189214 : FrameRegs ®s = cx->regs();
444 1189214 : unsigned nvals = regs.fp()->numSlots() + STACK_JIT_EXTRA;
445 1189214 : return ensureSpace(cx, report, regs.sp, nvals)
446 : ? conservativeEnd_
447 1189214 : : NULL;
448 : }
449 :
450 : /*****************************************************************************/
451 :
452 : JS_ALWAYS_INLINE StackFrame *
453 22808333 : ContextStack::getCallFrame(JSContext *cx, MaybeReportError report, const CallArgs &args,
454 : JSFunction *fun, JSScript *script, StackFrame::Flags *flags) const
455 : {
456 22808333 : JS_ASSERT(fun->script() == script);
457 22808333 : unsigned nformal = fun->nargs;
458 :
459 22808333 : Value *firstUnused = args.end();
460 22808333 : JS_ASSERT(firstUnused == space().firstUnused());
461 :
462 : /* Include extra space to satisfy the method-jit stackLimit invariant. */
463 22808333 : unsigned nvals = VALUES_PER_STACK_FRAME + script->nslots + StackSpace::STACK_JIT_EXTRA;
464 :
465 : /* Maintain layout invariant: &formalArgs[0] == ((Value *)fp) - nformal. */
466 :
467 22808333 : if (args.length() == nformal) {
468 20353103 : if (!space().ensureSpace(cx, report, firstUnused, nvals))
469 71 : return NULL;
470 20353032 : return reinterpret_cast<StackFrame *>(firstUnused);
471 : }
472 :
473 2455230 : if (args.length() < nformal) {
474 62791 : *flags = StackFrame::Flags(*flags | StackFrame::UNDERFLOW_ARGS);
475 62791 : unsigned nmissing = nformal - args.length();
476 62791 : if (!space().ensureSpace(cx, report, firstUnused, nmissing + nvals))
477 1 : return NULL;
478 62790 : SetValueRangeToUndefined(firstUnused, nmissing);
479 62790 : return reinterpret_cast<StackFrame *>(firstUnused + nmissing);
480 : }
481 :
482 2392439 : *flags = StackFrame::Flags(*flags | StackFrame::OVERFLOW_ARGS);
483 2392439 : unsigned ncopy = 2 + nformal;
484 2392439 : if (!space().ensureSpace(cx, report, firstUnused, ncopy + nvals))
485 41 : return NULL;
486 2392398 : Value *dst = firstUnused;
487 2392398 : Value *src = args.base();
488 2392398 : PodCopy(dst, src, ncopy);
489 2392398 : return reinterpret_cast<StackFrame *>(firstUnused + ncopy);
490 : }
491 :
492 : JS_ALWAYS_INLINE bool
493 20497516 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args,
494 : JSFunction &callee, JSScript *script,
495 : InitialFrameFlags initial)
496 : {
497 20497516 : JS_ASSERT(onTop());
498 20497516 : JS_ASSERT(regs.sp == args.end());
499 : /* Cannot assert callee == args.callee() since this is called from LeaveTree. */
500 20497516 : JS_ASSERT(script == callee.script());
501 :
502 20497516 : StackFrame::Flags flags = ToFrameFlags(initial);
503 20497516 : StackFrame *fp = getCallFrame(cx, REPORT_ERROR, args, &callee, script, &flags);
504 20497516 : if (!fp)
505 73 : return false;
506 :
507 : /* Initialize frame, locals, regs. */
508 20497443 : fp->initCallFrame(cx, callee, script, args.length(), flags);
509 :
510 : /*
511 : * N.B. regs may differ from the active registers, if the parent is about
512 : * to repoint the active registers to regs. See UncachedInlineCall.
513 : */
514 20497443 : regs.prepareToRun(*fp, script);
515 20497443 : return true;
516 : }
517 :
518 : JS_ALWAYS_INLINE bool
519 11195172 : ContextStack::pushInlineFrame(JSContext *cx, FrameRegs ®s, const CallArgs &args,
520 : JSFunction &callee, JSScript *script,
521 : InitialFrameFlags initial, Value **stackLimit)
522 : {
523 11195172 : if (!pushInlineFrame(cx, regs, args, callee, script, initial))
524 21 : return false;
525 11195151 : *stackLimit = space().conservativeEnd_;
526 11195151 : return true;
527 : }
528 :
529 : JS_ALWAYS_INLINE StackFrame *
530 935060 : ContextStack::getFixupFrame(JSContext *cx, MaybeReportError report,
531 : const CallArgs &args, JSFunction *fun, JSScript *script,
532 : void *ncode, InitialFrameFlags initial, Value **stackLimit)
533 : {
534 935060 : JS_ASSERT(onTop());
535 935060 : JS_ASSERT(fun->script() == args.callee().toFunction()->script());
536 935060 : JS_ASSERT(fun->script() == script);
537 :
538 935060 : StackFrame::Flags flags = ToFrameFlags(initial);
539 935060 : StackFrame *fp = getCallFrame(cx, report, args, fun, script, &flags);
540 935060 : if (!fp)
541 12 : return NULL;
542 :
543 : /* Do not init late prologue or regs; this is done by jit code. */
544 935048 : fp->initFixupFrame(cx->fp(), flags, ncode, args.length());
545 :
546 935048 : *stackLimit = space().conservativeEnd_;
547 935048 : return fp;
548 : }
549 :
550 : JS_ALWAYS_INLINE void
551 11369071 : ContextStack::popInlineFrame(FrameRegs ®s)
552 : {
553 11369071 : JS_ASSERT(onTop());
554 11369071 : JS_ASSERT(®s == &seg_->regs());
555 :
556 11369071 : StackFrame *fp = regs.fp();
557 11369071 : fp->functionEpilogue();
558 :
559 11369071 : Value *newsp = fp->actualArgs() - 1;
560 11369071 : JS_ASSERT(newsp >= fp->prev()->base());
561 :
562 11369071 : newsp[-1] = fp->returnValue();
563 11369071 : regs.popFrame(newsp);
564 11369071 : }
565 :
566 : inline void
567 16 : ContextStack::popFrameAfterOverflow()
568 : {
569 : /* Restore the regs to what they were on entry to JSOP_CALL. */
570 16 : FrameRegs ®s = seg_->regs();
571 16 : StackFrame *fp = regs.fp();
572 16 : regs.popFrame(fp->actualArgsEnd());
573 16 : }
574 :
575 : inline JSScript *
576 10828314 : ContextStack::currentScript(jsbytecode **ppc) const
577 : {
578 10828314 : if (ppc)
579 3703622 : *ppc = NULL;
580 :
581 10828314 : FrameRegs *regs = maybeRegs();
582 10828314 : StackFrame *fp = regs ? regs->fp() : NULL;
583 21672645 : while (fp && fp->isDummyFrame())
584 16017 : fp = fp->prev();
585 10828314 : if (!fp)
586 2 : return NULL;
587 :
588 : #ifdef JS_METHODJIT
589 10828312 : mjit::CallSite *inlined = regs->inlined();
590 10828312 : if (inlined) {
591 2863 : mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
592 2863 : JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
593 2863 : mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
594 2863 : JSScript *script = frame->fun->script();
595 2863 : if (script->compartment() != cx_->compartment)
596 0 : return NULL;
597 2863 : if (ppc)
598 237 : *ppc = script->code + inlined->pcOffset;
599 2863 : return script;
600 : }
601 : #endif
602 :
603 10825449 : JSScript *script = fp->script();
604 10825449 : if (script->compartment() != cx_->compartment)
605 16017 : return NULL;
606 :
607 10809432 : if (ppc)
608 3687375 : *ppc = fp->pcQuadratic(*this);
609 10809432 : return script;
610 : }
611 :
612 : inline JSScript *
613 5034879 : ContextStack::currentScriptWithDiagnostics(jsbytecode **ppc) const
614 : {
615 5034879 : if (ppc)
616 0 : *ppc = NULL;
617 :
618 5034879 : FrameRegs *regs = maybeRegs();
619 5034879 : StackFrame *fp = regs ? regs->fp() : NULL;
620 10069758 : while (fp && fp->isDummyFrame())
621 0 : fp = fp->prev();
622 5034879 : if (!fp)
623 0 : *(int *) 0x10 = 0;
624 :
625 : #ifdef JS_METHODJIT
626 5034879 : mjit::CallSite *inlined = regs->inlined();
627 5034879 : if (inlined) {
628 1367 : mjit::JITChunk *chunk = fp->jit()->chunk(regs->pc);
629 1367 : JS_ASSERT(inlined->inlineIndex < chunk->nInlineFrames);
630 1367 : mjit::InlineFrame *frame = &chunk->inlineFrames()[inlined->inlineIndex];
631 1367 : JSScript *script = frame->fun->script();
632 1367 : if (script->compartment() != cx_->compartment)
633 0 : *(int *) 0x20 = 0;
634 1367 : if (ppc)
635 0 : *ppc = script->code + inlined->pcOffset;
636 1367 : return script;
637 : }
638 : #endif
639 :
640 5033512 : JSScript *script = fp->script();
641 5033512 : if (script->compartment() != cx_->compartment)
642 0 : *(int *) 0x30 = 0;
643 :
644 5033512 : if (ppc)
645 0 : *ppc = fp->pcQuadratic(*this);
646 5033512 : if (!script)
647 0 : *(int *) 0x40 = 0;
648 5033512 : return script;
649 : }
650 :
651 : inline JSObject *
652 37458477 : ContextStack::currentScriptedScopeChain() const
653 : {
654 37458477 : return &fp()->scopeChain();
655 : }
656 :
657 : } /* namespace js */
658 : #endif /* Stack_inl_h__ */
|