gecko/js/src/jsinterp.h

497 lines
17 KiB
C
Raw Normal View History

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=78:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef jsinterp_h___
#define jsinterp_h___
/*
* JS interpreter interface.
*/
#include "jsprvtd.h"
#include "jspubtd.h"
#include "jsfun.h"
#include "jsopcode.h"
#include "jsscript.h"
typedef struct JSFrameRegs {
jsbytecode *pc; /* program counter */
2010-05-10 22:01:31 -07:00
js::Value *sp; /* stack pointer */
} JSFrameRegs;
2010-03-03 17:52:26 -08:00
/* JS stack frame flags. */
2010-03-03 17:52:26 -08:00
enum JSFrameFlags {
JSFRAME_CONSTRUCTING = 0x01, /* frame is for a constructor invocation */
JSFRAME_COMPUTED_THIS = 0x02, /* frame.thisv was computed already and
2010-05-11 00:41:08 -07:00
JSVAL_IS_OBJECT(thisv) */
2010-03-03 17:52:26 -08:00
JSFRAME_ASSIGNING = 0x04, /* a complex (not simplex JOF_ASSIGNING) op
2010-05-11 00:41:08 -07:00
is currently assigning to a property */
2010-03-03 17:52:26 -08:00
JSFRAME_DEBUGGER = 0x08, /* frame for JS_EvaluateInStackFrame */
JSFRAME_EVAL = 0x10, /* frame for obj_eval */
JSFRAME_FLOATING_GENERATOR = 0x20, /* frame copy stored in a generator obj */
JSFRAME_YIELDING = 0x40, /* js_Interpret dispatched JSOP_YIELD */
JSFRAME_ITERATOR = 0x80, /* trying to get an iterator for for-in */
JSFRAME_GENERATOR = 0x200, /* frame belongs to generator-iterator */
JSFRAME_OVERRIDE_ARGS = 0x400, /* overridden arguments local variable */
JSFRAME_SPECIAL = JSFRAME_DEBUGGER | JSFRAME_EVAL
};
/*
* JS stack frame, may be allocated on the C stack by native callers. Always
* allocated on cx->stackPool for calls from the interpreter to an interpreted
* function.
*
* NB: This struct is manually initialized in jsinterp.c and jsiter.c. If you
2010-03-03 18:10:13 -08:00
* add new members, update both files.
*/
2010-03-03 17:52:26 -08:00
struct JSStackFrame
{
2010-05-10 22:01:31 -07:00
/* N.B. alignment (TODO: remove these members) */
js::Value thisv; /* "this" pointer if in method */
js::Value rval; /* function return value */
2010-03-03 17:52:26 -08:00
jsbytecode *imacpc; /* null or interpreter macro call pc */
JSObject *callobj; /* lazily created Call object */
2010-05-10 22:01:31 -07:00
JSObject *argsobj; /* lazily created arguments object */
2010-03-03 17:52:26 -08:00
JSScript *script; /* script being interpreted */
JSFunction *fun; /* function being called or null */
uintN argc; /* actual argument count */
2010-05-10 22:01:31 -07:00
js::Value *argv; /* base of argument stack slots */
2010-03-03 17:52:26 -08:00
void *annotation; /* used by Java security */
/* Maintained by StackSpace operations */
JSStackFrame *down; /* previous frame, part of
stack layout invariant */
2010-03-03 18:10:13 -08:00
jsbytecode *savedPC; /* only valid if cx->fp != this */
#ifdef DEBUG
static jsbytecode *const sInvalidPC;
#endif
Bug 480132: Clone lexical blocks only when needed. r=igor Terminology: A "script block" is an object of class Block allocated by the byte compiler and associated with a script. Script blocks are never modified, and may be used as a prototype for a "closure block": A "closure block" is an object of class Block that holds variables that have been closed over (although we actually leave the variables on the stack until we leave their dynamic scope). A closure block is a clone of a script block (its prototype is a script block). Adjust the meanings of fp->blockChain and fp->scopeChain: fp->blockChain is always the innermost script block in whose static scope we're executing. fp->scopeChain is the current scope chain, including 'call' objects and closure blocks for those function calls and blocks in whose static scope we are currently executing, and 'with' objects for with statements; the chain is typically terminated by a global object. However, as an optimization, the young end of the chain omits block objects we have not yet needed to clone. Closures need fully reified scope chains, so have js_GetScopeChain reify any closure blocks missing from the young end of fp->scopeChain by cloning script blocks as needed from fp->blockChain. Thus, if we never actually close over a particular block, we never place a closure block for it on fp->scopeChain. Have JSOP_ENTERBLOCK and JSOP_LEAVEBLOCK always keep fp->blockChain current. When JSOP_LEAVEBLOCK pops a block from fp->blockChain that has been cloned on fp->scopeChain, pop fp->scopeChain as well. Remove the JSFRAME_POP_BLOCKS flag, as it is no longer needed. Ensure that the JIT won't have to create closure blocks or call js_PutBlockObject; it can't handle those things yet. Note our current script block when we begin recording. Abort recording if we leave that block; we can't tell in advance whether it will need to be "put" in future trace invocations. Leave trace if we call js_GetScopeChain while in the static scope of lexical blocks. Remove JIT tests based on JSFRAME_POP_BLOCKS. Verify that generators capture the correct value for blockChain. Add a constructor to JSAutoTempValueRooter for rooting JSObject pointers.
2009-03-16 09:55:06 -07:00
/*
* We can't determine in advance which local variables can live on
* the stack and be freed when their dynamic scope ends, and which
* will be closed over and need to live in the heap. So we place
* variables on the stack initially, note when they are closed
* over, and copy those that are out to the heap when we leave
* their dynamic scope.
*
Bug 480132: Clone lexical blocks only when needed. r=igor Terminology: A "script block" is an object of class Block allocated by the byte compiler and associated with a script. Script blocks are never modified, and may be used as a prototype for a "closure block": A "closure block" is an object of class Block that holds variables that have been closed over (although we actually leave the variables on the stack until we leave their dynamic scope). A closure block is a clone of a script block (its prototype is a script block). Adjust the meanings of fp->blockChain and fp->scopeChain: fp->blockChain is always the innermost script block in whose static scope we're executing. fp->scopeChain is the current scope chain, including 'call' objects and closure blocks for those function calls and blocks in whose static scope we are currently executing, and 'with' objects for with statements; the chain is typically terminated by a global object. However, as an optimization, the young end of the chain omits block objects we have not yet needed to clone. Closures need fully reified scope chains, so have js_GetScopeChain reify any closure blocks missing from the young end of fp->scopeChain by cloning script blocks as needed from fp->blockChain. Thus, if we never actually close over a particular block, we never place a closure block for it on fp->scopeChain. Have JSOP_ENTERBLOCK and JSOP_LEAVEBLOCK always keep fp->blockChain current. When JSOP_LEAVEBLOCK pops a block from fp->blockChain that has been cloned on fp->scopeChain, pop fp->scopeChain as well. Remove the JSFRAME_POP_BLOCKS flag, as it is no longer needed. Ensure that the JIT won't have to create closure blocks or call js_PutBlockObject; it can't handle those things yet. Note our current script block when we begin recording. Abort recording if we leave that block; we can't tell in advance whether it will need to be "put" in future trace invocations. Leave trace if we call js_GetScopeChain while in the static scope of lexical blocks. Remove JIT tests based on JSFRAME_POP_BLOCKS. Verify that generators capture the correct value for blockChain. Add a constructor to JSAutoTempValueRooter for rooting JSObject pointers.
2009-03-16 09:55:06 -07:00
* The bytecode compiler produces a tree of block objects
* accompanying each JSScript representing those lexical blocks in
* the script that have let-bound variables associated with them.
* These block objects are never modified, and never become part
* of any function's scope chain. Their parent slots point to the
* innermost block that encloses them, or are NULL in the
* outermost blocks within a function or in eval or global code.
*
* When we are in the static scope of such a block, blockChain
* points to its compiler-allocated block object; otherwise, it is
* NULL.
*
Bug 480132: Clone lexical blocks only when needed. r=igor Terminology: A "script block" is an object of class Block allocated by the byte compiler and associated with a script. Script blocks are never modified, and may be used as a prototype for a "closure block": A "closure block" is an object of class Block that holds variables that have been closed over (although we actually leave the variables on the stack until we leave their dynamic scope). A closure block is a clone of a script block (its prototype is a script block). Adjust the meanings of fp->blockChain and fp->scopeChain: fp->blockChain is always the innermost script block in whose static scope we're executing. fp->scopeChain is the current scope chain, including 'call' objects and closure blocks for those function calls and blocks in whose static scope we are currently executing, and 'with' objects for with statements; the chain is typically terminated by a global object. However, as an optimization, the young end of the chain omits block objects we have not yet needed to clone. Closures need fully reified scope chains, so have js_GetScopeChain reify any closure blocks missing from the young end of fp->scopeChain by cloning script blocks as needed from fp->blockChain. Thus, if we never actually close over a particular block, we never place a closure block for it on fp->scopeChain. Have JSOP_ENTERBLOCK and JSOP_LEAVEBLOCK always keep fp->blockChain current. When JSOP_LEAVEBLOCK pops a block from fp->blockChain that has been cloned on fp->scopeChain, pop fp->scopeChain as well. Remove the JSFRAME_POP_BLOCKS flag, as it is no longer needed. Ensure that the JIT won't have to create closure blocks or call js_PutBlockObject; it can't handle those things yet. Note our current script block when we begin recording. Abort recording if we leave that block; we can't tell in advance whether it will need to be "put" in future trace invocations. Leave trace if we call js_GetScopeChain while in the static scope of lexical blocks. Remove JIT tests based on JSFRAME_POP_BLOCKS. Verify that generators capture the correct value for blockChain. Add a constructor to JSAutoTempValueRooter for rooting JSObject pointers.
2009-03-16 09:55:06 -07:00
* scopeChain is the current scope chain, including 'call' and
* 'block' objects for those function calls and lexical blocks
* whose static scope we are currently executing in, and 'with'
* objects for with statements; the chain is typically terminated
* by a global object. However, as an optimization, the young end
* of the chain omits block objects we have not yet cloned. To
* create a closure, we clone the missing blocks from blockChain
* (which is always current), place them at the head of
* scopeChain, and use that for the closure's scope chain. If we
* never close over a lexical block, we never place a mutable
* clone of it on scopeChain.
*
* This lazy cloning is implemented in js_GetScopeChain, which is
* also used in some other cases --- entering 'with' blocks, for
* example.
*/
2010-05-10 22:01:31 -07:00
JSObject *scopeChain;
Bug 480132: Clone lexical blocks only when needed. r=igor Terminology: A "script block" is an object of class Block allocated by the byte compiler and associated with a script. Script blocks are never modified, and may be used as a prototype for a "closure block": A "closure block" is an object of class Block that holds variables that have been closed over (although we actually leave the variables on the stack until we leave their dynamic scope). A closure block is a clone of a script block (its prototype is a script block). Adjust the meanings of fp->blockChain and fp->scopeChain: fp->blockChain is always the innermost script block in whose static scope we're executing. fp->scopeChain is the current scope chain, including 'call' objects and closure blocks for those function calls and blocks in whose static scope we are currently executing, and 'with' objects for with statements; the chain is typically terminated by a global object. However, as an optimization, the young end of the chain omits block objects we have not yet needed to clone. Closures need fully reified scope chains, so have js_GetScopeChain reify any closure blocks missing from the young end of fp->scopeChain by cloning script blocks as needed from fp->blockChain. Thus, if we never actually close over a particular block, we never place a closure block for it on fp->scopeChain. Have JSOP_ENTERBLOCK and JSOP_LEAVEBLOCK always keep fp->blockChain current. When JSOP_LEAVEBLOCK pops a block from fp->blockChain that has been cloned on fp->scopeChain, pop fp->scopeChain as well. Remove the JSFRAME_POP_BLOCKS flag, as it is no longer needed. Ensure that the JIT won't have to create closure blocks or call js_PutBlockObject; it can't handle those things yet. Note our current script block when we begin recording. Abort recording if we leave that block; we can't tell in advance whether it will need to be "put" in future trace invocations. Leave trace if we call js_GetScopeChain while in the static scope of lexical blocks. Remove JIT tests based on JSFRAME_POP_BLOCKS. Verify that generators capture the correct value for blockChain. Add a constructor to JSAutoTempValueRooter for rooting JSObject pointers.
2009-03-16 09:55:06 -07:00
JSObject *blockChain;
uint32 flags; /* frame flags -- see below */
JSStackFrame *displaySave; /* previous value of display entry for
script->staticLevel */
2010-03-03 17:52:26 -08:00
/* Members only needed for inline calls. */
void *hookData; /* debugger call hook data */
JSVersion callerVersion; /* dynamic version of calling script */
void putActivationObjects(JSContext *cx) {
/*
* The order of calls here is important as js_PutCallObject needs to
* access argsobj.
*/
if (callobj) {
js_PutCallObject(cx, this);
JS_ASSERT(!argsobj);
} else if (argsobj) {
js_PutArgsObject(cx, this);
}
}
2010-03-03 18:10:13 -08:00
/* Get the frame's current bytecode, assuming |this| is in |cx|. */
jsbytecode *pc(JSContext *cx) const;
2010-05-10 22:01:31 -07:00
js::Value *argEnd() const {
return (js::Value *)this;
2010-03-03 17:52:26 -08:00
}
2010-05-10 22:01:31 -07:00
js::Value *slots() const {
return (js::Value *)(this + 1);
2010-03-03 17:52:26 -08:00
}
2010-05-10 22:01:31 -07:00
js::Value *base() const {
return slots() + script->nfixed;
}
2010-05-10 22:01:31 -07:00
const js::Value &calleeValue() {
JS_ASSERT(argv);
2010-05-10 22:01:31 -07:00
return argv[-2];
}
JSObject *callee() {
2010-05-10 22:01:31 -07:00
return argv ? &argv[-2].asObject() : NULL;
}
/*
* Get the object associated with the Execution Context's
* VariableEnvironment (ES5 10.3). The given CallStack must contain this
* stack frame.
*/
2010-03-03 17:52:26 -08:00
JSObject *varobj(js::CallStack *cs) const;
/* Short for: varobj(cx->activeCallStack()). */
2010-03-03 17:52:26 -08:00
JSObject *varobj(JSContext *cx) const;
2010-05-17 22:15:51 -07:00
inline JSObject *getThisObject(JSContext *cx);
2010-03-03 17:52:26 -08:00
bool isGenerator() const { return flags & JSFRAME_GENERATOR; }
bool isFloatingGenerator() const {
JS_ASSERT_IF(flags & JSFRAME_FLOATING_GENERATOR, isGenerator());
return flags & JSFRAME_FLOATING_GENERATOR;
}
};
2010-03-03 17:52:26 -08:00
namespace js {
2010-05-10 22:01:31 -07:00
JS_STATIC_ASSERT(sizeof(JSStackFrame) % sizeof(Value) == 0);
2010-05-11 19:00:59 -07:00
static const size_t VALUES_PER_STACK_FRAME = sizeof(JSStackFrame) / sizeof(Value);
2010-03-03 17:52:26 -08:00
2010-05-10 22:01:31 -07:00
} /* namespace js */
static JS_INLINE uintN
GlobalVarCount(JSStackFrame *fp)
{
JS_ASSERT(!fp->fun);
return fp->script->nfixed;
}
/*
* Refresh and return fp->scopeChain. It may be stale if block scopes are
* active but not yet reflected by objects in the scope chain. If a block
* scope contains a with, eval, XML filtering predicate, or similar such
* dynamically scoped construct, then compile-time block scope at fp->blocks
* must reflect at runtime.
*/
extern JSObject *
js_GetScopeChain(JSContext *cx, JSStackFrame *fp);
/*
* Given a context and a vector of [callee, this, args...] for a function that
* was specified with a JSFUN_THISP_PRIMITIVE flag, get the primitive value of
* |this| into *thisvp. In doing so, if |this| is an object, insist it is an
* instance of clasp and extract its private slot value to return via *thisvp.
*
* NB: this function loads and uses *vp before storing *thisvp, so the two may
2010-05-10 22:01:31 -07:00
* alias the same Value.
*/
extern JSBool
2010-05-13 18:55:25 -07:00
js_GetPrimitiveThis(JSContext *cx, js::Value *vp, js::Class *clasp,
const js::Value **vpp);
2010-05-10 22:01:31 -07:00
namespace js {
/*
* For a call with arguments argv including argv[-1] (nominal |this|) and
* argv[-2] (callee) replace null |this| with callee's parent, replace
* primitive values with the equivalent wrapper objects and censor activation
* objects as, per ECMA-262, they may not be referred to by |this|. argv[-1]
* must not be a JSVAL_VOID.
*/
2010-05-10 22:01:31 -07:00
extern bool
ComputeThisFromArgv(JSContext *cx, js::Value *argv);
JS_ALWAYS_INLINE JSObject *
ComputeThisObjectFromVp(JSContext *cx, js::Value *vp)
{
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
2010-05-18 17:25:12 -07:00
return ComputeThisFromArgv(cx, vp + 2) ? &vp[1].asObject() : NULL;
2010-05-10 22:01:31 -07:00
}
JS_ALWAYS_INLINE bool
2010-05-13 18:55:25 -07:00
ComputeThisFromVpInPlace(JSContext *cx, js::Value *vp)
2010-05-10 22:01:31 -07:00
{
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
2010-05-13 18:55:25 -07:00
return ComputeThisFromArgv(cx, vp + 2);
2010-05-10 22:01:31 -07:00
}
class PrimitiveValue
{
static const unsigned THISP_MASK = 0x7;
static const unsigned THISP_ARRAY_SIZE = 8;
static const unsigned THISP_SHIFT = 8;
void staticAssert() {
JS_STATIC_ASSERT(JSFUN_THISP_PRIMITIVE >> THISP_SHIFT == THISP_MASK);
JS_STATIC_ASSERT(THISP_MASK == THISP_ARRAY_SIZE - 1);
}
2010-05-10 22:01:31 -07:00
static const Value::MaskType Masks[THISP_ARRAY_SIZE];
public:
static bool test(JSFunction *fun, const Value &v) {
return bool(Masks[(fun->flags >> THISP_SHIFT) & THISP_MASK] & v.mask);
}
};
/*
2010-03-03 17:52:26 -08:00
* The js::InvokeArgumentsGuard passed to js_Invoke must come from an
* immediately-enclosing successful call to js::StackSpace::pushInvokeArgs,
* i.e., there must have been no un-popped pushes to cx->stack(). Furthermore,
* |args.getvp()[0]| should be the callee, |args.getvp()[1]| should be |this|,
* and the range [args.getvp() + 2, args.getvp() + 2 + args.getArgc()) should
* be initialized actual arguments.
*/
2010-05-10 22:01:31 -07:00
extern JS_REQUIRES_STACK bool
Invoke(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
extern JS_REQUIRES_STACK JS_FRIEND_API(bool)
InvokeFriendAPI(JSContext *cx, const InvokeArgsGuard &args, uintN flags);
/*
* Consolidated js_Invoke flags simply rename certain JSFRAME_* flags, so that
* we can share bits stored in JSStackFrame.flags and passed to:
*
* js_Invoke
* js_InternalInvoke
* js_ValueToFunction
* js_ValueToFunctionObject
* js_ValueToCallableObject
* js_ReportIsNotFunction
*
* See jsfun.h for the latter four and flag renaming macros.
*/
#define JSINVOKE_CONSTRUCT JSFRAME_CONSTRUCTING
#define JSINVOKE_ITERATOR JSFRAME_ITERATOR
/*
* Mask to isolate construct and iterator flags for use with jsfun.h functions.
*/
#define JSINVOKE_FUNFLAGS (JSINVOKE_CONSTRUCT | JSINVOKE_ITERATOR)
2010-05-10 22:01:31 -07:00
extern bool
InternalInvoke(JSContext *cx, JSObject *obj, const Value &fval, uintN flags,
uintN argc, const Value *argv, Value *rval);
2010-05-10 22:01:31 -07:00
static JS_ALWAYS_INLINE bool
InternalCall(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
const Value *argv, Value *rval)
{
return InternalInvoke(cx, obj, fval, 0, argc, argv, rval);
}
2010-05-10 22:01:31 -07:00
static JS_ALWAYS_INLINE bool
InternalConstruct(JSContext *cx, JSObject *obj, const Value &fval, uintN argc,
const Value *argv, Value *rval)
{
return InternalInvoke(cx, obj, fval, JSINVOKE_CONSTRUCT, argc, argv, rval);
}
2010-05-10 22:01:31 -07:00
extern bool
InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
JSAccessMode mode, uintN argc, const Value *argv, Value *rval);
2010-05-10 22:01:31 -07:00
extern JS_FORCES_STACK bool
Execute(JSContext *cx, JSObject *chain, JSScript *script,
JSStackFrame *down, uintN flags, Value *result);
2010-05-10 22:01:31 -07:00
extern JS_REQUIRES_STACK bool
2010-05-11 00:41:08 -07:00
InvokeConstructor(JSContext *cx, const InvokeArgsGuard &args, JSBool clampReturn);
2010-05-10 22:01:31 -07:00
extern JS_REQUIRES_STACK bool
Interpret(JSContext *cx);
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */
2010-05-10 22:01:31 -07:00
extern bool
CheckRedeclaration(JSContext *cx, JSObject *obj, jsid id, uintN attrs,
JSObject **objp, JSProperty **propp);
2010-05-10 22:01:31 -07:00
extern bool
StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval);
/* === except that NaN is the same as NaN and -0 is not the same as +0. */
2010-05-10 22:01:31 -07:00
extern bool
SameValue(JSContext *cx, const Value &v1, const Value &v2);
2010-05-12 19:05:43 -07:00
extern JSType
2010-05-10 22:01:31 -07:00
TypeOfValue(JSContext *cx, const js::Value &v);
inline bool
InstanceOf(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
{
if (obj && obj->getClass() == clasp)
return true;
extern bool InstanceOfSlow(JSContext *, JSObject *, Class *, Value *);
return InstanceOfSlow(cx, obj, clasp, argv);
}
inline void *
GetInstancePrivate(JSContext *cx, JSObject *obj, Class *clasp, Value *argv)
{
if (!InstanceOf(cx, obj, clasp, argv))
return NULL;
return obj->getPrivate();
}
2010-05-13 02:03:08 -07:00
extern Value
2010-05-12 22:58:11 -07:00
BoxedWordToValue(jsboxedword w);
extern bool
ValueToBoxedWord(JSContext *cx, const Value &v, jsboxedword *w);
2010-05-12 19:05:43 -07:00
extern Value
IdToValue(jsid id);
extern bool
ValueToId(JSContext *cx, const Value &v, jsid *idp);
2010-05-10 22:01:31 -07:00
} /* namespace js */
2009-03-17 16:36:45 -07:00
/*
* Given an active context, a static scope level, and an upvar cookie, return
* the value of the upvar.
*/
2010-05-10 22:01:31 -07:00
extern const js::Value &
js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
/*
* JS_LONE_INTERPRET indicates that the compiler should see just the code for
* the js_Interpret function when compiling jsinterp.cpp. The rest of the code
* from the file should be visible only when compiling jsinvoke.cpp. It allows
* platform builds to optimize selectively js_Interpret when the granularity
* of the optimizations with the given compiler is a compilation unit.
*
* JS_STATIC_INTERPRET is the modifier for functions defined in jsinterp.cpp
* that only js_Interpret calls. When JS_LONE_INTERPRET is true all such
* functions are declared below.
*/
#ifndef JS_LONE_INTERPRET
# ifdef _MSC_VER
# define JS_LONE_INTERPRET 0
# else
# define JS_LONE_INTERPRET 1
# endif
#endif
#define JS_MAX_INLINE_CALL_COUNT 3000
#if !JS_LONE_INTERPRET
# define JS_STATIC_INTERPRET static
#else
# define JS_STATIC_INTERPRET
extern JS_REQUIRES_STACK JSBool
js_EnterWith(JSContext *cx, jsint stackIndex);
extern JS_REQUIRES_STACK void
js_LeaveWith(JSContext *cx);
2010-05-10 22:01:31 -07:00
extern JS_REQUIRES_STACK js::Class *
js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth);
/*
* Unwind block and scope chains to match the given depth. The function sets
* fp->sp on return to stackDepth.
*/
extern JS_REQUIRES_STACK JSBool
2010-03-03 18:10:13 -08:00
js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind);
extern JSBool
2010-05-10 22:01:31 -07:00
js_OnUnknownMethod(JSContext *cx, js::Value *vp);
/*
* Find the results of incrementing or decrementing *vp. For pre-increments,
* both *vp and *vp2 will contain the result on return. For post-increments,
* vp will contain the original value converted to a number and vp2 will get
* the result. Both vp and vp2 must be roots.
*/
extern JSBool
2010-05-10 22:01:31 -07:00
js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, js::Value *vp, js::Value *vp2);
/*
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the
* previous opcode.
*/
extern JS_REQUIRES_STACK void
js_TraceOpcode(JSContext *cx);
/*
* JS_OPMETER helper functions.
*/
extern void
js_MeterOpcodePair(JSOp op1, JSOp op2);
extern void
js_MeterSlotOpcode(JSOp op, uint32 slot);
#endif /* JS_LONE_INTERPRET */
2010-05-17 22:15:51 -07:00
inline JSObject *
JSStackFrame::getThisObject(JSContext *cx)
{
if (flags & JSFRAME_COMPUTED_THIS)
2010-05-17 22:15:51 -07:00
return &thisv.asObject();
2010-05-10 22:01:31 -07:00
if (!js::ComputeThisFromArgv(cx, argv))
2010-05-17 22:15:51 -07:00
return NULL;
thisv = argv[-1];
flags |= JSFRAME_COMPUTED_THIS;
2010-05-17 22:15:51 -07:00
return &thisv.asObject();
}
#endif /* jsinterp_h___ */