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 */
106 args
.nactual
= argsObj().getArgsInitialLength();
108 JS_ASSERT(!(flags_
& ~(JSFRAME_FUNCTION
|
109 JSFRAME_OVERFLOW_ARGS
|
110 JSFRAME_UNDERFLOW_ARGS
|
111 JSFRAME_HAS_CALL_OBJ
|
112 JSFRAME_HAS_ARGS_OBJ
|
113 JSFRAME_OVERRIDE_ARGS
|
116 JSFRAME_HAS_SCOPECHAIN
|
117 JSFRAME_HAS_ANNOTATION
|
118 JSFRAME_FINISHED_IN_INTERPRETER
)));
119 flags_
&= JSFRAME_FUNCTION
|
120 JSFRAME_OVERFLOW_ARGS
|
122 JSFRAME_UNDERFLOW_ARGS
;
124 JS_ASSERT_IF(!hasCallObj(), scopeChain_
== calleeValue().toObject().getParent());
125 JS_ASSERT_IF(hasCallObj(), scopeChain_
== callObj().getParent());
127 scopeChain_
= callObj().getParent();
129 JS_ASSERT(exec
.fun
== calleeValue().toObject().getFunctionPrivate());
130 JS_ASSERT(!hasImacropc());
131 JS_ASSERT(!hasHookData());
132 JS_ASSERT(annotation() == NULL
);
133 JS_ASSERT(!hasCallObj());
137 JSStackFrame::initCallFrameCallerHalf(JSContext
*cx
, uint32 flagsArg
,
140 JS_ASSERT((flagsArg
& ~(JSFRAME_CONSTRUCTING
|
142 JSFRAME_OVERFLOW_ARGS
|
143 JSFRAME_UNDERFLOW_ARGS
)) == 0);
145 flags_
= JSFRAME_FUNCTION
| flagsArg
;
146 prev_
= cx
->regs
->fp
;
151 * The "early prologue" refers to the members that are stored for the benefit
152 * of slow paths before initializing the rest of the members.
155 JSStackFrame::initCallFrameEarlyPrologue(JSFunction
*fun
, uint32 nactual
)
158 if (flags_
& (JSFRAME_OVERFLOW_ARGS
| JSFRAME_UNDERFLOW_ARGS
))
159 args
.nactual
= nactual
;
163 * The "late prologue" refers to the members that are stored after having
164 * checked for stack overflow and formal/actual arg mismatch.
167 JSStackFrame::initCallFrameLatePrologue()
169 SetValueRangeToUndefined(slots(), script()->nfixed
);
173 JSStackFrame::initEvalFrame(JSContext
*cx
, JSScript
*script
, JSStackFrame
*prev
, uint32 flagsArg
)
175 JS_ASSERT(flagsArg
& JSFRAME_EVAL
);
176 JS_ASSERT((flagsArg
& ~(JSFRAME_EVAL
| JSFRAME_DEBUGGER
)) == 0);
177 JS_ASSERT(prev
->flags_
& (JSFRAME_FUNCTION
| JSFRAME_GLOBAL
));
179 /* Copy (callee, thisv). */
180 js::Value
*dstvp
= (js::Value
*)this - 2;
181 js::Value
*srcvp
= prev
->flags_
& (JSFRAME_GLOBAL
| JSFRAME_EVAL
)
182 ? (js::Value
*)prev
- 2
183 : prev
->formalArgs() - 2;
186 JS_ASSERT_IF(prev
->flags_
& JSFRAME_FUNCTION
,
187 dstvp
[0].toObject().isFunction());
189 /* Initialize stack frame members. */
190 flags_
= flagsArg
| JSFRAME_HAS_PREVPC
| JSFRAME_HAS_SCOPECHAIN
|
191 (prev
->flags_
& (JSFRAME_FUNCTION
| JSFRAME_GLOBAL
| JSFRAME_HAS_CALL_OBJ
));
192 if (isFunctionFrame()) {
194 args
.script
= script
;
196 exec
.script
= script
;
199 scopeChain_
= &prev
->scopeChain();
200 JS_ASSERT_IF(isFunctionFrame(), &callObj() == &prev
->callObj());
203 prevpc_
= prev
->pc(cx
);
204 JS_ASSERT(!hasImacropc());
205 JS_ASSERT(!hasHookData());
206 setAnnotation(prev
->annotation());
210 JSStackFrame::initGlobalFrame(JSScript
*script
, JSObject
&chain
, uint32 flagsArg
)
212 JS_ASSERT((flagsArg
& ~(JSFRAME_EVAL
| JSFRAME_DEBUGGER
)) == 0);
214 /* Initialize (callee, thisv). */
215 js::Value
*vp
= (js::Value
*)this - 2;
216 vp
[0].setUndefined();
217 vp
[1].setUndefined(); /* Set after frame pushed using thisObject */
219 /* Initialize stack frame members. */
220 flags_
= flagsArg
| JSFRAME_GLOBAL
| JSFRAME_HAS_PREVPC
| JSFRAME_HAS_SCOPECHAIN
;
221 exec
.script
= script
;
222 args
.script
= (JSScript
*)0xbad;
223 scopeChain_
= &chain
;
225 JS_ASSERT(!hasImacropc());
226 JS_ASSERT(!hasHookData());
227 JS_ASSERT(annotation() == NULL
);
231 JSStackFrame::initDummyFrame(JSContext
*cx
, JSObject
&chain
)
234 flags_
= JSFRAME_DUMMY
| JSFRAME_HAS_PREVPC
| JSFRAME_HAS_SCOPECHAIN
;
237 setScopeChainNoCallObj(chain
);
241 JSStackFrame::stealFrameAndSlots(js::Value
*vp
, JSStackFrame
*otherfp
,
242 js::Value
*othervp
, js::Value
*othersp
)
244 JS_ASSERT(vp
== (js::Value
*)this - (otherfp
->formalArgsEnd() - othervp
));
245 JS_ASSERT(othervp
== otherfp
->actualArgs() - 2);
246 JS_ASSERT(othersp
>= otherfp
->slots());
247 JS_ASSERT(othersp
<= otherfp
->base() + otherfp
->numSlots());
249 PodCopy(vp
, othervp
, othersp
- othervp
);
250 JS_ASSERT(vp
== this->actualArgs() - 2);
252 /* Catch bad-touching of non-canonical args (e.g., generator_trace). */
253 if (otherfp
->hasOverflowArgs())
254 Debug_SetValueRangeToCrashOnTouch(othervp
, othervp
+ 2 + otherfp
->numFormalArgs());
257 * Repoint Call, Arguments, Block and With objects to the new live frame.
258 * Call and Arguments are done directly because we have pointers to them.
259 * Block and With objects are done indirectly through 'liveFrame'. See
260 * js_LiveFrameToFloating comment in jsiter.h.
263 callObj().setPrivate(this);
264 otherfp
->flags_
&= ~JSFRAME_HAS_CALL_OBJ
;
265 if (js_IsNamedLambda(fun())) {
266 JSObject
*env
= callObj().getParent();
267 JS_ASSERT(env
->getClass() == &js_DeclEnvClass
);
268 env
->setPrivate(this);
272 JSObject
&args
= argsObj();
273 JS_ASSERT(args
.isArguments());
274 if (args
.isNormalArguments())
275 args
.setPrivate(this);
277 JS_ASSERT(!args
.getPrivate());
278 otherfp
->flags_
&= ~JSFRAME_HAS_ARGS_OBJ
;
283 JSStackFrame::canonicalActualArg(uintN i
) const
285 if (i
< numFormalArgs())
287 JS_ASSERT(i
< numActualArgs());
288 return actualArgs()[i
];
293 JSStackFrame::forEachCanonicalActualArg(Op op
)
295 uintN nformal
= fun()->nargs
;
296 js::Value
*formals
= formalArgsEnd() - nformal
;
297 uintN nactual
= numActualArgs();
298 if (nactual
<= nformal
) {
300 js::Value
*actualsEnd
= formals
+ nactual
;
301 for (js::Value
*p
= formals
; p
!= actualsEnd
; ++p
, ++i
)
305 js::Value
*formalsEnd
= formalArgsEnd();
306 for (js::Value
*p
= formals
; p
!= formalsEnd
; ++p
, ++i
)
308 js::Value
*actuals
= formalsEnd
- (nactual
+ 2);
309 js::Value
*actualsEnd
= formals
- 2;
310 for (js::Value
*p
= actuals
; p
!= actualsEnd
; ++p
, ++i
)
317 JSStackFrame::forEachFormalArg(Op op
)
319 js::Value
*formals
= formalArgsEnd() - fun()->nargs
;
320 js::Value
*formalsEnd
= formalArgsEnd();
322 for (js::Value
*p
= formals
; p
!= formalsEnd
; ++p
, ++i
)
328 struct STATIC_SKIP_INFERENCE CopyNonHoleArgsTo
330 CopyNonHoleArgsTo(JSObject
*aobj
, Value
*dst
) : aobj(aobj
), dst(dst
) {}
333 void operator()(uintN argi
, Value
*src
) {
334 if (aobj
->getArgsElement(argi
).isMagic(JS_ARGS_HOLE
))
345 CopyTo(Value
*dst
) : dst(dst
) {}
346 void operator()(uintN
, Value
*src
) {
353 JS_ALWAYS_INLINE
void
354 JSStackFrame::clearMissingArgs()
356 if (flags_
& JSFRAME_UNDERFLOW_ARGS
)
357 SetValueRangeToUndefined(formalArgs() + numActualArgs(), formalArgsEnd());
361 JSStackFrame::computeThis(JSContext
*cx
)
363 js::Value
&thisv
= thisValue();
364 if (thisv
.isObject())
366 if (isFunctionFrame()) {
367 if (fun()->inStrictMode())
370 * Eval function frames have their own |this| slot, which is a copy of the function's
371 * |this| slot. If we lazily wrap a primitive |this| in an eval function frame, the
372 * eval's frame will get the wrapper, but the function's frame will not. To prevent
373 * this, we always wrap a function's |this| before pushing an eval frame, and should
374 * thus never see an unwrapped primitive in a non-strict eval function frame.
376 JS_ASSERT(!isEvalFrame());
378 if (!js::BoxThisForVp(cx
, &thisv
- 1))
384 JSStackFrame::varobj(js::StackSegment
*seg
) const
386 JS_ASSERT(seg
->contains(this));
387 return isFunctionFrame() ? callObj() : seg
->getInitialVarObj();
391 JSStackFrame::varobj(JSContext
*cx
) const
393 JS_ASSERT(cx
->activeSegment()->contains(this));
394 return isFunctionFrame() ? callObj() : cx
->activeSegment()->getInitialVarObj();
398 JSStackFrame::numActualArgs() const
400 JS_ASSERT(hasArgs());
401 if (JS_UNLIKELY(flags_
& (JSFRAME_OVERFLOW_ARGS
| JSFRAME_UNDERFLOW_ARGS
)))
402 return hasArgsObj() ? argsObj().getArgsInitialLength() : args
.nactual
;
403 return numFormalArgs();
407 JSStackFrame::actualArgs() const
409 JS_ASSERT(hasArgs());
410 js::Value
*argv
= formalArgs();
411 if (JS_UNLIKELY(flags_
& JSFRAME_OVERFLOW_ARGS
)) {
412 uintN nactual
= hasArgsObj() ? argsObj().getArgsInitialLength() : args
.nactual
;
413 return argv
- (2 + nactual
);
419 JSStackFrame::actualArgsEnd() const
421 JS_ASSERT(hasArgs());
422 if (JS_UNLIKELY(flags_
& JSFRAME_OVERFLOW_ARGS
))
423 return formalArgs() - 2;
424 return formalArgs() + numActualArgs();
428 JSStackFrame::setArgsObj(JSObject
&obj
)
430 JS_ASSERT_IF(hasArgsObj(), &obj
== args
.obj
);
431 JS_ASSERT_IF(!hasArgsObj(), numActualArgs() == obj
.getArgsInitialLength());
433 flags_
|= JSFRAME_HAS_ARGS_OBJ
;
437 JSStackFrame::clearArgsObj()
439 JS_ASSERT(hasArgsObj());
440 args
.nactual
= args
.obj
->getArgsInitialLength();
441 flags_
^= JSFRAME_HAS_ARGS_OBJ
;
445 JSStackFrame::setScopeChainNoCallObj(JSObject
&obj
)
448 JS_ASSERT(&obj
!= NULL
);
449 JSObject
*callObjBefore
= maybeCallObj();
450 if (!hasCallObj() && &scopeChain() != sInvalidScopeChain
) {
451 for (JSObject
*pobj
= &scopeChain(); pobj
; pobj
= pobj
->getParent())
452 JS_ASSERT_IF(pobj
->isCall(), pobj
->getPrivate() != this);
456 flags_
|= JSFRAME_HAS_SCOPECHAIN
;
457 JS_ASSERT(callObjBefore
== maybeCallObj());
461 JSStackFrame::setScopeChainAndCallObj(JSObject
&obj
)
463 JS_ASSERT(&obj
!= NULL
);
464 JS_ASSERT(!hasCallObj() && obj
.isCall() && obj
.getPrivate() == this);
466 flags_
|= JSFRAME_HAS_SCOPECHAIN
| JSFRAME_HAS_CALL_OBJ
;
470 JSStackFrame::clearCallObj()
472 JS_ASSERT(hasCallObj());
473 flags_
^= JSFRAME_HAS_CALL_OBJ
;
477 JSStackFrame::callObj() const
479 JS_ASSERT(hasCallObj());
480 JSObject
*pobj
= &scopeChain();
481 while (JS_UNLIKELY(pobj
->getClass() != &js_CallClass
)) {
482 JS_ASSERT(js_IsCacheableNonGlobalScope(pobj
) || pobj
->isWith());
483 pobj
= pobj
->getParent();
489 JSStackFrame::maybeCallObj() const
491 return hasCallObj() ? &callObj() : NULL
;
496 class AutoPreserveEnumerators
{
498 JSObject
*enumerators
;
501 AutoPreserveEnumerators(JSContext
*cx
) : cx(cx
), enumerators(cx
->enumerators
)
505 ~AutoPreserveEnumerators()
507 cx
->enumerators
= enumerators
;
511 struct AutoInterpPreparer
{
515 AutoInterpPreparer(JSContext
*cx
, JSScript
*script
)
516 : cx(cx
), script(script
)
521 ~AutoInterpPreparer()
528 PutActivationObjects(JSContext
*cx
, JSStackFrame
*fp
)
530 JS_ASSERT(fp
->isFunctionFrame() && !fp
->isEvalFrame());
532 /* The order is important as js_PutCallObject needs to access argsObj. */
533 if (fp
->hasCallObj()) {
534 js_PutCallObject(cx
, fp
);
535 } else if (fp
->hasArgsObj()) {
536 js_PutArgsObject(cx
, fp
);
540 class InvokeSessionGuard
542 InvokeArgsGuard args_
;
543 InvokeFrameGuard frame_
;
544 Value savedCallee_
, savedThis_
;
545 Value
*formals_
, *actuals_
;
551 bool optimized() const { return frame_
.pushed(); }
554 InvokeSessionGuard() : args_(), frame_() {}
555 ~InvokeSessionGuard() {}
557 bool start(JSContext
*cx
, const Value
&callee
, const Value
&thisv
, uintN argc
);
558 bool invoke(JSContext
*cx
) const;
560 bool started() const {
561 return args_
.pushed();
564 Value
&operator[](unsigned i
) const {
565 JS_ASSERT(i
< argc());
566 Value
&arg
= i
< nformals_
? formals_
[i
] : actuals_
[i
];
567 JS_ASSERT_IF(optimized(), &arg
== &frame_
.fp()->canonicalActualArg(i
));
568 JS_ASSERT_IF(!optimized(), &arg
== &args_
[i
]);
576 const Value
&rval() const {
577 return optimized() ? frame_
.fp()->returnValue() : args_
.rval();
582 InvokeSessionGuard::invoke(JSContext
*cx
) const
584 /* N.B. Must be kept in sync with Invoke */
586 /* Refer to canonical (callee, this) for optimized() sessions. */
587 formals_
[-2] = savedCallee_
;
588 formals_
[-1] = savedThis_
;
592 if (!optimized() || !(code
= script_
->getJIT(false /* !constructing */)->invokeEntry
))
596 return Invoke(cx
, args_
, 0);
598 /* Clear any garbage left from the last Invoke. */
599 JSStackFrame
*fp
= frame_
.fp();
600 fp
->clearMissingArgs();
601 fp
->resetInvokeCallFrame();
602 SetValueRangeToUndefined(fp
->slots(), script_
->nfixed
);
606 AutoPreserveEnumerators
preserve(cx
);
607 Probes::enterJSFun(cx
, fp
->fun(), script_
);
609 AutoInterpPreparer
prepareInterp(cx
, script_
);
610 ok
= mjit::EnterMethodJIT(cx
, fp
, code
, stackLimit_
);
611 cx
->regs
->pc
= stop_
;
613 cx
->regs
->pc
= script_
->code
;
614 ok
= Interpret(cx
, cx
->fp());
616 Probes::exitJSFun(cx
, fp
->fun(), script_
);
619 PutActivationObjects(cx
, fp
);
621 /* Don't clobber callee with rval; rval gets read from fp->rval. */
627 template<typename T
> class PrimitiveBehavior
{ };
630 class PrimitiveBehavior
<JSString
*> {
632 static inline bool isType(const Value
&v
) { return v
.isString(); }
633 static inline JSString
*extract(const Value
&v
) { return v
.toString(); }
634 static inline Class
*getClass() { return &js_StringClass
; }
638 class PrimitiveBehavior
<bool> {
640 static inline bool isType(const Value
&v
) { return v
.isBoolean(); }
641 static inline bool extract(const Value
&v
) { return v
.toBoolean(); }
642 static inline Class
*getClass() { return &js_BooleanClass
; }
646 class PrimitiveBehavior
<double> {
648 static inline bool isType(const Value
&v
) { return v
.isNumber(); }
649 static inline double extract(const Value
&v
) { return v
.toNumber(); }
650 static inline Class
*getClass() { return &js_NumberClass
; }
653 } // namespace detail
655 template <typename T
>
657 GetPrimitiveThis(JSContext
*cx
, Value
*vp
, T
*v
)
659 typedef detail::PrimitiveBehavior
<T
> Behavior
;
661 const Value
&thisv
= vp
[1];
662 if (Behavior::isType(thisv
)) {
663 *v
= Behavior::extract(thisv
);
667 if (thisv
.isObject() && thisv
.toObject().getClass() == Behavior::getClass()) {
668 *v
= Behavior::extract(thisv
.toObject().getPrimitiveThis());
672 ReportIncompatibleMethod(cx
, vp
, Behavior::getClass());
677 * Return an object on which we should look for the properties of |value|.
678 * This helps us implement the custom [[Get]] method that ES5's GetValue
679 * algorithm uses for primitive values, without actually constructing the
680 * temporary object that the specification does.
682 * For objects, return the object itself. For string, boolean, and number
683 * primitive values, return the appropriate constructor's prototype. For
684 * undefined and null, throw an error and return NULL, attributing the
685 * problem to the value at |spindex| on the stack.
687 JS_ALWAYS_INLINE JSObject
*
688 ValuePropertyBearer(JSContext
*cx
, const Value
&v
, int spindex
)
691 return &v
.toObject();
695 protoKey
= JSProto_String
;
696 } else if (v
.isNumber()) {
697 protoKey
= JSProto_Number
;
698 } else if (v
.isBoolean()) {
699 protoKey
= JSProto_Boolean
;
701 JS_ASSERT(v
.isNull() || v
.isUndefined());
702 js_ReportIsNullOrUndefined(cx
, spindex
, v
, NULL
);
707 if (!js_GetClassPrototype(cx
, NULL
, protoKey
, &pobj
))
713 ScriptEpilogue(JSContext
*cx
, JSStackFrame
*fp
, JSBool ok
)
715 if (!fp
->isExecuteFrame())
716 Probes::exitJSFun(cx
, fp
->maybeFun(), fp
->maybeScript());
718 JSInterpreterHook hook
=
719 fp
->isExecuteFrame() ? cx
->debugHooks
->executeHook
: cx
->debugHooks
->callHook
;
722 if (JS_UNLIKELY(hook
!= NULL
) && (hookData
= fp
->maybeHookData()))
723 hook(cx
, fp
, JS_FALSE
, &ok
, hookData
);
725 if (fp
->isEvalFrame()) {
727 * The parent (ancestor for nested eval) of a non-strict eval frame
728 * owns its activation objects. Strict mode eval frames own their own
729 * Call objects but never have an arguments object (the first non-eval
730 * parent frame has it).
732 if (fp
->script()->strictModeCode
) {
733 JS_ASSERT(!fp
->isYielding());
734 JS_ASSERT(!fp
->hasArgsObj());
735 JS_ASSERT(fp
->hasCallObj());
736 JS_ASSERT(fp
->callObj().callIsForEval());
737 js_PutCallObject(cx
, fp
);
741 * Otherwise only function frames have activation objects. A yielding
742 * frame's activation objects are transferred to the floating frame,
743 * stored in the generator, and thus need not be synced.
745 if (fp
->isFunctionFrame() && !fp
->isYielding()) {
746 JS_ASSERT_IF(fp
->hasCallObj(), !fp
->callObj().callIsForEval());
747 PutActivationObjects(cx
, fp
);
752 * If inline-constructing, replace primitive rval with the new object
753 * passed in via |this|, and instrument this constructor invocation.
755 if (fp
->isConstructing() && ok
) {
756 if (fp
->returnValue().isPrimitive())
757 fp
->setReturnValue(ObjectValue(fp
->constructorThis()));
758 JS_RUNTIME_METER(cx
->runtime
, constructs
);
766 #endif /* jsinterpinlines_h__ */