82 |
jsval rval; /* function return value */ |
jsval rval; /* function return value */ |
83 |
JSStackFrame *down; /* previous frame */ |
JSStackFrame *down; /* previous frame */ |
84 |
void *annotation; /* used by Java security */ |
void *annotation; /* used by Java security */ |
85 |
JSObject *scopeChain; /* scope chain */ |
|
86 |
|
/* |
87 |
|
* We can't determine in advance which local variables can live on |
88 |
|
* the stack and be freed when their dynamic scope ends, and which |
89 |
|
* will be closed over and need to live in the heap. So we place |
90 |
|
* variables on the stack initially, note when they are closed |
91 |
|
* over, and copy those that are out to the heap when we leave |
92 |
|
* their dynamic scope. |
93 |
|
* |
94 |
|
* The bytecode compiler produces a tree of block objects |
95 |
|
* accompanying each JSScript representing those lexical blocks in |
96 |
|
* the script that have let-bound variables associated with them. |
97 |
|
* These block objects are never modified, and never become part |
98 |
|
* of any function's scope chain. Their parent slots point to the |
99 |
|
* innermost block that encloses them, or are NULL in the |
100 |
|
* outermost blocks within a function or in eval or global code. |
101 |
|
* |
102 |
|
* When we are in the static scope of such a block, blockChain |
103 |
|
* points to its compiler-allocated block object; otherwise, it is |
104 |
|
* NULL. |
105 |
|
* |
106 |
|
* scopeChain is the current scope chain, including 'call' and |
107 |
|
* 'block' objects for those function calls and lexical blocks |
108 |
|
* whose static scope we are currently executing in, and 'with' |
109 |
|
* objects for with statements; the chain is typically terminated |
110 |
|
* by a global object. However, as an optimization, the young end |
111 |
|
* of the chain omits block objects we have not yet cloned. To |
112 |
|
* create a closure, we clone the missing blocks from blockChain |
113 |
|
* (which is always current), place them at the head of |
114 |
|
* scopeChain, and use that for the closure's scope chain. If we |
115 |
|
* never close over a lexical block, we never place a mutable |
116 |
|
* clone of it on scopeChain. |
117 |
|
* |
118 |
|
* This lazy cloning is implemented in js_GetScopeChain, which is |
119 |
|
* also used in some other cases --- entering 'with' blocks, for |
120 |
|
* example. |
121 |
|
*/ |
122 |
|
JSObject *scopeChain; |
123 |
|
JSObject *blockChain; |
124 |
|
|
125 |
uintN sharpDepth; /* array/object initializer depth */ |
uintN sharpDepth; /* array/object initializer depth */ |
126 |
JSObject *sharpArray; /* scope for #n= initializer vars */ |
JSObject *sharpArray; /* scope for #n= initializer vars */ |
127 |
uint32 flags; /* frame flags -- see below */ |
uint32 flags; /* frame flags -- see below */ |
128 |
JSStackFrame *dormantNext; /* next dormant frame chain */ |
JSStackFrame *dormantNext; /* next dormant frame chain */ |
129 |
JSObject *xmlNamespace; /* null or default xml namespace in E4X */ |
JSObject *xmlNamespace; /* null or default xml namespace in E4X */ |
|
JSObject *blockChain; /* active compile-time block scopes */ |
|
130 |
JSStackFrame *displaySave; /* previous value of display entry for |
JSStackFrame *displaySave; /* previous value of display entry for |
131 |
script->staticDepth */ |
script->staticLevel */ |
132 |
#ifdef DEBUG |
|
133 |
jsrefcount pcDisabledSave; /* for balanced property cache control */ |
#ifdef __cplusplus /* Aargh, LiveConnect, bug 442399. */ |
134 |
|
inline void assertValidStackDepth(uintN depth); |
135 |
#endif |
#endif |
136 |
}; |
}; |
137 |
|
|
|
#ifdef DEBUG |
|
138 |
#ifdef __cplusplus |
#ifdef __cplusplus |
139 |
static JS_INLINE uintN |
static JS_INLINE uintN |
140 |
FramePCOffset(JSStackFrame* fp) |
FramePCOffset(JSStackFrame* fp) |
142 |
return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code); |
return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code); |
143 |
} |
} |
144 |
#endif |
#endif |
|
#endif |
|
145 |
|
|
146 |
static JS_INLINE jsval * |
static JS_INLINE jsval * |
147 |
StackBase(JSStackFrame *fp) |
StackBase(JSStackFrame *fp) |
149 |
return fp->slots + fp->script->nfixed; |
return fp->slots + fp->script->nfixed; |
150 |
} |
} |
151 |
|
|
152 |
|
#ifdef __cplusplus /* Aargh, LiveConnect, bug 442399. */ |
153 |
|
void |
154 |
|
JSStackFrame::assertValidStackDepth(uintN depth) |
155 |
|
{ |
156 |
|
JS_ASSERT(0 <= regs->sp - StackBase(this)); |
157 |
|
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(this))); |
158 |
|
} |
159 |
|
#endif |
160 |
|
|
161 |
static JS_INLINE uintN |
static JS_INLINE uintN |
162 |
GlobalVarCount(JSStackFrame *fp) |
GlobalVarCount(JSStackFrame *fp) |
163 |
{ |
{ |
188 |
#define JSFRAME_ROOTED_ARGV 0x20 /* frame.argv is rooted by the caller */ |
#define JSFRAME_ROOTED_ARGV 0x20 /* frame.argv is rooted by the caller */ |
189 |
#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */ |
#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */ |
190 |
#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */ |
#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */ |
|
#define JSFRAME_POP_BLOCKS 0x100 /* scope chain contains blocks to pop */ |
|
191 |
#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */ |
#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */ |
|
#define JSFRAME_IMACRO_START 0x400 /* imacro starting -- see jstracer.h */ |
|
192 |
|
|
193 |
#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */ |
#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */ |
194 |
#define JSFRAME_OVERRIDE_BITS 8 |
#define JSFRAME_OVERRIDE_BITS 8 |
235 |
#define PCVCAP_TAGMASK JS_BITMASK(PCVCAP_TAGBITS) |
#define PCVCAP_TAGMASK JS_BITMASK(PCVCAP_TAGBITS) |
236 |
#define PCVCAP_TAG(t) ((t) & PCVCAP_TAGMASK) |
#define PCVCAP_TAG(t) ((t) & PCVCAP_TAGMASK) |
237 |
|
|
238 |
#define PCVCAP_MAKE(t,s,p) (((t) << PCVCAP_TAGBITS) | \ |
#define PCVCAP_MAKE(t,s,p) ((uint32(t) << PCVCAP_TAGBITS) | \ |
239 |
((s) << PCVCAP_PROTOBITS) | \ |
((s) << PCVCAP_PROTOBITS) | \ |
240 |
(p)) |
(p)) |
241 |
#define PCVCAP_SHAPE(t) ((t) >> PCVCAP_TAGBITS) |
#define PCVCAP_SHAPE(t) ((t) >> PCVCAP_TAGBITS) |
242 |
|
|
243 |
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS) |
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS) |
244 |
|
|
245 |
/* |
#ifndef JS_THREADSAFE |
246 |
* When sprop is not null and the shape generation triggers the GC due to a |
# define js_GenerateShape(cx, gcLocked) js_GenerateShape (cx) |
247 |
* shape overflow, the functions roots sprop. |
#endif |
248 |
*/ |
|
249 |
extern uint32 |
extern uint32 |
250 |
js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop); |
js_GenerateShape(JSContext *cx, JSBool gcLocked); |
251 |
|
|
252 |
struct JSPropCacheEntry { |
struct JSPropCacheEntry { |
253 |
jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */ |
jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */ |
256 |
jsuword vword; /* value word, see PCVAL_* below */ |
jsuword vword; /* value word, see PCVAL_* below */ |
257 |
}; |
}; |
258 |
|
|
259 |
|
/* |
260 |
|
* Special value for functions returning JSPropCacheEntry * to distinguish |
261 |
|
* between failure and no no-cache-fill cases. |
262 |
|
*/ |
263 |
|
#define JS_NO_PROP_CACHE_FILL ((JSPropCacheEntry *) NULL + 1) |
264 |
|
|
265 |
#if defined DEBUG_brendan || defined DEBUG_brendaneich |
#if defined DEBUG_brendan || defined DEBUG_brendaneich |
266 |
#define JS_PROPERTY_CACHE_METERING 1 |
#define JS_PROPERTY_CACHE_METERING 1 |
267 |
#endif |
#endif |
269 |
typedef struct JSPropertyCache { |
typedef struct JSPropertyCache { |
270 |
JSPropCacheEntry table[PROPERTY_CACHE_SIZE]; |
JSPropCacheEntry table[PROPERTY_CACHE_SIZE]; |
271 |
JSBool empty; |
JSBool empty; |
|
jsrefcount disabled; /* signed for anti-underflow asserts */ |
|
272 |
#ifdef JS_PROPERTY_CACHE_METERING |
#ifdef JS_PROPERTY_CACHE_METERING |
273 |
|
JSPropCacheEntry *pctestentry; /* entry of the last PC-based test */ |
274 |
uint32 fills; /* number of cache entry fills */ |
uint32 fills; /* number of cache entry fills */ |
275 |
uint32 nofills; /* couldn't fill (e.g. default get) */ |
uint32 nofills; /* couldn't fill (e.g. default get) */ |
276 |
uint32 rofills; /* set on read-only prop can't fill */ |
uint32 rofills; /* set on read-only prop can't fill */ |
344 |
* Fill property cache entry for key cx->fp->pc, optimized value word computed |
* Fill property cache entry for key cx->fp->pc, optimized value word computed |
345 |
* from obj and sprop, and entry capability forged from 24-bit OBJ_SHAPE(obj), |
* from obj and sprop, and entry capability forged from 24-bit OBJ_SHAPE(obj), |
346 |
* 4-bit scopeIndex, and 4-bit protoIndex. |
* 4-bit scopeIndex, and 4-bit protoIndex. |
347 |
|
* |
348 |
|
* Return the filled cache entry or JS_NO_PROP_CACHE_FILL if caching was not |
349 |
|
* possible. |
350 |
*/ |
*/ |
351 |
extern void |
extern JS_REQUIRES_STACK JSPropCacheEntry * |
352 |
js_FillPropertyCache(JSContext *cx, JSObject *obj, jsuword kshape, |
js_FillPropertyCache(JSContext *cx, JSObject *obj, |
353 |
uintN scopeIndex, uintN protoIndex, |
uintN scopeIndex, uintN protoIndex, JSObject *pobj, |
354 |
JSObject *pobj, JSScopeProperty *sprop, |
JSScopeProperty *sprop, JSBool adding); |
|
JSPropCacheEntry **entryp); |
|
355 |
|
|
356 |
/* |
/* |
357 |
* Property cache lookup macros. PROPERTY_CACHE_TEST is designed to inline the |
* Property cache lookup macros. PROPERTY_CACHE_TEST is designed to inline the |
374 |
JSPropertyCache *cache_ = &JS_PROPERTY_CACHE(cx); \ |
JSPropertyCache *cache_ = &JS_PROPERTY_CACHE(cx); \ |
375 |
uint32 kshape_ = (JS_ASSERT(OBJ_IS_NATIVE(obj)), OBJ_SHAPE(obj)); \ |
uint32 kshape_ = (JS_ASSERT(OBJ_IS_NATIVE(obj)), OBJ_SHAPE(obj)); \ |
376 |
entry = &cache_->table[PROPERTY_CACHE_HASH_PC(pc, kshape_)]; \ |
entry = &cache_->table[PROPERTY_CACHE_HASH_PC(pc, kshape_)]; \ |
377 |
|
PCMETER(cache_->pctestentry = entry); \ |
378 |
PCMETER(cache_->tests++); \ |
PCMETER(cache_->tests++); \ |
379 |
JS_ASSERT(&obj != &pobj); \ |
JS_ASSERT(&obj != &pobj); \ |
380 |
if (entry->kpc == pc && entry->kshape == kshape_) { \ |
if (entry->kpc == pc && entry->kshape == kshape_) { \ |
403 |
PCMETER(cache_->misses++); \ |
PCMETER(cache_->misses++); \ |
404 |
} while (0) |
} while (0) |
405 |
|
|
406 |
extern JSAtom * |
extern JS_REQUIRES_STACK JSAtom * |
407 |
js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, |
js_FullTestPropertyCache(JSContext *cx, jsbytecode *pc, |
408 |
JSObject **objp, JSObject **pobjp, |
JSObject **objp, JSObject **pobjp, |
409 |
JSPropCacheEntry **entryp); |
JSPropCacheEntry **entryp); |
410 |
|
|
411 |
extern void |
/* The property cache does not need a destructor. */ |
412 |
js_FlushPropertyCache(JSContext *cx); |
#define js_FinishPropertyCache(cache) ((void) 0) |
413 |
|
|
414 |
extern void |
extern void |
415 |
js_FlushPropertyCacheForScript(JSContext *cx, JSScript *script); |
js_PurgePropertyCache(JSContext *cx, JSPropertyCache *cache); |
416 |
|
|
417 |
extern void |
extern void |
418 |
js_DisablePropertyCache(JSContext *cx); |
js_PurgePropertyCacheForScript(JSContext *cx, JSScript *script); |
|
|
|
|
extern void |
|
|
js_EnablePropertyCache(JSContext *cx); |
|
419 |
|
|
420 |
/* |
/* |
421 |
* Interpreter stack arena-pool alloc and free functions. |
* Interpreter stack arena-pool alloc and free functions. |
422 |
*/ |
*/ |
423 |
extern JS_FRIEND_API(jsval *) |
extern JS_REQUIRES_STACK JS_FRIEND_API(jsval *) |
424 |
js_AllocStack(JSContext *cx, uintN nslots, void **markp); |
js_AllocStack(JSContext *cx, uintN nslots, void **markp); |
425 |
|
|
426 |
extern JS_FRIEND_API(void) |
extern JS_REQUIRES_STACK JS_FRIEND_API(void) |
427 |
js_FreeStack(JSContext *cx, void *mark); |
js_FreeStack(JSContext *cx, void *mark); |
428 |
|
|
429 |
/* |
/* |
465 |
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \ |
JSFUN_THISP_TEST(JSFUN_THISP_FLAGS((fun)->flags), \ |
466 |
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1])) |
js_PrimitiveTestFlags[JSVAL_TAG(thisv) - 1])) |
467 |
|
|
468 |
|
#ifdef __cplusplus /* Aargh, libgjs, bug 492720. */ |
469 |
|
static JS_INLINE JSObject * |
470 |
|
js_ComputeThisForFrame(JSContext *cx, JSStackFrame *fp) |
471 |
|
{ |
472 |
|
JSObject* obj; |
473 |
|
if (fp->flags & JSFRAME_COMPUTED_THIS) |
474 |
|
return fp->thisp; |
475 |
|
obj = js_ComputeThis(cx, JS_TRUE, fp->argv); |
476 |
|
if (!obj) |
477 |
|
return NULL; |
478 |
|
fp->thisp = obj; |
479 |
|
fp->flags |= JSFRAME_COMPUTED_THIS; |
480 |
|
return obj; |
481 |
|
} |
482 |
|
#endif |
483 |
|
|
484 |
/* |
/* |
485 |
* NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp |
* NB: js_Invoke requires that cx is currently running JS (i.e., that cx->fp |
486 |
* is non-null), and that vp points to the callee, |this| parameter, and |
* is non-null), and that vp points to the callee, |this| parameter, and |
490 |
* so the caller should not use that space for values that must be preserved |
* so the caller should not use that space for values that must be preserved |
491 |
* across the call. |
* across the call. |
492 |
*/ |
*/ |
493 |
extern JS_FRIEND_API(JSBool) |
extern JS_REQUIRES_STACK JS_FRIEND_API(JSBool) |
494 |
js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags); |
js_Invoke(JSContext *cx, uintN argc, jsval *vp, uintN flags); |
495 |
|
|
496 |
/* |
/* |
532 |
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, |
js_InternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, jsval fval, |
533 |
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval); |
JSAccessMode mode, uintN argc, jsval *argv, jsval *rval); |
534 |
|
|
535 |
extern JSBool |
extern JS_FORCES_STACK JSBool |
536 |
js_Execute(JSContext *cx, JSObject *chain, JSScript *script, |
js_Execute(JSContext *cx, JSObject *chain, JSScript *script, |
537 |
JSStackFrame *down, uintN flags, jsval *result); |
JSStackFrame *down, uintN flags, jsval *result); |
538 |
|
|
539 |
extern JSBool |
extern JS_REQUIRES_STACK JSBool |
540 |
js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp); |
js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp); |
541 |
|
|
542 |
extern JSBool |
extern JS_REQUIRES_STACK JSBool |
543 |
js_Interpret(JSContext *cx); |
js_Interpret(JSContext *cx); |
544 |
|
|
545 |
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */ |
#define JSPROP_INITIALIZER 0x100 /* NB: Not a valid property attribute. */ |
551 |
extern JSBool |
extern JSBool |
552 |
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval); |
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval); |
553 |
|
|
554 |
|
extern JSBool |
555 |
|
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp); |
556 |
|
|
557 |
|
/* Work around liveconnect building this file as C on 1.9.1 branch */ |
558 |
|
#ifdef __cplusplus |
559 |
|
|
560 |
|
/* |
561 |
|
* Given an active context, a static scope level, and an upvar cookie, return |
562 |
|
* the value of the upvar. |
563 |
|
*/ |
564 |
|
extern jsval& |
565 |
|
js_GetUpvar(JSContext *cx, uintN level, uintN cookie); |
566 |
|
|
567 |
|
#endif |
568 |
|
|
569 |
/* |
/* |
570 |
* JS_LONE_INTERPRET indicates that the compiler should see just the code for |
* JS_LONE_INTERPRET indicates that the compiler should see just the code for |
571 |
* the js_Interpret function when compiling jsinterp.cpp. The rest of the code |
* the js_Interpret function when compiling jsinterp.cpp. The rest of the code |
590 |
#else |
#else |
591 |
# define JS_STATIC_INTERPRET |
# define JS_STATIC_INTERPRET |
592 |
|
|
593 |
extern jsval * |
extern JS_REQUIRES_STACK jsval * |
594 |
js_AllocRawStack(JSContext *cx, uintN nslots, void **markp); |
js_AllocRawStack(JSContext *cx, uintN nslots, void **markp); |
595 |
|
|
596 |
extern void |
extern JS_REQUIRES_STACK void |
597 |
js_FreeRawStack(JSContext *cx, void *mark); |
js_FreeRawStack(JSContext *cx, void *mark); |
598 |
|
|
599 |
/* |
/* |
614 |
extern JSObject * |
extern JSObject * |
615 |
js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv); |
js_ComputeGlobalThis(JSContext *cx, JSBool lazy, jsval *argv); |
616 |
|
|
617 |
extern JSBool |
extern JS_REQUIRES_STACK JSBool |
618 |
js_EnterWith(JSContext *cx, jsint stackIndex); |
js_EnterWith(JSContext *cx, jsint stackIndex); |
619 |
|
|
620 |
extern void |
extern JS_REQUIRES_STACK void |
621 |
js_LeaveWith(JSContext *cx); |
js_LeaveWith(JSContext *cx); |
622 |
|
|
623 |
extern JSClass * |
extern JS_REQUIRES_STACK JSClass * |
624 |
js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth); |
js_IsActiveWithOrBlock(JSContext *cx, JSObject *obj, int stackDepth); |
625 |
|
|
|
extern jsint |
|
|
js_CountWithBlocks(JSContext *cx, JSStackFrame *fp); |
|
|
|
|
626 |
/* |
/* |
627 |
* Unwind block and scope chains to match the given depth. The function sets |
* Unwind block and scope chains to match the given depth. The function sets |
628 |
* fp->sp on return to stackDepth. |
* fp->sp on return to stackDepth. |
629 |
*/ |
*/ |
630 |
extern JSBool |
extern JS_REQUIRES_STACK JSBool |
631 |
js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth, |
js_UnwindScope(JSContext *cx, JSStackFrame *fp, jsint stackDepth, |
632 |
JSBool normalUnwind); |
JSBool normalUnwind); |
633 |
|
|
634 |
extern JSBool |
extern JSBool |
|
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp); |
|
|
|
|
|
extern JSBool |
|
635 |
js_OnUnknownMethod(JSContext *cx, jsval *vp); |
js_OnUnknownMethod(JSContext *cx, jsval *vp); |
636 |
|
|
637 |
/* |
/* |
647 |
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the |
* Opcode tracing helper. When len is not 0, cx->fp->regs->pc[-len] gives the |
648 |
* previous opcode. |
* previous opcode. |
649 |
*/ |
*/ |
650 |
extern void |
extern JS_REQUIRES_STACK void |
651 |
js_TraceOpcode(JSContext *cx, jsint len); |
js_TraceOpcode(JSContext *cx); |
652 |
|
|
653 |
/* |
/* |
654 |
* JS_OPMETER helper functions. |
* JS_OPMETER helper functions. |