1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
17 * The Original Code is SpiderMonkey code.
19 * The Initial Developer of the Original Code is
20 * Mozilla Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 2010
22 * the Initial Developer. All Rights Reserved.
25 * Luke Wagner <lw@mozilla.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or 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.
39 * ***** END LICENSE BLOCK ***** */
41 #ifndef jsinterpinlines_h__
42 #define jsinterpinlines_h__
50 #include "methodjit/MethodJIT.h"
52 #include "jsfuninlines.h"
55 JSStackFrame::initPrev(JSContext *cx)
57 JS_ASSERT(flags_ & JSFRAME_HAS_PREVPC);
58 if (JSFrameRegs *regs = cx->regs) {
61 JS_ASSERT_IF(!prev_->isDummyFrame() && !prev_->hasImacropc(),
62 uint32(prevpc_ - prev_->script()->code) < prev_->script()->length);
66 prevpc_ = (jsbytecode *)0xbadc;
72 JSStackFrame::resetGeneratorPrev(JSContext *cx)
74 flags_ |= JSFRAME_HAS_PREVPC;
79 JSStackFrame::initCallFrame(JSContext *cx, JSObject &callee, JSFunction *fun,
80 uint32 nactual, uint32 flagsArg)
82 JS_ASSERT((flagsArg & ~(JSFRAME_CONSTRUCTING |
83 JSFRAME_OVERFLOW_ARGS |
84 JSFRAME_UNDERFLOW_ARGS)) == 0);
85 JS_ASSERT(fun == callee.getFunctionPrivate());
87 /* Initialize stack frame members. */
88 flags_ = JSFRAME_FUNCTION | JSFRAME_HAS_PREVPC | JSFRAME_HAS_SCOPECHAIN | flagsArg;
90 args.nactual = nactual; /* only need to write if over/under-flow */
91 scopeChain_ = callee.getParent();
93 JS_ASSERT(!hasImacropc());
94 JS_ASSERT(!hasHookData());
95 JS_ASSERT(annotation() == NULL);
97 JS_ASSERT(!hasCallObj());
101 JSStackFrame::resetInvokeCallFrame()
103 /* Undo changes to frame made during execution; see initCallFrame */
105 JS_ASSERT(!(flags_ & ~(JSFRAME_FUNCTION |
106 JSFRAME_OVERFLOW_ARGS |
107 JSFRAME_UNDERFLOW_ARGS |
108 JSFRAME_OVERRIDE_ARGS |
111 JSFRAME_HAS_SCOPECHAIN |
112 JSFRAME_HAS_ANNOTATION |
113 JSFRAME_FINISHED_IN_INTERPRETER)));
114 flags_ &= JSFRAME_FUNCTION |
115 JSFRAME_OVERFLOW_ARGS |
117 JSFRAME_UNDERFLOW_ARGS;
119 JS_ASSERT(exec.fun == callee().getFunctionPrivate());
120 scopeChain_ = callee().getParent();
124 JSStackFrame::initCallFrameCallerHalf(JSContext *cx, uint32 flagsArg,
127 JS_ASSERT((flagsArg & ~(JSFRAME_CONSTRUCTING |
129 JSFRAME_OVERFLOW_ARGS |
130 JSFRAME_UNDERFLOW_ARGS)) == 0);
132 flags_ = JSFRAME_FUNCTION | flagsArg;
133 prev_ = cx->regs->fp;
138 * The "early prologue" refers to the members that are stored for the benefit
139 * of slow paths before initializing the rest of the members.
142 JSStackFrame::initCallFrameEarlyPrologue(JSFunction *fun, uint32 nactual)
145 if (flags_ & (JSFRAME_OVERFLOW_ARGS | JSFRAME_UNDERFLOW_ARGS))
146 args.nactual = nactual;
150 * The "late prologue" refers to the members that are stored after having
151 * checked for stack overflow and formal/actual arg mismatch.
154 JSStackFrame::initCallFrameLatePrologue()
156 SetValueRangeToUndefined(slots(), script()->nfixed);
160 JSStackFrame::initEvalFrame(JSContext *cx, JSScript *script, JSStackFrame *prev, uint32 flagsArg)
162 JS_ASSERT(flagsArg & JSFRAME_EVAL);
163 JS_ASSERT((flagsArg & ~(JSFRAME_EVAL | JSFRAME_DEBUGGER)) == 0);
164 JS_ASSERT(prev->flags_ & (JSFRAME_FUNCTION | JSFRAME_GLOBAL));
166 /* Copy (callee, thisv). */
167 js::Value *dstvp = (js::Value *)this - 2;
168 js::Value *srcvp = prev->flags_ & (JSFRAME_GLOBAL | JSFRAME_EVAL)
169 ? (js::Value *)prev - 2
170 : prev->formalArgs() - 2;
173 JS_ASSERT_IF(prev->flags_ & JSFRAME_FUNCTION,
174 dstvp[0].toObject().isFunction());
176 /* Initialize stack frame members. */
177 flags_ = flagsArg | JSFRAME_HAS_PREVPC | JSFRAME_HAS_SCOPECHAIN |
178 (prev->flags_ & (JSFRAME_FUNCTION | JSFRAME_GLOBAL | JSFRAME_HAS_CALL_OBJ));
179 if (isFunctionFrame()) {
181 args.script = script;
183 exec.script = script;
186 scopeChain_ = &prev->scopeChain();
187 JS_ASSERT_IF(isFunctionFrame(), &callObj() == &prev->callObj());
190 prevpc_ = prev->pc(cx);
191 JS_ASSERT(!hasImacropc());
192 JS_ASSERT(!hasHookData());
193 setAnnotation(prev->annotation());
197 JSStackFrame::initGlobalFrame(JSScript *script, JSObject &chain, uint32 flagsArg)
199 JS_ASSERT((flagsArg & ~(JSFRAME_EVAL | JSFRAME_DEBUGGER)) == 0);
201 /* Initialize (callee, thisv). */
202 js::Value *vp = (js::Value *)this - 2;
203 vp[0].setUndefined();
204 vp[1].setUndefined(); /* Set after frame pushed using thisObject */
206 /* Initialize stack frame members. */
207 flags_ = flagsArg | JSFRAME_GLOBAL | JSFRAME_HAS_PREVPC | JSFRAME_HAS_SCOPECHAIN;
208 exec.script = script;
209 args.script = (JSScript *)0xbad;
210 scopeChain_ = &chain;
212 JS_ASSERT(!hasImacropc());
213 JS_ASSERT(!hasHookData());
214 JS_ASSERT(annotation() == NULL);
218 JSStackFrame::initDummyFrame(JSContext *cx, JSObject &chain)
221 flags_ = JSFRAME_DUMMY | JSFRAME_HAS_PREVPC | JSFRAME_HAS_SCOPECHAIN;
224 setScopeChainNoCallObj(chain);
228 JSStackFrame::stealFrameAndSlots(js::Value *vp, JSStackFrame *otherfp,
229 js::Value *othervp, js::Value *othersp)
231 JS_ASSERT(vp == (js::Value *)this - (otherfp->formalArgsEnd() - othervp));
232 JS_ASSERT(othervp == otherfp->actualArgs() - 2);
233 JS_ASSERT(othersp >= otherfp->slots());
234 JS_ASSERT(othersp <= otherfp->base() + otherfp->numSlots());
236 PodCopy(vp, othervp, othersp - othervp);
237 JS_ASSERT(vp == this->actualArgs() - 2);
239 /* Catch bad-touching of non-canonical args (e.g., generator_trace). */
240 if (otherfp->hasOverflowArgs())
241 Debug_SetValueRangeToCrashOnTouch(othervp, othervp + 2 + otherfp->numFormalArgs());
244 * Repoint Call, Arguments, Block and With objects to the new live frame.
245 * Call and Arguments are done directly because we have pointers to them.
246 * Block and With objects are done indirectly through 'liveFrame'. See
247 * js_LiveFrameToFloating comment in jsiter.h.
250 callObj().setPrivate(this);
251 otherfp->flags_ &= ~JSFRAME_HAS_CALL_OBJ;
252 if (js_IsNamedLambda(fun())) {
253 JSObject *env = callObj().getParent();
254 JS_ASSERT(env->getClass() == &js_DeclEnvClass);
255 env->setPrivate(this);
259 JSObject &args = argsObj();
260 JS_ASSERT(args.isArguments());
261 if (args.isNormalArguments())
262 args.setPrivate(this);
264 JS_ASSERT(!args.getPrivate());
265 otherfp->flags_ &= ~JSFRAME_HAS_ARGS_OBJ;
270 JSStackFrame::canonicalActualArg(uintN i) const
272 if (i < numFormalArgs())
274 JS_ASSERT(i < numActualArgs());
275 return actualArgs()[i];
280 JSStackFrame::forEachCanonicalActualArg(Op op)
282 uintN nformal = fun()->nargs;
283 js::Value *formals = formalArgsEnd() - nformal;
284 uintN nactual = numActualArgs();
285 if (nactual <= nformal) {
287 js::Value *actualsEnd = formals + nactual;
288 for (js::Value *p = formals; p != actualsEnd; ++p, ++i)
292 js::Value *formalsEnd = formalArgsEnd();
293 for (js::Value *p = formals; p != formalsEnd; ++p, ++i)
295 js::Value *actuals = formalsEnd - (nactual + 2);
296 js::Value *actualsEnd = formals - 2;
297 for (js::Value *p = actuals; p != actualsEnd; ++p, ++i)
304 JSStackFrame::forEachFormalArg(Op op)
306 js::Value *formals = formalArgsEnd() - fun()->nargs;
307 js::Value *formalsEnd = formalArgsEnd();
309 for (js::Value *p = formals; p != formalsEnd; ++p, ++i)
315 struct STATIC_SKIP_INFERENCE CopyNonHoleArgsTo
317 CopyNonHoleArgsTo(JSObject *aobj, Value *dst) : aobj(aobj), dst(dst) {}
320 void operator()(uintN argi, Value *src) {
321 if (aobj->getArgsElement(argi).isMagic(JS_ARGS_HOLE))
332 CopyTo(Value *dst) : dst(dst) {}
333 void operator()(uintN, Value *src) {
340 JS_ALWAYS_INLINE void
341 JSStackFrame::clearMissingArgs()
343 if (flags_ & JSFRAME_UNDERFLOW_ARGS)
344 SetValueRangeToUndefined(formalArgs() + numActualArgs(), formalArgsEnd());
348 JSStackFrame::computeThis(JSContext *cx)
350 js::Value &thisv = thisValue();
351 if (thisv.isObject())
353 if (isFunctionFrame()) {
354 if (fun()->inStrictMode())
357 * Eval function frames have their own |this| slot, which is a copy of the function's
358 * |this| slot. If we lazily wrap a primitive |this| in an eval function frame, the
359 * eval's frame will get the wrapper, but the function's frame will not. To prevent
360 * this, we always wrap a function's |this| before pushing an eval frame, and should
361 * thus never see an unwrapped primitive in a non-strict eval function frame.
363 JS_ASSERT(!isEvalFrame());
365 if (!js::BoxThisForVp(cx, &thisv - 1))
371 JSStackFrame::varobj(js::StackSegment *seg) const
373 JS_ASSERT(seg->contains(this));
374 return isFunctionFrame() ? callObj() : seg->getInitialVarObj();
378 JSStackFrame::varobj(JSContext *cx) const
380 JS_ASSERT(cx->activeSegment()->contains(this));
381 return isFunctionFrame() ? callObj() : cx->activeSegment()->getInitialVarObj();
385 JSStackFrame::numActualArgs() const
387 JS_ASSERT(hasArgs());
388 if (JS_UNLIKELY(flags_ & (JSFRAME_OVERFLOW_ARGS | JSFRAME_UNDERFLOW_ARGS)))
389 return hasArgsObj() ? argsObj().getArgsInitialLength() : args.nactual;
390 return numFormalArgs();
394 JSStackFrame::actualArgs() const
396 JS_ASSERT(hasArgs());
397 js::Value *argv = formalArgs();
398 if (JS_UNLIKELY(flags_ & JSFRAME_OVERFLOW_ARGS)) {
399 uintN nactual = hasArgsObj() ? argsObj().getArgsInitialLength() : args.nactual;
400 return argv - (2 + nactual);
406 JSStackFrame::actualArgsEnd() const
408 JS_ASSERT(hasArgs());
409 if (JS_UNLIKELY(flags_ & JSFRAME_OVERFLOW_ARGS))
410 return formalArgs() - 2;
411 return formalArgs() + numActualArgs();
415 JSStackFrame::setArgsObj(JSObject &obj)
417 JS_ASSERT_IF(hasArgsObj(), &obj == args.obj);
418 JS_ASSERT_IF(!hasArgsObj(), numActualArgs() == obj.getArgsInitialLength());
420 flags_ |= JSFRAME_HAS_ARGS_OBJ;
424 JSStackFrame::clearArgsObj()
426 JS_ASSERT(hasArgsObj());
427 args.nactual = args.obj->getArgsInitialLength();
428 flags_ ^= JSFRAME_HAS_ARGS_OBJ;
432 JSStackFrame::setScopeChainNoCallObj(JSObject &obj)
435 JS_ASSERT(&obj != NULL);
436 JSObject *callObjBefore = maybeCallObj();
437 if (!hasCallObj() && &scopeChain() != sInvalidScopeChain) {
438 for (JSObject *pobj = &scopeChain(); pobj; pobj = pobj->getParent())
439 JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
443 flags_ |= JSFRAME_HAS_SCOPECHAIN;
444 JS_ASSERT(callObjBefore == maybeCallObj());
448 JSStackFrame::setScopeChainAndCallObj(JSObject &obj)
450 JS_ASSERT(&obj != NULL);
451 JS_ASSERT(!hasCallObj() && obj.isCall() && obj.getPrivate() == this);
453 flags_ |= JSFRAME_HAS_SCOPECHAIN | JSFRAME_HAS_CALL_OBJ;
457 JSStackFrame::clearCallObj()
459 JS_ASSERT(hasCallObj());
460 flags_ ^= JSFRAME_HAS_CALL_OBJ;
464 JSStackFrame::callObj() const
466 JS_ASSERT(hasCallObj());
467 JSObject *pobj = &scopeChain();
468 while (JS_UNLIKELY(pobj->getClass() != &js_CallClass)) {
469 JS_ASSERT(js::IsCacheableNonGlobalScope(pobj) || pobj->isWith());
470 pobj = pobj->getParent();
476 JSStackFrame::maybeCallObj() const
478 return hasCallObj() ? &callObj() : NULL;
483 class AutoPreserveEnumerators {
485 JSObject *enumerators;
488 AutoPreserveEnumerators(JSContext *cx) : cx(cx), enumerators(cx->enumerators)
492 ~AutoPreserveEnumerators()
494 cx->enumerators = enumerators;
498 struct AutoInterpPreparer {
502 AutoInterpPreparer(JSContext *cx, JSScript *script)
503 : cx(cx), script(script)
508 ~AutoInterpPreparer()
515 PutActivationObjects(JSContext *cx, JSStackFrame *fp)
517 JS_ASSERT(!fp->isYielding());
518 JS_ASSERT(!fp->isEvalFrame() || fp->script()->strictModeCode);
520 /* The order is important as js_PutCallObject needs to access argsObj. */
521 if (fp->hasCallObj()) {
522 js_PutCallObject(cx, fp);
523 } else if (fp->hasArgsObj()) {
524 js_PutArgsObject(cx, fp);
529 * FIXME Remove with bug 635811
531 * NB: a non-strict eval frame aliases its non-eval-parent's call/args object.
534 PutOwnedActivationObjects(JSContext *cx, JSStackFrame *fp)
536 JS_ASSERT(!fp->isYielding());
537 if (!fp->isEvalFrame() || fp->script()->strictModeCode)
538 PutActivationObjects(cx, fp);
541 class InvokeSessionGuard
543 InvokeArgsGuard args_;
544 InvokeFrameGuard frame_;
545 Value savedCallee_, savedThis_;
546 Value *formals_, *actuals_;
552 bool optimized() const { return frame_.pushed(); }
555 InvokeSessionGuard() : args_(), frame_() {}
556 inline ~InvokeSessionGuard();
558 bool start(JSContext *cx, const Value &callee, const Value &thisv, uintN argc);
559 bool invoke(JSContext *cx) const;
561 bool started() const {
562 return args_.pushed();
565 Value &operator[](unsigned i) const {
566 JS_ASSERT(i < argc());
567 Value &arg = i < nformals_ ? formals_[i] : actuals_[i];
568 JS_ASSERT_IF(optimized(), &arg == &frame_.fp()->canonicalActualArg(i));
569 JS_ASSERT_IF(!optimized(), &arg == &args_[i]);
577 const Value &rval() const {
578 return optimized() ? frame_.fp()->returnValue() : args_.rval();
583 InvokeSessionGuard::~InvokeSessionGuard()
586 PutActivationObjects(frame_.pushedFrameContext(), frame_.fp());
590 InvokeSessionGuard::invoke(JSContext *cx) const
592 /* N.B. Must be kept in sync with Invoke */
594 /* Refer to canonical (callee, this) for optimized() sessions. */
595 formals_[-2] = savedCallee_;
596 formals_[-1] = savedThis_;
600 if (!optimized() || !(code = script_->getJIT(false /* !constructing */)->invokeEntry))
604 return Invoke(cx, args_, 0);
606 /* Clear any garbage left from the last Invoke. */
607 JSStackFrame *fp = frame_.fp();
608 fp->clearMissingArgs();
609 PutActivationObjects(cx, frame_.fp());
610 fp->resetInvokeCallFrame();
611 SetValueRangeToUndefined(fp->slots(), script_->nfixed);
615 AutoPreserveEnumerators preserve(cx);
616 Probes::enterJSFun(cx, fp->fun(), script_);
618 AutoInterpPreparer prepareInterp(cx, script_);
619 ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_);
620 cx->regs->pc = stop_;
622 cx->regs->pc = script_->code;
623 ok = Interpret(cx, cx->fp());
625 Probes::exitJSFun(cx, fp->fun(), script_);
628 /* Don't clobber callee with rval; rval gets read from fp->rval. */
634 template<typename T> class PrimitiveBehavior { };
637 class PrimitiveBehavior<JSString *> {
639 static inline bool isType(const Value &v) { return v.isString(); }
640 static inline JSString *extract(const Value &v) { return v.toString(); }
641 static inline Class *getClass() { return &js_StringClass; }
645 class PrimitiveBehavior<bool> {
647 static inline bool isType(const Value &v) { return v.isBoolean(); }
648 static inline bool extract(const Value &v) { return v.toBoolean(); }
649 static inline Class *getClass() { return &js_BooleanClass; }
653 class PrimitiveBehavior<double> {
655 static inline bool isType(const Value &v) { return v.isNumber(); }
656 static inline double extract(const Value &v) { return v.toNumber(); }
657 static inline Class *getClass() { return &js_NumberClass; }
660 } // namespace detail
663 * Compute the implicit |this| parameter for a call expression where the callee
664 * is an unqualified name reference.
666 * We can avoid computing |this| eagerly and push the implicit callee-coerced
667 * |this| value, undefined, according to this decision tree:
669 * 1. If the called value, funval, is not an object, bind |this| to undefined.
671 * 2. The nominal |this|, obj, has one of Block, Call, or DeclEnv class (this
672 * is what IsCacheableNonGlobalScope tests). Such objects-as-scopes must be
675 * 3. obj is a global. There are several sub-cases:
677 * a) obj is a proxy: we try unwrapping it (see jswrapper.cpp) in order to find
678 * a function object inside. If the proxy is not a wrapper, or else it wraps
679 * a non-function, then bind |this| to undefined per ES5-strict/Harmony.
681 * [Else fall through with callee pointing to an unwrapped function object.]
683 * b) If callee is a function (after unwrapping if necessary), check whether it
684 * is interpreted and in strict mode. If so, then bind |this| to undefined
687 * c) Now check that callee is scoped by the same global object as the object
688 * in which its unqualified name was bound as a property. ES1-3 bound |this|
689 * to the name's "Reference base object", which in the context of multiple
690 * global objects may not be the callee's global. If globals match, bind
691 * |this| to undefined.
693 * This is a backward compatibility measure; see bug 634590.
695 * 4. Finally, obj is neither a declarative scope object to be censored, nor a
696 * global where the callee requires no backward-compatible special handling
697 * or future-proofing based on (explicit or imputed by Harmony status in the
698 * proxy case) strict mode opt-in. Bind |this| to obj->thisObject().
700 * We set *vp to undefined early to reduce code size and bias this code for the
701 * common and future-friendly cases.
704 ComputeImplicitThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
708 if (!funval.isObject())
711 if (!obj->isGlobal()) {
712 if (IsCacheableNonGlobalScope(obj))
715 JSObject *callee = &funval.toObject();
717 if (callee->isProxy()) {
718 callee = callee->unwrap();
719 if (!callee->isFunction())
720 return true; // treat any non-wrapped-function proxy as strict
722 if (callee->isFunction()) {
723 JSFunction *fun = callee->getFunctionPrivate();
724 if (fun->isInterpreted() && fun->inStrictMode())
727 if (callee->getGlobal() == cx->fp()->scopeChain().getGlobal())
731 obj = obj->thisObject(cx);
739 template <typename T>
741 GetPrimitiveThis(JSContext *cx, Value *vp, T *v)
743 typedef detail::PrimitiveBehavior<T> Behavior;
745 const Value &thisv = vp[1];
746 if (Behavior::isType(thisv)) {
747 *v = Behavior::extract(thisv);
751 if (thisv.isObject() && thisv.toObject().getClass() == Behavior::getClass()) {
752 *v = Behavior::extract(thisv.toObject().getPrimitiveThis());
756 ReportIncompatibleMethod(cx, vp, Behavior::getClass());
761 * Return an object on which we should look for the properties of |value|.
762 * This helps us implement the custom [[Get]] method that ES5's GetValue
763 * algorithm uses for primitive values, without actually constructing the
764 * temporary object that the specification does.
766 * For objects, return the object itself. For string, boolean, and number
767 * primitive values, return the appropriate constructor's prototype. For
768 * undefined and null, throw an error and return NULL, attributing the
769 * problem to the value at |spindex| on the stack.
771 JS_ALWAYS_INLINE JSObject *
772 ValuePropertyBearer(JSContext *cx, const Value &v, int spindex)
775 return &v.toObject();
779 protoKey = JSProto_String;
780 } else if (v.isNumber()) {
781 protoKey = JSProto_Number;
782 } else if (v.isBoolean()) {
783 protoKey = JSProto_Boolean;
785 JS_ASSERT(v.isNull() || v.isUndefined());
786 js_ReportIsNullOrUndefined(cx, spindex, v, NULL);
791 if (!js_GetClassPrototype(cx, NULL, protoKey, &pobj))
797 ScriptEpilogue(JSContext *cx, JSStackFrame *fp, JSBool ok)
799 if (!fp->isExecuteFrame())
800 Probes::exitJSFun(cx, fp->maybeFun(), fp->maybeScript());
802 JSInterpreterHook hook =
803 fp->isExecuteFrame() ? cx->debugHooks->executeHook : cx->debugHooks->callHook;
806 if (JS_UNLIKELY(hook != NULL) && (hookData = fp->maybeHookData()))
807 hook(cx, fp, JS_FALSE, &ok, hookData);
809 if (fp->isEvalFrame()) {
811 * The parent (ancestor for nested eval) of a non-strict eval frame
812 * owns its activation objects. Strict mode eval frames own their own
813 * Call objects but never have an arguments object (the first non-eval
814 * parent frame has it).
816 if (fp->script()->strictModeCode) {
817 JS_ASSERT(!fp->isYielding());
818 JS_ASSERT(!fp->hasArgsObj());
819 JS_ASSERT(fp->hasCallObj());
820 JS_ASSERT(fp->callObj().callIsForEval());
821 js_PutCallObject(cx, fp);
825 * Otherwise only function frames have activation objects. A yielding
826 * frame's activation objects are transferred to the floating frame,
827 * stored in the generator, and thus need not be synced.
829 if (fp->isFunctionFrame() && !fp->isYielding()) {
830 JS_ASSERT_IF(fp->hasCallObj(), !fp->callObj().callIsForEval());
831 PutActivationObjects(cx, fp);
836 * If inline-constructing, replace primitive rval with the new object
837 * passed in via |this|, and instrument this constructor invocation.
839 if (fp->isConstructing() && ok) {
840 if (fp->returnValue().isPrimitive())
841 fp->setReturnValue(ObjectValue(fp->constructorThis()));
842 JS_RUNTIME_METER(cx->runtime, constructs);
850 #endif /* jsinterpinlines_h__ */