71 |
jsbytecode *imacpc; /* null or interpreter macro call pc */ |
jsbytecode *imacpc; /* null or interpreter macro call pc */ |
72 |
jsval *slots; /* variables, locals and operand stack */ |
jsval *slots; /* variables, locals and operand stack */ |
73 |
JSObject *callobj; /* lazily created Call object */ |
JSObject *callobj; /* lazily created Call object */ |
74 |
JSObject *argsobj; /* lazily created arguments object */ |
jsval argsobj; /* lazily created arguments object, must be |
75 |
|
JSVAL_OBJECT */ |
76 |
JSObject *varobj; /* variables object, where vars go */ |
JSObject *varobj; /* variables object, where vars go */ |
|
JSObject *callee; /* function or script object */ |
|
77 |
JSScript *script; /* script being interpreted */ |
JSScript *script; /* script being interpreted */ |
78 |
JSFunction *fun; /* function being called or null */ |
JSFunction *fun; /* function being called or null */ |
79 |
JSObject *thisp; /* "this" pointer if in method */ |
JSObject *thisp; /* "this" pointer if in method */ |
90 |
* variables on the stack initially, note when they are closed |
* variables on the stack initially, note when they are closed |
91 |
* over, and copy those that are out to the heap when we leave |
* over, and copy those that are out to the heap when we leave |
92 |
* their dynamic scope. |
* their dynamic scope. |
93 |
* |
* |
94 |
* The bytecode compiler produces a tree of block objects |
* The bytecode compiler produces a tree of block objects |
95 |
* accompanying each JSScript representing those lexical blocks in |
* accompanying each JSScript representing those lexical blocks in |
96 |
* the script that have let-bound variables associated with them. |
* the script that have let-bound variables associated with them. |
102 |
* When we are in the static scope of such a block, blockChain |
* When we are in the static scope of such a block, blockChain |
103 |
* points to its compiler-allocated block object; otherwise, it is |
* points to its compiler-allocated block object; otherwise, it is |
104 |
* NULL. |
* NULL. |
105 |
* |
* |
106 |
* scopeChain is the current scope chain, including 'call' and |
* scopeChain is the current scope chain, including 'call' and |
107 |
* 'block' objects for those function calls and lexical blocks |
* 'block' objects for those function calls and lexical blocks |
108 |
* whose static scope we are currently executing in, and 'with' |
* whose static scope we are currently executing in, and 'with' |
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 */ |
|
JSObject *xmlNamespace; /* null or default xml namespace in E4X */ |
|
129 |
JSStackFrame *displaySave; /* previous value of display entry for |
JSStackFrame *displaySave; /* previous value of display entry for |
130 |
script->staticLevel */ |
script->staticLevel */ |
131 |
|
|
132 |
#ifdef __cplusplus /* Aargh, LiveConnect, bug 442399. */ |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
133 |
|
|
134 |
inline void assertValidStackDepth(uintN depth); |
inline void assertValidStackDepth(uintN depth); |
135 |
#endif |
|
136 |
|
void putActivationObjects(JSContext *cx) { |
137 |
|
/* |
138 |
|
* The order of calls here is important as js_PutCallObject needs to |
139 |
|
* access argsobj. |
140 |
|
*/ |
141 |
|
if (callobj) { |
142 |
|
js_PutCallObject(cx, this); |
143 |
|
JS_ASSERT(!argsobj); |
144 |
|
} else if (argsobj) { |
145 |
|
js_PutArgsObject(cx, this); |
146 |
|
} |
147 |
|
} |
148 |
|
|
149 |
|
JSObject *callee() { |
150 |
|
return argv ? JSVAL_TO_OBJECT(argv[-2]) : NULL; |
151 |
|
} |
152 |
|
|
153 |
|
#endif /* __cplusplus */ |
154 |
}; |
}; |
155 |
|
|
156 |
#ifdef __cplusplus |
#ifdef __cplusplus |
157 |
|
|
158 |
static JS_INLINE uintN |
static JS_INLINE uintN |
159 |
FramePCOffset(JSStackFrame* fp) |
FramePCOffset(JSStackFrame* fp) |
160 |
{ |
{ |
161 |
return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code); |
return uintN((fp->imacpc ? fp->imacpc : fp->regs->pc) - fp->script->code); |
162 |
} |
} |
|
#endif |
|
163 |
|
|
164 |
static JS_INLINE jsval * |
static JS_INLINE jsval * |
165 |
StackBase(JSStackFrame *fp) |
StackBase(JSStackFrame *fp) |
167 |
return fp->slots + fp->script->nfixed; |
return fp->slots + fp->script->nfixed; |
168 |
} |
} |
169 |
|
|
|
#ifdef __cplusplus /* Aargh, LiveConnect, bug 442399. */ |
|
170 |
void |
void |
171 |
JSStackFrame::assertValidStackDepth(uintN depth) |
JSStackFrame::assertValidStackDepth(uintN depth) |
172 |
{ |
{ |
173 |
JS_ASSERT(0 <= regs->sp - StackBase(this)); |
JS_ASSERT(0 <= regs->sp - StackBase(this)); |
174 |
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(this))); |
JS_ASSERT(depth <= uintptr_t(regs->sp - StackBase(this))); |
175 |
} |
} |
|
#endif |
|
176 |
|
|
177 |
static JS_INLINE uintN |
static JS_INLINE uintN |
178 |
GlobalVarCount(JSStackFrame *fp) |
GlobalVarCount(JSStackFrame *fp) |
179 |
{ |
{ |
180 |
uintN n; |
uintN n; |
181 |
|
|
182 |
JS_ASSERT(!fp->fun); |
JS_ASSERT(!fp->fun); |
183 |
n = fp->script->nfixed; |
n = fp->script->nfixed; |
184 |
if (fp->script->regexpsOffset != 0) |
if (fp->script->regexpsOffset != 0) |
185 |
n -= JS_SCRIPT_REGEXPS(fp->script)->length; |
n -= fp->script->regexps()->length; |
186 |
return n; |
return n; |
187 |
} |
} |
188 |
|
|
189 |
|
#endif /* __cplusplus */ |
190 |
|
|
191 |
typedef struct JSInlineFrame { |
typedef struct JSInlineFrame { |
192 |
JSStackFrame frame; /* base struct */ |
JSStackFrame frame; /* base struct */ |
193 |
JSFrameRegs callerRegs; /* parent's frame registers */ |
JSFrameRegs callerRegs; /* parent's frame registers */ |
207 |
#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */ |
#define JSFRAME_YIELDING 0x40 /* js_Interpret dispatched JSOP_YIELD */ |
208 |
#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */ |
#define JSFRAME_ITERATOR 0x80 /* trying to get an iterator for for-in */ |
209 |
#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */ |
#define JSFRAME_GENERATOR 0x200 /* frame belongs to generator-iterator */ |
210 |
|
#define JSFRAME_OVERRIDE_ARGS 0x400 /* overridden arguments local variable */ |
|
#define JSFRAME_OVERRIDE_SHIFT 24 /* override bit-set params; see jsfun.c */ |
|
|
#define JSFRAME_OVERRIDE_BITS 8 |
|
211 |
|
|
212 |
#define JSFRAME_SPECIAL (JSFRAME_DEBUGGER | JSFRAME_EVAL) |
#define JSFRAME_SPECIAL (JSFRAME_DEBUGGER | JSFRAME_EVAL) |
213 |
|
|
214 |
/* |
/* |
215 |
* Property cache with structurally typed capabilities for invalidation, for |
* Property cache with structurally typed capabilities for invalidation, for |
216 |
* polymorphic callsite method/get/set speedups. |
* polymorphic callsite method/get/set speedups. For details, see |
217 |
* |
* <https://developer.mozilla.org/en/SpiderMonkey/Internals/Property_cache>. |
|
* See bug https://bugzilla.mozilla.org/show_bug.cgi?id=365851. |
|
218 |
*/ |
*/ |
219 |
#define PROPERTY_CACHE_LOG2 12 |
#define PROPERTY_CACHE_LOG2 12 |
220 |
#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2) |
#define PROPERTY_CACHE_SIZE JS_BIT(PROPERTY_CACHE_LOG2) |
232 |
#define PROPERTY_CACHE_HASH_PC(pc,kshape) \ |
#define PROPERTY_CACHE_HASH_PC(pc,kshape) \ |
233 |
PROPERTY_CACHE_HASH(pc, kshape) |
PROPERTY_CACHE_HASH(pc, kshape) |
234 |
|
|
235 |
#define PROPERTY_CACHE_HASH_ATOM(atom,obj,pobj) \ |
#define PROPERTY_CACHE_HASH_ATOM(atom,obj) \ |
236 |
PROPERTY_CACHE_HASH((jsuword)(atom) >> 2, OBJ_SHAPE(obj)) |
PROPERTY_CACHE_HASH((jsuword)(atom) >> 2, OBJ_SHAPE(obj)) |
237 |
|
|
238 |
/* |
/* |
257 |
|
|
258 |
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS) |
#define SHAPE_OVERFLOW_BIT JS_BIT(32 - PCVCAP_TAGBITS) |
259 |
|
|
|
#ifndef JS_THREADSAFE |
|
|
# define js_GenerateShape(cx, gcLocked) js_GenerateShape (cx) |
|
|
#endif |
|
|
|
|
|
extern uint32 |
|
|
js_GenerateShape(JSContext *cx, JSBool gcLocked); |
|
|
|
|
260 |
struct JSPropCacheEntry { |
struct JSPropCacheEntry { |
261 |
jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */ |
jsbytecode *kpc; /* pc if vcap tag is <= 1, else atom */ |
262 |
jsuword kshape; /* key shape if pc, else obj for atom */ |
jsuword kshape; /* key shape if pc, else obj for atom */ |
263 |
jsuword vcap; /* value capability, see above */ |
jsuword vcap; /* value capability, see above */ |
264 |
jsuword vword; /* value word, see PCVAL_* below */ |
jsuword vword; /* value word, see PCVAL_* below */ |
265 |
|
|
266 |
|
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
267 |
|
bool adding() const { |
268 |
|
return PCVCAP_TAG(vcap) == 0 && kshape != PCVCAP_SHAPE(vcap); |
269 |
|
} |
270 |
|
#endif |
271 |
}; |
}; |
272 |
|
|
273 |
/* |
/* |
394 |
if (entry->kpc == pc && entry->kshape == kshape_) { \ |
if (entry->kpc == pc && entry->kshape == kshape_) { \ |
395 |
JSObject *tmp_; \ |
JSObject *tmp_; \ |
396 |
pobj = obj; \ |
pobj = obj; \ |
|
JS_LOCK_OBJ(cx, pobj); \ |
|
397 |
JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \ |
JS_ASSERT(PCVCAP_TAG(entry->vcap) <= 1); \ |
398 |
if (PCVCAP_TAG(entry->vcap) == 1 && \ |
if (PCVCAP_TAG(entry->vcap) == 1 && \ |
399 |
(tmp_ = LOCKED_OBJ_GET_PROTO(pobj)) != NULL && \ |
(tmp_ = OBJ_GET_PROTO(cx, pobj)) != NULL) { \ |
|
OBJ_IS_NATIVE(tmp_)) { \ |
|
|
JS_UNLOCK_OBJ(cx, pobj); \ |
|
400 |
pobj = tmp_; \ |
pobj = tmp_; \ |
|
JS_LOCK_OBJ(cx, pobj); \ |
|
401 |
} \ |
} \ |
402 |
if (PCVCAP_SHAPE(entry->vcap) == OBJ_SHAPE(pobj)) { \ |
\ |
403 |
|
if (JS_LOCK_OBJ_IF_SHAPE(cx, pobj, PCVCAP_SHAPE(entry->vcap))) { \ |
404 |
PCMETER(cache_->pchits++); \ |
PCMETER(cache_->pchits++); \ |
405 |
PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \ |
PCMETER(!PCVCAP_TAG(entry->vcap) || cache_->protopchits++); \ |
|
pobj = OBJ_SCOPE(pobj)->object; \ |
|
406 |
atom = NULL; \ |
atom = NULL; \ |
407 |
break; \ |
break; \ |
408 |
} \ |
} \ |
|
JS_UNLOCK_OBJ(cx, pobj); \ |
|
409 |
} \ |
} \ |
410 |
atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, &entry); \ |
atom = js_FullTestPropertyCache(cx, pc, &obj, &pobj, &entry); \ |
411 |
if (atom) \ |
if (atom) \ |
478 |
static JS_INLINE JSObject * |
static JS_INLINE JSObject * |
479 |
js_ComputeThisForFrame(JSContext *cx, JSStackFrame *fp) |
js_ComputeThisForFrame(JSContext *cx, JSStackFrame *fp) |
480 |
{ |
{ |
|
JSObject* obj; |
|
481 |
if (fp->flags & JSFRAME_COMPUTED_THIS) |
if (fp->flags & JSFRAME_COMPUTED_THIS) |
482 |
return fp->thisp; |
return fp->thisp; |
483 |
obj = js_ComputeThis(cx, JS_TRUE, fp->argv); |
JSObject* obj = js_ComputeThis(cx, JS_TRUE, fp->argv); |
484 |
if (!obj) |
if (!obj) |
485 |
return NULL; |
return NULL; |
486 |
fp->thisp = obj; |
fp->thisp = obj; |
559 |
extern JSBool |
extern JSBool |
560 |
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval); |
js_StrictlyEqual(JSContext *cx, jsval lval, jsval rval); |
561 |
|
|
562 |
|
/* === except that NaN is the same as NaN and -0 is not the same as +0. */ |
563 |
|
extern JSBool |
564 |
|
js_SameValue(jsval v1, jsval v2, JSContext *cx); |
565 |
|
|
566 |
extern JSBool |
extern JSBool |
567 |
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp); |
js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp); |
568 |
|
|
569 |
/* Work around liveconnect building this file as C on 1.9.1 branch */ |
#ifdef __cplusplus /* Allow inclusion from LiveConnect C files. */ |
|
#ifdef __cplusplus |
|
570 |
|
|
571 |
/* |
/* |
572 |
* Given an active context, a static scope level, and an upvar cookie, return |
* Given an active context, a static scope level, and an upvar cookie, return |
575 |
extern jsval& |
extern jsval& |
576 |
js_GetUpvar(JSContext *cx, uintN level, uintN cookie); |
js_GetUpvar(JSContext *cx, uintN level, uintN cookie); |
577 |
|
|
578 |
#endif |
#endif /* __cplusplus */ |
579 |
|
|
580 |
/* |
/* |
581 |
* 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 |