/[jscoverage]/trunk/js/jsinterp.cpp
ViewVC logotype

Diff of /trunk/js/jsinterp.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 332 by siliconforks, Thu Oct 23 19:03:33 2008 UTC revision 399 by siliconforks, Tue Dec 9 03:37:47 2008 UTC
# Line 85  Line 85 
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,
# Line 309  Line 314 
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];
# Line 1260  Line 1266 
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;
# Line 1492  Line 1499 
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) {
# Line 1764  Line 1773 
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);
# Line 1999  Line 2011 
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);
# Line 2025  Line 2035 
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);
# Line 2573  Line 2584 
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    
# Line 2600  Line 2621 
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    
# Line 2617  Line 2641 
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 == &regs);                                     \              JS_ASSERT(fp->regs == &regs);                                     \
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    
# Line 2652  Line 2678 
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();                                                              \
# Line 2733  Line 2759 
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 = &regs;          fp->regs = &regs;
2772    #if JS_HAS_GENERATORS
2773      } else {      } else {
2774          JSGenerator *gen;          JSGenerator *gen;
2775    
# Line 2766  Line 2797 
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
# Line 2846  Line 2878 
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)
# Line 2931  Line 2962 
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)) {
# Line 3031  Line 3079 
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);
# Line 3181  Line 3226 
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, &regs.sp[-1]))              if (!js_ValueToIterator(cx, flags, &regs.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]), &regs.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, &regs.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, &regs.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));
# Line 3320  Line 3324 
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. */        \
# Line 3505  Line 3517 
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);                                                 \
# Line 4622  Line 4639 
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
# Line 4699  Line 4716 
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:
# Line 4771  Line 4792 
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);
# Line 4897  Line 5032 
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. */
# Line 4936  Line 5072 
5072                      newifp->frame.regs = &regs;                      newifp->frame.regs = &regs;
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);
# Line 4994  Line 5127 
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              }              }
# Line 5039  Line 5173 
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);
# Line 5119  Line 5247 
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              }              }
# Line 6708  Line 6832 
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);
# Line 6819  Line 6932 
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:
# Line 6830  Line 6940 
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    
# Line 6865  Line 6977 
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. */
# Line 6948  Line 7079 
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
# Line 6965  Line 7096 
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.
# Line 6976  Line 7107 
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;
# Line 7039  Line 7172 
7172      JS_ASSERT(fp->regs == &regs);      JS_ASSERT(fp->regs == &regs);
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    
# Line 7049  Line 7183 
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;
# Line 7067  Line 7203 
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;

Legend:
Removed from v.332  
changed lines
  Added in v.399

  ViewVC Help
Powered by ViewVC 1.1.24