85 |
#if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___ |
#if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___ |
86 |
|
|
87 |
uint32 |
uint32 |
88 |
js_GenerateShape(JSContext *cx, JSBool gcLocked) |
js_GenerateShape(JSContext *cx, JSBool gcLocked, JSScopeProperty *sprop) |
89 |
{ |
{ |
90 |
JSRuntime *rt; |
JSRuntime *rt; |
91 |
uint32 shape; |
uint32 shape; |
92 |
|
JSTempValueRooter tvr; |
93 |
|
|
94 |
rt = cx->runtime; |
rt = cx->runtime; |
95 |
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen); |
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen); |
96 |
JS_ASSERT(shape != 0); |
JS_ASSERT(shape != 0); |
97 |
if (shape & SHAPE_OVERFLOW_BIT) { |
if (shape & SHAPE_OVERFLOW_BIT) { |
98 |
rt->gcPoke = JS_TRUE; |
rt->gcPoke = JS_TRUE; |
99 |
|
if (sprop) |
100 |
|
JS_PUSH_TEMP_ROOT_SPROP(cx, sprop, &tvr); |
101 |
js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL); |
js_GC(cx, gcLocked ? GC_LOCK_HELD : GC_NORMAL); |
102 |
|
if (sprop) |
103 |
|
JS_POP_TEMP_ROOT(cx, &tvr); |
104 |
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen); |
shape = JS_ATOMIC_INCREMENT(&rt->shapeGen); |
105 |
JS_ASSERT(shape != 0); |
JS_ASSERT(shape != 0); |
106 |
JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT, |
JS_ASSERT_IF(shape & SHAPE_OVERFLOW_BIT, |
314 |
JSPropCacheEntry *entry; |
JSPropCacheEntry *entry; |
315 |
uint32 vcap; |
uint32 vcap; |
316 |
|
|
317 |
JS_ASSERT(JS_UPTRDIFF(pc, cx->fp->script->code) < cx->fp->script->length); |
JS_ASSERT(uintN((cx->fp->imacpc ? cx->fp->imacpc : pc) - cx->fp->script->code) |
318 |
|
< cx->fp->script->length); |
319 |
|
|
320 |
op = (JSOp) *pc; |
op = (JSOp) *pc; |
321 |
cs = &js_CodeSpec[op]; |
cs = &js_CodeSpec[op]; |
1266 |
frame.annotation = NULL; |
frame.annotation = NULL; |
1267 |
frame.scopeChain = NULL; /* set below for real, after cx->fp is set */ |
frame.scopeChain = NULL; /* set below for real, after cx->fp is set */ |
1268 |
frame.regs = NULL; |
frame.regs = NULL; |
1269 |
|
frame.imacpc = NULL; |
1270 |
frame.slots = NULL; |
frame.slots = NULL; |
1271 |
frame.sharpDepth = 0; |
frame.sharpDepth = 0; |
1272 |
frame.sharpArray = NULL; |
frame.sharpArray = NULL; |
1499 |
frame.annotation = NULL; |
frame.annotation = NULL; |
1500 |
frame.sharpArray = NULL; |
frame.sharpArray = NULL; |
1501 |
} |
} |
1502 |
|
|
1503 |
|
frame.imacpc = NULL; |
1504 |
if (script->nslots != 0) { |
if (script->nslots != 0) { |
1505 |
frame.slots = js_AllocRawStack(cx, script->nslots, &mark); |
frame.slots = js_AllocRawStack(cx, script->nslots, &mark); |
1506 |
if (!frame.slots) { |
if (!frame.slots) { |
1773 |
|
|
1774 |
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) { |
if (OBJ_GET_CLASS(cx, obj2) == &js_FunctionClass) { |
1775 |
fun2 = GET_FUNCTION_PRIVATE(cx, obj2); |
fun2 = GET_FUNCTION_PRIVATE(cx, obj2); |
1776 |
if (!FUN_INTERPRETED(fun2) && fun2->u.n.clasp) |
if (!FUN_INTERPRETED(fun2) && |
1777 |
clasp = fun2->u.n.clasp; |
!(fun2->flags & JSFUN_TRACEABLE) && |
1778 |
|
fun2->u.n.u.clasp) { |
1779 |
|
clasp = fun2->u.n.u.clasp; |
1780 |
|
} |
1781 |
} |
} |
1782 |
} |
} |
1783 |
obj = js_NewObject(cx, clasp, proto, parent, 0); |
obj = js_NewObject(cx, clasp, proto, parent, 0); |
2011 |
prevop = (JSOp) regs->pc[-len]; |
prevop = (JSOp) regs->pc[-len]; |
2012 |
ndefs = js_CodeSpec[prevop].ndefs; |
ndefs = js_CodeSpec[prevop].ndefs; |
2013 |
if (ndefs != 0) { |
if (ndefs != 0) { |
|
if (prevop == JSOP_FORELEM && regs->sp[-1] == JSVAL_FALSE) |
|
|
--ndefs; |
|
2014 |
for (n = -ndefs; n < 0; n++) { |
for (n = -ndefs; n < 0; n++) { |
2015 |
char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], |
char *bytes = js_DecompileValueGenerator(cx, n, regs->sp[n], |
2016 |
NULL); |
NULL); |
2035 |
fputc('\n', tracefp); |
fputc('\n', tracefp); |
2036 |
} |
} |
2037 |
|
|
2038 |
fprintf(tracefp, "%4u: ", js_PCToLineNumber(cx, fp->script, regs->pc)); |
fprintf(tracefp, "%4u: ", |
2039 |
|
js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : regs->pc)); |
2040 |
js_Disassemble1(cx, fp->script, regs->pc, |
js_Disassemble1(cx, fp->script, regs->pc, |
2041 |
PTRDIFF(regs->pc, fp->script->code, jsbytecode), |
PTRDIFF(regs->pc, fp->script->code, jsbytecode), |
2042 |
JS_FALSE, tracefp); |
JS_FALSE, tracefp); |
2584 |
tr = TRACE_RECORDER(cx); |
tr = TRACE_RECORDER(cx); |
2585 |
SET_TRACE_RECORDER(cx, NULL); |
SET_TRACE_RECORDER(cx, NULL); |
2586 |
JS_TRACE_MONITOR(cx).onTrace = JS_FALSE; |
JS_TRACE_MONITOR(cx).onTrace = JS_FALSE; |
2587 |
|
/* |
2588 |
|
* ON_TRACE means either recording or coming from traced code. |
2589 |
|
* If there's no recorder (the latter case), don't care. |
2590 |
|
*/ |
2591 |
|
if (tr) { |
2592 |
|
if (tr->wasDeepAborted()) |
2593 |
|
tr->removeFragmentoReferences(); |
2594 |
|
else |
2595 |
|
tr->pushAbortStack(); |
2596 |
|
} |
2597 |
} |
} |
2598 |
#endif |
#endif |
2599 |
|
|
2621 |
|
|
2622 |
#define LOAD_ATOM(PCOFF) \ |
#define LOAD_ATOM(PCOFF) \ |
2623 |
JS_BEGIN_MACRO \ |
JS_BEGIN_MACRO \ |
2624 |
JS_ASSERT((size_t)(atoms - script->atomMap.vector) < \ |
JS_ASSERT(fp->imacpc \ |
2625 |
(size_t)(script->atomMap.length - \ |
? atoms == COMMON_ATOMS_START(&rt->atomState) && \ |
2626 |
GET_INDEX(regs.pc + PCOFF))); \ |
GET_INDEX(regs.pc + PCOFF) < js_common_atom_count \ |
2627 |
|
: (size_t)(atoms - script->atomMap.vector) < \ |
2628 |
|
(size_t)(script->atomMap.length - \ |
2629 |
|
GET_INDEX(regs.pc + PCOFF))); \ |
2630 |
atom = atoms[GET_INDEX(regs.pc + PCOFF)]; \ |
atom = atoms[GET_INDEX(regs.pc + PCOFF)]; \ |
2631 |
JS_END_MACRO |
JS_END_MACRO |
2632 |
|
|
2641 |
|
|
2642 |
#ifdef JS_TRACER |
#ifdef JS_TRACER |
2643 |
|
|
2644 |
#define MONITOR_BRANCH(oldpc) \ |
#define MONITOR_BRANCH() \ |
2645 |
JS_BEGIN_MACRO \ |
JS_BEGIN_MACRO \ |
2646 |
if (TRACING_ENABLED(cx)) { \ |
if (TRACING_ENABLED(cx)) { \ |
2647 |
ENABLE_TRACER(js_MonitorLoopEdge(cx, oldpc, inlineCallCount)); \ |
ENABLE_TRACER(js_MonitorLoopEdge(cx, inlineCallCount)); \ |
2648 |
fp = cx->fp; \ |
fp = cx->fp; \ |
2649 |
script = fp->script; \ |
script = fp->script; \ |
2650 |
atoms = script->atomMap.vector; \ |
atoms = script->atomMap.vector; \ |
2651 |
currentVersion = (JSVersion) script->version; \ |
currentVersion = (JSVersion) script->version; \ |
2652 |
JS_ASSERT(fp->regs == ®s); \ |
JS_ASSERT(fp->regs == ®s); \ |
2653 |
|
if (cx->throwing) \ |
2654 |
|
goto error; \ |
2655 |
} \ |
} \ |
2656 |
JS_END_MACRO |
JS_END_MACRO |
2657 |
|
|
2658 |
#else /* !JS_TRACER */ |
#else /* !JS_TRACER */ |
2659 |
|
|
2660 |
#define MONITOR_BRANCH(oldpc) ((void) 0) |
#define MONITOR_BRANCH() ((void) 0) |
2661 |
|
|
2662 |
#endif /* !JS_TRACER */ |
#endif /* !JS_TRACER */ |
2663 |
|
|
2678 |
regs.pc += n; \ |
regs.pc += n; \ |
2679 |
if (n <= 0) { \ |
if (n <= 0) { \ |
2680 |
CHECK_BRANCH(); \ |
CHECK_BRANCH(); \ |
2681 |
MONITOR_BRANCH(regs.pc - n); \ |
MONITOR_BRANCH(); \ |
2682 |
} \ |
} \ |
2683 |
op = (JSOp) *regs.pc; \ |
op = (JSOp) *regs.pc; \ |
2684 |
DO_OP(); \ |
DO_OP(); \ |
2759 |
|
|
2760 |
LOAD_INTERRUPT_HANDLER(cx); |
LOAD_INTERRUPT_HANDLER(cx); |
2761 |
|
|
2762 |
/* Initialize the pc and pc registers unless we're resuming a generator. */ |
#if !JS_HAS_GENERATORS |
2763 |
|
JS_ASSERT(!fp->regs); |
2764 |
|
#else |
2765 |
|
/* Initialize the pc and sp registers unless we're resuming a generator. */ |
2766 |
if (JS_LIKELY(!fp->regs)) { |
if (JS_LIKELY(!fp->regs)) { |
2767 |
|
#endif |
2768 |
ASSERT_NOT_THROWING(cx); |
ASSERT_NOT_THROWING(cx); |
2769 |
regs.pc = script->code; |
regs.pc = script->code; |
2770 |
regs.sp = StackBase(fp); |
regs.sp = StackBase(fp); |
2771 |
fp->regs = ®s; |
fp->regs = ®s; |
2772 |
|
#if JS_HAS_GENERATORS |
2773 |
} else { |
} else { |
2774 |
JSGenerator *gen; |
JSGenerator *gen; |
2775 |
|
|
2797 |
goto error; |
goto error; |
2798 |
} |
} |
2799 |
} |
} |
2800 |
|
#endif /* JS_HAS_GENERATORS */ |
2801 |
|
|
2802 |
/* |
/* |
2803 |
* It is important that "op" be initialized before calling DO_OP because |
* It is important that "op" be initialized before calling DO_OP because |
2878 |
|
|
2879 |
/* No-ops for ease of decompilation. */ |
/* No-ops for ease of decompilation. */ |
2880 |
ADD_EMPTY_CASE(JSOP_NOP) |
ADD_EMPTY_CASE(JSOP_NOP) |
|
ADD_EMPTY_CASE(JSOP_GROUP) |
|
2881 |
ADD_EMPTY_CASE(JSOP_CONDSWITCH) |
ADD_EMPTY_CASE(JSOP_CONDSWITCH) |
2882 |
ADD_EMPTY_CASE(JSOP_TRY) |
ADD_EMPTY_CASE(JSOP_TRY) |
2883 |
ADD_EMPTY_CASE(JSOP_FINALLY) |
ADD_EMPTY_CASE(JSOP_FINALLY) |
2962 |
* will be false after the inline_return label. |
* will be false after the inline_return label. |
2963 |
*/ |
*/ |
2964 |
ASSERT_NOT_THROWING(cx); |
ASSERT_NOT_THROWING(cx); |
2965 |
|
|
2966 |
|
if (fp->imacpc) { |
2967 |
|
/* |
2968 |
|
* If we are at the end of an imacro, return to its caller in |
2969 |
|
* the current frame. |
2970 |
|
*/ |
2971 |
|
JS_ASSERT(op == JSOP_STOP); |
2972 |
|
|
2973 |
|
end_imacro: |
2974 |
|
JS_ASSERT((uintN)(regs.sp - fp->slots) <= script->nslots); |
2975 |
|
regs.pc = fp->imacpc + js_CodeSpec[*fp->imacpc].length; |
2976 |
|
fp->imacpc = NULL; |
2977 |
|
atoms = script->atomMap.vector; |
2978 |
|
op = JSOp(*regs.pc); |
2979 |
|
DO_OP(); |
2980 |
|
} |
2981 |
|
|
2982 |
JS_ASSERT(regs.sp == StackBase(fp)); |
JS_ASSERT(regs.sp == StackBase(fp)); |
2983 |
if ((fp->flags & JSFRAME_CONSTRUCTING) && |
if ((fp->flags & JSFRAME_CONSTRUCTING) && |
2984 |
JSVAL_IS_PRIMITIVE(fp->rval)) { |
JSVAL_IS_PRIMITIVE(fp->rval)) { |
3079 |
/* Resume execution in the calling frame. */ |
/* Resume execution in the calling frame. */ |
3080 |
inlineCallCount--; |
inlineCallCount--; |
3081 |
if (JS_LIKELY(ok)) { |
if (JS_LIKELY(ok)) { |
3082 |
#ifdef JS_TRACER |
TRACE_0(LeaveFrame); |
|
if (TRACE_RECORDER(cx)) |
|
|
RECORD(LeaveFrame); |
|
|
#endif |
|
3083 |
JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH); |
JS_ASSERT(js_CodeSpec[*regs.pc].length == JSOP_CALL_LENGTH); |
3084 |
len = JSOP_CALL_LENGTH; |
len = JSOP_CALL_LENGTH; |
3085 |
DO_NEXT_OP(len); |
DO_NEXT_OP(len); |
3226 |
END_CASE(JSOP_IN) |
END_CASE(JSOP_IN) |
3227 |
|
|
3228 |
BEGIN_CASE(JSOP_ITER) |
BEGIN_CASE(JSOP_ITER) |
|
flags = regs.pc[1]; |
|
3229 |
JS_ASSERT(regs.sp > StackBase(fp)); |
JS_ASSERT(regs.sp > StackBase(fp)); |
3230 |
|
flags = regs.pc[1]; |
3231 |
if (!js_ValueToIterator(cx, flags, ®s.sp[-1])) |
if (!js_ValueToIterator(cx, flags, ®s.sp[-1])) |
3232 |
goto error; |
goto error; |
3233 |
|
LOAD_INTERRUPT_HANDLER(cx); |
3234 |
JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1])); |
JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1])); |
3235 |
|
PUSH(JSVAL_VOID); |
3236 |
END_CASE(JSOP_ITER) |
END_CASE(JSOP_ITER) |
3237 |
|
|
3238 |
BEGIN_CASE(JSOP_FORPROP) |
BEGIN_CASE(JSOP_NEXTITER) |
3239 |
|
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3240 |
|
JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-2])); |
3241 |
|
if (!js_CallIteratorNext(cx, JSVAL_TO_OBJECT(regs.sp[-2]), ®s.sp[-1])) |
3242 |
|
goto error; |
3243 |
|
LOAD_INTERRUPT_HANDLER(cx); |
3244 |
|
rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE); |
3245 |
|
PUSH(rval); |
3246 |
|
TRACE_0(IteratorNextComplete); |
3247 |
|
END_CASE(JSOP_NEXTITER) |
3248 |
|
|
3249 |
|
BEGIN_CASE(JSOP_ENDITER) |
3250 |
/* |
/* |
3251 |
* Handle JSOP_FORPROP first, so the cost of the goto do_forinloop |
* Decrease the stack pointer even when !ok -- see comments in the |
3252 |
* is not paid for the more common cases. |
* exception capturing code for details. |
3253 |
*/ |
*/ |
3254 |
LOAD_ATOM(0); |
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3255 |
id = ATOM_TO_JSID(atom); |
ok = js_CloseIterator(cx, regs.sp[-2]); |
3256 |
i = -2; |
regs.sp -= 2; |
3257 |
goto do_forinloop; |
if (!ok) |
3258 |
|
goto error; |
3259 |
|
END_CASE(JSOP_ENDITER) |
3260 |
|
|
3261 |
|
BEGIN_CASE(JSOP_FORARG) |
3262 |
|
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3263 |
|
slot = GET_ARGNO(regs.pc); |
3264 |
|
JS_ASSERT(slot < fp->fun->nargs); |
3265 |
|
fp->argv[slot] = regs.sp[-1]; |
3266 |
|
END_CASE(JSOP_FORARG) |
3267 |
|
|
3268 |
|
BEGIN_CASE(JSOP_FORLOCAL) |
3269 |
|
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3270 |
|
slot = GET_SLOTNO(regs.pc); |
3271 |
|
JS_ASSERT(slot < fp->script->nslots); |
3272 |
|
vp = &fp->slots[slot]; |
3273 |
|
GC_POKE(cx, *vp); |
3274 |
|
*vp = regs.sp[-1]; |
3275 |
|
END_CASE(JSOP_FORLOCAL) |
3276 |
|
|
3277 |
BEGIN_CASE(JSOP_FORNAME) |
BEGIN_CASE(JSOP_FORNAME) |
3278 |
|
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3279 |
LOAD_ATOM(0); |
LOAD_ATOM(0); |
3280 |
id = ATOM_TO_JSID(atom); |
id = ATOM_TO_JSID(atom); |
3281 |
/* FALL THROUGH */ |
if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) |
3282 |
|
goto error; |
3283 |
|
if (prop) |
3284 |
|
OBJ_DROP_PROPERTY(cx, obj2, prop); |
3285 |
|
ok = OBJ_SET_PROPERTY(cx, obj, id, ®s.sp[-1]); |
3286 |
|
if (!ok) |
3287 |
|
goto error; |
3288 |
|
END_CASE(JSOP_FORNAME) |
3289 |
|
|
3290 |
BEGIN_CASE(JSOP_FORARG) |
BEGIN_CASE(JSOP_FORPROP) |
3291 |
BEGIN_CASE(JSOP_FORCONST) |
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3292 |
BEGIN_CASE(JSOP_FORLOCAL) |
LOAD_ATOM(0); |
3293 |
/* |
id = ATOM_TO_JSID(atom); |
3294 |
* These bytecodes don't require any lval computation here, |
FETCH_OBJECT(cx, -1, lval, obj); |
3295 |
* because they address slots on the stack (in fp->args or |
ok = OBJ_SET_PROPERTY(cx, obj, id, ®s.sp[-2]); |
3296 |
* fp->slots). |
if (!ok) |
3297 |
*/ |
goto error; |
3298 |
/* FALL THROUGH */ |
regs.sp--; |
3299 |
|
END_CASE(JSOP_FORPROP) |
3300 |
|
|
3301 |
BEGIN_CASE(JSOP_FORELEM) |
BEGIN_CASE(JSOP_FORELEM) |
3302 |
/* |
/* |
3303 |
* JSOP_FORELEM simply initializes or updates the iteration state |
* JSOP_FORELEM simply dups the property identifier at top of stack |
3304 |
* and leaves the index expression evaluation and assignment to the |
* and lets the subsequent JSOP_ENUMELEM opcode sequence handle the |
3305 |
* enumerator until after the next property has been acquired, via |
* left-hand side expression evaluation and assignment. This opcode |
3306 |
* a JSOP_ENUMELEM bytecode. |
* exists solely to help the decompiler. |
|
*/ |
|
|
i = -1; |
|
|
|
|
|
do_forinloop: |
|
|
/* |
|
|
* Reach under the top of stack to find our property iterator, a |
|
|
* JSObject that contains the iteration state. |
|
3307 |
*/ |
*/ |
3308 |
JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[i])); |
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3309 |
if (!js_CallIteratorNext(cx, JSVAL_TO_OBJECT(regs.sp[i]), &rval)) |
rval = FETCH_OPND(-1); |
3310 |
goto error; |
PUSH(rval); |
3311 |
if (rval == JSVAL_HOLE) { |
END_CASE(JSOP_FORELEM) |
|
rval = JSVAL_FALSE; |
|
|
#ifdef JS_TRACER |
|
|
if (TRACE_RECORDER(cx)) { |
|
|
js_AbortRecording(cx, regs.pc, "Untraceable for-in loop"); |
|
|
ENABLE_TRACER(0); |
|
|
} |
|
|
#endif |
|
|
goto end_forinloop; |
|
|
} |
|
|
|
|
|
switch (op) { |
|
|
case JSOP_FORARG: |
|
|
slot = GET_ARGNO(regs.pc); |
|
|
JS_ASSERT(slot < fp->fun->nargs); |
|
|
fp->argv[slot] = rval; |
|
|
break; |
|
|
|
|
|
case JSOP_FORCONST: |
|
|
/* Don't update the const slot. */ |
|
|
break; |
|
|
|
|
|
case JSOP_FORLOCAL: |
|
|
slot = GET_SLOTNO(regs.pc); |
|
|
JS_ASSERT(slot < fp->script->nslots); |
|
|
vp = &fp->slots[slot]; |
|
|
GC_POKE(cx, *vp); |
|
|
*vp = rval; |
|
|
break; |
|
|
|
|
|
case JSOP_FORELEM: |
|
|
/* FORELEM is not a SET operation, it's more like BINDNAME. */ |
|
|
PUSH_OPND(rval); |
|
|
break; |
|
|
|
|
|
case JSOP_FORPROP: |
|
|
/* |
|
|
* We fetch object here to ensure that the iterator is called |
|
|
* even if lval is null or undefined that throws in |
|
|
* FETCH_OBJECT. See bug 372331. |
|
|
*/ |
|
|
FETCH_OBJECT(cx, -1, lval, obj); |
|
|
goto set_for_property; |
|
|
|
|
|
default: |
|
|
JS_ASSERT(op == JSOP_FORNAME); |
|
|
|
|
|
/* |
|
|
* We find property here after the iterator call to ensure |
|
|
* that we take into account side effects of the iterator |
|
|
* call. See bug 372331. |
|
|
*/ |
|
|
if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) |
|
|
goto error; |
|
|
if (prop) |
|
|
OBJ_DROP_PROPERTY(cx, obj2, prop); |
|
|
|
|
|
set_for_property: |
|
|
/* Set the variable obj[id] to refer to rval. */ |
|
|
fp->flags |= JSFRAME_ASSIGNING; |
|
|
ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); |
|
|
fp->flags &= ~JSFRAME_ASSIGNING; |
|
|
if (!ok) |
|
|
goto error; |
|
|
break; |
|
|
} |
|
|
|
|
|
/* Push true to keep looping through properties. */ |
|
|
rval = JSVAL_TRUE; |
|
|
|
|
|
end_forinloop: |
|
|
regs.sp += i + 1; |
|
|
PUSH_OPND(rval); |
|
|
len = js_CodeSpec[op].length; |
|
|
DO_NEXT_OP(len); |
|
3312 |
|
|
3313 |
BEGIN_CASE(JSOP_DUP) |
BEGIN_CASE(JSOP_DUP) |
3314 |
JS_ASSERT(regs.sp > StackBase(fp)); |
JS_ASSERT(regs.sp > StackBase(fp)); |
3324 |
PUSH(rval); |
PUSH(rval); |
3325 |
END_CASE(JSOP_DUP2) |
END_CASE(JSOP_DUP2) |
3326 |
|
|
3327 |
|
BEGIN_CASE(JSOP_SWAP) |
3328 |
|
JS_ASSERT(regs.sp - 2 >= StackBase(fp)); |
3329 |
|
lval = FETCH_OPND(-2); |
3330 |
|
rval = FETCH_OPND(-1); |
3331 |
|
STORE_OPND(-1, lval); |
3332 |
|
STORE_OPND(-2, rval); |
3333 |
|
END_CASE(JSOP_SWAP) |
3334 |
|
|
3335 |
#define PROPERTY_OP(n, call) \ |
#define PROPERTY_OP(n, call) \ |
3336 |
JS_BEGIN_MACRO \ |
JS_BEGIN_MACRO \ |
3337 |
/* Fetch the left part and resolve it to a non-null object. */ \ |
/* Fetch the left part and resolve it to a non-null object. */ \ |
3517 |
PUSH_OPND(OBJECT_TO_JSVAL(obj)); |
PUSH_OPND(OBJECT_TO_JSVAL(obj)); |
3518 |
END_CASE(JSOP_BINDNAME) |
END_CASE(JSOP_BINDNAME) |
3519 |
|
|
3520 |
|
BEGIN_CASE(JSOP_IMACOP) |
3521 |
|
JS_ASSERT(JS_UPTRDIFF(fp->imacpc, script->code) < script->length); |
3522 |
|
op = JSOp(*fp->imacpc); |
3523 |
|
DO_OP(); |
3524 |
|
|
3525 |
#define BITWISE_OP(OP) \ |
#define BITWISE_OP(OP) \ |
3526 |
JS_BEGIN_MACRO \ |
JS_BEGIN_MACRO \ |
3527 |
FETCH_INT(cx, -2, i); \ |
FETCH_INT(cx, -2, i); \ |
4639 |
} |
} |
4640 |
#ifdef JS_TRACER |
#ifdef JS_TRACER |
4641 |
if (!entry && TRACE_RECORDER(cx)) { |
if (!entry && TRACE_RECORDER(cx)) { |
4642 |
js_AbortRecording(cx, NULL, "SetPropUncached"); |
js_AbortRecording(cx, "SetPropUncached"); |
4643 |
ENABLE_TRACER(0); |
ENABLE_TRACER(0); |
4644 |
} |
} |
4645 |
#endif |
#endif |
4716 |
rval = FETCH_OPND(-1); |
rval = FETCH_OPND(-1); |
4717 |
FETCH_OBJECT(cx, -3, lval, obj); |
FETCH_OBJECT(cx, -3, lval, obj); |
4718 |
FETCH_ELEMENT_ID(obj, -2, id); |
FETCH_ELEMENT_ID(obj, -2, id); |
4719 |
if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) { |
do { |
4720 |
jsuint length; |
if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) { |
4721 |
|
jsuint length; |
4722 |
|
|
4723 |
length = ARRAY_DENSE_LENGTH(obj); |
length = ARRAY_DENSE_LENGTH(obj); |
4724 |
i = JSID_TO_INT(id); |
i = JSID_TO_INT(id); |
4725 |
if ((jsuint)i < length) { |
if ((jsuint)i < length) { |
4726 |
if (obj->dslots[i] == JSVAL_HOLE) { |
if (obj->dslots[i] == JSVAL_HOLE) { |
4727 |
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH]) |
if (rt->anyArrayProtoHasElement) |
4728 |
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1; |
break; |
4729 |
obj->fslots[JSSLOT_ARRAY_COUNT]++; |
if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH]) |
4730 |
|
obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1; |
4731 |
|
obj->fslots[JSSLOT_ARRAY_COUNT]++; |
4732 |
|
} |
4733 |
|
obj->dslots[i] = rval; |
4734 |
|
goto end_setelem; |
4735 |
} |
} |
|
obj->dslots[i] = rval; |
|
|
goto end_setelem; |
|
4736 |
} |
} |
4737 |
} |
} while (0); |
4738 |
if (!OBJ_SET_PROPERTY(cx, obj, id, &rval)) |
if (!OBJ_SET_PROPERTY(cx, obj, id, &rval)) |
4739 |
goto error; |
goto error; |
4740 |
end_setelem: |
end_setelem: |
4792 |
goto error; |
goto error; |
4793 |
regs.sp = vp + 1; |
regs.sp = vp + 1; |
4794 |
LOAD_INTERRUPT_HANDLER(cx); |
LOAD_INTERRUPT_HANDLER(cx); |
4795 |
JS_ASSERT(regs.pc[JSOP_NEW_LENGTH] == JSOP_RESUME); |
END_CASE(JSOP_NEW) |
|
len = JSOP_NEW_LENGTH + JSOP_RESUME_LENGTH; |
|
|
END_VARLEN_CASE |
|
4796 |
|
|
4797 |
|
BEGIN_CASE(JSOP_APPLY) |
4798 |
|
{ |
4799 |
|
argc = GET_ARGC(regs.pc); |
4800 |
|
vp = regs.sp - (argc + 2); |
4801 |
|
lval = *vp; |
4802 |
|
if (!VALUE_IS_FUNCTION(cx, lval)) |
4803 |
|
goto do_call; |
4804 |
|
obj = JSVAL_TO_OBJECT(lval); |
4805 |
|
fun = GET_FUNCTION_PRIVATE(cx, obj); |
4806 |
|
if (FUN_INTERPRETED(fun)) |
4807 |
|
goto do_call; |
4808 |
|
|
4809 |
|
bool apply = (JSFastNative)fun->u.n.native == js_fun_apply; |
4810 |
|
if (!apply && (JSFastNative)fun->u.n.native != js_fun_call) |
4811 |
|
goto do_call; |
4812 |
|
|
4813 |
|
/* |
4814 |
|
* If the second arg to apply is null or void, treat it as an empty |
4815 |
|
* array. |
4816 |
|
*/ |
4817 |
|
jsuint applylen = 0; |
4818 |
|
if (apply && argc >= 2 && |
4819 |
|
!JSVAL_IS_VOID(vp[3]) && !JSVAL_IS_NULL(vp[3])) { |
4820 |
|
/* |
4821 |
|
* Fall back on js_Invoke when the array argument has a wrong |
4822 |
|
* type or when it has too many elements to fit into the |
4823 |
|
* current stack chunk. |
4824 |
|
*/ |
4825 |
|
if (!JSVAL_IS_OBJECT(vp[3])) |
4826 |
|
goto do_call; |
4827 |
|
|
4828 |
|
JSBool arraylike; |
4829 |
|
JSObject* aobj = JSVAL_TO_OBJECT(vp[3]); |
4830 |
|
if (!js_IsArrayLike(cx, aobj, &arraylike, &applylen)) |
4831 |
|
goto error; |
4832 |
|
if (!arraylike || applylen > ARGC_LIMIT) |
4833 |
|
goto do_call; |
4834 |
|
|
4835 |
|
JSArena *a = cx->stackPool.current; |
4836 |
|
JS_ASSERT(jsuword(vp + 2) <= a->limit); |
4837 |
|
|
4838 |
|
/* |
4839 |
|
* We need space for applylen elements plus an extra slot to |
4840 |
|
* temporary root the array object when we unpack its elements |
4841 |
|
* using OBJ_GET_PROPERTY below. |
4842 |
|
*/ |
4843 |
|
if (a->limit - jsuword(vp + 2) < (applylen + 1) * sizeof(jsval)) |
4844 |
|
goto do_call; |
4845 |
|
} |
4846 |
|
|
4847 |
|
if (!VALUE_IS_FUNCTION(cx, vp[1])) |
4848 |
|
goto do_call; |
4849 |
|
vp[0] = vp[1]; |
4850 |
|
|
4851 |
|
if (argc == 0) { |
4852 |
|
/* |
4853 |
|
* Call fun with its global object as the 'this' param if |
4854 |
|
* no args. |
4855 |
|
*/ |
4856 |
|
obj = NULL; |
4857 |
|
} else { |
4858 |
|
/* Convert the first arg to 'this'. */ |
4859 |
|
if (!JSVAL_IS_PRIMITIVE(vp[2])) |
4860 |
|
obj = JSVAL_TO_OBJECT(vp[2]); |
4861 |
|
else if (!js_ValueToObject(cx, vp[2], &obj)) |
4862 |
|
goto error; |
4863 |
|
} |
4864 |
|
vp[1] = OBJECT_TO_JSVAL(obj); |
4865 |
|
|
4866 |
|
if (!apply) { |
4867 |
|
if (argc != 0) { |
4868 |
|
--argc; |
4869 |
|
memmove(vp + 2, vp + 3, argc * sizeof *vp); |
4870 |
|
} |
4871 |
|
} else if (applylen == 0) { |
4872 |
|
argc = 0; |
4873 |
|
} else { |
4874 |
|
/* |
4875 |
|
* Make room for missing arguments to the right including the |
4876 |
|
* temporary root nulling any extra stack slots for GC safety. |
4877 |
|
*/ |
4878 |
|
jsval* newsp = vp + 2 + applylen + 1; |
4879 |
|
if (newsp > regs.sp) { |
4880 |
|
JSArena *a = cx->stackPool.current; |
4881 |
|
JS_ASSERT(jsuword(newsp) <= a->limit); /* see above */ |
4882 |
|
if ((jsuword) newsp > a->avail) |
4883 |
|
a->avail = (jsuword) newsp; |
4884 |
|
memset(vp + 2 + argc, 0, (applylen - argc) * sizeof(jsval)); |
4885 |
|
} |
4886 |
|
|
4887 |
|
JSObject *aobj = JSVAL_TO_OBJECT(vp[3]); |
4888 |
|
newsp[-1] = vp[3]; |
4889 |
|
regs.sp = newsp; |
4890 |
|
|
4891 |
|
/* Expand array content onto the stack. */ |
4892 |
|
for (i = 0; i < jsint(applylen); i++) { |
4893 |
|
id = INT_TO_JSID(i); |
4894 |
|
if (!OBJ_GET_PROPERTY(cx, aobj, id, &vp[2 + i])) { |
4895 |
|
/* |
4896 |
|
* There is no good way to restore the original stack |
4897 |
|
* state here, but it is in a reasonable state with |
4898 |
|
* either original elements or nulls for all arguments |
4899 |
|
* we didn't unpack yet, so we leave it at that. |
4900 |
|
*/ |
4901 |
|
goto error; |
4902 |
|
} |
4903 |
|
} |
4904 |
|
argc = applylen; |
4905 |
|
} |
4906 |
|
regs.sp = vp + 2 + argc; |
4907 |
|
goto do_call_with_specified_vp_and_argc; |
4908 |
|
} |
4909 |
|
|
4910 |
BEGIN_CASE(JSOP_CALL) |
BEGIN_CASE(JSOP_CALL) |
4911 |
BEGIN_CASE(JSOP_EVAL) |
BEGIN_CASE(JSOP_EVAL) |
4912 |
|
do_call: |
4913 |
argc = GET_ARGC(regs.pc); |
argc = GET_ARGC(regs.pc); |
4914 |
vp = regs.sp - (argc + 2); |
vp = regs.sp - (argc + 2); |
4915 |
|
|
4916 |
|
do_call_with_specified_vp_and_argc: |
4917 |
lval = *vp; |
lval = *vp; |
4918 |
if (VALUE_IS_FUNCTION(cx, lval)) { |
if (VALUE_IS_FUNCTION(cx, lval)) { |
4919 |
obj = JSVAL_TO_OBJECT(lval); |
obj = JSVAL_TO_OBJECT(lval); |
5032 |
newifp->frame.thisp = (JSObject *)vp[1]; |
newifp->frame.thisp = (JSObject *)vp[1]; |
5033 |
|
|
5034 |
newifp->frame.regs = NULL; |
newifp->frame.regs = NULL; |
5035 |
|
newifp->frame.imacpc = NULL; |
5036 |
newifp->frame.slots = newsp; |
newifp->frame.slots = newsp; |
5037 |
|
|
5038 |
/* Push void to initialize local variables. */ |
/* Push void to initialize local variables. */ |
5072 |
newifp->frame.regs = ®s; |
newifp->frame.regs = ®s; |
5073 |
cx->fp = fp = &newifp->frame; |
cx->fp = fp = &newifp->frame; |
5074 |
|
|
5075 |
#ifdef JS_TRACER |
TRACE_0(EnterFrame); |
|
if (TRACE_RECORDER(cx)) |
|
|
RECORD(EnterFrame); |
|
|
#endif |
|
5076 |
|
|
5077 |
inlineCallCount++; |
inlineCallCount++; |
5078 |
JS_RUNTIME_METER(rt, inlineCalls); |
JS_RUNTIME_METER(rt, inlineCalls); |
5127 |
regs.sp = vp + 1; |
regs.sp = vp + 1; |
5128 |
if (!ok) |
if (!ok) |
5129 |
goto error; |
goto error; |
5130 |
|
TRACE_0(FastNativeCallComplete); |
5131 |
goto end_call; |
goto end_call; |
5132 |
} |
} |
5133 |
} |
} |
5173 |
cx->rval2set = JS_FALSE; |
cx->rval2set = JS_FALSE; |
5174 |
} |
} |
5175 |
#endif /* JS_HAS_LVALUE_RETURN */ |
#endif /* JS_HAS_LVALUE_RETURN */ |
5176 |
JS_ASSERT(regs.pc[JSOP_CALL_LENGTH] == JSOP_RESUME); |
END_CASE(JSOP_CALL) |
5177 |
len = JSOP_CALL_LENGTH + JSOP_RESUME_LENGTH; |
|
|
END_VARLEN_CASE |
|
|
|
|
|
BEGIN_CASE(JSOP_RESUME) |
|
|
/* This case is not truly empty. The tracer is invoked transparently. */ |
|
|
END_CASE(JSOP_RESUME) |
|
|
|
|
5178 |
#if JS_HAS_LVALUE_RETURN |
#if JS_HAS_LVALUE_RETURN |
5179 |
BEGIN_CASE(JSOP_SETCALL) |
BEGIN_CASE(JSOP_SETCALL) |
5180 |
argc = GET_ARGC(regs.pc); |
argc = GET_ARGC(regs.pc); |
5247 |
if (!prop) { |
if (!prop) { |
5248 |
/* Kludge to allow (typeof foo == "undefined") tests. */ |
/* Kludge to allow (typeof foo == "undefined") tests. */ |
5249 |
endpc = script->code + script->length; |
endpc = script->code + script->length; |
5250 |
for (pc2 = regs.pc + JSOP_NAME_LENGTH; pc2 < endpc; pc2++) { |
op2 = (JSOp) regs.pc[JSOP_NAME_LENGTH]; |
5251 |
op2 = (JSOp)*pc2; |
if (op2 == JSOP_TYPEOF) { |
5252 |
if (op2 == JSOP_TYPEOF) { |
PUSH_OPND(JSVAL_VOID); |
5253 |
PUSH_OPND(JSVAL_VOID); |
len = JSOP_NAME_LENGTH; |
5254 |
len = JSOP_NAME_LENGTH; |
DO_NEXT_OP(len); |
|
DO_NEXT_OP(len); |
|
|
} |
|
|
if (op2 != JSOP_GROUP) |
|
|
break; |
|
5255 |
} |
} |
5256 |
goto atom_not_defined; |
goto atom_not_defined; |
5257 |
} |
} |
6832 |
} |
} |
6833 |
END_CASE(JSOP_LEAVEBLOCK) |
END_CASE(JSOP_LEAVEBLOCK) |
6834 |
|
|
|
BEGIN_CASE(JSOP_ENDITER) |
|
|
/* |
|
|
* Decrease the stack pointer even when !ok, see comments in the |
|
|
* exception capturing code for details. |
|
|
*/ |
|
|
ok = js_CloseIterator(cx, regs.sp[-1]); |
|
|
regs.sp--; |
|
|
if (!ok) |
|
|
goto error; |
|
|
END_CASE(JSOP_ENDITER) |
|
|
|
|
6835 |
#if JS_HAS_GENERATORS |
#if JS_HAS_GENERATORS |
6836 |
BEGIN_CASE(JSOP_GENERATOR) |
BEGIN_CASE(JSOP_GENERATOR) |
6837 |
ASSERT_NOT_THROWING(cx); |
ASSERT_NOT_THROWING(cx); |
6932 |
L_JSOP_DEFXMLNS: |
L_JSOP_DEFXMLNS: |
6933 |
# endif |
# endif |
6934 |
|
|
6935 |
L_JSOP_UNUSED76: |
L_JSOP_UNUSED131: |
|
L_JSOP_UNUSED77: |
|
|
L_JSOP_UNUSED78: |
|
|
L_JSOP_UNUSED79: |
|
6936 |
L_JSOP_UNUSED201: |
L_JSOP_UNUSED201: |
6937 |
L_JSOP_UNUSED202: |
L_JSOP_UNUSED202: |
6938 |
L_JSOP_UNUSED203: |
L_JSOP_UNUSED203: |
6940 |
L_JSOP_UNUSED205: |
L_JSOP_UNUSED205: |
6941 |
L_JSOP_UNUSED206: |
L_JSOP_UNUSED206: |
6942 |
L_JSOP_UNUSED207: |
L_JSOP_UNUSED207: |
6943 |
|
L_JSOP_UNUSED208: |
6944 |
|
L_JSOP_UNUSED209: |
6945 |
L_JSOP_UNUSED219: |
L_JSOP_UNUSED219: |
6946 |
L_JSOP_UNUSED226: |
L_JSOP_UNUSED226: |
6947 |
|
|
6977 |
#endif /* !JS_THREADED_INTERP */ |
#endif /* !JS_THREADED_INTERP */ |
6978 |
|
|
6979 |
error: |
error: |
6980 |
|
if (fp->imacpc && cx->throwing) { |
6981 |
|
// To keep things simple, we hard-code imacro exception handlers here. |
6982 |
|
if (*fp->imacpc == JSOP_NEXTITER) { |
6983 |
|
JS_ASSERT(*regs.pc == JSOP_CALL); |
6984 |
|
if (js_ValueIsStopIteration(cx->exception)) { |
6985 |
|
cx->throwing = JS_FALSE; |
6986 |
|
cx->exception = JSVAL_VOID; |
6987 |
|
regs.sp[-1] = JSVAL_HOLE; |
6988 |
|
PUSH(JSVAL_FALSE); |
6989 |
|
goto end_imacro; |
6990 |
|
} |
6991 |
|
} |
6992 |
|
|
6993 |
|
// Handle other exceptions as if they came from the imacro-calling pc. |
6994 |
|
regs.pc = fp->imacpc; |
6995 |
|
fp->imacpc = NULL; |
6996 |
|
atoms = script->atomMap.vector; |
6997 |
|
} |
6998 |
|
|
6999 |
JS_ASSERT((size_t)(regs.pc - script->code) < script->length); |
JS_ASSERT((size_t)(regs.pc - script->code) < script->length); |
7000 |
if (!cx->throwing) { |
if (!cx->throwing) { |
7001 |
/* This is an error, not a catchable exception, quit the frame ASAP. */ |
/* This is an error, not a catchable exception, quit the frame ASAP. */ |
7079 |
} |
} |
7080 |
|
|
7081 |
switch (tn->kind) { |
switch (tn->kind) { |
7082 |
case JSTN_CATCH: |
case JSTRY_CATCH: |
7083 |
JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK); |
JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK); |
7084 |
|
|
7085 |
#if JS_HAS_GENERATORS |
#if JS_HAS_GENERATORS |
7096 |
len = 0; |
len = 0; |
7097 |
DO_NEXT_OP(len); |
DO_NEXT_OP(len); |
7098 |
|
|
7099 |
case JSTN_FINALLY: |
case JSTRY_FINALLY: |
7100 |
/* |
/* |
7101 |
* Push (true, exception) pair for finally to indicate that |
* Push (true, exception) pair for finally to indicate that |
7102 |
* [retsub] should rethrow the exception. |
* [retsub] should rethrow the exception. |
7107 |
len = 0; |
len = 0; |
7108 |
DO_NEXT_OP(len); |
DO_NEXT_OP(len); |
7109 |
|
|
7110 |
case JSTN_ITER: |
case JSTRY_ITER: |
7111 |
/* |
/* |
7112 |
* This is similar to JSOP_ENDITER in the interpreter loop |
* This is similar to JSOP_ENDITER in the interpreter loop, |
7113 |
* except the code now uses a reserved stack slot to save and |
* except the code now uses the stack slot normally used by |
7114 |
* restore the exception. |
* JSOP_NEXTITER, namely regs.sp[-1] before the regs.sp -= 2 |
7115 |
|
* adjustment and regs.sp[1] after, to save and restore the |
7116 |
|
* pending exception. |
7117 |
*/ |
*/ |
7118 |
JS_ASSERT(*regs.pc == JSOP_ENDITER); |
JS_ASSERT(*regs.pc == JSOP_ENDITER); |
7119 |
PUSH(cx->exception); |
regs.sp[-1] = cx->exception; |
7120 |
cx->throwing = JS_FALSE; |
cx->throwing = JS_FALSE; |
7121 |
ok = js_CloseIterator(cx, regs.sp[-2]); |
ok = js_CloseIterator(cx, regs.sp[-2]); |
7122 |
regs.sp -= 2; |
regs.sp -= 2; |
7172 |
JS_ASSERT(fp->regs == ®s); |
JS_ASSERT(fp->regs == ®s); |
7173 |
#ifdef JS_TRACER |
#ifdef JS_TRACER |
7174 |
if (TRACE_RECORDER(cx)) |
if (TRACE_RECORDER(cx)) |
7175 |
js_AbortRecording(cx, regs.pc, "recording out of js_Interpret"); |
js_AbortRecording(cx, "recording out of js_Interpret"); |
7176 |
#endif |
#endif |
7177 |
|
#if JS_HAS_GENERATORS |
7178 |
if (JS_UNLIKELY(fp->flags & JSFRAME_YIELDING)) { |
if (JS_UNLIKELY(fp->flags & JSFRAME_YIELDING)) { |
7179 |
JSGenerator *gen; |
JSGenerator *gen; |
7180 |
|
|
7183 |
gen->frame.regs = &gen->savedRegs; |
gen->frame.regs = &gen->savedRegs; |
7184 |
JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp); |
JS_PROPERTY_CACHE(cx).disabled -= js_CountWithBlocks(cx, fp); |
7185 |
JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0); |
JS_ASSERT(JS_PROPERTY_CACHE(cx).disabled >= 0); |
7186 |
} else { |
} else |
7187 |
|
#endif /* JS_HAS_GENERATORS */ |
7188 |
|
{ |
7189 |
JS_ASSERT(!fp->blockChain); |
JS_ASSERT(!fp->blockChain); |
7190 |
JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0)); |
JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0)); |
7191 |
fp->regs = NULL; |
fp->regs = NULL; |
7203 |
if (tr) { |
if (tr) { |
7204 |
JS_TRACE_MONITOR(cx).onTrace = JS_TRUE; |
JS_TRACE_MONITOR(cx).onTrace = JS_TRUE; |
7205 |
SET_TRACE_RECORDER(cx, tr); |
SET_TRACE_RECORDER(cx, tr); |
7206 |
tr->deepAbort(); |
if (!tr->wasDeepAborted()) { |
7207 |
|
tr->popAbortStack(); |
7208 |
|
tr->deepAbort(); |
7209 |
|
} |
7210 |
} |
} |
7211 |
#endif |
#endif |
7212 |
return ok; |
return ok; |