/[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 506 by siliconforks, Sat Sep 26 23:15:22 2009 UTC revision 507 by siliconforks, Sun Jan 10 07:23:34 2010 UTC
# Line 1  Line 1 
1  /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2   * vim: set ts=8 sw=4 et tw=79:   * vim: set ts=8 sw=4 et tw=79:
3   *   *
4   * ***** BEGIN LICENSE BLOCK *****   * ***** BEGIN LICENSE BLOCK *****
# Line 41  Line 41 
41  /*  /*
42   * JavaScript bytecode interpreter.   * JavaScript bytecode interpreter.
43   */   */
 #include "jsstddef.h"  
44  #include <stdio.h>  #include <stdio.h>
45  #include <string.h>  #include <string.h>
46  #include <math.h>  #include <math.h>
47  #include "jstypes.h"  #include "jstypes.h"
48    #include "jsstdint.h"
49  #include "jsarena.h" /* Added by JSIFY */  #include "jsarena.h" /* Added by JSIFY */
50  #include "jsutil.h" /* Added by JSIFY */  #include "jsutil.h" /* Added by JSIFY */
51  #include "jsprf.h"  #include "jsprf.h"
# Line 71  Line 71 
71  #include "jsstr.h"  #include "jsstr.h"
72  #include "jsstaticcheck.h"  #include "jsstaticcheck.h"
73  #include "jstracer.h"  #include "jstracer.h"
74    #include "jslibmath.h"
75    #include "jsvector.h"
76    #include "jsstrinlines.h"
77    
78  #ifdef INCLUDE_MOZILLA_DTRACE  #ifdef INCLUDE_MOZILLA_DTRACE
79  #include "jsdtracef.h"  #include "jsdtracef.h"
# Line 80  Line 83 
83  #include "jsxml.h"  #include "jsxml.h"
84  #endif  #endif
85    
86    #include "jsatominlines.h"
87    #include "jsscriptinlines.h"
88    
89  #include "jsautooplen.h"  #include "jsautooplen.h"
90    
91  /* jsinvoke_cpp___ indicates inclusion from jsinvoke.cpp. */  /* jsinvoke_cpp___ indicates inclusion from jsinvoke.cpp. */
92  #if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___  #if !JS_LONE_INTERPRET ^ defined jsinvoke_cpp___
93    
 uint32  
 js_GenerateShape(JSContext *cx, JSBool gcLocked)  
 {  
     JSRuntime *rt;  
     uint32 shape;  
   
     rt = cx->runtime;  
     shape = JS_ATOMIC_INCREMENT(&rt->shapeGen);  
     JS_ASSERT(shape != 0);  
     if (shape >= SHAPE_OVERFLOW_BIT) {  
         /*  
          * FIXME bug 440834: The shape id space has overflowed. Currently we  
          * cope badly with this and schedule the GC on the every call. But  
          * first we make sure that increments from other threads would not  
          * have a chance to wrap around shapeGen to zero.  
          */  
         rt->shapeGen = SHAPE_OVERFLOW_BIT;  
         js_TriggerGC(cx, gcLocked);  
     }  
     return shape;  
 }  
   
94  JS_REQUIRES_STACK JSPropCacheEntry *  JS_REQUIRES_STACK JSPropCacheEntry *
95  js_FillPropertyCache(JSContext *cx, JSObject *obj,  js_FillPropertyCache(JSContext *cx, JSObject *obj,
96                       uintN scopeIndex, uintN protoIndex, JSObject *pobj,                       uintN scopeIndex, uintN protoIndex, JSObject *pobj,
# Line 137  Line 121 
121       * from pobj's scope (via unwatch or delete, e.g.).       * from pobj's scope (via unwatch or delete, e.g.).
122       */       */
123      scope = OBJ_SCOPE(pobj);      scope = OBJ_SCOPE(pobj);
124      JS_ASSERT(scope->object == pobj);      if (!scope->has(sprop)) {
     if (!SCOPE_HAS_PROPERTY(scope, sprop)) {  
125          PCMETER(cache->oddfills++);          PCMETER(cache->oddfills++);
126          return JS_NO_PROP_CACHE_FILL;          return JS_NO_PROP_CACHE_FILL;
127      }      }
# Line 148  Line 131 
131       * and setter hooks can change the prototype chain using JS_SetPrototype       * and setter hooks can change the prototype chain using JS_SetPrototype
132       * after js_LookupPropertyWithFlags has returned the nominal protoIndex,       * after js_LookupPropertyWithFlags has returned the nominal protoIndex,
133       * we have to validate protoIndex if it is non-zero. If it is zero, then       * we have to validate protoIndex if it is non-zero. If it is zero, then
134       * we know thanks to the SCOPE_HAS_PROPERTY test above, and from the fact       * we know thanks to the scope->has test above, combined with the fact that
135       * that obj == pobj, that protoIndex is invariant.       * obj == pobj, that protoIndex is invariant.
136       *       *
137       * The scopeIndex can't be wrong. We require JS_SetParent calls to happen       * The scopeIndex can't be wrong. We require JS_SetParent calls to happen
138       * before any running script might consult a parent-linked scope chain. If       * before any running script might consult a parent-linked scope chain. If
# Line 202  Line 185 
185          /*          /*
186           * Check for a prototype "plain old method" callee computation. What           * Check for a prototype "plain old method" callee computation. What
187           * is a plain old method? It's a function-valued property with stub           * is a plain old method? It's a function-valued property with stub
188           * getter and setter, so get of a function is idempotent and set is           * getter, so get of a function is idempotent.
          * transparent.  
189           */           */
190          if (cs->format & JOF_CALLOP) {          if ((cs->format & JOF_CALLOP) &&
191              if (SPROP_HAS_STUB_GETTER(sprop) &&              SPROP_HAS_STUB_GETTER(sprop) &&
192                  SPROP_HAS_VALID_SLOT(sprop, scope)) {              SPROP_HAS_VALID_SLOT(sprop, scope)) {
193                  jsval v;              jsval v;
194    
195                  v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);              v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
196                  if (VALUE_IS_FUNCTION(cx, v)) {              if (VALUE_IS_FUNCTION(cx, v)) {
197                      /*                  /*
198                       * Great, we have a function-valued prototype property                   * Great, we have a function-valued prototype property where
199                       * where the getter is JS_PropertyStub. The type id in                   * the getter is JS_PropertyStub. The type id in pobj's scope
200                       * pobj's scope does not evolve with changes to property                   * does not evolve with changes to property values, however.
201                       * values, however.                   *
202                       *                   * So here, on first cache fill for this method, we brand the
203                       * So here, on first cache fill for this method, we brand                   * scope with a new shape and set the SCOPE_BRANDED flag. Once
204                       * the scope with a new shape and set the SCOPE_BRANDED                   * this scope flag is set, any write to a function-valued plain
205                       * flag. Once this scope flag is set, any write that adds                   * old property in pobj will result in shape being regenerated.
206                       * or deletes a function-valued plain old property in                   */
207                       * scope->object will result in shape being regenerated.                  if (!scope->branded()) {
208                       */                      PCMETER(cache->brandfills++);
                     if (!SCOPE_IS_BRANDED(scope)) {  
                         PCMETER(cache->brandfills++);  
209  #ifdef DEBUG_notme  #ifdef DEBUG_notme
210                          fprintf(stderr,                      fprintf(stderr,
211                              "branding %p (%s) for funobj %p (%s), shape %lu\n",                              "branding %p (%s) for funobj %p (%s), shape %lu\n",
212                              pobj, LOCKED_OBJ_GET_CLASS(pobj)->name,                              pobj, pobj->getClass()->name,
213                              JSVAL_TO_OBJECT(v),                              JSVAL_TO_OBJECT(v),
214                              JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx,                              JS_GetFunctionName(GET_FUNCTION_PRIVATE(cx, JSVAL_TO_OBJECT(v))),
                                                  JSVAL_TO_OBJECT(v))),  
215                              OBJ_SHAPE(obj));                              OBJ_SHAPE(obj));
216  #endif  #endif
217                          js_MakeScopeShapeUnique(cx, scope);                      scope->brandingShapeChange(cx, sprop->slot, v);
218                          if (js_IsPropertyCacheDisabled(cx)) {                      if (js_IsPropertyCacheDisabled(cx))  /* check for rt->shapeGen overflow */
219                              /*                          return JS_NO_PROP_CACHE_FILL;
220                               * js_GenerateShape could not recover from                      scope->setBranded();
                              * rt->shapeGen's overflow.  
                              */  
                             return JS_NO_PROP_CACHE_FILL;  
                         }  
                         SCOPE_SET_BRANDED(scope);  
                     }  
                     vword = JSVAL_OBJECT_TO_PCVAL(v);  
                     break;  
221                  }                  }
222                    vword = JSVAL_OBJECT_TO_PCVAL(v);
223                    break;
224              }              }
225          }          }
226    
# Line 290  Line 263 
263                   * iterations the cache will be hit since the shape no longer                   * iterations the cache will be hit since the shape no longer
264                   * mutates.                   * mutates.
265                   */                   */
266                  JS_ASSERT(scope->object == obj);                  JS_ASSERT(scope->owned());
267                  if (sprop->parent) {                  if (sprop->parent) {
268                      kshape = sprop->parent->shape;                      kshape = sprop->parent->shape;
269                  } else {                  } else {
270                        /*
271                         * If obj had its own empty scope before, with a unique
272                         * shape, that is lost. Here we only attempt to find a
273                         * matching empty scope. In unusual cases involving
274                         * __proto__ assignment we may not find one.
275                         */
276                      JSObject *proto = STOBJ_GET_PROTO(obj);                      JSObject *proto = STOBJ_GET_PROTO(obj);
277                      if (proto && OBJ_IS_NATIVE(proto))                      if (!proto || !OBJ_IS_NATIVE(proto))
278                          kshape = OBJ_SHAPE(proto);                          return JS_NO_PROP_CACHE_FILL;
279                        JSScope *protoscope = OBJ_SCOPE(proto);
280                        if (!protoscope->emptyScope ||
281                            protoscope->emptyScope->clasp != obj->getClass()) {
282                            return JS_NO_PROP_CACHE_FILL;
283                        }
284                        kshape = protoscope->emptyScope->shape;
285                  }                  }
286    
287                  /*                  /*
# Line 316  Line 301 
301      khash = PROPERTY_CACHE_HASH_PC(pc, kshape);      khash = PROPERTY_CACHE_HASH_PC(pc, kshape);
302      if (obj == pobj) {      if (obj == pobj) {
303          JS_ASSERT(scopeIndex == 0 && protoIndex == 0);          JS_ASSERT(scopeIndex == 0 && protoIndex == 0);
         JS_ASSERT(OBJ_SCOPE(obj)->object == obj);  
         JS_ASSERT(kshape != 0);  
304      } else {      } else {
305          if (op == JSOP_LENGTH) {          if (op == JSOP_LENGTH) {
306              atom = cx->runtime->atomState.lengthAtom;              atom = cx->runtime->atomState.lengthAtom;
# Line 334  Line 317 
317  #endif  #endif
318    
319          if (scopeIndex != 0 || protoIndex != 1) {          if (scopeIndex != 0 || protoIndex != 1) {
320              khash = PROPERTY_CACHE_HASH_ATOM(atom, obj, pobj);              khash = PROPERTY_CACHE_HASH_ATOM(atom, obj);
321              PCMETER(if (PCVCAP_TAG(cache->table[khash].vcap) <= 1)              PCMETER(if (PCVCAP_TAG(cache->table[khash].vcap) <= 1)
322                          cache->pcrecycles++);                          cache->pcrecycles++);
323              pc = (jsbytecode *) atom;              pc = (jsbytecode *) atom;
# Line 350  Line 333 
333               * platforms where another CPU can fail to see this write, it's OK               * platforms where another CPU can fail to see this write, it's OK
334               * because the property cache and JIT cache are thread-local.               * because the property cache and JIT cache are thread-local.
335               */               */
336              OBJ_SET_DELEGATE(cx, obj);              obj->setDelegate();
337          }          }
338      }      }
339    
# Line 400  Line 383 
383    
384      obj = *objp;      obj = *objp;
385      JS_ASSERT(OBJ_IS_NATIVE(obj));      JS_ASSERT(OBJ_IS_NATIVE(obj));
386      entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_ATOM(atom, obj, NULL)];      entry = &JS_PROPERTY_CACHE(cx).table[PROPERTY_CACHE_HASH_ATOM(atom, obj)];
387      *entryp = entry;      *entryp = entry;
388      vcap = entry->vcap;      vcap = entry->vcap;
389    
# Line 420  Line 403 
403                  entry->kshape,                  entry->kshape,
404                  OBJ_SHAPE(obj));                  OBJ_SHAPE(obj));
405                  js_Disassemble1(cx, cx->fp->script, pc,                  js_Disassemble1(cx, cx->fp->script, pc,
406                                  PTRDIFF(pc, cx->fp->script->code, jsbytecode),                                  pc - cx->fp->script->code,
407                                  JS_FALSE, stderr);                                  JS_FALSE, stderr);
408  #endif  #endif
409    
# Line 433  Line 416 
416      }      }
417    
418      pobj = obj;      pobj = obj;
     JS_LOCK_OBJ(cx, pobj);  
419    
420      if (JOF_MODE(cs->format) == JOF_NAME) {      if (JOF_MODE(cs->format) == JOF_NAME) {
421          while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) {          while (vcap & (PCVCAP_SCOPEMASK << PCVCAP_PROTOBITS)) {
422              tmp = LOCKED_OBJ_GET_PARENT(pobj);              tmp = OBJ_GET_PARENT(cx, pobj);
423              if (!tmp || !OBJ_IS_NATIVE(tmp))              if (!tmp || !OBJ_IS_NATIVE(tmp))
424                  break;                  break;
             JS_UNLOCK_OBJ(cx, pobj);  
425              pobj = tmp;              pobj = tmp;
             JS_LOCK_OBJ(cx, pobj);  
426              vcap -= PCVCAP_PROTOSIZE;              vcap -= PCVCAP_PROTOSIZE;
427          }          }
428    
# Line 450  Line 430 
430      }      }
431    
432      while (vcap & PCVCAP_PROTOMASK) {      while (vcap & PCVCAP_PROTOMASK) {
433          tmp = LOCKED_OBJ_GET_PROTO(pobj);          tmp = OBJ_GET_PROTO(cx, pobj);
434          if (!tmp || !OBJ_IS_NATIVE(tmp))          if (!tmp || !OBJ_IS_NATIVE(tmp))
435              break;              break;
         JS_UNLOCK_OBJ(cx, pobj);  
436          pobj = tmp;          pobj = tmp;
         JS_LOCK_OBJ(cx, pobj);  
437          --vcap;          --vcap;
438      }      }
439    
440      if (PCVCAP_SHAPE(vcap) == OBJ_SHAPE(pobj)) {      if (JS_LOCK_OBJ_IF_SHAPE(cx, pobj, PCVCAP_SHAPE(vcap))) {
441  #ifdef DEBUG  #ifdef DEBUG
442          jsid id = ATOM_TO_JSID(atom);          jsid id = ATOM_TO_JSID(atom);
443    
444          CHECK_FOR_STRING_INDEX(id);          id = js_CheckForStringIndex(id);
445          JS_ASSERT(SCOPE_GET_PROPERTY(OBJ_SCOPE(pobj), id));          JS_ASSERT(OBJ_SCOPE(pobj)->lookup(id));
446          JS_ASSERT(OBJ_SCOPE(pobj)->object == pobj);          JS_ASSERT_IF(OBJ_SCOPE(pobj)->object, OBJ_SCOPE(pobj)->object == pobj);
447  #endif  #endif
448          *pobjp = pobj;          *pobjp = pobj;
449          return NULL;          return NULL;
450      }      }
451    
452      PCMETER(JS_PROPERTY_CACHE(cx).vcmisses++);      PCMETER(JS_PROPERTY_CACHE(cx).vcmisses++);
     JS_UNLOCK_OBJ(cx, pobj);  
453      return atom;      return atom;
454  }  }
455    
# Line 618  Line 595 
595      jsval *sp;      jsval *sp;
596    
597      JS_ASSERT(nslots != 0);      JS_ASSERT(nslots != 0);
598      js_LeaveTrace(cx);      JS_ASSERT_NOT_ON_TRACE(cx);
599    
600      if (!cx->stackPool.first.next) {      if (!cx->stackPool.first.next) {
601          int64 *timestamp;          int64 *timestamp;
# Line 747  Line 724 
724      JSObject *limitBlock, *limitClone;      JSObject *limitBlock, *limitClone;
725      if (fp->fun && !fp->callobj) {      if (fp->fun && !fp->callobj) {
726          JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass ||          JS_ASSERT(OBJ_GET_CLASS(cx, fp->scopeChain) != &js_BlockClass ||
727                    OBJ_GET_PRIVATE(cx, fp->scopeChain) != fp);                    fp->scopeChain->getPrivate() != fp);
728          if (!js_GetCallObject(cx, fp))          if (!js_GetCallObject(cx, fp))
729              return NULL;              return NULL;
730    
# Line 794  Line 771 
771       * Special-case cloning the innermost block; this doesn't have enough in       * Special-case cloning the innermost block; this doesn't have enough in
772       * common with subsequent steps to include in the loop.       * common with subsequent steps to include in the loop.
773       *       *
774       * We pass fp->scopeChain and not null even if we override the parent slot       * js_CloneBlockObject leaves the clone's parent slot uninitialized. We
775       * later as null triggers useless calculations of slot's value in       * populate it below.
      * js_NewObject that js_CloneBlockObject calls.  
776       */       */
777      JSObject *innermostNewChild      JSObject *innermostNewChild = js_CloneBlockObject(cx, sharedBlock, fp);
         = js_CloneBlockObject(cx, sharedBlock, fp->scopeChain, fp);  
778      if (!innermostNewChild)      if (!innermostNewChild)
779          return NULL;          return NULL;
780      JSAutoTempValueRooter tvr(cx, innermostNewChild);      JSAutoTempValueRooter tvr(cx, innermostNewChild);
# Line 819  Line 794 
794    
795          /* As in the call above, we don't know the real parent yet.  */          /* As in the call above, we don't know the real parent yet.  */
796          JSObject *clone          JSObject *clone
797              = js_CloneBlockObject(cx, sharedBlock, fp->scopeChain, fp);              = js_CloneBlockObject(cx, sharedBlock, fp);
798          if (!clone)          if (!clone)
799              return NULL;              return NULL;
800    
# Line 830  Line 805 
805          STOBJ_SET_PARENT(newChild, clone);          STOBJ_SET_PARENT(newChild, clone);
806          newChild = clone;          newChild = clone;
807      }      }
808        STOBJ_SET_PARENT(newChild, fp->scopeChain);
809    
810    
811      /*      /*
812       * If we found a limit block belonging to this frame, then we should have       * If we found a limit block belonging to this frame, then we should have
# Line 837  Line 814 
814       */       */
815      JS_ASSERT_IF(limitBlock &&      JS_ASSERT_IF(limitBlock &&
816                   OBJ_GET_CLASS(cx, limitBlock) == &js_BlockClass &&                   OBJ_GET_CLASS(cx, limitBlock) == &js_BlockClass &&
817                   OBJ_GET_PRIVATE(cx, limitClone) == fp,                   limitClone->getPrivate() == fp,
818                   sharedBlock);                   sharedBlock);
819    
820      /* Place our newly cloned blocks at the head of the scope chain.  */      /* Place our newly cloned blocks at the head of the scope chain.  */
# Line 856  Line 833 
833          obj = JS_THIS_OBJECT(cx, vp);          obj = JS_THIS_OBJECT(cx, vp);
834          if (!JS_InstanceOf(cx, obj, clasp, vp + 2))          if (!JS_InstanceOf(cx, obj, clasp, vp + 2))
835              return JS_FALSE;              return JS_FALSE;
836          v = OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);          v = obj->fslots[JSSLOT_PRIMITIVE_THIS];
837      }      }
838      *thisvp = v;      *thisvp = v;
839      return JS_TRUE;      return JS_TRUE;
840  }  }
841    
842    /* Some objects (e.g., With) delegate 'this' to another object. */
843    static inline JSObject *
844    CallThisObjectHook(JSContext *cx, JSObject *obj, jsval *argv)
845    {
846        JSObject *thisp = obj->thisObject(cx);
847        if (!thisp)
848            return NULL;
849        argv[-1] = OBJECT_TO_JSVAL(thisp);
850        return thisp;
851    }
852    
853  /*  /*
854   * ECMA requires "the global object", but in embeddings such as the browser,   * ECMA requires "the global object", but in embeddings such as the browser,
855   * which have multiple top-level objects (windows, frames, etc. in the DOM),   * which have multiple top-level objects (windows, frames, etc. in the DOM),
# Line 914  Line 902 
902          thisp = JSVAL_TO_OBJECT(argv[-2]);          thisp = JSVAL_TO_OBJECT(argv[-2]);
903          id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);          id = ATOM_TO_JSID(cx->runtime->atomState.parentAtom);
904    
905          ok = OBJ_CHECK_ACCESS(cx, thisp, id, JSACC_PARENT, &v, &attrs);          ok = thisp->checkAccess(cx, id, JSACC_PARENT, &v, &attrs);
906          if (lazy) {          if (lazy) {
907              cx->dormantFrameChain = fp->dormantNext;              cx->dormantFrameChain = fp->dormantNext;
908              fp->dormantNext = NULL;              fp->dormantNext = NULL;
# Line 931  Line 919 
919              thisp = parent;              thisp = parent;
920      }      }
921    
922      /* Some objects (e.g., With) delegate 'this' to another object. */      return CallThisObjectHook(cx, thisp, argv);
     thisp = OBJ_THIS_OBJECT(cx, thisp);  
     if (!thisp)  
         return NULL;  
     argv[-1] = OBJECT_TO_JSVAL(thisp);  
     return thisp;  
923  }  }
924    
925  static JSObject *  static JSObject *
# Line 949  Line 932 
932          if (!js_PrimitiveToObject(cx, &argv[-1]))          if (!js_PrimitiveToObject(cx, &argv[-1]))
933              return NULL;              return NULL;
934          thisp = JSVAL_TO_OBJECT(argv[-1]);          thisp = JSVAL_TO_OBJECT(argv[-1]);
935      } else {          return thisp;
936          thisp = JSVAL_TO_OBJECT(argv[-1]);      }
         if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass ||  
             OBJ_GET_CLASS(cx, thisp) == &js_BlockClass) {  
             return js_ComputeGlobalThis(cx, lazy, argv);  
         }  
937    
938          /* Some objects (e.g., With) delegate 'this' to another object. */      thisp = JSVAL_TO_OBJECT(argv[-1]);
939          thisp = OBJ_THIS_OBJECT(cx, thisp);      if (OBJ_GET_CLASS(cx, thisp) == &js_CallClass || OBJ_GET_CLASS(cx, thisp) == &js_BlockClass)
940          if (!thisp)          return js_ComputeGlobalThis(cx, lazy, argv);
941              return NULL;  
942          argv[-1] = OBJECT_TO_JSVAL(thisp);      return CallThisObjectHook(cx, thisp, argv);
     }  
     return thisp;  
943  }  }
944    
945  JSObject *  JSObject *
946  js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)  js_ComputeThis(JSContext *cx, JSBool lazy, jsval *argv)
947  {  {
948        JS_ASSERT(argv[-1] != JSVAL_HOLE);  // check for SynthesizeFrame poisoning
949      if (JSVAL_IS_NULL(argv[-1]))      if (JSVAL_IS_NULL(argv[-1]))
950          return js_ComputeGlobalThis(cx, lazy, argv);          return js_ComputeGlobalThis(cx, lazy, argv);
951      return ComputeThis(cx, lazy, argv);      return ComputeThis(cx, lazy, argv);
# Line 975  Line 953 
953    
954  #if JS_HAS_NO_SUCH_METHOD  #if JS_HAS_NO_SUCH_METHOD
955    
956  #define JSSLOT_FOUND_FUNCTION   JSSLOT_PRIVATE  const uint32 JSSLOT_FOUND_FUNCTION  = JSSLOT_PRIVATE;
957  #define JSSLOT_SAVED_ID         (JSSLOT_PRIVATE + 1)  const uint32 JSSLOT_SAVED_ID        = JSSLOT_PRIVATE + 1;
958    
959  JSClass js_NoSuchMethodClass = {  JSClass js_NoSuchMethodClass = {
960      "NoSuchMethod",      "NoSuchMethod",
961      JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,      JSCLASS_HAS_RESERVED_SLOTS(2) | JSCLASS_IS_ANONYMOUS,
962      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,   JS_PropertyStub,      JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,   JS_PropertyStub,
963      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,    JS_FinalizeStub,      JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,    NULL,
964      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
965  };  };
966    
# Line 1003  Line 981 
981  JS_STATIC_INTERPRET JSBool  JS_STATIC_INTERPRET JSBool
982  js_OnUnknownMethod(JSContext *cx, jsval *vp)  js_OnUnknownMethod(JSContext *cx, jsval *vp)
983  {  {
     JSObject *obj;  
     jsid id;  
     JSTempValueRooter tvr;  
     JSBool ok;  
   
984      JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));      JS_ASSERT(!JSVAL_IS_PRIMITIVE(vp[1]));
     obj = JSVAL_TO_OBJECT(vp[1]);  
     JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);  
985    
986      MUST_FLOW_THROUGH("out");      JSObject *obj = JSVAL_TO_OBJECT(vp[1]);
987      id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);      jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
988      ok = js_GetMethod(cx, obj, id, false, &tvr.u.value);      JSAutoTempValueRooter tvr(cx, JSVAL_NULL);
989      if (!ok)      if (!js_GetMethod(cx, obj, id, false, tvr.addr()))
990          goto out;          return false;
991      if (JSVAL_IS_PRIMITIVE(tvr.u.value)) {      if (JSVAL_IS_PRIMITIVE(tvr.value())) {
992          vp[0] = tvr.u.value;          vp[0] = tvr.value();
993      } else {      } else {
994  #if JS_HAS_XML_SUPPORT  #if JS_HAS_XML_SUPPORT
995          /* Extract the function name from function::name qname. */          /* Extract the function name from function::name qname. */
996          if (!JSVAL_IS_PRIMITIVE(vp[0])) {          if (!JSVAL_IS_PRIMITIVE(vp[0])) {
997              obj = JSVAL_TO_OBJECT(vp[0]);              obj = JSVAL_TO_OBJECT(vp[0]);
998              ok = js_IsFunctionQName(cx, obj, &id);              if (!js_IsFunctionQName(cx, obj, &id))
999              if (!ok)                  return false;
                 goto out;  
1000              if (id != 0)              if (id != 0)
1001                  vp[0] = ID_TO_VALUE(id);                  vp[0] = ID_TO_VALUE(id);
1002          }          }
1003  #endif  #endif
1004          obj = js_NewObjectWithGivenProto(cx, &js_NoSuchMethodClass,          obj = js_NewObjectWithGivenProto(cx, &js_NoSuchMethodClass,
1005                                           NULL, NULL, 0);                                           NULL, NULL);
1006          if (!obj) {          if (!obj)
1007              ok = JS_FALSE;              return false;
1008              goto out;          obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.value();
         }  
         obj->fslots[JSSLOT_FOUND_FUNCTION] = tvr.u.value;  
1009          obj->fslots[JSSLOT_SAVED_ID] = vp[0];          obj->fslots[JSSLOT_SAVED_ID] = vp[0];
1010          vp[0] = OBJECT_TO_JSVAL(obj);          vp[0] = OBJECT_TO_JSVAL(obj);
1011      }      }
1012      ok = JS_TRUE;      return true;
   
   out:  
     JS_POP_TEMP_ROOT(cx, &tvr);  
     return ok;  
1013  }  }
1014    
1015  static JS_REQUIRES_STACK JSBool  static JS_REQUIRES_STACK JSBool
# Line 1091  Line 1055 
1055  JS_STATIC_ASSERT(JSVAL_INT == 1);  JS_STATIC_ASSERT(JSVAL_INT == 1);
1056  JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);  JS_STATIC_ASSERT(JSVAL_DOUBLE == 2);
1057  JS_STATIC_ASSERT(JSVAL_STRING == 4);  JS_STATIC_ASSERT(JSVAL_STRING == 4);
1058  JS_STATIC_ASSERT(JSVAL_BOOLEAN == 6);  JS_STATIC_ASSERT(JSVAL_SPECIAL == 6);
1059    
1060  const uint16 js_PrimitiveTestFlags[] = {  const uint16 js_PrimitiveTestFlags[] = {
1061      JSFUN_THISP_NUMBER,     /* INT     */      JSFUN_THISP_NUMBER,     /* INT     */
# Line 1119  Line 1083 
1083      JSObject *funobj, *parent;      JSObject *funobj, *parent;
1084      JSBool ok;      JSBool ok;
1085      JSClass *clasp;      JSClass *clasp;
1086      JSObjectOps *ops;      const JSObjectOps *ops;
1087      JSNative native;      JSNative native;
1088      JSFunction *fun;      JSFunction *fun;
1089      JSScript *script;      JSScript *script;
# Line 1128  Line 1092 
1092      JSInterpreterHook hook;      JSInterpreterHook hook;
1093      void *hookData;      void *hookData;
1094    
1095        JS_ASSERT(argc <= JS_ARGS_LENGTH_MAX);
1096    
1097      /* [vp .. vp + 2 + argc) must belong to the last JS stack arena. */      /* [vp .. vp + 2 + argc) must belong to the last JS stack arena. */
1098      JS_ASSERT((jsval *) cx->stackPool.current->base <= vp);      JS_ASSERT((jsval *) cx->stackPool.current->base <= vp);
1099      JS_ASSERT(vp + 2 + argc <= (jsval *) cx->stackPool.current->avail);      JS_ASSERT(vp + 2 + argc <= (jsval *) cx->stackPool.current->avail);
# Line 1157  Line 1123 
1123          /*          /*
1124           * XXX this makes no sense -- why convert to function if clasp->call?           * XXX this makes no sense -- why convert to function if clasp->call?
1125           * XXX better to call that hook without converting           * XXX better to call that hook without converting
          * XXX the only thing that needs fixing is liveconnect  
1126           *           *
1127           * FIXME bug 408416: try converting to function, for API compatibility           * FIXME bug 408416: try converting to function, for API compatibility
1128           * if there is a call op defined.           * if there is a call op defined.
# Line 1314  Line 1279 
1279       */       */
1280      frame.thisp = (JSObject *)vp[1];      frame.thisp = (JSObject *)vp[1];
1281      frame.varobj = NULL;      frame.varobj = NULL;
1282      frame.callobj = frame.argsobj = NULL;      frame.callobj = NULL;
1283        frame.argsobj = NULL;
1284      frame.script = script;      frame.script = script;
     frame.callee = funobj;  
1285      frame.fun = fun;      frame.fun = fun;
1286      frame.argc = argc;      frame.argc = argc;
1287      frame.argv = argv;      frame.argv = argv;
# Line 1334  Line 1299 
1299      frame.sharpArray = NULL;      frame.sharpArray = NULL;
1300      frame.flags = flags | rootedArgsFlag;      frame.flags = flags | rootedArgsFlag;
1301      frame.dormantNext = NULL;      frame.dormantNext = NULL;
     frame.xmlNamespace = NULL;  
1302      frame.displaySave = NULL;      frame.displaySave = NULL;
1303    
1304      MUST_FLOW_THROUGH("out");      MUST_FLOW_THROUGH("out");
# Line 1373  Line 1337 
1337      if (hook)      if (hook)
1338          hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);          hookData = hook(cx, &frame, JS_TRUE, 0, cx->debugHooks->callHookData);
1339    
1340    #ifdef INCLUDE_MOZILLA_DTRACE
1341        /* DTrace function entry, non-inlines */
1342        if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
1343            jsdtrace_function_entry(cx, &frame, fun);
1344        if (JAVASCRIPT_FUNCTION_INFO_ENABLED())
1345            jsdtrace_function_info(cx, &frame, frame.down, fun);
1346        if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())
1347            jsdtrace_function_args(cx, &frame, fun, frame.argc, frame.argv);
1348    #endif
1349    
1350      /* Call the function, either a native method or an interpreted script. */      /* Call the function, either a native method or an interpreted script. */
1351      if (native) {      if (native) {
1352  #ifdef DEBUG_NOT_THROWING  #ifdef DEBUG_NOT_THROWING
# Line 1394  Line 1368 
1368          ok = js_Interpret(cx);          ok = js_Interpret(cx);
1369      }      }
1370    
1371    #ifdef INCLUDE_MOZILLA_DTRACE
1372        /* DTrace function return, non-inlines */
1373        if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())
1374            jsdtrace_function_rval(cx, &frame, fun, &frame.rval);
1375        if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
1376            jsdtrace_function_return(cx, &frame, fun);
1377    #endif
1378    
1379  out:  out:
1380      if (hookData) {      if (hookData) {
1381          hook = cx->debugHooks->callHook;          hook = cx->debugHooks->callHook;
# Line 1401  Line 1383 
1383              hook(cx, &frame, JS_FALSE, &ok, hookData);              hook(cx, &frame, JS_FALSE, &ok, hookData);
1384      }      }
1385    
1386      /* If frame has a call object, sync values and clear back-pointer. */      frame.putActivationObjects(cx);
     if (frame.callobj)  
         ok &= js_PutCallObject(cx, &frame);  
   
     /* If frame has an arguments object, sync values and clear back-pointer. */  
     if (frame.argsobj)  
         ok &= js_PutArgsObject(cx, &frame);  
1387    
1388      *vp = frame.rval;      *vp = frame.rval;
1389    
# Line 1536  Line 1512 
1512          frame.callobj = down->callobj;          frame.callobj = down->callobj;
1513          frame.argsobj = down->argsobj;          frame.argsobj = down->argsobj;
1514          frame.varobj = down->varobj;          frame.varobj = down->varobj;
         frame.callee = down->callee;  
1515          frame.fun = down->fun;          frame.fun = down->fun;
1516          frame.thisp = down->thisp;          frame.thisp = down->thisp;
1517          if (down->flags & JSFRAME_COMPUTED_THIS)          if (down->flags & JSFRAME_COMPUTED_THIS)
# Line 1547  Line 1522 
1522          frame.sharpArray = down->sharpArray;          frame.sharpArray = down->sharpArray;
1523          JS_ASSERT(script->nfixed == 0);          JS_ASSERT(script->nfixed == 0);
1524      } else {      } else {
1525          frame.callobj = frame.argsobj = NULL;          frame.callobj = NULL;
1526            frame.argsobj = NULL;
1527          obj = chain;          obj = chain;
1528          if (cx->options & JSOPTION_VAROBJFIX) {          if (cx->options & JSOPTION_VAROBJFIX) {
1529              while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)              while ((tmp = OBJ_GET_PARENT(cx, obj)) != NULL)
1530                  obj = tmp;                  obj = tmp;
1531          }          }
1532          frame.varobj = obj;          frame.varobj = obj;
         frame.callee = NULL;  
1533          frame.fun = NULL;          frame.fun = NULL;
1534          frame.thisp = chain;          frame.thisp = chain;
1535          frame.argc = 0;          frame.argc = 0;
# Line 1582  Line 1557 
1557      frame.sharpDepth = 0;      frame.sharpDepth = 0;
1558      frame.flags = flags;      frame.flags = flags;
1559      frame.dormantNext = NULL;      frame.dormantNext = NULL;
     frame.xmlNamespace = NULL;  
1560      frame.blockChain = NULL;      frame.blockChain = NULL;
1561    
1562      /*      /*
# Line 1606  Line 1580 
1580    
1581      cx->fp = &frame;      cx->fp = &frame;
1582      if (!down) {      if (!down) {
1583          frame.thisp = OBJ_THIS_OBJECT(cx, frame.thisp);          OBJ_TO_INNER_OBJECT(cx, chain);
1584            if (!chain)
1585                return JS_FALSE;
1586            frame.scopeChain = chain;
1587    
1588            frame.thisp = frame.thisp->thisObject(cx);
1589          if (!frame.thisp) {          if (!frame.thisp) {
1590              ok = JS_FALSE;              ok = JS_FALSE;
1591              goto out2;              goto out2;
# Line 1655  Line 1634 
1634      JSObject *obj2;      JSObject *obj2;
1635      JSProperty *prop;      JSProperty *prop;
1636      uintN oldAttrs, report;      uintN oldAttrs, report;
1637      JSBool isFunction;      bool isFunction;
1638      jsval value;      jsval value;
1639      const char *type, *name;      const char *type, *name;
1640    
# Line 1674  Line 1653 
1653      JS_ASSERT_IF(attrs & JSPROP_INITIALIZER, attrs == JSPROP_INITIALIZER);      JS_ASSERT_IF(attrs & JSPROP_INITIALIZER, attrs == JSPROP_INITIALIZER);
1654      JS_ASSERT_IF(attrs == JSPROP_INITIALIZER, !propp);      JS_ASSERT_IF(attrs == JSPROP_INITIALIZER, !propp);
1655    
1656      if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))      if (!obj->lookupProperty(cx, id, &obj2, &prop))
1657          return JS_FALSE;          return JS_FALSE;
1658      if (!prop)      if (!prop)
1659          return JS_TRUE;          return JS_TRUE;
1660    
1661      /* Use prop as a speedup hint to OBJ_GET_ATTRIBUTES. */      /* Use prop as a speedup hint to obj->getAttributes. */
1662      if (!OBJ_GET_ATTRIBUTES(cx, obj2, id, prop, &oldAttrs)) {      if (!obj2->getAttributes(cx, id, prop, &oldAttrs)) {
1663          OBJ_DROP_PROPERTY(cx, obj2, prop);          obj2->dropProperty(cx, prop);
1664          return JS_FALSE;          return JS_FALSE;
1665      }      }
1666    
# Line 1689  Line 1668 
1668       * If our caller doesn't want prop, drop it (we don't need it any longer).       * If our caller doesn't want prop, drop it (we don't need it any longer).
1669       */       */
1670      if (!propp) {      if (!propp) {
1671          OBJ_DROP_PROPERTY(cx, obj2, prop);          obj2->dropProperty(cx, prop);
1672          prop = NULL;          prop = NULL;
1673      } else {      } else {
1674          *objp = obj2;          *objp = obj2;
# Line 1704  Line 1683 
1683          /* The property must be dropped already. */          /* The property must be dropped already. */
1684          JS_ASSERT(!prop);          JS_ASSERT(!prop);
1685          report = JSREPORT_WARNING | JSREPORT_STRICT;          report = JSREPORT_WARNING | JSREPORT_STRICT;
1686    
1687    #ifdef __GNUC__
1688            isFunction = false;     /* suppress bogus gcc warnings */
1689    #endif
1690      } else {      } else {
1691          /* We allow redeclaring some non-readonly properties. */          /* We allow redeclaring some non-readonly properties. */
1692          if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {          if (((oldAttrs | attrs) & JSPROP_READONLY) == 0) {
# Line 1730  Line 1713 
1713                  return JS_TRUE;                  return JS_TRUE;
1714          }          }
1715          if (prop)          if (prop)
1716              OBJ_DROP_PROPERTY(cx, obj2, prop);              obj2->dropProperty(cx, prop);
1717    
1718          report = JSREPORT_ERROR;          report = JSREPORT_ERROR;
1719          isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;          isFunction = (oldAttrs & (JSPROP_GETTER | JSPROP_SETTER)) != 0;
1720          if (!isFunction) {          if (!isFunction) {
1721              if (!OBJ_GET_PROPERTY(cx, obj, id, &value))              if (!obj->getProperty(cx, id, &value))
1722                  return JS_FALSE;                  return JS_FALSE;
1723              isFunction = VALUE_IS_FUNCTION(cx, value);              isFunction = VALUE_IS_FUNCTION(cx, value);
1724          }          }
# Line 1804  Line 1787 
1787      return lval == rval;      return lval == rval;
1788  }  }
1789    
1790    static inline bool
1791    IsNegativeZero(jsval v)
1792    {
1793        return JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NEGZERO(*JSVAL_TO_DOUBLE(v));
1794    }
1795    
1796    static inline bool
1797    IsNaN(jsval v)
1798    {
1799        return JSVAL_IS_DOUBLE(v) && JSDOUBLE_IS_NaN(*JSVAL_TO_DOUBLE(v));
1800    }
1801    
1802    JSBool
1803    js_SameValue(jsval v1, jsval v2, JSContext *cx)
1804    {
1805        if (IsNegativeZero(v1))
1806            return IsNegativeZero(v2);
1807        if (IsNegativeZero(v2))
1808            return JS_FALSE;
1809        if (IsNaN(v1) && IsNaN(v2))
1810            return JS_TRUE;
1811        return js_StrictlyEqual(cx, v1, v2);
1812    }
1813    
1814  JS_REQUIRES_STACK JSBool  JS_REQUIRES_STACK JSBool
1815  js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)  js_InvokeConstructor(JSContext *cx, uintN argc, JSBool clampReturn, jsval *vp)
1816  {  {
# Line 1837  Line 1844 
1844           * root to protect this prototype, in case it has no other           * root to protect this prototype, in case it has no other
1845           * strong refs.           * strong refs.
1846           */           */
1847          if (!OBJ_GET_PROPERTY(cx, obj2,          if (!obj2->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom),
1848                                ATOM_TO_JSID(cx->runtime->atomState                                 &vp[1])) {
                                            .classPrototypeAtom),  
                               &vp[1])) {  
1849              return JS_FALSE;              return JS_FALSE;
1850          }          }
1851          rval = vp[1];          rval = vp[1];
# Line 1853  Line 1858 
1858                  clasp = fun2->u.n.clasp;                  clasp = fun2->u.n.clasp;
1859          }          }
1860      }      }
1861      obj = js_NewObject(cx, clasp, proto, parent, 0);      obj = js_NewObject(cx, clasp, proto, parent);
1862      if (!obj)      if (!obj)
1863          return JS_FALSE;          return JS_FALSE;
1864    
1865      /* Now we have an object with a constructor method; call it. */      /* Now we have an object with a constructor method; call it. */
1866      vp[1] = OBJECT_TO_JSVAL(obj);      vp[1] = OBJECT_TO_JSVAL(obj);
1867      if (!js_Invoke(cx, argc, vp, JSINVOKE_CONSTRUCT)) {      if (!js_Invoke(cx, argc, vp, JSINVOKE_CONSTRUCT))
         cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
1868          return JS_FALSE;          return JS_FALSE;
     }  
1869    
1870      /* Check the return value and if it's primitive, force it to be obj. */      /* Check the return value and if it's primitive, force it to be obj. */
1871      rval = *vp;      rval = *vp;
# Line 1951  Line 1954 
1954    
1955      withobj = cx->fp->scopeChain;      withobj = cx->fp->scopeChain;
1956      JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);      JS_ASSERT(OBJ_GET_CLASS(cx, withobj) == &js_WithClass);
1957      JS_ASSERT(OBJ_GET_PRIVATE(cx, withobj) == cx->fp);      JS_ASSERT(withobj->getPrivate() == cx->fp);
1958      JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);      JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
1959      cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj);      cx->fp->scopeChain = OBJ_GET_PARENT(cx, withobj);
1960      JS_SetPrivate(cx, withobj, NULL);      withobj->setPrivate(NULL);
1961  }  }
1962    
1963  JS_REQUIRES_STACK JSClass *  JS_REQUIRES_STACK JSClass *
# Line 1964  Line 1967 
1967    
1968      clasp = OBJ_GET_CLASS(cx, obj);      clasp = OBJ_GET_CLASS(cx, obj);
1969      if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&      if ((clasp == &js_WithClass || clasp == &js_BlockClass) &&
1970          OBJ_GET_PRIVATE(cx, obj) == cx->fp &&          obj->getPrivate() == cx->fp &&
1971          OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {          OBJ_BLOCK_DEPTH(cx, obj) >= stackDepth) {
1972          return clasp;          return clasp;
1973      }      }
# Line 2062  Line 2065 
2065      } else if (slot == CALLEE_UPVAR_SLOT) {      } else if (slot == CALLEE_UPVAR_SLOT) {
2066          vp = &fp->argv[-2];          vp = &fp->argv[-2];
2067          slot = 0;          slot = 0;
2068      } else {      } else {
2069          slot -= fp->fun->nargs;          slot -= fp->fun->nargs;
2070          JS_ASSERT(slot < fp->script->nslots);          JS_ASSERT(slot < fp->script->nslots);
2071          vp = fp->slots;          vp = fp->slots;
# Line 2099  Line 2102 
2102                                  fp->script, cx->tracePrevPc);                                  fp->script, cx->tracePrevPc);
2103    
2104          /*          /*
2105           * If there aren't that many elements on the stack, then           * If there aren't that many elements on the stack, then
2106           * we have probably entered a new frame, and printing output           * we have probably entered a new frame, and printing output
2107           * would just be misleading.           * would just be misleading.
2108           */           */
# Line 2112  Line 2115 
2115                      fprintf(tracefp, "%s %s",                      fprintf(tracefp, "%s %s",
2116                              (n == -ndefs) ? "  output:" : ",",                              (n == -ndefs) ? "  output:" : ",",
2117                              bytes);                              bytes);
2118                      JS_free(cx, bytes);                      cx->free(bytes);
2119                  }                  }
2120              }              }
2121              fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));              fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
# Line 2132  Line 2135 
2135      fprintf(tracefp, "%4u: ",      fprintf(tracefp, "%4u: ",
2136              js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : regs->pc));              js_PCToLineNumber(cx, fp->script, fp->imacpc ? fp->imacpc : regs->pc));
2137      js_Disassemble1(cx, fp->script, regs->pc,      js_Disassemble1(cx, fp->script, regs->pc,
2138                      PTRDIFF(regs->pc, fp->script->code, jsbytecode),                      regs->pc - fp->script->code,
2139                      JS_FALSE, tracefp);                      JS_FALSE, tracefp);
2140      op = (JSOp) *regs->pc;      op = (JSOp) *regs->pc;
2141      nuses = js_GetStackUses(&js_CodeSpec[op], op, regs->pc);      nuses = js_GetStackUses(&js_CodeSpec[op], op, regs->pc);
# Line 2144  Line 2147 
2147                  fprintf(tracefp, "%s %s",                  fprintf(tracefp, "%s %s",
2148                          (n == -nuses) ? "  inputs:" : ",",                          (n == -nuses) ? "  inputs:" : ",",
2149                          bytes);                          bytes);
2150                  JS_free(cx, bytes);                  cx->free(bytes);
2151              }              }
2152          }          }
2153          fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));          fprintf(tracefp, " @ %u\n", (uintN) (regs->sp - StackBase(fp)));
# Line 2231  Line 2234 
2234    
2235  # define SIGNIFICANT(count,total) (200. * (count) >= (total))  # define SIGNIFICANT(count,total) (200. * (count) >= (total))
2236    
2237      graph = (Edge *) calloc(nedges, sizeof graph[0]);      graph = (Edge *) js_calloc(nedges * sizeof graph[0]);
2238      for (i = nedges = 0; i < JSOP_LIMIT; i++) {      for (i = nedges = 0; i < JSOP_LIMIT; i++) {
2239          from = js_CodeName[i];          from = js_CodeName[i];
2240          for (j = 0; j < JSOP_LIMIT; j++) {          for (j = 0; j < JSOP_LIMIT; j++) {
# Line 2260  Line 2263 
2263                  graph[i].from, graph[i].to,                  graph[i].from, graph[i].to,
2264                  (unsigned long)graph[i].count, style);                  (unsigned long)graph[i].count, style);
2265      }      }
2266      free(graph);      js_free(graph);
2267      fputs("}\n", fp);      fputs("}\n", fp);
2268      fclose(fp);      fclose(fp);
2269    
# Line 2430  Line 2433 
2433      JS_BEGIN_MACRO                                                            \      JS_BEGIN_MACRO                                                            \
2434          JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));                                    \          JS_ASSERT(!JSVAL_IS_PRIMITIVE(v));                                    \
2435          JS_ASSERT(v == regs.sp[n]);                                           \          JS_ASSERT(v == regs.sp[n]);                                           \
2436          if (!OBJ_DEFAULT_VALUE(cx, JSVAL_TO_OBJECT(v), hint, &regs.sp[n]))    \          if (!JSVAL_TO_OBJECT(v)->defaultValue(cx, hint, &regs.sp[n]))         \
2437              goto error;                                                       \              goto error;                                                       \
2438          v = regs.sp[n];                                                       \          v = regs.sp[n];                                                       \
2439      JS_END_MACRO      JS_END_MACRO
# Line 2444  Line 2447 
2447  #define CAN_DO_FAST_INC_DEC(v)     (((((v) << 1) ^ v) & 0x80000001) == 1)  #define CAN_DO_FAST_INC_DEC(v)     (((((v) << 1) ^ v) & 0x80000001) == 1)
2448    
2449  JS_STATIC_ASSERT(JSVAL_INT == 1);  JS_STATIC_ASSERT(JSVAL_INT == 1);
2450  JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MIN)));  JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL_CONSTEXPR(JSVAL_INT_MIN)));
2451  JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL(JSVAL_INT_MAX)));  JS_STATIC_ASSERT(!CAN_DO_FAST_INC_DEC(INT_TO_JSVAL_CONSTEXPR(JSVAL_INT_MAX)));
2452    
2453  /*  /*
2454   * Conditional assert to detect failure to clear a pending exception that is   * Conditional assert to detect failure to clear a pending exception that is
# Line 2551  Line 2554 
2554          return true;          return true;
2555      if (cx->runtime->gcNumber != sample ||      if (cx->runtime->gcNumber != sample ||
2556          PCVCAP_SHAPE(entry->vcap) != OBJ_SHAPE(pobj)) {          PCVCAP_SHAPE(entry->vcap) != OBJ_SHAPE(pobj)) {
2557          OBJ_DROP_PROPERTY(cx, pobj, prop);          pobj->dropProperty(cx, prop);
2558          return true;          return true;
2559      }      }
2560      JS_ASSERT(prop);      JS_ASSERT(prop);
# Line 2566  Line 2569 
2569          jsval v;          jsval v;
2570          JS_ASSERT(PCVAL_IS_OBJECT(entry->vword));          JS_ASSERT(PCVAL_IS_OBJECT(entry->vword));
2571          JS_ASSERT(entry->vword != PCVAL_NULL);          JS_ASSERT(entry->vword != PCVAL_NULL);
2572          JS_ASSERT(SCOPE_IS_BRANDED(OBJ_SCOPE(pobj)));          JS_ASSERT(OBJ_SCOPE(pobj)->branded());
2573          JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop));          JS_ASSERT(SPROP_HAS_STUB_GETTER(sprop));
2574          JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));          JS_ASSERT(SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj)));
2575          v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);          v = LOCKED_OBJ_GET_SLOT(pobj, sprop->slot);
# Line 2574  Line 2577 
2577          JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v));          JS_ASSERT(PCVAL_TO_OBJECT(entry->vword) == JSVAL_TO_OBJECT(v));
2578      }      }
2579    
2580      OBJ_DROP_PROPERTY(cx, pobj, prop);      pobj->dropProperty(cx, prop);
2581      return true;      return true;
2582  }  }
2583    
# Line 2630  Line 2633 
2633  JS_REQUIRES_STACK JSBool  JS_REQUIRES_STACK JSBool
2634  js_Interpret(JSContext *cx)  js_Interpret(JSContext *cx)
2635  {  {
2636    #ifdef MOZ_TRACEVIS
2637        TraceVisStateObj tvso(cx, S_INTERP);
2638    #endif
2639    
2640      JSRuntime *rt;      JSRuntime *rt;
2641      JSStackFrame *fp;      JSStackFrame *fp;
2642      JSScript *script;      JSScript *script;
# Line 2680  Line 2687 
2687       * 'op=x; DO_OP()' to let another opcode's implementation finish       * 'op=x; DO_OP()' to let another opcode's implementation finish
2688       * their work, and many opcodes share entry points with a run of       * their work, and many opcodes share entry points with a run of
2689       * consecutive BEGIN_CASEs.       * consecutive BEGIN_CASEs.
2690       *       *
2691       * Take care to trace OP only when it is the opcode fetched from       * Take care to trace OP only when it is the opcode fetched from
2692       * the instruction stream, so the trace matches what one would       * the instruction stream, so the trace matches what one would
2693       * expect from looking at the code.  (We do omit POPs after SETs;       * expect from looking at the code.  (We do omit POPs after SETs;
# Line 2784  Line 2791 
2791  #endif /* !JS_THREADED_INTERP */  #endif /* !JS_THREADED_INTERP */
2792    
2793  #ifdef JS_TRACER  #ifdef JS_TRACER
2794      /* We had better not be entering the interpreter from JIT-compiled code. */      /* We cannot reenter the interpreter while recording. */
2795      TraceRecorder *tr = TRACE_RECORDER(cx);      if (TRACE_RECORDER(cx))
2796      SET_TRACE_RECORDER(cx, NULL);          js_AbortRecording(cx, "attempt to reenter interpreter while recording");
   
     /* If a recorder is pending and we try to re-enter the interpreter, flag  
        the recorder to be destroyed when we return. */  
     if (tr) {  
         if (tr->wasDeepAborted())  
             tr->removeFragmentoReferences();  
         else  
             tr->pushAbortStack();  
     }  
2797  #endif  #endif
2798    
2799      /* Check for too deep of a native thread stack. */      /* Check for too deep of a native thread stack. */
# Line 2835  Line 2833 
2833      (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))      (atoms - script->atomMap.vector + GET_INDEX(regs.pc + PCOFF))
2834    
2835  #define LOAD_OBJECT(PCOFF)                                                    \  #define LOAD_OBJECT(PCOFF)                                                    \
2836      JS_GET_SCRIPT_OBJECT(script, GET_FULL_INDEX(PCOFF), obj)      (obj = script->getObject(GET_FULL_INDEX(PCOFF)))
2837    
2838  #define LOAD_FUNCTION(PCOFF)                                                  \  #define LOAD_FUNCTION(PCOFF)                                                  \
2839      JS_GET_SCRIPT_FUNCTION(script, GET_FULL_INDEX(PCOFF), fun)      (fun = script->getFunction(GET_FULL_INDEX(PCOFF)))
2840    
2841  #ifdef JS_TRACER  #ifdef JS_TRACER
2842    
2843    #ifdef MOZ_TRACEVIS
2844    #if JS_THREADED_INTERP
2845    #define MONITOR_BRANCH_TRACEVIS                                               \
2846        JS_BEGIN_MACRO                                                            \
2847            if (jumpTable != interruptJumpTable)                                  \
2848                js_EnterTraceVisState(cx, S_RECORD, R_NONE);                      \
2849        JS_END_MACRO
2850    #else /* !JS_THREADED_INTERP */
2851    #define MONITOR_BRANCH_TRACEVIS                                               \
2852        JS_BEGIN_MACRO                                                            \
2853            js_EnterTraceVisState(cx, S_RECORD, R_NONE);                          \
2854        JS_END_MACRO
2855    #endif
2856    #else
2857    #define MONITOR_BRANCH_TRACEVIS
2858    #endif
2859    
2860  #define MONITOR_BRANCH()                                                      \  #define MONITOR_BRANCH()                                                      \
2861      JS_BEGIN_MACRO                                                            \      JS_BEGIN_MACRO                                                            \
2862          if (TRACING_ENABLED(cx)) {                                            \          if (TRACING_ENABLED(cx)) {                                            \
2863              if (js_MonitorLoopEdge(cx, inlineCallCount)) {                    \              if (js_MonitorLoopEdge(cx, inlineCallCount)) {                    \
2864                  JS_ASSERT(TRACE_RECORDER(cx));                                \                  JS_ASSERT(TRACE_RECORDER(cx));                                \
2865                    MONITOR_BRANCH_TRACEVIS;                                      \
2866                  ENABLE_INTERRUPTS();                                          \                  ENABLE_INTERRUPTS();                                          \
2867              }                                                                 \              }                                                                 \
2868              fp = cx->fp;                                                      \              fp = cx->fp;                                                      \
# Line 2892  Line 2908 
2908                  } else {                                                      \                  } else {                                                      \
2909                      op = (JSOp) *++regs.pc;                                   \                      op = (JSOp) *++regs.pc;                                   \
2910                  }                                                             \                  }                                                             \
2911              } else if (op == JSOP_LOOP) {                                     \              } else if (op == JSOP_TRACE) {                                    \
2912                  MONITOR_BRANCH();                                             \                  MONITOR_BRANCH();                                             \
2913                  op = (JSOp) *regs.pc;                                         \                  op = (JSOp) *regs.pc;                                         \
2914              }                                                                 \              }                                                                 \
# Line 2994  Line 3010 
3010       * calling the interrupt handler, dispatches through normalJumpTable to       * calling the interrupt handler, dispatches through normalJumpTable to
3011       * continue the normal bytecode processing.       * continue the normal bytecode processing.
3012       */       */
3013    interrupt:  
3014  #else /* !JS_THREADED_INTERP */  #else /* !JS_THREADED_INTERP */
3015      for (;;) {      for (;;) {
3016        advance_pc_by_one:        advance_pc_by_one:
# Line 3010  Line 3026 
3026          switchOp = intN(op) | switchMask;          switchOp = intN(op) | switchMask;
3027        do_switch:        do_switch:
3028          switch (switchOp) {          switch (switchOp) {
           case -1:  
             JS_ASSERT(switchMask == -1);  
 #endif /* !JS_THREADED_INTERP */  
           {  
             bool moreInterrupts = false;  
             JSTrapHandler handler = cx->debugHooks->interruptHandler;  
             if (handler) {  
 #ifdef JS_TRACER  
                 if (TRACE_RECORDER(cx))  
                     js_AbortRecording(cx, "interrupt handler");  
 #endif  
                 switch (handler(cx, script, regs.pc, &rval,  
                                 cx->debugHooks->interruptHandlerData)) {  
                   case JSTRAP_ERROR:  
                     goto error;  
                   case JSTRAP_CONTINUE:  
                     break;  
                   case JSTRAP_RETURN:  
                     fp->rval = rval;  
                     ok = JS_TRUE;  
                     goto forced_return;  
                   case JSTRAP_THROW:  
                     cx->throwing = JS_TRUE;  
                     cx->exception = rval;  
                     goto error;  
                   default:;  
                 }  
                 moreInterrupts = true;  
             }  
   
 #ifdef JS_TRACER  
             TraceRecorder* tr = TRACE_RECORDER(cx);  
             if (tr) {  
                 JSRecordingStatus status = TraceRecorder::monitorRecording(cx, tr, op);  
                 switch (status) {  
                 case JSRS_CONTINUE:  
                     moreInterrupts = true;  
                     break;  
                 case JSRS_IMACRO:  
                     atoms = COMMON_ATOMS_START(&rt->atomState);  
                     op = JSOp(*regs.pc);  
                     DO_OP();    /* keep interrupting for op. */  
                     break;  
                 case JSRS_ERROR:  
                     // The code at 'error:' aborts the recording.  
                     goto error;  
                 case JSRS_STOP:  
                     break;  
                 default:  
                     JS_NOT_REACHED("Bad recording status");  
                 }  
             }  
 #endif /* !JS_TRACER */  
   
 #if JS_THREADED_INTERP  
             jumpTable = moreInterrupts ? interruptJumpTable : normalJumpTable;  
             JS_EXTENSION_(goto *normalJumpTable[op]);  
 #else  
             switchMask = moreInterrupts ? -1 : 0;  
             switchOp = intN(op);  
             goto do_switch;  
 #endif  
           }  
   
           /* No-ops for ease of decompilation. */  
           ADD_EMPTY_CASE(JSOP_NOP)  
           ADD_EMPTY_CASE(JSOP_CONDSWITCH)  
           ADD_EMPTY_CASE(JSOP_TRY)  
 #if JS_HAS_XML_SUPPORT  
           ADD_EMPTY_CASE(JSOP_STARTXML)  
           ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)  
 #endif  
           END_EMPTY_CASES  
   
           /* ADD_EMPTY_CASE is not used here as JSOP_LINENO_LENGTH == 3. */  
           BEGIN_CASE(JSOP_LINENO)  
           END_CASE(JSOP_LINENO)  
   
           BEGIN_CASE(JSOP_PUSH)  
             PUSH_OPND(JSVAL_VOID);  
           END_CASE(JSOP_PUSH)  
   
           BEGIN_CASE(JSOP_POP)  
             regs.sp--;  
           END_CASE(JSOP_POP)  
   
           BEGIN_CASE(JSOP_POPN)  
             regs.sp -= GET_UINT16(regs.pc);  
 #ifdef DEBUG  
             JS_ASSERT(StackBase(fp) <= regs.sp);  
             obj = fp->blockChain;  
             JS_ASSERT_IF(obj,  
                          OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)  
                          <= (size_t) (regs.sp - StackBase(fp)));  
             for (obj = fp->scopeChain; obj; obj = OBJ_GET_PARENT(cx, obj)) {  
                 clasp = OBJ_GET_CLASS(cx, obj);  
                 if (clasp != &js_BlockClass && clasp != &js_WithClass)  
                     continue;  
                 if (OBJ_GET_PRIVATE(cx, obj) != fp)  
                     break;  
                 JS_ASSERT(StackBase(fp) + OBJ_BLOCK_DEPTH(cx, obj)  
                                      + ((clasp == &js_BlockClass)  
                                         ? OBJ_BLOCK_COUNT(cx, obj)  
                                         : 1)  
                           <= regs.sp);  
             }  
 #endif  
           END_CASE(JSOP_POPN)  
   
           BEGIN_CASE(JSOP_SETRVAL)  
           BEGIN_CASE(JSOP_POPV)  
             ASSERT_NOT_THROWING(cx);  
             fp->rval = POP_OPND();  
           END_CASE(JSOP_POPV)  
   
           BEGIN_CASE(JSOP_ENTERWITH)  
             if (!js_EnterWith(cx, -1))  
                 goto error;  
   
             /*  
              * We must ensure that different "with" blocks have different  
              * stack depth associated with them. This allows the try handler  
              * search to properly recover the scope chain. Thus we must keep  
              * the stack at least at the current level.  
              *  
              * We set sp[-1] to the current "with" object to help asserting  
              * the enter/leave balance in [leavewith].  
              */  
             regs.sp[-1] = OBJECT_TO_JSVAL(fp->scopeChain);  
           END_CASE(JSOP_ENTERWITH)  
   
           BEGIN_CASE(JSOP_LEAVEWITH)  
             JS_ASSERT(regs.sp[-1] == OBJECT_TO_JSVAL(fp->scopeChain));  
             regs.sp--;  
             js_LeaveWith(cx);  
           END_CASE(JSOP_LEAVEWITH)  
   
           BEGIN_CASE(JSOP_RETURN)  
             fp->rval = POP_OPND();  
             /* FALL THROUGH */  
   
           BEGIN_CASE(JSOP_RETRVAL)    /* fp->rval already set */  
           BEGIN_CASE(JSOP_STOP)  
             /*  
              * When the inlined frame exits with an exception or an error, ok  
              * will be false after the inline_return label.  
              */  
             ASSERT_NOT_THROWING(cx);  
             CHECK_BRANCH();  
   
             if (fp->imacpc) {  
                 /*  
                  * If we are at the end of an imacro, return to its caller in  
                  * the current frame.  
                  */  
                 JS_ASSERT(op == JSOP_STOP);  
   
               end_imacro:  
                 JS_ASSERT((uintN)(regs.sp - fp->slots) <= script->nslots);  
                 regs.pc = fp->imacpc + js_CodeSpec[*fp->imacpc].length;  
                 fp->imacpc = NULL;  
                 atoms = script->atomMap.vector;  
                 op = JSOp(*regs.pc);  
                 DO_OP();  
             }  
   
             JS_ASSERT(regs.sp == StackBase(fp));  
             if ((fp->flags & JSFRAME_CONSTRUCTING) &&  
                 JSVAL_IS_PRIMITIVE(fp->rval)) {  
                 if (!fp->fun) {  
                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,  
                                          JSMSG_BAD_NEW_RESULT,  
                                          js_ValueToPrintableString(cx, rval));  
                     goto error;  
                 }  
                 fp->rval = OBJECT_TO_JSVAL(fp->thisp);  
             }  
             ok = JS_TRUE;  
             if (inlineCallCount)  
           inline_return:  
             {  
                 JSInlineFrame *ifp = (JSInlineFrame *) fp;  
                 void *hookData = ifp->hookData;  
   
                 JS_ASSERT(!fp->blockChain);  
                 JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));  
   
                 if (script->staticLevel < JS_DISPLAY_SIZE)  
                     cx->display[script->staticLevel] = fp->displaySave;  
   
                 if (hookData) {  
                     JSInterpreterHook hook;  
                     JSBool status;  
   
                     hook = cx->debugHooks->callHook;  
                     if (hook) {  
                         /*  
                          * Do not pass &ok directly as exposing the address  
                          * inhibits optimizations and uninitialised warnings.  
                          */  
                         status = ok;  
                         hook(cx, fp, JS_FALSE, &status, hookData);  
                         ok = status;  
                         CHECK_INTERRUPT_HANDLER();  
                     }  
                 }  
   
                 /*  
                  * If fp has a call object, sync values and clear the back-  
                  * pointer. This can happen for a lightweight function if it  
                  * calls eval unexpectedly (in a way that is hidden from the  
                  * compiler). See bug 325540.  
                  */  
                 if (fp->callobj)  
                     ok &= js_PutCallObject(cx, fp);  
   
                 if (fp->argsobj)  
                     ok &= js_PutArgsObject(cx, fp);  
   
 #ifdef INCLUDE_MOZILLA_DTRACE  
                 /* DTrace function return, inlines */  
                 if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())  
                     jsdtrace_function_rval(cx, fp, fp->fun);  
                 if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())  
                     jsdtrace_function_return(cx, fp, fp->fun);  
 #endif  
   
                 /* Restore context version only if callee hasn't set version. */  
                 if (JS_LIKELY(cx->version == currentVersion)) {  
                     currentVersion = ifp->callerVersion;  
                     if (currentVersion != cx->version)  
                         js_SetVersion(cx, currentVersion);  
                 }  
   
                 /*  
                  * If inline-constructing, replace primitive rval with the new  
                  * object passed in via |this|, and instrument this constructor  
                  * invocation  
                  */  
                 if (fp->flags & JSFRAME_CONSTRUCTING) {  
                     if (JSVAL_IS_PRIMITIVE(fp->rval))  
                         fp->rval = OBJECT_TO_JSVAL(fp->thisp);  
                     JS_RUNTIME_METER(cx->runtime, constructs);  
                 }  
   
                 /* Restore caller's registers. */  
                 regs = ifp->callerRegs;  
   
                 /* Store the return value in the caller's operand frame. */  
                 regs.sp -= 1 + (size_t) ifp->frame.argc;  
                 regs.sp[-1] = fp->rval;  
   
                 /* Restore cx->fp and release the inline frame's space. */  
                 cx->fp = fp = fp->down;  
                 JS_ASSERT(fp->regs == &ifp->callerRegs);  
                 fp->regs = &regs;  
                 JS_ARENA_RELEASE(&cx->stackPool, ifp->mark);  
   
                 /* Restore the calling script's interpreter registers. */  
                 script = fp->script;  
                 atoms = FrameAtomBase(cx, fp);  
   
                 /* Resume execution in the calling frame. */  
                 inlineCallCount--;  
                 if (JS_LIKELY(ok)) {  
                     TRACE_0(LeaveFrame);  
                     JS_ASSERT(js_CodeSpec[js_GetOpcode(cx, script, regs.pc)].length  
                               == JSOP_CALL_LENGTH);  
                     len = JSOP_CALL_LENGTH;  
                     DO_NEXT_OP(len);  
                 }  
                 goto error;  
             }  
             goto exit;  
   
           BEGIN_CASE(JSOP_DEFAULT)  
             (void) POP();  
             /* FALL THROUGH */  
           BEGIN_CASE(JSOP_GOTO)  
             len = GET_JUMP_OFFSET(regs.pc);  
             BRANCH(len);  
           END_CASE(JSOP_GOTO)  
   
           BEGIN_CASE(JSOP_IFEQ)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_FALSE) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
           END_CASE(JSOP_IFEQ)  
   
           BEGIN_CASE(JSOP_IFNE)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond != JS_FALSE) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
           END_CASE(JSOP_IFNE)  
   
           BEGIN_CASE(JSOP_OR)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_TRUE) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 PUSH_OPND(rval);  
                 DO_NEXT_OP(len);  
             }  
           END_CASE(JSOP_OR)  
   
           BEGIN_CASE(JSOP_AND)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_FALSE) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 PUSH_OPND(rval);  
                 DO_NEXT_OP(len);  
             }  
           END_CASE(JSOP_AND)  
   
           BEGIN_CASE(JSOP_DEFAULTX)  
             (void) POP();  
             /* FALL THROUGH */  
           BEGIN_CASE(JSOP_GOTOX)  
             len = GET_JUMPX_OFFSET(regs.pc);  
             BRANCH(len);  
           END_CASE(JSOP_GOTOX);  
   
           BEGIN_CASE(JSOP_IFEQX)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_FALSE) {  
                 len = GET_JUMPX_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
           END_CASE(JSOP_IFEQX)  
   
           BEGIN_CASE(JSOP_IFNEX)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond != JS_FALSE) {  
                 len = GET_JUMPX_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
           END_CASE(JSOP_IFNEX)  
   
           BEGIN_CASE(JSOP_ORX)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_TRUE) {  
                 len = GET_JUMPX_OFFSET(regs.pc);  
                 PUSH_OPND(rval);  
                 DO_NEXT_OP(len);  
             }  
           END_CASE(JSOP_ORX)  
   
           BEGIN_CASE(JSOP_ANDX)  
             POP_BOOLEAN(cx, rval, cond);  
             if (cond == JS_FALSE) {  
                 len = GET_JUMPX_OFFSET(regs.pc);  
                 PUSH_OPND(rval);  
                 DO_NEXT_OP(len);  
             }  
           END_CASE(JSOP_ANDX)  
   
 /*  
  * If the index value at sp[n] is not an int that fits in a jsval, it could  
  * be an object (an XML QName, AttributeName, or AnyName), but only if we are  
  * compiling with JS_HAS_XML_SUPPORT.  Otherwise convert the index value to a  
  * string atom id.  
  */  
 #define FETCH_ELEMENT_ID(obj, n, id)                                          \  
     JS_BEGIN_MACRO                                                            \  
         jsval idval_ = FETCH_OPND(n);                                         \  
         if (JSVAL_IS_INT(idval_)) {                                           \  
             id = INT_JSVAL_TO_JSID(idval_);                                   \  
         } else {                                                              \  
             if (!js_InternNonIntElementId(cx, obj, idval_, &id))              \  
                 goto error;                                                   \  
             regs.sp[n] = ID_TO_VALUE(id);                                     \  
         }                                                                     \  
     JS_END_MACRO  
   
 #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \  
     JS_BEGIN_MACRO                                                            \  
         uintN diff_;                                                          \  
         JS_ASSERT(js_CodeSpec[op].length == 1);                               \  
         diff_ = (uintN) regs.pc[1] - (uintN) JSOP_IFEQ;                       \  
         if (diff_ <= 1) {                                                     \  
             regs.sp -= spdec;                                                 \  
             if (cond == (diff_ != 0)) {                                       \  
                 ++regs.pc;                                                    \  
                 len = GET_JUMP_OFFSET(regs.pc);                               \  
                 BRANCH(len);                                                  \  
             }                                                                 \  
             len = 1 + JSOP_IFEQ_LENGTH;                                       \  
             DO_NEXT_OP(len);                                                  \  
         }                                                                     \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_IN)  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_PRIMITIVE(rval)) {  
                 js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rval, NULL);  
                 goto error;  
             }  
             obj = JSVAL_TO_OBJECT(rval);  
             FETCH_ELEMENT_ID(obj, -2, id);  
             if (!OBJ_LOOKUP_PROPERTY(cx, obj, id, &obj2, &prop))  
                 goto error;  
             cond = prop != NULL;  
             if (prop)  
                 OBJ_DROP_PROPERTY(cx, obj2, prop);  
             TRY_BRANCH_AFTER_COND(cond, 2);  
             regs.sp--;  
             STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));  
           END_CASE(JSOP_IN)  
   
           BEGIN_CASE(JSOP_ITER)  
             JS_ASSERT(regs.sp > StackBase(fp));  
             flags = regs.pc[1];  
             if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))  
                 goto error;  
             CHECK_INTERRUPT_HANDLER();  
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));  
             PUSH(JSVAL_VOID);  
           END_CASE(JSOP_ITER)  
   
           BEGIN_CASE(JSOP_NEXTITER)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-2]));  
             if (!js_CallIteratorNext(cx, JSVAL_TO_OBJECT(regs.sp[-2]), &regs.sp[-1]))  
                 goto error;  
             CHECK_INTERRUPT_HANDLER();  
             rval = BOOLEAN_TO_JSVAL(regs.sp[-1] != JSVAL_HOLE);  
             PUSH(rval);  
           END_CASE(JSOP_NEXTITER)  
   
           BEGIN_CASE(JSOP_ENDITER)  
             /*  
              * Decrease the stack pointer even when !ok -- see comments in the  
              * exception capturing code for details.  
              */  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             ok = js_CloseIterator(cx, regs.sp[-2]);  
             regs.sp -= 2;  
             if (!ok)  
                 goto error;  
           END_CASE(JSOP_ENDITER)  
   
           BEGIN_CASE(JSOP_FORARG)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             slot = GET_ARGNO(regs.pc);  
             JS_ASSERT(slot < fp->fun->nargs);  
             fp->argv[slot] = regs.sp[-1];  
           END_CASE(JSOP_FORARG)  
   
           BEGIN_CASE(JSOP_FORLOCAL)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < fp->script->nslots);  
             vp = &fp->slots[slot];  
             *vp = regs.sp[-1];  
           END_CASE(JSOP_FORLOCAL)  
   
           BEGIN_CASE(JSOP_FORNAME)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             LOAD_ATOM(0);  
             id = ATOM_TO_JSID(atom);  
             if (!js_FindProperty(cx, id, &obj, &obj2, &prop))  
                 goto error;  
             if (prop)  
                 OBJ_DROP_PROPERTY(cx, obj2, prop);  
             ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);  
             if (!ok)  
                 goto error;  
           END_CASE(JSOP_FORNAME)  
   
           BEGIN_CASE(JSOP_FORPROP)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             LOAD_ATOM(0);  
             id = ATOM_TO_JSID(atom);  
             FETCH_OBJECT(cx, -1, lval, obj);  
             ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-2]);  
             if (!ok)  
                 goto error;  
             regs.sp--;  
           END_CASE(JSOP_FORPROP)  
   
           BEGIN_CASE(JSOP_FORELEM)  
             /*  
              * JSOP_FORELEM simply dups the property identifier at top of stack  
              * and lets the subsequent JSOP_ENUMELEM opcode sequence handle the  
              * left-hand side expression evaluation and assignment. This opcode  
              * exists solely to help the decompiler.  
              */  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             rval = FETCH_OPND(-1);  
             PUSH(rval);  
           END_CASE(JSOP_FORELEM)  
   
           BEGIN_CASE(JSOP_DUP)  
             JS_ASSERT(regs.sp > StackBase(fp));  
             rval = FETCH_OPND(-1);  
             PUSH(rval);  
           END_CASE(JSOP_DUP)  
   
           BEGIN_CASE(JSOP_DUP2)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             lval = FETCH_OPND(-2);  
             rval = FETCH_OPND(-1);  
             PUSH(lval);  
             PUSH(rval);  
           END_CASE(JSOP_DUP2)  
   
           BEGIN_CASE(JSOP_SWAP)  
             JS_ASSERT(regs.sp - 2 >= StackBase(fp));  
             lval = FETCH_OPND(-2);  
             rval = FETCH_OPND(-1);  
             STORE_OPND(-1, lval);  
             STORE_OPND(-2, rval);  
           END_CASE(JSOP_SWAP)  
   
           BEGIN_CASE(JSOP_PICK)  
             i = regs.pc[1];  
             JS_ASSERT(regs.sp - (i+1) >= StackBase(fp));  
             lval = regs.sp[-(i+1)];  
             memmove(regs.sp - (i+1), regs.sp - i, sizeof(jsval)*i);  
             regs.sp[-1] = lval;  
           END_CASE(JSOP_PICK)  
   
 #define PROPERTY_OP(n, call)                                                  \  
     JS_BEGIN_MACRO                                                            \  
         /* Fetch the left part and resolve it to a non-null object. */        \  
         FETCH_OBJECT(cx, n, lval, obj);                                       \  
                                                                               \  
         /* Get or set the property. */                                        \  
         if (!call)                                                            \  
             goto error;                                                       \  
     JS_END_MACRO  
   
 #define ELEMENT_OP(n, call)                                                   \  
     JS_BEGIN_MACRO                                                            \  
         /* Fetch the left part and resolve it to a non-null object. */        \  
         FETCH_OBJECT(cx, n - 1, lval, obj);                                   \  
                                                                               \  
         /* Fetch index and convert it to id suitable for use with obj. */     \  
         FETCH_ELEMENT_ID(obj, n, id);                                         \  
                                                                               \  
         /* Get or set the element. */                                         \  
         if (!call)                                                            \  
             goto error;                                                       \  
     JS_END_MACRO  
   
 #define NATIVE_GET(cx,obj,pobj,sprop,vp)                                      \  
     JS_BEGIN_MACRO                                                            \  
         if (SPROP_HAS_STUB_GETTER(sprop)) {                                   \  
             /* Fast path for Object instance properties. */                   \  
             JS_ASSERT((sprop)->slot != SPROP_INVALID_SLOT ||                  \  
                       !SPROP_HAS_STUB_SETTER(sprop));                         \  
             *vp = ((sprop)->slot != SPROP_INVALID_SLOT)                       \  
                   ? LOCKED_OBJ_GET_SLOT(pobj, (sprop)->slot)                  \  
                   : JSVAL_VOID;                                               \  
         } else {                                                              \  
             if (!js_NativeGet(cx, obj, pobj, sprop, vp))                      \  
                 goto error;                                                   \  
         }                                                                     \  
     JS_END_MACRO  
   
 #define NATIVE_SET(cx,obj,sprop,entry,vp)                                     \  
     JS_BEGIN_MACRO                                                            \  
         TRACE_2(SetPropHit, entry, sprop);                                    \  
         if (SPROP_HAS_STUB_SETTER(sprop) &&                                   \  
             (sprop)->slot != SPROP_INVALID_SLOT) {                            \  
             /* Fast path for, e.g., Object instance properties. */            \  
             LOCKED_OBJ_WRITE_BARRIER(cx, obj, (sprop)->slot, *vp);            \  
         } else {                                                              \  
             if (!js_NativeSet(cx, obj, sprop, vp))                            \  
                 goto error;                                                   \  
         }                                                                     \  
     JS_END_MACRO  
   
 /*  
  * Skip the JSOP_POP typically found after a JSOP_SET* opcode, where oplen is  
  * the constant length of the SET opcode sequence, and spdec is the constant  
  * by which to decrease the stack pointer to pop all of the SET op's operands.  
  *  
  * NB: unlike macros that could conceivably be replaced by functions (ignoring  
  * goto error), where a call should not have to be braced in order to expand  
  * correctly (e.g., in if (cond) FOO(); else BAR()), these three macros lack  
  * JS_{BEGIN,END}_MACRO brackets. They are also indented so as to align with  
  * nearby opcode code.  
  */  
 #define SKIP_POP_AFTER_SET(oplen,spdec)                                       \  
             if (regs.pc[oplen] == JSOP_POP) {                                 \  
                 regs.sp -= spdec;                                             \  
                 regs.pc += oplen + JSOP_POP_LENGTH;                           \  
                 op = (JSOp) *regs.pc;                                         \  
                 DO_OP();                                                      \  
             }  
   
 #define END_SET_CASE(OP)                                                      \  
             SKIP_POP_AFTER_SET(OP##_LENGTH, 1);                               \  
           END_CASE(OP)  
   
 #define END_SET_CASE_STORE_RVAL(OP,spdec)                                     \  
             SKIP_POP_AFTER_SET(OP##_LENGTH, spdec);                           \  
             rval = FETCH_OPND(-1);                                            \  
             regs.sp -= (spdec) - 1;                                           \  
             STORE_OPND(-1, rval);                                             \  
           END_CASE(OP)  
   
           BEGIN_CASE(JSOP_SETCONST)  
             LOAD_ATOM(0);  
             obj = fp->varobj;  
             rval = FETCH_OPND(-1);  
             if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), rval,  
                                      JS_PropertyStub, JS_PropertyStub,  
                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |  
                                      JSPROP_READONLY,  
                                      NULL)) {  
                 goto error;  
             }  
           END_SET_CASE(JSOP_SETCONST);  
   
 #if JS_HAS_DESTRUCTURING  
           BEGIN_CASE(JSOP_ENUMCONSTELEM)  
             rval = FETCH_OPND(-3);  
             FETCH_OBJECT(cx, -2, lval, obj);  
             FETCH_ELEMENT_ID(obj, -1, id);  
             if (!OBJ_DEFINE_PROPERTY(cx, obj, id, rval,  
                                      JS_PropertyStub, JS_PropertyStub,  
                                      JSPROP_ENUMERATE | JSPROP_PERMANENT |  
                                      JSPROP_READONLY,  
                                      NULL)) {  
                 goto error;  
             }  
             regs.sp -= 3;  
           END_CASE(JSOP_ENUMCONSTELEM)  
 #endif  
   
           BEGIN_CASE(JSOP_BINDNAME)  
             do {  
                 JSPropCacheEntry *entry;  
   
                 /*  
                  * We can skip the property lookup for the global object. If  
                  * the property does not exist anywhere on the scope chain,  
                  * JSOP_SETNAME adds the property to the global.  
                  *  
                  * As a consequence of this optimization for the global object  
                  * we run its JSRESOLVE_ASSIGNING-tolerant resolve hooks only  
                  * in JSOP_SETNAME, after the interpreter evaluates the right-  
                  * hand-side of the assignment, and not here.  
                  *  
                  * This should be transparent to the hooks because the script,  
                  * instead of name = rhs, could have used global.name = rhs  
                  * given a global object reference, which also calls the hooks  
                  * only after evaluating the rhs. We desire such resolve hook  
                  * equivalence between the two forms.  
                  */  
                 obj = fp->scopeChain;  
                 if (!OBJ_GET_PARENT(cx, obj))  
                     break;  
                 if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {  
                     PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);  
                     if (!atom) {  
                         ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);  
                         JS_UNLOCK_OBJ(cx, obj2);  
                         break;  
                     }  
                 } else {  
                     entry = NULL;  
                     LOAD_ATOM(0);  
                 }  
                 id = ATOM_TO_JSID(atom);  
                 obj = js_FindIdentifierBase(cx, fp->scopeChain, id);  
                 if (!obj)  
                     goto error;  
             } while (0);  
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_BINDNAME)  
   
           BEGIN_CASE(JSOP_IMACOP)  
             JS_ASSERT(JS_UPTRDIFF(fp->imacpc, script->code) < script->length);  
             op = JSOp(*fp->imacpc);  
             DO_OP();  
   
 #define BITWISE_OP(OP)                                                        \  
     JS_BEGIN_MACRO                                                            \  
         FETCH_INT(cx, -2, i);                                                 \  
         FETCH_INT(cx, -1, j);                                                 \  
         i = i OP j;                                                           \  
         regs.sp--;                                                            \  
         STORE_INT(cx, -1, i);                                                 \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_BITOR)  
             BITWISE_OP(|);  
           END_CASE(JSOP_BITOR)  
   
           BEGIN_CASE(JSOP_BITXOR)  
             BITWISE_OP(^);  
           END_CASE(JSOP_BITXOR)  
   
           BEGIN_CASE(JSOP_BITAND)  
             BITWISE_OP(&);  
           END_CASE(JSOP_BITAND)  
   
 #define RELATIONAL_OP(OP)                                                     \  
     JS_BEGIN_MACRO                                                            \  
         rval = FETCH_OPND(-1);                                                \  
         lval = FETCH_OPND(-2);                                                \  
         /* Optimize for two int-tagged operands (typical loop control). */    \  
         if ((lval & rval) & JSVAL_INT) {                                      \  
             cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval);                  \  
         } else {                                                              \  
             if (!JSVAL_IS_PRIMITIVE(lval))                                    \  
                 DEFAULT_VALUE(cx, -2, JSTYPE_NUMBER, lval);                   \  
             if (!JSVAL_IS_PRIMITIVE(rval))                                    \  
                 DEFAULT_VALUE(cx, -1, JSTYPE_NUMBER, rval);                   \  
             if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) {             \  
                 str  = JSVAL_TO_STRING(lval);                                 \  
                 str2 = JSVAL_TO_STRING(rval);                                 \  
                 cond = js_CompareStrings(str, str2) OP 0;                     \  
             } else {                                                          \  
                 VALUE_TO_NUMBER(cx, -2, lval, d);                             \  
                 VALUE_TO_NUMBER(cx, -1, rval, d2);                            \  
                 cond = JSDOUBLE_COMPARE(d, OP, d2, JS_FALSE);                 \  
             }                                                                 \  
         }                                                                     \  
         TRY_BRANCH_AFTER_COND(cond, 2);                                       \  
         regs.sp--;                                                            \  
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \  
     JS_END_MACRO  
   
 /*  
  * NB: These macros can't use JS_BEGIN_MACRO/JS_END_MACRO around their bodies  
  * because they begin if/else chains, so callers must not put semicolons after  
  * the call expressions!  
  */  
 #if JS_HAS_XML_SUPPORT  
 #define XML_EQUALITY_OP(OP)                                                   \  
     if ((ltmp == JSVAL_OBJECT &&                                              \  
          (obj2 = JSVAL_TO_OBJECT(lval)) &&                                    \  
          OBJECT_IS_XML(cx, obj2)) ||                                          \  
         (rtmp == JSVAL_OBJECT &&                                              \  
          (obj2 = JSVAL_TO_OBJECT(rval)) &&                                    \  
          OBJECT_IS_XML(cx, obj2))) {                                          \  
         if (JSVAL_IS_OBJECT(rval) && obj2 == JSVAL_TO_OBJECT(rval))           \  
             rval = lval;                                                      \  
         if (!js_TestXMLEquality(cx, obj2, rval, &cond))                       \  
             goto error;                                                       \  
         cond = cond OP JS_TRUE;                                               \  
     } else  
   
 #define EXTENDED_EQUALITY_OP(OP)                                              \  
     if (ltmp == JSVAL_OBJECT &&                                               \  
         (obj2 = JSVAL_TO_OBJECT(lval)) &&                                     \  
         ((clasp = OBJ_GET_CLASS(cx, obj2))->flags & JSCLASS_IS_EXTENDED)) {   \  
         JSExtendedClass *xclasp;                                              \  
                                                                               \  
         xclasp = (JSExtendedClass *) clasp;                                   \  
         if (!xclasp->equality(cx, obj2, rval, &cond))                         \  
             goto error;                                                       \  
         cond = cond OP JS_TRUE;                                               \  
     } else  
 #else  
 #define XML_EQUALITY_OP(OP)             /* nothing */  
 #define EXTENDED_EQUALITY_OP(OP)        /* nothing */  
 #endif  
   
 #define EQUALITY_OP(OP, IFNAN)                                                \  
     JS_BEGIN_MACRO                                                            \  
         rval = FETCH_OPND(-1);                                                \  
         lval = FETCH_OPND(-2);                                                \  
         ltmp = JSVAL_TAG(lval);                                               \  
         rtmp = JSVAL_TAG(rval);                                               \  
         XML_EQUALITY_OP(OP)                                                   \  
         if (ltmp == rtmp) {                                                   \  
             if (ltmp == JSVAL_STRING) {                                       \  
                 str  = JSVAL_TO_STRING(lval);                                 \  
                 str2 = JSVAL_TO_STRING(rval);                                 \  
                 cond = js_EqualStrings(str, str2) OP JS_TRUE;                 \  
             } else if (ltmp == JSVAL_DOUBLE) {                                \  
                 d  = *JSVAL_TO_DOUBLE(lval);                                  \  
                 d2 = *JSVAL_TO_DOUBLE(rval);                                  \  
                 cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN);                    \  
             } else {                                                          \  
                 EXTENDED_EQUALITY_OP(OP)                                      \  
                 /* Handle all undefined (=>NaN) and int combinations. */      \  
                 cond = lval OP rval;                                          \  
             }                                                                 \  
         } else {                                                              \  
             if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) {                 \  
                 cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1;     \  
             } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) {          \  
                 cond = 1 OP 0;                                                \  
             } else {                                                          \  
                 if (ltmp == JSVAL_OBJECT) {                                   \  
                     DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);                 \  
                     ltmp = JSVAL_TAG(lval);                                   \  
                 } else if (rtmp == JSVAL_OBJECT) {                            \  
                     DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);                 \  
                     rtmp = JSVAL_TAG(rval);                                   \  
                 }                                                             \  
                 if (ltmp == JSVAL_STRING && rtmp == JSVAL_STRING) {           \  
                     str  = JSVAL_TO_STRING(lval);                             \  
                     str2 = JSVAL_TO_STRING(rval);                             \  
                     cond = js_EqualStrings(str, str2) OP JS_TRUE;             \  
                 } else {                                                      \  
                     VALUE_TO_NUMBER(cx, -2, lval, d);                         \  
                     VALUE_TO_NUMBER(cx, -1, rval, d2);                        \  
                     cond = JSDOUBLE_COMPARE(d, OP, d2, IFNAN);                \  
                 }                                                             \  
             }                                                                 \  
         }                                                                     \  
         TRY_BRANCH_AFTER_COND(cond, 2);                                       \  
         regs.sp--;                                                            \  
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_EQ)  
             EQUALITY_OP(==, JS_FALSE);  
           END_CASE(JSOP_EQ)  
   
           BEGIN_CASE(JSOP_NE)  
             EQUALITY_OP(!=, JS_TRUE);  
           END_CASE(JSOP_NE)  
   
 #define STRICT_EQUALITY_OP(OP)                                                \  
     JS_BEGIN_MACRO                                                            \  
         rval = FETCH_OPND(-1);                                                \  
         lval = FETCH_OPND(-2);                                                \  
         cond = js_StrictlyEqual(cx, lval, rval) OP JS_TRUE;                   \  
         regs.sp--;                                                            \  
         STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));                               \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_STRICTEQ)  
             STRICT_EQUALITY_OP(==);  
           END_CASE(JSOP_STRICTEQ)  
   
           BEGIN_CASE(JSOP_STRICTNE)  
             STRICT_EQUALITY_OP(!=);  
           END_CASE(JSOP_STRICTNE)  
   
           BEGIN_CASE(JSOP_CASE)  
             STRICT_EQUALITY_OP(==);  
             (void) POP();  
             if (cond) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
             PUSH(lval);  
           END_CASE(JSOP_CASE)  
   
           BEGIN_CASE(JSOP_CASEX)  
             STRICT_EQUALITY_OP(==);  
             (void) POP();  
             if (cond) {  
                 len = GET_JUMPX_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
             PUSH(lval);  
           END_CASE(JSOP_CASEX)  
   
           BEGIN_CASE(JSOP_LT)  
             RELATIONAL_OP(<);  
           END_CASE(JSOP_LT)  
   
           BEGIN_CASE(JSOP_LE)  
             RELATIONAL_OP(<=);  
           END_CASE(JSOP_LE)  
   
           BEGIN_CASE(JSOP_GT)  
             RELATIONAL_OP(>);  
           END_CASE(JSOP_GT)  
   
           BEGIN_CASE(JSOP_GE)  
             RELATIONAL_OP(>=);  
           END_CASE(JSOP_GE)  
   
 #undef EQUALITY_OP  
 #undef RELATIONAL_OP  
   
 #define SIGNED_SHIFT_OP(OP)                                                   \  
     JS_BEGIN_MACRO                                                            \  
         FETCH_INT(cx, -2, i);                                                 \  
         FETCH_INT(cx, -1, j);                                                 \  
         i = i OP (j & 31);                                                    \  
         regs.sp--;                                                            \  
         STORE_INT(cx, -1, i);                                                 \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_LSH)  
             SIGNED_SHIFT_OP(<<);  
           END_CASE(JSOP_LSH)  
   
           BEGIN_CASE(JSOP_RSH)  
             SIGNED_SHIFT_OP(>>);  
           END_CASE(JSOP_RSH)  
   
           BEGIN_CASE(JSOP_URSH)  
           {  
             uint32 u;  
   
             FETCH_UINT(cx, -2, u);  
             FETCH_INT(cx, -1, j);  
             u >>= (j & 31);  
             regs.sp--;  
             STORE_UINT(cx, -1, u);  
           }  
           END_CASE(JSOP_URSH)  
   
 #undef BITWISE_OP  
 #undef SIGNED_SHIFT_OP  
   
           BEGIN_CASE(JSOP_ADD)  
             rval = FETCH_OPND(-1);  
             lval = FETCH_OPND(-2);  
 #if JS_HAS_XML_SUPPORT  
             if (!JSVAL_IS_PRIMITIVE(lval) &&  
                 (obj2 = JSVAL_TO_OBJECT(lval), OBJECT_IS_XML(cx, obj2)) &&  
                 VALUE_IS_XML(cx, rval)) {  
                 if (!js_ConcatenateXML(cx, obj2, rval, &rval))  
                     goto error;  
                 regs.sp--;  
                 STORE_OPND(-1, rval);  
             } else  
 #endif  
             {  
                 if (!JSVAL_IS_PRIMITIVE(lval))  
                     DEFAULT_VALUE(cx, -2, JSTYPE_VOID, lval);  
                 if (!JSVAL_IS_PRIMITIVE(rval))  
                     DEFAULT_VALUE(cx, -1, JSTYPE_VOID, rval);  
                 if ((cond = JSVAL_IS_STRING(lval)) || JSVAL_IS_STRING(rval)) {  
                     if (cond) {  
                         str = JSVAL_TO_STRING(lval);  
                         str2 = js_ValueToString(cx, rval);  
                         if (!str2)  
                             goto error;  
                         regs.sp[-1] = STRING_TO_JSVAL(str2);  
                     } else {  
                         str2 = JSVAL_TO_STRING(rval);  
                         str = js_ValueToString(cx, lval);  
                         if (!str)  
                             goto error;  
                         regs.sp[-2] = STRING_TO_JSVAL(str);  
                     }  
                     str = js_ConcatStrings(cx, str, str2);  
                     if (!str)  
                         goto error;  
                     regs.sp--;  
                     STORE_OPND(-1, STRING_TO_JSVAL(str));  
                 } else {  
                     VALUE_TO_NUMBER(cx, -2, lval, d);  
                     VALUE_TO_NUMBER(cx, -1, rval, d2);  
                     d += d2;  
                     regs.sp--;  
                     STORE_NUMBER(cx, -1, d);  
                 }  
             }  
           END_CASE(JSOP_ADD)  
   
 #define BINARY_OP(OP)                                                         \  
     JS_BEGIN_MACRO                                                            \  
         FETCH_NUMBER(cx, -2, d);                                              \  
         FETCH_NUMBER(cx, -1, d2);                                             \  
         d = d OP d2;                                                          \  
         regs.sp--;                                                            \  
         STORE_NUMBER(cx, -1, d);                                              \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_SUB)  
             BINARY_OP(-);  
           END_CASE(JSOP_SUB)  
   
           BEGIN_CASE(JSOP_MUL)  
             BINARY_OP(*);  
           END_CASE(JSOP_MUL)  
   
           BEGIN_CASE(JSOP_DIV)  
             FETCH_NUMBER(cx, -1, d2);  
             FETCH_NUMBER(cx, -2, d);  
             regs.sp--;  
             if (d2 == 0) {  
 #ifdef XP_WIN  
                 /* XXX MSVC miscompiles such that (NaN == 0) */  
                 if (JSDOUBLE_IS_NaN(d2))  
                     rval = DOUBLE_TO_JSVAL(rt->jsNaN);  
                 else  
 #endif  
                 if (d == 0 || JSDOUBLE_IS_NaN(d))  
                     rval = DOUBLE_TO_JSVAL(rt->jsNaN);  
                 else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)  
                     rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);  
                 else  
                     rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);  
                 STORE_OPND(-1, rval);  
             } else {  
                 d /= d2;  
                 STORE_NUMBER(cx, -1, d);  
             }  
           END_CASE(JSOP_DIV)  
   
           BEGIN_CASE(JSOP_MOD)  
             FETCH_NUMBER(cx, -1, d2);  
             FETCH_NUMBER(cx, -2, d);  
             regs.sp--;  
             if (d2 == 0) {  
                 STORE_OPND(-1, DOUBLE_TO_JSVAL(rt->jsNaN));  
             } else {  
 #ifdef XP_WIN  
               /* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */  
               if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))  
 #endif  
                 d = fmod(d, d2);  
                 STORE_NUMBER(cx, -1, d);  
             }  
           END_CASE(JSOP_MOD)  
   
           BEGIN_CASE(JSOP_NOT)  
             POP_BOOLEAN(cx, rval, cond);  
             PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));  
           END_CASE(JSOP_NOT)  
   
           BEGIN_CASE(JSOP_BITNOT)  
             FETCH_INT(cx, -1, i);  
             i = ~i;  
             STORE_INT(cx, -1, i);  
           END_CASE(JSOP_BITNOT)  
   
           BEGIN_CASE(JSOP_NEG)  
             /*  
              * When the operand is int jsval, INT_FITS_IN_JSVAL(i) implies  
              * INT_FITS_IN_JSVAL(-i) unless i is 0 or JSVAL_INT_MIN when the  
              * results, -0.0 or JSVAL_INT_MAX + 1, are jsdouble values.  
              */  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_INT(rval) &&  
                 rval != INT_TO_JSVAL(JSVAL_INT_MIN) &&  
                 (i = JSVAL_TO_INT(rval)) != 0) {  
                 JS_STATIC_ASSERT(!INT_FITS_IN_JSVAL(-JSVAL_INT_MIN));  
                 i = -i;  
                 JS_ASSERT(INT_FITS_IN_JSVAL(i));  
                 regs.sp[-1] = INT_TO_JSVAL(i);  
             } else {  
                 if (JSVAL_IS_DOUBLE(rval)) {  
                     d = *JSVAL_TO_DOUBLE(rval);  
                 } else {  
                     d = js_ValueToNumber(cx, &regs.sp[-1]);  
                     if (JSVAL_IS_NULL(regs.sp[-1]))  
                         goto error;  
                     JS_ASSERT(JSVAL_IS_NUMBER(regs.sp[-1]) ||  
                               regs.sp[-1] == JSVAL_TRUE);  
                 }  
 #ifdef HPUX  
                 /*  
                  * Negation of a zero doesn't produce a negative  
                  * zero on HPUX. Perform the operation by bit  
                  * twiddling.  
                  */  
                 JSDOUBLE_HI32(d) ^= JSDOUBLE_HI32_SIGNBIT;  
 #else  
                 d = -d;  
 #endif  
                 if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))  
                     goto error;  
             }  
           END_CASE(JSOP_NEG)  
   
           BEGIN_CASE(JSOP_POS)  
             rval = FETCH_OPND(-1);  
             if (!JSVAL_IS_NUMBER(rval)) {  
                 d = js_ValueToNumber(cx, &regs.sp[-1]);  
                 rval = regs.sp[-1];  
                 if (JSVAL_IS_NULL(rval))  
                     goto error;  
                 if (rval == JSVAL_TRUE) {  
                     if (!js_NewNumberInRootedValue(cx, d, &regs.sp[-1]))  
                         goto error;  
                 } else {  
                     JS_ASSERT(JSVAL_IS_NUMBER(rval));  
                 }  
             }  
           END_CASE(JSOP_POS)  
   
           BEGIN_CASE(JSOP_DELNAME)  
             LOAD_ATOM(0);  
             id = ATOM_TO_JSID(atom);  
             if (!js_FindProperty(cx, id, &obj, &obj2, &prop))  
                 goto error;  
   
             /* ECMA says to return true if name is undefined or inherited. */  
             PUSH_OPND(JSVAL_TRUE);  
             if (prop) {  
                 OBJ_DROP_PROPERTY(cx, obj2, prop);  
                 if (!OBJ_DELETE_PROPERTY(cx, obj, id, &regs.sp[-1]))  
                     goto error;  
             }  
           END_CASE(JSOP_DELNAME)  
   
           BEGIN_CASE(JSOP_DELPROP)  
             LOAD_ATOM(0);  
             id = ATOM_TO_JSID(atom);  
             PROPERTY_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_DELPROP)  
   
           BEGIN_CASE(JSOP_DELELEM)  
             ELEMENT_OP(-1, OBJ_DELETE_PROPERTY(cx, obj, id, &rval));  
             regs.sp--;  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_DELELEM)  
   
           BEGIN_CASE(JSOP_TYPEOFEXPR)  
           BEGIN_CASE(JSOP_TYPEOF)  
             rval = FETCH_OPND(-1);  
             type = JS_TypeOfValue(cx, rval);  
             atom = rt->atomState.typeAtoms[type];  
             STORE_OPND(-1, ATOM_KEY(atom));  
           END_CASE(JSOP_TYPEOF)  
   
           BEGIN_CASE(JSOP_VOID)  
             STORE_OPND(-1, JSVAL_VOID);  
           END_CASE(JSOP_VOID)  
   
           BEGIN_CASE(JSOP_INCELEM)  
           BEGIN_CASE(JSOP_DECELEM)  
           BEGIN_CASE(JSOP_ELEMINC)  
           BEGIN_CASE(JSOP_ELEMDEC)  
             /*  
              * Delay fetching of id until we have the object to ensure  
              * the proper evaluation order. See bug 372331.  
              */  
             id = 0;  
             i = -2;  
             goto fetch_incop_obj;  
   
           BEGIN_CASE(JSOP_INCPROP)  
           BEGIN_CASE(JSOP_DECPROP)  
           BEGIN_CASE(JSOP_PROPINC)  
           BEGIN_CASE(JSOP_PROPDEC)  
             LOAD_ATOM(0);  
             id = ATOM_TO_JSID(atom);  
             i = -1;  
   
           fetch_incop_obj:  
             FETCH_OBJECT(cx, i, lval, obj);  
             if (id == 0)  
                 FETCH_ELEMENT_ID(obj, -1, id);  
             goto do_incop;  
   
           BEGIN_CASE(JSOP_INCNAME)  
           BEGIN_CASE(JSOP_DECNAME)  
           BEGIN_CASE(JSOP_NAMEINC)  
           BEGIN_CASE(JSOP_NAMEDEC)  
           {  
             JSPropCacheEntry *entry;  
   
             obj = fp->scopeChain;  
             if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {  
                 PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);  
                 if (!atom) {  
                     ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);  
                     if (obj == obj2 && PCVAL_IS_SLOT(entry->vword)) {  
                         slot = PCVAL_TO_SLOT(entry->vword);  
                         JS_ASSERT(slot < OBJ_SCOPE(obj)->freeslot);  
                         rval = LOCKED_OBJ_GET_SLOT(obj, slot);  
                         if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {  
                             rtmp = rval;  
                             rval += (js_CodeSpec[op].format & JOF_INC) ? 2 : -2;  
                             if (!(js_CodeSpec[op].format & JOF_POST))  
                                 rtmp = rval;  
                             LOCKED_OBJ_SET_SLOT(obj, slot, rval);  
                             JS_UNLOCK_OBJ(cx, obj);  
                             PUSH_OPND(rtmp);  
                             len = JSOP_INCNAME_LENGTH;  
                             DO_NEXT_OP(len);  
                         }  
                     }  
                     JS_UNLOCK_OBJ(cx, obj2);  
                     LOAD_ATOM(0);  
                 }  
             } else {  
                 LOAD_ATOM(0);  
             }  
             id = ATOM_TO_JSID(atom);  
             if (!js_FindPropertyHelper(cx, id, true, &obj, &obj2, &prop))  
                 goto error;  
             if (!prop)  
                 goto atom_not_defined;  
             OBJ_DROP_PROPERTY(cx, obj2, prop);  
           }  
   
           do_incop:  
           {  
             const JSCodeSpec *cs;  
             jsval v;  
   
             /*  
              * We need a root to store the value to leave on the stack until  
              * we have done with OBJ_SET_PROPERTY.  
              */  
             PUSH_OPND(JSVAL_NULL);  
             if (!OBJ_GET_PROPERTY(cx, obj, id, &regs.sp[-1]))  
                 goto error;  
   
             cs = &js_CodeSpec[op];  
             JS_ASSERT(cs->ndefs == 1);  
             JS_ASSERT((cs->format & JOF_TMPSLOT_MASK) == JOF_TMPSLOT2);  
             v = regs.sp[-1];  
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(v))) {  
                 jsval incr;  
   
                 incr = (cs->format & JOF_INC) ? 2 : -2;  
                 if (cs->format & JOF_POST) {  
                     regs.sp[-1] = v + incr;  
                 } else {  
                     v += incr;  
                     regs.sp[-1] = v;  
                 }  
                 fp->flags |= JSFRAME_ASSIGNING;  
                 ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);  
                 fp->flags &= ~JSFRAME_ASSIGNING;  
                 if (!ok)  
                     goto error;  
   
                 /*  
                  * We must set regs.sp[-1] to v for both post and pre increments  
                  * as the setter overwrites regs.sp[-1].  
                  */  
                 regs.sp[-1] = v;  
             } else {  
                 /* We need an extra root for the result. */  
                 PUSH_OPND(JSVAL_NULL);  
                 if (!js_DoIncDec(cx, cs, &regs.sp[-2], &regs.sp[-1]))  
                     goto error;  
                 fp->flags |= JSFRAME_ASSIGNING;  
                 ok = OBJ_SET_PROPERTY(cx, obj, id, &regs.sp[-1]);  
                 fp->flags &= ~JSFRAME_ASSIGNING;  
                 if (!ok)  
                     goto error;  
                 regs.sp--;  
             }  
   
             if (cs->nuses == 0) {  
                 /* regs.sp[-1] already contains the result of name increment. */  
             } else {  
                 rtmp = regs.sp[-1];  
                 regs.sp -= cs->nuses;  
                 regs.sp[-1] = rtmp;  
             }  
             len = cs->length;  
             DO_NEXT_OP(len);  
           }  
   
           {  
             jsval incr, incr2;  
   
             /* Position cases so the most frequent i++ does not need a jump. */  
           BEGIN_CASE(JSOP_DECARG)  
             incr = -2; incr2 = -2; goto do_arg_incop;  
           BEGIN_CASE(JSOP_ARGDEC)  
             incr = -2; incr2 =  0; goto do_arg_incop;  
           BEGIN_CASE(JSOP_INCARG)  
             incr =  2; incr2 =  2; goto do_arg_incop;  
           BEGIN_CASE(JSOP_ARGINC)  
             incr =  2; incr2 =  0;  
   
           do_arg_incop:  
             slot = GET_ARGNO(regs.pc);  
             JS_ASSERT(slot < fp->fun->nargs);  
             METER_SLOT_OP(op, slot);  
             vp = fp->argv + slot;  
             goto do_int_fast_incop;  
   
           BEGIN_CASE(JSOP_DECLOCAL)  
             incr = -2; incr2 = -2; goto do_local_incop;  
           BEGIN_CASE(JSOP_LOCALDEC)  
             incr = -2; incr2 =  0; goto do_local_incop;  
           BEGIN_CASE(JSOP_INCLOCAL)  
             incr =  2; incr2 =  2; goto do_local_incop;  
           BEGIN_CASE(JSOP_LOCALINC)  
             incr =  2; incr2 =  0;  
   
           /*  
            * do_local_incop comes right before do_int_fast_incop as we want to  
            * avoid an extra jump for variable cases as local++ is more frequent  
            * than arg++.  
            */  
           do_local_incop:  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < fp->script->nslots);  
             vp = fp->slots + slot;  
             METER_SLOT_OP(op, slot);  
             vp = fp->slots + slot;  
   
           do_int_fast_incop:  
             rval = *vp;  
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {  
                 *vp = rval + incr;  
                 JS_ASSERT(JSOP_INCARG_LENGTH == js_CodeSpec[op].length);  
                 SKIP_POP_AFTER_SET(JSOP_INCARG_LENGTH, 0);  
                 PUSH_OPND(rval + incr2);  
             } else {  
                 PUSH_OPND(rval);  
                 if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-1], vp))  
                     goto error;  
             }  
             len = JSOP_INCARG_LENGTH;  
             JS_ASSERT(len == js_CodeSpec[op].length);  
             DO_NEXT_OP(len);  
           }  
   
 /* NB: This macro doesn't use JS_BEGIN_MACRO/JS_END_MACRO around its body. */  
 #define FAST_GLOBAL_INCREMENT_OP(SLOWOP,INCR,INCR2)                           \  
     op2 = SLOWOP;                                                             \  
     incr = INCR;                                                              \  
     incr2 = INCR2;                                                            \  
     goto do_global_incop  
   
           {  
             jsval incr, incr2;  
   
           BEGIN_CASE(JSOP_DECGVAR)  
             FAST_GLOBAL_INCREMENT_OP(JSOP_DECNAME, -2, -2);  
           BEGIN_CASE(JSOP_GVARDEC)  
             FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEDEC, -2,  0);  
           BEGIN_CASE(JSOP_INCGVAR)  
               FAST_GLOBAL_INCREMENT_OP(JSOP_INCNAME,  2,  2);  
           BEGIN_CASE(JSOP_GVARINC)  
             FAST_GLOBAL_INCREMENT_OP(JSOP_NAMEINC,  2,  0);  
   
 #undef FAST_GLOBAL_INCREMENT_OP  
   
           do_global_incop:  
             JS_ASSERT((js_CodeSpec[op].format & JOF_TMPSLOT_MASK) ==  
                       JOF_TMPSLOT2);  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < GlobalVarCount(fp));  
             METER_SLOT_OP(op, slot);  
             lval = fp->slots[slot];  
             if (JSVAL_IS_NULL(lval)) {  
                 op = op2;  
                 DO_OP();  
             }  
             slot = JSVAL_TO_INT(lval);  
             rval = OBJ_GET_SLOT(cx, fp->varobj, slot);  
             if (JS_LIKELY(CAN_DO_FAST_INC_DEC(rval))) {  
                 PUSH_OPND(rval + incr2);  
                 rval += incr;  
             } else {  
                 PUSH_OPND(rval);  
                 PUSH_OPND(JSVAL_NULL);  /* Extra root */  
                 if (!js_DoIncDec(cx, &js_CodeSpec[op], &regs.sp[-2], &regs.sp[-1]))  
                     goto error;  
                 rval = regs.sp[-1];  
                 --regs.sp;  
             }  
             OBJ_SET_SLOT(cx, fp->varobj, slot, rval);  
             len = JSOP_INCGVAR_LENGTH;  /* all gvar incops are same length */  
             JS_ASSERT(len == js_CodeSpec[op].length);  
             DO_NEXT_OP(len);  
           }  
   
 #define COMPUTE_THIS(cx, fp, obj)                                             \  
     JS_BEGIN_MACRO                                                            \  
         if (!(obj = js_ComputeThisForFrame(cx, fp)))                          \  
             goto error;                                                       \  
     JS_END_MACRO  
   
           BEGIN_CASE(JSOP_THIS)  
             COMPUTE_THIS(cx, fp, obj);  
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_THIS)  
   
           BEGIN_CASE(JSOP_GETTHISPROP)  
             i = 0;  
             COMPUTE_THIS(cx, fp, obj);  
             PUSH(JSVAL_NULL);  
             goto do_getprop_with_obj;  
   
 #undef COMPUTE_THIS  
   
           BEGIN_CASE(JSOP_GETARGPROP)  
             i = ARGNO_LEN;  
             slot = GET_ARGNO(regs.pc);  
             JS_ASSERT(slot < fp->fun->nargs);  
             PUSH_OPND(fp->argv[slot]);  
             goto do_getprop_body;  
   
           BEGIN_CASE(JSOP_GETLOCALPROP)  
             i = SLOTNO_LEN;  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < script->nslots);  
             PUSH_OPND(fp->slots[slot]);  
             goto do_getprop_body;  
   
           BEGIN_CASE(JSOP_GETPROP)  
           BEGIN_CASE(JSOP_GETXPROP)  
             i = 0;  
   
           do_getprop_body:  
             lval = FETCH_OPND(-1);  
   
           do_getprop_with_lval:  
             VALUE_TO_OBJECT(cx, -1, lval, obj);  
   
           do_getprop_with_obj:  
             do {  
                 JSObject *aobj;  
                 JSPropCacheEntry *entry;  
   
                 aobj = js_GetProtoIfDenseArray(cx, obj);  
                 if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {  
                     PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);  
                     if (!atom) {  
                         ASSERT_VALID_PROPERTY_CACHE_HIT(i, aobj, obj2, entry);  
                         if (PCVAL_IS_OBJECT(entry->vword)) {  
                             rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);  
                         } else if (PCVAL_IS_SLOT(entry->vword)) {  
                             slot = PCVAL_TO_SLOT(entry->vword);  
                             JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);  
                             rval = LOCKED_OBJ_GET_SLOT(obj2, slot);  
                         } else {  
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                             sprop = PCVAL_TO_SPROP(entry->vword);  
                             NATIVE_GET(cx, obj, obj2, sprop, &rval);  
                         }  
                         JS_UNLOCK_OBJ(cx, obj2);  
                         break;  
                     }  
                 } else {  
                     entry = NULL;  
                     if (i < 0)  
                         atom = rt->atomState.lengthAtom;  
                     else  
                         LOAD_ATOM(i);  
                 }  
                 id = ATOM_TO_JSID(atom);  
                 if (entry  
                     ? !js_GetPropertyHelper(cx, obj, id, true, &rval)  
                     : !OBJ_GET_PROPERTY(cx, obj, id, &rval)) {  
                     goto error;  
                 }  
             } while (0);  
   
             STORE_OPND(-1, rval);  
             JS_ASSERT(JSOP_GETPROP_LENGTH + i == js_CodeSpec[op].length);  
             len = JSOP_GETPROP_LENGTH + i;  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_LENGTH)  
             lval = FETCH_OPND(-1);  
             if (JSVAL_IS_STRING(lval)) {  
                 str = JSVAL_TO_STRING(lval);  
                 regs.sp[-1] = INT_TO_JSVAL(JSSTRING_LENGTH(str));  
             } else if (!JSVAL_IS_PRIMITIVE(lval) &&  
                        (obj = JSVAL_TO_OBJECT(lval), OBJ_IS_ARRAY(cx, obj))) {  
                 jsuint length;  
   
                 /*  
                  * We know that the array is created with only its 'length'  
                  * private data in a fixed slot at JSSLOT_ARRAY_LENGTH. See  
                  * also JSOP_ARRAYPUSH, far below.  
                  */  
                 length = obj->fslots[JSSLOT_ARRAY_LENGTH];  
                 if (length <= JSVAL_INT_MAX) {  
                     regs.sp[-1] = INT_TO_JSVAL(length);  
                 } else if (!js_NewDoubleInRootedValue(cx, (jsdouble) length,  
                                                       &regs.sp[-1])) {  
                     goto error;  
                 }  
             } else {  
                 i = -2;  
                 goto do_getprop_with_lval;  
             }  
           END_CASE(JSOP_LENGTH)  
   
           BEGIN_CASE(JSOP_CALLPROP)  
           {  
             JSObject *aobj;  
             JSPropCacheEntry *entry;  
   
             lval = FETCH_OPND(-1);  
             if (!JSVAL_IS_PRIMITIVE(lval)) {  
                 obj = JSVAL_TO_OBJECT(lval);  
             } else {  
                 if (JSVAL_IS_STRING(lval)) {  
                     i = JSProto_String;  
                 } else if (JSVAL_IS_NUMBER(lval)) {  
                     i = JSProto_Number;  
                 } else if (JSVAL_IS_BOOLEAN(lval)) {  
                     i = JSProto_Boolean;  
                 } else {  
                     JS_ASSERT(JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval));  
                     js_ReportIsNullOrUndefined(cx, -1, lval, NULL);  
                     goto error;  
                 }  
   
                 if (!js_GetClassPrototype(cx, NULL, INT_TO_JSID(i), &obj))  
                     goto error;  
             }  
   
             aobj = js_GetProtoIfDenseArray(cx, obj);  
             if (JS_LIKELY(aobj->map->ops->getProperty == js_GetProperty)) {  
                 PROPERTY_CACHE_TEST(cx, regs.pc, aobj, obj2, entry, atom);  
                 if (!atom) {  
                     ASSERT_VALID_PROPERTY_CACHE_HIT(0, aobj, obj2, entry);  
                     if (PCVAL_IS_OBJECT(entry->vword)) {  
                         rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);  
                     } else if (PCVAL_IS_SLOT(entry->vword)) {  
                         slot = PCVAL_TO_SLOT(entry->vword);  
                         JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);  
                         rval = LOCKED_OBJ_GET_SLOT(obj2, slot);  
                     } else {  
                         JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                         sprop = PCVAL_TO_SPROP(entry->vword);  
                         NATIVE_GET(cx, obj, obj2, sprop, &rval);  
                     }  
                     JS_UNLOCK_OBJ(cx, obj2);  
                     STORE_OPND(-1, rval);  
                     PUSH_OPND(lval);  
                     goto end_callprop;  
                 }  
             } else {  
                 entry = NULL;  
                 LOAD_ATOM(0);  
             }  
   
             /*  
              * Cache miss: use the immediate atom that was loaded for us under  
              * PROPERTY_CACHE_TEST.  
              */  
             id = ATOM_TO_JSID(atom);  
             PUSH(JSVAL_NULL);  
             if (!JSVAL_IS_PRIMITIVE(lval)) {  
                 if (!js_GetMethod(cx, obj, id, !!entry, &rval))  
                     goto error;  
                 STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
                 STORE_OPND(-2, rval);  
             } else {  
                 JS_ASSERT(obj->map->ops->getProperty == js_GetProperty);  
                 if (!js_GetPropertyHelper(cx, obj, id, true, &rval))  
                     goto error;  
                 STORE_OPND(-1, lval);  
                 STORE_OPND(-2, rval);  
             }  
   
           end_callprop:  
             /* Wrap primitive lval in object clothing if necessary. */  
             if (JSVAL_IS_PRIMITIVE(lval)) {  
                 /* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */  
                 if (!VALUE_IS_FUNCTION(cx, rval) ||  
                     (obj = JSVAL_TO_OBJECT(rval),  
                      fun = GET_FUNCTION_PRIVATE(cx, obj),  
                      !PRIMITIVE_THIS_TEST(fun, lval))) {  
                     if (!js_PrimitiveToObject(cx, &regs.sp[-1]))  
                         goto error;  
                 }  
             }  
 #if JS_HAS_NO_SUCH_METHOD  
             if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {  
                 LOAD_ATOM(0);  
                 regs.sp[-2] = ATOM_KEY(atom);  
                 if (!js_OnUnknownMethod(cx, regs.sp - 2))  
                     goto error;  
             }  
 #endif  
           }  
           END_CASE(JSOP_CALLPROP)  
   
           BEGIN_CASE(JSOP_SETNAME)  
           BEGIN_CASE(JSOP_SETPROP)  
             rval = FETCH_OPND(-1);  
             lval = FETCH_OPND(-2);  
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval) || op == JSOP_SETPROP);  
             VALUE_TO_OBJECT(cx, -2, lval, obj);  
   
             do {  
                 JSPropCacheEntry *entry;  
   
                 entry = NULL;  
                 atom = NULL;  
                 if (JS_LIKELY(obj->map->ops->setProperty == js_SetProperty)) {  
                     JSPropertyCache *cache = &JS_PROPERTY_CACHE(cx);  
                     uint32 kshape = OBJ_SHAPE(obj);  
   
                     /*  
                      * Open-code JS_PROPERTY_CACHE_TEST, specializing for two  
                      * important set-property cases. First:  
                      *  
                      *   function f(a, b, c) {  
                      *     var o = {p:a, q:b, r:c};  
                      *     return o;  
                      *   }  
                      *  
                      * or similar real-world cases, which evolve a newborn  
                      * native object predicatably through some bounded number  
                      * of property additions. And second:  
                      *  
                      *   o.p = x;  
                      *  
                      * in a frequently executed method or loop body, where p  
                      * will (possibly after the first iteration) always exist  
                      * in native object o.  
                      */  
                     entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];  
                     PCMETER(cache->pctestentry = entry);  
                     PCMETER(cache->tests++);  
                     PCMETER(cache->settests++);  
                     if (entry->kpc == regs.pc &&  
                         entry->kshape == kshape &&  
                         PCVCAP_SHAPE(entry->vcap) == rt->protoHazardShape) {  
                         JS_ASSERT(PCVCAP_TAG(entry->vcap) == 0);  
   
                         JS_LOCK_OBJ(cx, obj);  
                         JSScope *scope = OBJ_SCOPE(obj);  
                         if (scope->shape == kshape) {  
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                             sprop = PCVAL_TO_SPROP(entry->vword);  
                             JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));  
                             JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj)));  
   
                             /*  
                              * Fastest path: check whether the cached sprop is  
                              * already in scope and call NATIVE_GET and break  
                              * to get out of the do-while(0). But we can call  
                              * NATIVE_GET only if obj owns scope or sprop is  
                              * shared.  
                              */  
                             bool checkForAdd;  
                             if (scope->object == obj ||  
                                 (sprop->attrs & JSPROP_SHARED)) {  
                                 if (sprop == scope->lastProp ||  
                                     SCOPE_HAS_PROPERTY(scope, sprop)) {  
                                     PCMETER(cache->pchits++);  
                                     PCMETER(cache->setpchits++);  
                                     NATIVE_SET(cx, obj, sprop, entry, &rval);  
                                     JS_UNLOCK_SCOPE(cx, scope);  
                                     break;  
                                 }  
                                 checkForAdd =  
                                     !(sprop->attrs & JSPROP_SHARED) &&  
                                     sprop->parent == scope->lastProp &&  
                                     !SCOPE_HAD_MIDDLE_DELETE(scope);  
   
                             } else {  
                                 scope = js_GetMutableScope(cx, obj);  
                                 if (!scope) {  
                                     JS_UNLOCK_OBJ(cx, obj);  
                                     goto error;  
                                 }  
                                 checkForAdd = !sprop->parent;  
                             }  
   
                             if (checkForAdd &&  
                                 SPROP_HAS_STUB_SETTER(sprop) &&  
                                 (slot = sprop->slot) == scope->freeslot) {  
                                 /*  
                                  * Fast path: adding a plain old property that  
                                  * was once at the frontier of the property  
                                  * tree, whose slot is next to claim among the  
                                  * allocated slots in obj, where scope->table  
                                  * has not been created yet.  
                                  *  
                                  * We may want to remove hazard conditions  
                                  * above and inline compensation code here,  
                                  * depending on real-world workloads.  
                                  */  
                                 JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &  
                                             JSCLASS_SHARE_ALL_PROPERTIES));  
   
                                 PCMETER(cache->pchits++);  
                                 PCMETER(cache->addpchits++);  
   
                                 /*  
                                  * Beware classes such as Function that use  
                                  * the reserveSlots hook to allocate a number  
                                  * of reserved slots that may vary with obj.  
                                  */  
                                 if (slot < STOBJ_NSLOTS(obj) &&  
                                     !OBJ_GET_CLASS(cx, obj)->reserveSlots) {  
                                     ++scope->freeslot;  
                                 } else {  
                                     if (!js_AllocSlot(cx, obj, &slot)) {  
                                         JS_UNLOCK_SCOPE(cx, scope);  
                                         goto error;  
                                     }  
                                 }  
   
                                 /*  
                                  * If this obj's number of reserved slots  
                                  * differed, or if something created a hash  
                                  * table for scope, we must pay the price of  
                                  * js_AddScopeProperty.  
                                  *  
                                  * If slot does not match the cached sprop's  
                                  * slot, update the cache entry in the hope  
                                  * that obj and other instances with the same  
                                  * number of reserved slots are now "hot".  
                                  */  
                                 if (slot != sprop->slot || scope->table) {  
                                     JSScopeProperty *sprop2 =  
                                         js_AddScopeProperty(cx, scope,  
                                                             sprop->id,  
                                                             sprop->getter,  
                                                             sprop->setter,  
                                                             slot,  
                                                             sprop->attrs,  
                                                             sprop->flags,  
                                                             sprop->shortid);  
                                     if (!sprop2) {  
                                         js_FreeSlot(cx, obj, slot);  
                                         JS_UNLOCK_SCOPE(cx, scope);  
                                         goto error;  
                                     }  
                                     if (sprop2 != sprop) {  
                                         PCMETER(cache->slotchanges++);  
                                         JS_ASSERT(slot != sprop->slot &&  
                                                   slot == sprop2->slot &&  
                                                   sprop2->id == sprop->id);  
                                         entry->vword = SPROP_TO_PCVAL(sprop2);  
                                     }  
                                     sprop = sprop2;  
                                 } else {  
                                     js_ExtendScopeShape(cx, scope, sprop);  
                                     ++scope->entryCount;  
                                     scope->lastProp = sprop;  
                                 }  
   
                                 GC_WRITE_BARRIER(cx, scope,  
                                                  LOCKED_OBJ_GET_SLOT(obj, slot),  
                                                  rval);  
                                 TRACE_2(SetPropHit, entry, sprop);  
                                 LOCKED_OBJ_SET_SLOT(obj, slot, rval);  
                                 JS_UNLOCK_SCOPE(cx, scope);  
   
                                 /*  
                                  * Purge the property cache of the id we may  
                                  * have just shadowed in obj's scope and proto  
                                  * chains. We do this after unlocking obj's  
                                  * scope to avoid lock nesting.  
                                  */  
                                 js_PurgeScopeChain(cx, obj, sprop->id);  
                                 break;  
                             }  
   
                             PCMETER(cache->setpcmisses++);  
                             atom = NULL;  
                         }  
   
                         JS_UNLOCK_OBJ(cx, obj);  
                     }  
   
                     atom = js_FullTestPropertyCache(cx, regs.pc, &obj, &obj2,  
                                                     &entry);  
                     if (atom) {  
                         PCMETER(cache->misses++);  
                         PCMETER(cache->setmisses++);  
                     } else {  
                         ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);  
                         sprop = NULL;  
                         if (obj == obj2) {  
                             JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                             sprop = PCVAL_TO_SPROP(entry->vword);  
                             JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));  
                             JS_ASSERT(!SCOPE_IS_SEALED(OBJ_SCOPE(obj2)));  
                             NATIVE_SET(cx, obj, sprop, entry, &rval);  
                         }  
                         JS_UNLOCK_OBJ(cx, obj2);  
                         if (sprop)  
                             break;  
                     }  
                 }  
   
                 if (!atom)  
                     LOAD_ATOM(0);  
                 id = ATOM_TO_JSID(atom);  
                 if (entry) {  
                     if (!js_SetPropertyHelper(cx, obj, id, true, &rval))  
                         goto error;  
                 } else {  
                     if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                         goto error;  
                     ABORT_RECORDING(cx, "Non-native set");  
                  }  
             } while (0);  
           END_SET_CASE_STORE_RVAL(JSOP_SETPROP, 2);  
   
           BEGIN_CASE(JSOP_GETELEM)  
             /* Open-coded ELEMENT_OP optimized for strings and dense arrays. */  
             lval = FETCH_OPND(-2);  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_STRING(lval) && JSVAL_IS_INT(rval)) {  
                 str = JSVAL_TO_STRING(lval);  
                 i = JSVAL_TO_INT(rval);  
                 if ((size_t)i < JSSTRING_LENGTH(str)) {  
                     str = js_GetUnitString(cx, str, (size_t)i);  
                     if (!str)  
                         goto error;  
                     rval = STRING_TO_JSVAL(str);  
                     goto end_getelem;  
                 }  
             }  
   
             VALUE_TO_OBJECT(cx, -2, lval, obj);  
             if (JSVAL_IS_INT(rval)) {  
                 if (OBJ_IS_DENSE_ARRAY(cx, obj)) {  
                     jsuint length;  
   
                     length = js_DenseArrayCapacity(obj);  
                     i = JSVAL_TO_INT(rval);  
                     if ((jsuint)i < length &&  
                         i < obj->fslots[JSSLOT_ARRAY_LENGTH]) {  
                         rval = obj->dslots[i];  
                         if (rval != JSVAL_HOLE)  
                             goto end_getelem;  
   
                         /* Reload rval from the stack in the rare hole case. */  
                         rval = FETCH_OPND(-1);  
                     }  
                 }  
                 id = INT_JSVAL_TO_JSID(rval);  
             } else {  
                 if (!js_InternNonIntElementId(cx, obj, rval, &id))  
                     goto error;  
             }  
   
             if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
           end_getelem:  
             regs.sp--;  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_GETELEM)  
   
           BEGIN_CASE(JSOP_CALLELEM)  
             ELEMENT_OP(-1, js_GetMethod(cx, obj, id, false, &rval));  
 #if JS_HAS_NO_SUCH_METHOD  
             if (JS_UNLIKELY(JSVAL_IS_VOID(rval))) {  
                 regs.sp[-2] = regs.sp[-1];  
                 regs.sp[-1] = OBJECT_TO_JSVAL(obj);  
                 if (!js_OnUnknownMethod(cx, regs.sp - 2))  
                     goto error;  
             } else  
 #endif  
             {  
                 STORE_OPND(-2, rval);  
                 STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
             }  
           END_CASE(JSOP_CALLELEM)  
   
           BEGIN_CASE(JSOP_SETELEM)  
             rval = FETCH_OPND(-1);  
             FETCH_OBJECT(cx, -3, lval, obj);  
             FETCH_ELEMENT_ID(obj, -2, id);  
             do {  
                 if (OBJ_IS_DENSE_ARRAY(cx, obj) && JSID_IS_INT(id)) {  
                     jsuint length;  
   
                     length = js_DenseArrayCapacity(obj);  
                     i = JSID_TO_INT(id);  
                     if ((jsuint)i < length) {  
                         if (obj->dslots[i] == JSVAL_HOLE) {  
                             if (js_PrototypeHasIndexedProperties(cx, obj))  
                                 break;  
                             if (i >= obj->fslots[JSSLOT_ARRAY_LENGTH])  
                                 obj->fslots[JSSLOT_ARRAY_LENGTH] = i + 1;  
                             obj->fslots[JSSLOT_ARRAY_COUNT]++;  
                         }  
                         obj->dslots[i] = rval;  
                         goto end_setelem;  
                     }  
                 }  
             } while (0);  
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
         end_setelem:  
           END_SET_CASE_STORE_RVAL(JSOP_SETELEM, 3)  
   
           BEGIN_CASE(JSOP_ENUMELEM)  
             /* Funky: the value to set is under the [obj, id] pair. */  
             rval = FETCH_OPND(-3);  
             FETCH_OBJECT(cx, -2, lval, obj);  
             FETCH_ELEMENT_ID(obj, -1, id);  
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
             regs.sp -= 3;  
           END_CASE(JSOP_ENUMELEM)  
   
           BEGIN_CASE(JSOP_NEW)  
             /* Get immediate argc and find the constructor function. */  
             argc = GET_ARGC(regs.pc);  
             vp = regs.sp - (2 + argc);  
             JS_ASSERT(vp >= StackBase(fp));  
   
             /*  
              * Assign lval, obj, and fun exactly as the code at inline_call:  
              * expects to find them, to avoid nesting a js_Interpret call via  
              * js_InvokeConstructor.  
              */  
             lval = *vp;  
             if (VALUE_IS_FUNCTION(cx, lval)) {  
                 obj = JSVAL_TO_OBJECT(lval);  
                 fun = GET_FUNCTION_PRIVATE(cx, obj);  
                 if (FUN_INTERPRETED(fun)) {  
                     /* Root as we go using vp[1]. */  
                     if (!OBJ_GET_PROPERTY(cx, obj,  
                                           ATOM_TO_JSID(cx->runtime->atomState  
                                                        .classPrototypeAtom),  
                                           &vp[1])) {  
                         goto error;  
                     }  
                     rval = vp[1];  
                     obj2 = js_NewObject(cx, &js_ObjectClass,  
                                         JSVAL_IS_OBJECT(rval)  
                                         ? JSVAL_TO_OBJECT(rval)  
                                         : NULL,  
                                         OBJ_GET_PARENT(cx, obj),  
                                         0);  
                     if (!obj2)  
                         goto error;  
                     vp[1] = OBJECT_TO_JSVAL(obj2);  
                     flags = JSFRAME_CONSTRUCTING;  
                     goto inline_call;  
                 }  
             }  
   
             if (!js_InvokeConstructor(cx, argc, JS_FALSE, vp))  
                 goto error;  
             regs.sp = vp + 1;  
             CHECK_INTERRUPT_HANDLER();  
             TRACE_0(NativeCallComplete);  
           END_CASE(JSOP_NEW)  
   
           BEGIN_CASE(JSOP_CALL)  
           BEGIN_CASE(JSOP_EVAL)  
           BEGIN_CASE(JSOP_APPLY)  
             argc = GET_ARGC(regs.pc);  
             vp = regs.sp - (argc + 2);  
   
             lval = *vp;  
             if (VALUE_IS_FUNCTION(cx, lval)) {  
                 obj = JSVAL_TO_OBJECT(lval);  
                 fun = GET_FUNCTION_PRIVATE(cx, obj);  
   
                 /* Clear frame flags since this is not a constructor call. */  
                 flags = 0;  
                 if (FUN_INTERPRETED(fun))  
               inline_call:  
                 {  
                     uintN nframeslots, nvars, missing;  
                     JSArena *a;  
                     jsuword nbytes;  
                     void *newmark;  
                     jsval *newsp;  
                     JSInlineFrame *newifp;  
                     JSInterpreterHook hook;  
   
                     /* Restrict recursion of lightweight functions. */  
                     if (inlineCallCount == MAX_INLINE_CALL_COUNT) {  
                         js_ReportOverRecursed(cx);  
                         goto error;  
                     }  
   
                     /* Compute the total number of stack slots needed by fun. */  
                     nframeslots = JS_HOWMANY(sizeof(JSInlineFrame),  
                                              sizeof(jsval));  
                     script = fun->u.i.script;  
                     atoms = script->atomMap.vector;  
                     nbytes = (nframeslots + script->nslots) * sizeof(jsval);  
   
                     /* Allocate missing expected args adjacent to actuals. */  
                     a = cx->stackPool.current;  
                     newmark = (void *) a->avail;  
                     if (fun->nargs <= argc) {  
                         missing = 0;  
                     } else {  
                         newsp = vp + 2 + fun->nargs;  
                         JS_ASSERT(newsp > regs.sp);  
                         if ((jsuword) newsp <= a->limit) {  
                             if ((jsuword) newsp > a->avail)  
                                 a->avail = (jsuword) newsp;  
                             jsval *argsp = newsp;  
                             do {  
                                 *--argsp = JSVAL_VOID;  
                             } while (argsp != regs.sp);  
                             missing = 0;  
                         } else {  
                             missing = fun->nargs - argc;  
                             nbytes += (2 + fun->nargs) * sizeof(jsval);  
                         }  
                     }  
   
                     /* Allocate the inline frame with its slots and operands. */  
                     if (a->avail + nbytes <= a->limit) {  
                         newsp = (jsval *) a->avail;  
                         a->avail += nbytes;  
                         JS_ASSERT(missing == 0);  
                     } else {  
                         JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool,  
                                                nbytes);  
                         if (!newsp) {  
                             js_ReportOutOfScriptQuota(cx);  
                             goto bad_inline_call;  
                         }  
   
                         /*  
                          * Move args if the missing ones overflow arena a, then  
                          * push undefined for the missing args.  
                          */  
                         if (missing) {  
                             memcpy(newsp, vp, (2 + argc) * sizeof(jsval));  
                             vp = newsp;  
                             newsp = vp + 2 + argc;  
                             do {  
                                 *newsp++ = JSVAL_VOID;  
                             } while (--missing != 0);  
                         }  
                     }  
   
                     /* Claim space for the stack frame and initialize it. */  
                     newifp = (JSInlineFrame *) newsp;  
                     newsp += nframeslots;  
                     newifp->frame.callobj = NULL;  
                     newifp->frame.argsobj = NULL;  
                     newifp->frame.varobj = NULL;  
                     newifp->frame.script = script;  
                     newifp->frame.callee = obj;  
                     newifp->frame.fun = fun;  
                     newifp->frame.argc = argc;  
                     newifp->frame.argv = vp + 2;  
                     newifp->frame.rval = JSVAL_VOID;  
                     newifp->frame.down = fp;  
                     newifp->frame.annotation = NULL;  
                     newifp->frame.scopeChain = parent = OBJ_GET_PARENT(cx, obj);  
                     newifp->frame.sharpDepth = 0;  
                     newifp->frame.sharpArray = NULL;  
                     newifp->frame.flags = flags;  
                     newifp->frame.dormantNext = NULL;  
                     newifp->frame.xmlNamespace = NULL;  
                     newifp->frame.blockChain = NULL;  
                     if (script->staticLevel < JS_DISPLAY_SIZE) {  
                         JSStackFrame **disp = &cx->display[script->staticLevel];  
                         newifp->frame.displaySave = *disp;  
                         *disp = &newifp->frame;  
                     }  
                     newifp->mark = newmark;  
   
                     /* Compute the 'this' parameter now that argv is set. */  
                     JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));  
                     JS_ASSERT(JSVAL_IS_OBJECT(vp[1]));  
                     newifp->frame.thisp = (JSObject *)vp[1];  
   
                     newifp->frame.regs = NULL;  
                     newifp->frame.imacpc = NULL;  
                     newifp->frame.slots = newsp;  
   
                     /* Push void to initialize local variables. */  
                     nvars = fun->u.i.nvars;  
                     while (nvars--)  
                         *newsp++ = JSVAL_VOID;  
   
                     /* Scope with a call object parented by callee's parent. */  
                     if (JSFUN_HEAVYWEIGHT_TEST(fun->flags) &&  
                         !js_GetCallObject(cx, &newifp->frame)) {  
                         goto bad_inline_call;  
                     }  
   
                     /* Switch version if currentVersion wasn't overridden. */  
                     newifp->callerVersion = (JSVersion) cx->version;  
                     if (JS_LIKELY(cx->version == currentVersion)) {  
                         currentVersion = (JSVersion) script->version;  
                         if (currentVersion != cx->version)  
                             js_SetVersion(cx, currentVersion);  
                     }  
   
                     /* Push the frame and set interpreter registers. */  
                     newifp->callerRegs = regs;  
                     fp->regs = &newifp->callerRegs;  
                     regs.sp = newsp;  
                     regs.pc = script->code;  
                     newifp->frame.regs = &regs;  
                     cx->fp = fp = &newifp->frame;  
   
                     /* Call the debugger hook if present. */  
                     hook = cx->debugHooks->callHook;  
                     if (hook) {  
                         newifp->hookData = hook(cx, &newifp->frame, JS_TRUE, 0,  
                                                 cx->debugHooks->callHookData);  
                         CHECK_INTERRUPT_HANDLER();  
                     } else {  
                         newifp->hookData = NULL;  
                     }  
   
                     TRACE_0(EnterFrame);  
   
                     inlineCallCount++;  
                     JS_RUNTIME_METER(rt, inlineCalls);  
   
 #ifdef INCLUDE_MOZILLA_DTRACE  
                     /* DTrace function entry, inlines */  
                     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())  
                         jsdtrace_function_entry(cx, fp, fun);  
                     if (JAVASCRIPT_FUNCTION_INFO_ENABLED())  
                         jsdtrace_function_info(cx, fp, fp->down, fun);  
                     if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())  
                         jsdtrace_function_args(cx, fp, fun);  
 #endif  
   
                     /* Load first op and dispatch it (safe since JSOP_STOP). */  
                     op = (JSOp) *regs.pc;  
                     DO_OP();  
   
                   bad_inline_call:  
                     JS_ASSERT(fp->regs == &regs);  
                     script = fp->script;  
                     atoms = script->atomMap.vector;  
                     js_FreeRawStack(cx, newmark);  
                     goto error;  
                 }  
   
 #ifdef INCLUDE_MOZILLA_DTRACE  
                 /* DTrace function entry, non-inlines */  
                 if (VALUE_IS_FUNCTION(cx, lval)) {  
                     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())  
                         jsdtrace_function_entry(cx, fp, fun);  
                     if (JAVASCRIPT_FUNCTION_INFO_ENABLED())  
                         jsdtrace_function_info(cx, fp, fp, fun);  
                     if (JAVASCRIPT_FUNCTION_ARGS_ENABLED())  
                         jsdtrace_function_args(cx, fp, fun);  
                 }  
 #endif  
   
                 if (fun->flags & JSFUN_FAST_NATIVE) {  
                     JS_ASSERT(fun->u.n.extra == 0);  
                     JS_ASSERT(JSVAL_IS_OBJECT(vp[1]) ||  
                               PRIMITIVE_THIS_TEST(fun, vp[1]));  
                     ok = ((JSFastNative) fun->u.n.native)(cx, argc, vp);  
 #ifdef INCLUDE_MOZILLA_DTRACE  
                     if (VALUE_IS_FUNCTION(cx, lval)) {  
                         if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())  
                             jsdtrace_function_rval(cx, fp, fun);  
                         if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())  
                             jsdtrace_function_return(cx, fp, fun);  
                     }  
 #endif  
                     regs.sp = vp + 1;  
                     if (!ok) {  
                         /*  
                          * If we are executing the JSOP_NEXTITER imacro and a Stopiteration  
                          * exception is raised, transform it into a JSVAL_HOLE return value.  
                          * The tracer generates equivalent code by calling CatchStopIteration_tn.  
                          */  
                         if (fp->imacpc && *fp->imacpc == JSOP_NEXTITER &&  
                             cx->throwing && js_ValueIsStopIteration(cx->exception)) {  
                             // pc may point to JSOP_DUP here due to bug 474854.  
                             JS_ASSERT(*regs.pc == JSOP_CALL || *regs.pc == JSOP_DUP);  
                             cx->throwing = JS_FALSE;  
                             cx->exception = JSVAL_VOID;  
                             regs.sp[-1] = JSVAL_HOLE;  
                         } else {  
                             goto error;  
                         }  
                     }  
                     TRACE_0(NativeCallComplete);  
                     goto end_call;  
                 }  
             }  
   
             ok = js_Invoke(cx, argc, vp, 0);  
 #ifdef INCLUDE_MOZILLA_DTRACE  
             /* DTrace function return, non-inlines */  
             if (VALUE_IS_FUNCTION(cx, lval)) {  
                 if (JAVASCRIPT_FUNCTION_RVAL_ENABLED())  
                     jsdtrace_function_rval(cx, fp, fun);  
                 if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())  
                     jsdtrace_function_return(cx, fp, fun);  
             }  
 #endif  
             regs.sp = vp + 1;  
             CHECK_INTERRUPT_HANDLER();  
             if (!ok)  
                 goto error;  
             JS_RUNTIME_METER(rt, nonInlineCalls);  
             TRACE_0(NativeCallComplete);  
   
           end_call:  
 #if JS_HAS_LVALUE_RETURN  
             if (cx->rval2set) {  
                 /*  
                  * Use the stack depth we didn't claim in our budget, but that  
                  * we know is there on account of [fun, this] already having  
                  * been pushed, at a minimum (if no args).  Those two slots  
                  * have been popped and [rval] has been pushed, which leaves  
                  * one more slot for rval2 before we might overflow.  
                  *  
                  * NB: rval2 must be the property identifier, and rval the  
                  * object from which to get the property.  The pair form an  
                  * ECMA "reference type", which can be used on the right- or  
                  * left-hand side of assignment ops.  Note well: only native  
                  * methods can return reference types.  See JSOP_SETCALL just  
                  * below for the left-hand-side case.  
                  */  
                 PUSH_OPND(cx->rval2);  
                 ELEMENT_OP(-1, OBJ_GET_PROPERTY(cx, obj, id, &rval));  
   
                 regs.sp--;  
                 STORE_OPND(-1, rval);  
                 cx->rval2set = JS_FALSE;  
             }  
 #endif /* JS_HAS_LVALUE_RETURN */  
           END_CASE(JSOP_CALL)  
   
 #if JS_HAS_LVALUE_RETURN  
           BEGIN_CASE(JSOP_SETCALL)  
             argc = GET_ARGC(regs.pc);  
             vp = regs.sp - argc - 2;  
             ok = js_Invoke(cx, argc, vp, 0);  
             regs.sp = vp + 1;  
             CHECK_INTERRUPT_HANDLER();  
             if (!ok)  
                 goto error;  
             if (!cx->rval2set) {  
                 op2 = js_GetOpcode(cx, script, regs.pc + JSOP_SETCALL_LENGTH);  
                 if (op2 != JSOP_DELELEM) {  
                     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,  
                                          JSMSG_BAD_LEFTSIDE_OF_ASS);  
                     goto error;  
                 }  
   
                 /*  
                  * Store true as the result of the emulated delete of a  
                  * non-existent property. NB: We don't METER_OP_PAIR here;  
                  * it doesn't seem worth the code for this obscure case.  
                  */  
                 *vp = JSVAL_TRUE;  
                 regs.pc += JSOP_SETCALL_LENGTH + JSOP_DELELEM_LENGTH;  
                 op = (JSOp) *regs.pc;  
                 DO_OP();  
             }  
             PUSH_OPND(cx->rval2);  
             cx->rval2set = JS_FALSE;  
           END_CASE(JSOP_SETCALL)  
 #endif  
   
           BEGIN_CASE(JSOP_NAME)  
           BEGIN_CASE(JSOP_CALLNAME)  
           {  
             JSPropCacheEntry *entry;  
   
             obj = fp->scopeChain;  
             if (JS_LIKELY(OBJ_IS_NATIVE(obj))) {  
                 PROPERTY_CACHE_TEST(cx, regs.pc, obj, obj2, entry, atom);  
                 if (!atom) {  
                     ASSERT_VALID_PROPERTY_CACHE_HIT(0, obj, obj2, entry);  
                     if (PCVAL_IS_OBJECT(entry->vword)) {  
                         rval = PCVAL_OBJECT_TO_JSVAL(entry->vword);  
                         JS_UNLOCK_OBJ(cx, obj2);  
                         goto do_push_rval;  
                     }  
   
                     if (PCVAL_IS_SLOT(entry->vword)) {  
                         slot = PCVAL_TO_SLOT(entry->vword);  
                         JS_ASSERT(slot < OBJ_SCOPE(obj2)->freeslot);  
                         rval = LOCKED_OBJ_GET_SLOT(obj2, slot);  
                         JS_UNLOCK_OBJ(cx, obj2);  
                         goto do_push_rval;  
                     }  
   
                     JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                     sprop = PCVAL_TO_SPROP(entry->vword);  
                     goto do_native_get;  
                 }  
             } else {  
                 LOAD_ATOM(0);  
             }  
   
             id = ATOM_TO_JSID(atom);  
             if (!js_FindPropertyHelper(cx, id, true, &obj, &obj2, &prop))  
                 goto error;  
             if (!prop) {  
                 /* Kludge to allow (typeof foo == "undefined") tests. */  
                 endpc = script->code + script->length;  
                 op2 = js_GetOpcode(cx, script, regs.pc + JSOP_NAME_LENGTH);  
                 if (op2 == JSOP_TYPEOF) {  
                     PUSH_OPND(JSVAL_VOID);  
                     len = JSOP_NAME_LENGTH;  
                     DO_NEXT_OP(len);  
                 }  
                 goto atom_not_defined;  
             }  
   
             /* Take the slow path if prop was not found in a native object. */  
             if (!OBJ_IS_NATIVE(obj) || !OBJ_IS_NATIVE(obj2)) {  
                 OBJ_DROP_PROPERTY(cx, obj2, prop);  
                 if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))  
                     goto error;  
             } else {  
                 sprop = (JSScopeProperty *)prop;  
           do_native_get:  
                 NATIVE_GET(cx, obj, obj2, sprop, &rval);  
                 OBJ_DROP_PROPERTY(cx, obj2, (JSProperty *) sprop);  
             }  
   
           do_push_rval:  
             PUSH_OPND(rval);  
             if (op == JSOP_CALLNAME)  
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           }  
           END_CASE(JSOP_NAME)  
   
           BEGIN_CASE(JSOP_UINT16)  
             i = (jsint) GET_UINT16(regs.pc);  
             rval = INT_TO_JSVAL(i);  
             PUSH_OPND(rval);  
           END_CASE(JSOP_UINT16)  
   
           BEGIN_CASE(JSOP_UINT24)  
             i = (jsint) GET_UINT24(regs.pc);  
             rval = INT_TO_JSVAL(i);  
             PUSH_OPND(rval);  
           END_CASE(JSOP_UINT24)  
   
           BEGIN_CASE(JSOP_INT8)  
             i = GET_INT8(regs.pc);  
             rval = INT_TO_JSVAL(i);  
             PUSH_OPND(rval);  
           END_CASE(JSOP_INT8)  
   
           BEGIN_CASE(JSOP_INT32)  
             i = GET_INT32(regs.pc);  
             rval = INT_TO_JSVAL(i);  
             PUSH_OPND(rval);  
           END_CASE(JSOP_INT32)  
   
           BEGIN_CASE(JSOP_INDEXBASE)  
             /*  
              * Here atoms can exceed script->atomMap.length as we use atoms  
              * as a segment register for object literals as well.  
              */  
             atoms += GET_INDEXBASE(regs.pc);  
           END_CASE(JSOP_INDEXBASE)  
   
           BEGIN_CASE(JSOP_INDEXBASE1)  
           BEGIN_CASE(JSOP_INDEXBASE2)  
           BEGIN_CASE(JSOP_INDEXBASE3)  
             atoms += (op - JSOP_INDEXBASE1 + 1) << 16;  
           END_CASE(JSOP_INDEXBASE3)  
   
           BEGIN_CASE(JSOP_RESETBASE0)  
           BEGIN_CASE(JSOP_RESETBASE)  
             atoms = script->atomMap.vector;  
           END_CASE(JSOP_RESETBASE)  
   
           BEGIN_CASE(JSOP_DOUBLE)  
           BEGIN_CASE(JSOP_STRING)  
             LOAD_ATOM(0);  
             PUSH_OPND(ATOM_KEY(atom));  
           END_CASE(JSOP_DOUBLE)  
   
           BEGIN_CASE(JSOP_OBJECT)  
             LOAD_OBJECT(0);  
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_OBJECT)  
   
           BEGIN_CASE(JSOP_REGEXP)  
           {  
             JSObject *funobj;  
   
             /*  
              * Push a regexp object for the atom mapped by the bytecode at pc,  
              * cloning the literal's regexp object if necessary, to simulate in  
              * the pre-compile/execute-later case what ECMA specifies for the  
              * compile-and-go case: that scanning each regexp literal creates  
              * a single corresponding RegExp object.  
              *  
              * To support pre-compilation transparently, we must handle the  
              * case where a regexp object literal is used in a different global  
              * at execution time from the global with which it was scanned at  
              * compile time.  We do this by re-wrapping the JSRegExp private  
              * data struct with a cloned object having the right prototype and  
              * parent, and having its own lastIndex property value storage.  
              *  
              * Unlike JSOP_DEFFUN and other prolog bytecodes that may clone  
              * literal objects, we don't want to pay a script prolog execution  
              * price for all regexp literals in a script (many may not be used  
              * by a particular execution of that script, depending on control  
              * flow), so we initialize lazily here.  
              *  
              * XXX This code is specific to regular expression objects.  If we  
              * need a similar op for other kinds of object literals, we should  
              * push cloning down under JSObjectOps and reuse code here.  
              */  
             index = GET_FULL_INDEX(0);  
             JS_ASSERT(index < JS_SCRIPT_REGEXPS(script)->length);  
   
             slot = index;  
             if (fp->fun) {  
                 /*  
                  * We're in function code, not global or eval code (in eval  
                  * code, JSOP_REGEXP is never emitted). The cloned funobj  
                  * contains JS_SCRIPT_REGEXPS(script)->length reserved slots  
                  * for the cloned regexps; see fun_reserveSlots, jsfun.c.  
                  */  
                 funobj = fp->callee;  
                 slot += JSCLASS_RESERVED_SLOTS(&js_FunctionClass);  
                 if (script->upvarsOffset != 0)  
                     slot += JS_SCRIPT_UPVARS(script)->length;  
                 if (!JS_GetReservedSlot(cx, funobj, slot, &rval))  
                     goto error;  
                 if (JSVAL_IS_VOID(rval))  
                     rval = JSVAL_NULL;  
             } else {  
                 /*  
                  * We're in global code. The code generator reserved a slot  
                  * for the regexp among script->nfixed slots. All such slots  
                  * are initialized to null, not void, for faster testing in  
                  * JSOP_*GVAR cases. To simplify index calculations we count  
                  * regexps in the reverse order down from script->nslots - 1.  
                  */  
                 JS_ASSERT(slot < script->nfixed);  
                 slot = script->nfixed - slot - 1;  
                 rval = fp->slots[slot];  
 #ifdef __GNUC__  
                 funobj = NULL;  /* suppress bogus gcc warnings */  
 #endif  
             }  
   
             if (JSVAL_IS_NULL(rval)) {  
                 /* Compute the current global object in obj2. */  
                 obj2 = fp->scopeChain;  
                 while ((parent = OBJ_GET_PARENT(cx, obj2)) != NULL)  
                     obj2 = parent;  
   
                 /*  
                  * If obj's parent is not obj2, we must clone obj so that it  
                  * has the right parent, and therefore, the right prototype.  
                  *  
                  * Yes, this means we assume that the correct RegExp.prototype  
                  * to which regexp instances (including literals) delegate can  
                  * be distinguished solely by the instance's parent, which was  
                  * set to the parent of the RegExp constructor function object  
                  * when the instance was created.  In other words,  
                  *  
                  *   (/x/.__parent__ == RegExp.__parent__) implies  
                  *   (/x/.__proto__ == RegExp.prototype)  
                  *  
                  * (unless you assign a different object to RegExp.prototype  
                  * at runtime, in which case, ECMA doesn't specify operation,  
                  * and you get what you deserve).  
                  *  
                  * This same coupling between instance parent and constructor  
                  * parent turns up everywhere (see jsobj.c's FindClassObject,  
                  * js_ConstructObject, and js_NewObject).  It's fundamental to  
                  * the design of the language when you consider multiple global  
                  * objects and separate compilation and execution, even though  
                  * it is not specified fully in ECMA.  
                  */  
                 JS_GET_SCRIPT_REGEXP(script, index, obj);  
                 if (OBJ_GET_PARENT(cx, obj) != obj2) {  
                     obj = js_CloneRegExpObject(cx, obj, obj2);  
                     if (!obj)  
                         goto error;  
                 }  
                 rval = OBJECT_TO_JSVAL(obj);  
   
                 /* Store the regexp object value in its cloneIndex slot. */  
                 if (fp->fun) {  
                     if (!JS_SetReservedSlot(cx, funobj, slot, rval))  
                         goto error;  
                 } else {  
                     fp->slots[slot] = rval;  
                 }  
             }  
   
             PUSH_OPND(rval);  
           }  
           END_CASE(JSOP_REGEXP)  
   
           BEGIN_CASE(JSOP_ZERO)  
             PUSH_OPND(JSVAL_ZERO);  
           END_CASE(JSOP_ZERO)  
   
           BEGIN_CASE(JSOP_ONE)  
             PUSH_OPND(JSVAL_ONE);  
           END_CASE(JSOP_ONE)  
   
           BEGIN_CASE(JSOP_NULL)  
             PUSH_OPND(JSVAL_NULL);  
           END_CASE(JSOP_NULL)  
   
           BEGIN_CASE(JSOP_FALSE)  
             PUSH_OPND(JSVAL_FALSE);  
           END_CASE(JSOP_FALSE)  
   
           BEGIN_CASE(JSOP_TRUE)  
             PUSH_OPND(JSVAL_TRUE);  
           END_CASE(JSOP_TRUE)  
   
           BEGIN_CASE(JSOP_TABLESWITCH)  
             pc2 = regs.pc;  
             len = GET_JUMP_OFFSET(pc2);  
   
             /*  
              * ECMAv2+ forbids conversion of discriminant, so we will skip to  
              * the default case if the discriminant isn't already an int jsval.  
              * (This opcode is emitted only for dense jsint-domain switches.)  
              */  
             rval = POP_OPND();  
             if (JSVAL_IS_INT(rval)) {  
                 i = JSVAL_TO_INT(rval);  
             } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {  
                 /* Treat -0 (double) as 0. */  
                 i = 0;  
             } else {  
                 DO_NEXT_OP(len);  
             }  
   
             pc2 += JUMP_OFFSET_LEN;  
             low = GET_JUMP_OFFSET(pc2);  
             pc2 += JUMP_OFFSET_LEN;  
             high = GET_JUMP_OFFSET(pc2);  
   
             i -= low;  
             if ((jsuint)i < (jsuint)(high - low + 1)) {  
                 pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;  
                 off = (jsint) GET_JUMP_OFFSET(pc2);  
                 if (off)  
                     len = off;  
             }  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_TABLESWITCHX)  
             pc2 = regs.pc;  
             len = GET_JUMPX_OFFSET(pc2);  
   
             /*  
              * ECMAv2+ forbids conversion of discriminant, so we will skip to  
              * the default case if the discriminant isn't already an int jsval.  
              * (This opcode is emitted only for dense jsint-domain switches.)  
              */  
             rval = POP_OPND();  
             if (JSVAL_IS_INT(rval)) {  
                 i = JSVAL_TO_INT(rval);  
             } else if (JSVAL_IS_DOUBLE(rval) && *JSVAL_TO_DOUBLE(rval) == 0) {  
                 /* Treat -0 (double) as 0. */  
                 i = 0;  
             } else {  
                 DO_NEXT_OP(len);  
             }  
   
             pc2 += JUMPX_OFFSET_LEN;  
             low = GET_JUMP_OFFSET(pc2);  
             pc2 += JUMP_OFFSET_LEN;  
             high = GET_JUMP_OFFSET(pc2);  
   
             i -= low;  
             if ((jsuint)i < (jsuint)(high - low + 1)) {  
                 pc2 += JUMP_OFFSET_LEN + JUMPX_OFFSET_LEN * i;  
                 off = (jsint) GET_JUMPX_OFFSET(pc2);  
                 if (off)  
                     len = off;  
             }  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_LOOKUPSWITCHX)  
             off = JUMPX_OFFSET_LEN;  
             goto do_lookup_switch;  
   
           BEGIN_CASE(JSOP_LOOKUPSWITCH)  
             off = JUMP_OFFSET_LEN;  
   
           do_lookup_switch:  
             /*  
              * JSOP_LOOKUPSWITCH and JSOP_LOOKUPSWITCHX are never used if  
              * any atom index in it would exceed 64K limit.  
              */  
             JS_ASSERT(atoms == script->atomMap.vector);  
             pc2 = regs.pc;  
             lval = POP_OPND();  
   
             if (!JSVAL_IS_NUMBER(lval) &&  
                 !JSVAL_IS_STRING(lval) &&  
                 !JSVAL_IS_BOOLEAN(lval)) {  
                 goto end_lookup_switch;  
             }  
   
             pc2 += off;  
             npairs = (jsint) GET_UINT16(pc2);  
             pc2 += UINT16_LEN;  
             JS_ASSERT(npairs);  /* empty switch uses JSOP_TABLESWITCH */  
   
 #define SEARCH_PAIRS(MATCH_CODE)                                              \  
     for (;;) {                                                                \  
         JS_ASSERT(GET_INDEX(pc2) < script->atomMap.length);                   \  
         atom = atoms[GET_INDEX(pc2)];                                         \  
         rval = ATOM_KEY(atom);                                                \  
         MATCH_CODE                                                            \  
         pc2 += INDEX_LEN;                                                     \  
         if (match)                                                            \  
             break;                                                            \  
         pc2 += off;                                                           \  
         if (--npairs == 0) {                                                  \  
             pc2 = regs.pc;                                                    \  
             break;                                                            \  
         }                                                                     \  
     }  
             if (JSVAL_IS_STRING(lval)) {  
                 str = JSVAL_TO_STRING(lval);  
                 SEARCH_PAIRS(  
                     match = (JSVAL_IS_STRING(rval) &&  
                              ((str2 = JSVAL_TO_STRING(rval)) == str ||  
                               js_EqualStrings(str2, str)));  
                 )  
             } else if (JSVAL_IS_DOUBLE(lval)) {  
                 d = *JSVAL_TO_DOUBLE(lval);  
                 SEARCH_PAIRS(  
                     match = (JSVAL_IS_DOUBLE(rval) &&  
                              *JSVAL_TO_DOUBLE(rval) == d);  
                 )  
             } else {  
                 SEARCH_PAIRS(  
                     match = (lval == rval);  
                 )  
             }  
 #undef SEARCH_PAIRS  
   
           end_lookup_switch:  
             len = (op == JSOP_LOOKUPSWITCH)  
                   ? GET_JUMP_OFFSET(pc2)  
                   : GET_JUMPX_OFFSET(pc2);  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_TRAP)  
           {  
             JSTrapStatus status;  
   
             status = JS_HandleTrap(cx, script, regs.pc, &rval);  
             switch (status) {  
               case JSTRAP_ERROR:  
                 goto error;  
               case JSTRAP_RETURN:  
                 fp->rval = rval;  
                 ok = JS_TRUE;  
                 goto forced_return;  
               case JSTRAP_THROW:  
                 cx->throwing = JS_TRUE;  
                 cx->exception = rval;  
                 goto error;  
               default:;  
                 break;  
             }  
             JS_ASSERT(status == JSTRAP_CONTINUE);  
             CHECK_INTERRUPT_HANDLER();  
             JS_ASSERT(JSVAL_IS_INT(rval));  
             op = (JSOp) JSVAL_TO_INT(rval);  
             JS_ASSERT((uintN)op < (uintN)JSOP_LIMIT);  
             DO_OP();  
           }  
   
           BEGIN_CASE(JSOP_ARGUMENTS)  
             if (!js_GetArgsValue(cx, fp, &rval))  
                 goto error;  
             PUSH_OPND(rval);  
           END_CASE(JSOP_ARGUMENTS)  
   
           BEGIN_CASE(JSOP_ARGSUB)  
             id = INT_TO_JSID(GET_ARGNO(regs.pc));  
             if (!js_GetArgsProperty(cx, fp, id, &rval))  
                 goto error;  
             PUSH_OPND(rval);  
           END_CASE(JSOP_ARGSUB)  
   
           BEGIN_CASE(JSOP_ARGCNT)  
             id = ATOM_TO_JSID(rt->atomState.lengthAtom);  
             if (!js_GetArgsProperty(cx, fp, id, &rval))  
                 goto error;  
             PUSH_OPND(rval);  
           END_CASE(JSOP_ARGCNT)  
   
           BEGIN_CASE(JSOP_GETARG)  
           BEGIN_CASE(JSOP_CALLARG)  
             slot = GET_ARGNO(regs.pc);  
             JS_ASSERT(slot < fp->fun->nargs);  
             METER_SLOT_OP(op, slot);  
             PUSH_OPND(fp->argv[slot]);  
             if (op == JSOP_CALLARG)  
                 PUSH_OPND(JSVAL_NULL);  
           END_CASE(JSOP_GETARG)  
   
           BEGIN_CASE(JSOP_SETARG)  
             slot = GET_ARGNO(regs.pc);  
             JS_ASSERT(slot < fp->fun->nargs);  
             METER_SLOT_OP(op, slot);  
             vp = &fp->argv[slot];  
             *vp = FETCH_OPND(-1);  
           END_SET_CASE(JSOP_SETARG)  
   
           BEGIN_CASE(JSOP_GETLOCAL)  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < script->nslots);  
             PUSH_OPND(fp->slots[slot]);  
           END_CASE(JSOP_GETLOCAL)  
   
           BEGIN_CASE(JSOP_CALLLOCAL)  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < script->nslots);  
             PUSH_OPND(fp->slots[slot]);  
             PUSH_OPND(JSVAL_NULL);  
           END_CASE(JSOP_CALLLOCAL)  
   
           BEGIN_CASE(JSOP_SETLOCAL)  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < script->nslots);  
             vp = &fp->slots[slot];  
             *vp = FETCH_OPND(-1);  
           END_SET_CASE(JSOP_SETLOCAL)  
   
           BEGIN_CASE(JSOP_GETUPVAR)  
           BEGIN_CASE(JSOP_CALLUPVAR)  
           {  
             JSUpvarArray *uva = JS_SCRIPT_UPVARS(script);  
   
             index = GET_UINT16(regs.pc);  
             JS_ASSERT(index < uva->length);  
   
             rval = js_GetUpvar(cx, script->staticLevel, uva->vector[index]);  
             PUSH_OPND(rval);  
   
             if (op == JSOP_CALLUPVAR)  
                 PUSH_OPND(JSVAL_NULL);  
           }  
           END_CASE(JSOP_GETUPVAR)  
   
           BEGIN_CASE(JSOP_GETUPVAR_DBG)  
           BEGIN_CASE(JSOP_CALLUPVAR_DBG)  
             fun = fp->fun;  
             JS_ASSERT(FUN_KIND(fun) == JSFUN_INTERPRETED);  
             JS_ASSERT(fun->u.i.wrapper);  
   
             /* Scope for tempPool mark and local names allocation in it. */  
             {  
                 void *mark = JS_ARENA_MARK(&cx->tempPool);  
                 jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);  
                 if (!names)  
                     goto error;  
   
                 index = fun->countArgsAndVars() + GET_UINT16(regs.pc);  
                 atom = JS_LOCAL_NAME_TO_ATOM(names[index]);  
                 id = ATOM_TO_JSID(atom);  
   
                 ok = js_FindProperty(cx, id, &obj, &obj2, &prop);  
                 JS_ARENA_RELEASE(&cx->tempPool, mark);  
                 if (!ok)  
                     goto error;  
             }  
   
             if (!prop)  
                 goto atom_not_defined;  
   
             /* Minimize footprint with generic code instead of NATIVE_GET. */  
             OBJ_DROP_PROPERTY(cx, obj2, prop);  
             vp = regs.sp;  
             PUSH_OPND(JSVAL_NULL);  
             if (!OBJ_GET_PROPERTY(cx, obj, id, vp))  
                 goto error;  
   
             if (op == JSOP_CALLUPVAR_DBG)  
                 PUSH_OPND(JSVAL_NULL);  
           END_CASE(JSOP_GETUPVAR_DBG)  
   
           BEGIN_CASE(JSOP_GETDSLOT)  
           BEGIN_CASE(JSOP_CALLDSLOT)  
             obj = fp->callee;  
             JS_ASSERT(obj);  
             JS_ASSERT(obj->dslots);  
   
             index = GET_UINT16(regs.pc);  
             JS_ASSERT(JS_INITIAL_NSLOTS + index < jsatomid(obj->dslots[-1]));  
             JS_ASSERT_IF(OBJ_SCOPE(obj)->object == obj,  
                          JS_INITIAL_NSLOTS + index < OBJ_SCOPE(obj)->freeslot);  
   
             PUSH_OPND(obj->dslots[index]);  
             if (op == JSOP_CALLDSLOT)  
                 PUSH_OPND(JSVAL_NULL);  
           END_CASE(JSOP_GETDSLOT)  
   
           BEGIN_CASE(JSOP_GETGVAR)  
           BEGIN_CASE(JSOP_CALLGVAR)  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < GlobalVarCount(fp));  
             METER_SLOT_OP(op, slot);  
             lval = fp->slots[slot];  
             if (JSVAL_IS_NULL(lval)) {  
                 op = (op == JSOP_GETGVAR) ? JSOP_NAME : JSOP_CALLNAME;  
                 DO_OP();  
             }  
             obj = fp->varobj;  
             slot = JSVAL_TO_INT(lval);  
             rval = OBJ_GET_SLOT(cx, obj, slot);  
             PUSH_OPND(rval);  
             if (op == JSOP_CALLGVAR)  
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_GETGVAR)  
   
           BEGIN_CASE(JSOP_SETGVAR)  
             slot = GET_SLOTNO(regs.pc);  
             JS_ASSERT(slot < GlobalVarCount(fp));  
             METER_SLOT_OP(op, slot);  
             rval = FETCH_OPND(-1);  
             obj = fp->varobj;  
             lval = fp->slots[slot];  
             if (JSVAL_IS_NULL(lval)) {  
                 /*  
                  * Inline-clone and deoptimize JSOP_SETNAME code here because  
                  * JSOP_SETGVAR has arity 1: [rval], not arity 2: [obj, rval]  
                  * as JSOP_SETNAME does, where [obj] is due to JSOP_BINDNAME.  
                  */  
 #ifdef JS_TRACER  
                 if (TRACE_RECORDER(cx))  
                     js_AbortRecording(cx, "SETGVAR with NULL slot");  
 #endif  
                 LOAD_ATOM(0);  
                 id = ATOM_TO_JSID(atom);  
                 if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                     goto error;  
             } else {  
                 slot = JSVAL_TO_INT(lval);  
                 JS_LOCK_OBJ(cx, obj);  
                 LOCKED_OBJ_WRITE_BARRIER(cx, obj, slot, rval);  
                 JS_UNLOCK_OBJ(cx, obj);  
             }  
           END_SET_CASE(JSOP_SETGVAR)  
   
           BEGIN_CASE(JSOP_DEFCONST)  
           BEGIN_CASE(JSOP_DEFVAR)  
             index = GET_INDEX(regs.pc);  
             atom = atoms[index];  
   
             /*  
              * index is relative to atoms at this point but for global var  
              * code below we need the absolute value.  
              */  
             index += atoms - script->atomMap.vector;  
             obj = fp->varobj;  
             attrs = JSPROP_ENUMERATE;  
             if (!(fp->flags & JSFRAME_EVAL))  
                 attrs |= JSPROP_PERMANENT;  
             if (op == JSOP_DEFCONST)  
                 attrs |= JSPROP_READONLY;  
   
             /* Lookup id in order to check for redeclaration problems. */  
             id = ATOM_TO_JSID(atom);  
             prop = NULL;  
             if (!js_CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))  
                 goto error;  
   
             /* Bind a variable only if it's not yet defined. */  
             if (!prop) {  
                 if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID,  
                                          JS_PropertyStub, JS_PropertyStub,  
                                          attrs, &prop)) {  
                     goto error;  
                 }  
                 JS_ASSERT(prop);  
                 obj2 = obj;  
             }  
   
             /*  
              * Try to optimize a property we either just created, or found  
              * directly in the global object, that is permanent, has a slot,  
              * and has stub getter and setter, into a "fast global" accessed  
              * by the JSOP_*GVAR opcodes.  
              */  
             if (!fp->fun &&  
                 index < GlobalVarCount(fp) &&  
                 obj2 == obj &&  
                 OBJ_IS_NATIVE(obj)) {  
                 sprop = (JSScopeProperty *) prop;  
                 if ((sprop->attrs & JSPROP_PERMANENT) &&  
                     SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(obj)) &&  
                     SPROP_HAS_STUB_GETTER(sprop) &&  
                     SPROP_HAS_STUB_SETTER(sprop)) {  
                     /*  
                      * Fast globals use frame variables to map the global  
                      * name's atom index to the permanent fp->varobj slot  
                      * number, tagged as a jsval. The atom index for the  
                      * global's name literal is identical to its variable  
                      * index.  
                      */  
                     fp->slots[index] = INT_TO_JSVAL(sprop->slot);  
                 }  
             }  
   
             OBJ_DROP_PROPERTY(cx, obj2, prop);  
           END_CASE(JSOP_DEFVAR)  
   
           BEGIN_CASE(JSOP_DEFFUN)  
           {  
             JSPropertyOp getter, setter;  
             bool doSet;  
             JSObject *pobj;  
             JSProperty *prop;  
             uint32 old;  
   
             /*  
              * A top-level function defined in Global or Eval code (see  
              * ECMA-262 Ed. 3), or else a SpiderMonkey extension: a named  
              * function statement in a compound statement (not at the top  
              * statement level of global code, or at the top level of a  
              * function body).  
              */  
             LOAD_FUNCTION(0);  
             obj = FUN_OBJECT(fun);  
   
             if (FUN_NULL_CLOSURE(fun)) {  
                 /*  
                  * Even a null closure needs a parent for principals finding.  
                  * FIXME: bug 476950, although debugger users may also demand  
                  * some kind of scope link for debugger-assisted eval-in-frame.  
                  */  
                 obj2 = fp->scopeChain;  
             } else {  
                 JS_ASSERT(!FUN_FLAT_CLOSURE(fun));  
   
                 /*  
                  * Inline js_GetScopeChain a bit to optimize for the case of a  
                  * top-level function.  
                  */  
                 if (!fp->blockChain) {  
                     obj2 = fp->scopeChain;  
                 } else {  
                     obj2 = js_GetScopeChain(cx, fp);  
                     if (!obj2)  
                         goto error;  
                 }  
             }  
   
             /*  
              * If static link is not current scope, clone fun's object to link  
              * to the current scope via parent. We do this to enable sharing of  
              * compiled functions among multiple equivalent scopes, amortizing  
              * the cost of compilation over a number of executions.  Examples  
              * include XUL scripts and event handlers shared among Firefox or  
              * other Mozilla app chrome windows, and user-defined JS functions  
              * precompiled and then shared among requests in server-side JS.  
              */  
             if (OBJ_GET_PARENT(cx, obj) != obj2) {  
                 obj = js_CloneFunctionObject(cx, fun, obj2);  
                 if (!obj)  
                     goto error;  
             }  
   
             /*  
              * Protect obj from any GC hiding below OBJ_DEFINE_PROPERTY.  All  
              * paths from here must flow through the "Restore fp->scopeChain"  
              * code below the OBJ_DEFINE_PROPERTY call.  
              */  
             MUST_FLOW_THROUGH("restore_scope");  
             fp->scopeChain = obj;  
   
             rval = OBJECT_TO_JSVAL(obj);  
   
             /*  
              * ECMA requires functions defined when entering Eval code to be  
              * impermanent.  
              */  
             attrs = (fp->flags & JSFRAME_EVAL)  
                     ? JSPROP_ENUMERATE  
                     : JSPROP_ENUMERATE | JSPROP_PERMANENT;  
   
             /*  
              * Load function flags that are also property attributes.  Getters  
              * and setters do not need a slot, their value is stored elsewhere  
              * in the property itself, not in obj slots.  
              */  
             setter = getter = JS_PropertyStub;  
             flags = JSFUN_GSFLAG2ATTR(fun->flags);  
             if (flags) {  
                 /* Function cannot be both getter a setter. */  
                 JS_ASSERT(flags == JSPROP_GETTER || flags == JSPROP_SETTER);  
                 attrs |= flags | JSPROP_SHARED;  
                 rval = JSVAL_VOID;  
                 if (flags == JSPROP_GETTER)  
                     getter = js_CastAsPropertyOp(obj);  
                 else  
                     setter = js_CastAsPropertyOp(obj);  
             }  
   
             /*  
              * We define the function as a property of the variable object and  
              * not the current scope chain even for the case of function  
              * expression statements and functions defined by eval inside let  
              * or with blocks.  
              */  
             parent = fp->varobj;  
             JS_ASSERT(parent);  
   
             /*  
              * Check for a const property of the same name -- or any kind  
              * of property if executing with the strict option.  We check  
              * here at runtime as well as at compile-time, to handle eval  
              * as well as multiple HTML script tags.  
              */  
             id = ATOM_TO_JSID(fun->atom);  
             prop = NULL;  
             ok = js_CheckRedeclaration(cx, parent, id, attrs, &pobj, &prop);  
             if (!ok)  
                 goto restore_scope;  
   
             /*  
              * We deviate from 10.1.2 in ECMA 262 v3 and under eval use for  
              * function declarations OBJ_SET_PROPERTY, not OBJ_DEFINE_PROPERTY,  
              * to preserve the JSOP_PERMANENT attribute of existing properties  
              * and make sure that such properties cannot be deleted.  
              *  
              * We also use OBJ_SET_PROPERTY for the existing properties of  
              * Call objects with matching attributes to preserve the native  
              * getters and setters that store the value of the property in the  
              * interpreter frame, see bug 467495.  
              */  
             doSet = (attrs == JSPROP_ENUMERATE);  
             JS_ASSERT_IF(doSet, fp->flags & JSFRAME_EVAL);  
             if (prop) {  
                 if (parent == pobj &&  
                     OBJ_GET_CLASS(cx, parent) == &js_CallClass &&  
                     (old = ((JSScopeProperty *) prop)->attrs,  
                      !(old & (JSPROP_GETTER|JSPROP_SETTER)) &&  
                      (old & (JSPROP_ENUMERATE|JSPROP_PERMANENT)) == attrs)) {  
                     /*  
                      * js_CheckRedeclaration must reject attempts to add a  
                      * getter or setter to an existing property without a  
                      * getter or setter.  
                      */  
                     JS_ASSERT(!(attrs & ~(JSPROP_ENUMERATE|JSPROP_PERMANENT)));  
                     JS_ASSERT(!(old & JSPROP_READONLY));  
                     doSet = JS_TRUE;  
                 }  
                 OBJ_DROP_PROPERTY(cx, pobj, prop);  
             }  
             ok = doSet  
                  ? OBJ_SET_PROPERTY(cx, parent, id, &rval)  
                  : OBJ_DEFINE_PROPERTY(cx, parent, id, rval, getter, setter,  
                                        attrs, NULL);  
   
           restore_scope:  
             /* Restore fp->scopeChain now that obj is defined in fp->varobj. */  
             fp->scopeChain = obj2;  
             if (!ok) {  
                 cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
                 goto error;  
             }  
           }  
           END_CASE(JSOP_DEFFUN)  
   
           BEGIN_CASE(JSOP_DEFFUN_FC)  
           BEGIN_CASE(JSOP_DEFFUN_DBGFC)  
             LOAD_FUNCTION(0);  
   
             obj = (op == JSOP_DEFFUN_FC)  
                   ? js_NewFlatClosure(cx, fun)  
                   : js_NewDebuggableFlatClosure(cx, fun);  
             if (!obj)  
                 goto error;  
             rval = OBJECT_TO_JSVAL(obj);  
   
             attrs = (fp->flags & JSFRAME_EVAL)  
                     ? JSPROP_ENUMERATE  
                     : JSPROP_ENUMERATE | JSPROP_PERMANENT;  
   
             flags = JSFUN_GSFLAG2ATTR(fun->flags);  
             if (flags) {  
                 attrs |= flags | JSPROP_SHARED;  
                 rval = JSVAL_VOID;  
             }  
   
             parent = fp->varobj;  
             JS_ASSERT(parent);  
   
             id = ATOM_TO_JSID(fun->atom);  
             ok = js_CheckRedeclaration(cx, parent, id, attrs, NULL, NULL);  
             if (ok) {  
                 if (attrs == JSPROP_ENUMERATE) {  
                     JS_ASSERT(fp->flags & JSFRAME_EVAL);  
                     ok = OBJ_SET_PROPERTY(cx, parent, id, &rval);  
                 } else {  
                     JS_ASSERT(attrs & JSPROP_PERMANENT);  
   
                     ok = OBJ_DEFINE_PROPERTY(cx, parent, id, rval,  
                                              (flags & JSPROP_GETTER)  
                                              ? JS_EXTENSION (JSPropertyOp) obj  
                                              : JS_PropertyStub,  
                                              (flags & JSPROP_SETTER)  
                                              ? JS_EXTENSION (JSPropertyOp) obj  
                                              : JS_PropertyStub,  
                                              attrs,  
                                              NULL);  
                 }  
             }  
   
             if (!ok) {  
                 cx->weakRoots.newborn[GCX_OBJECT] = NULL;  
                 goto error;  
             }  
           END_CASE(JSOP_DEFFUN_FC)  
   
           BEGIN_CASE(JSOP_DEFLOCALFUN)  
             /*  
              * Define a local function (i.e., one nested at the top level of  
              * another function), parented by the current scope chain, stored  
              * in a local variable slot that the compiler allocated.  This is  
              * an optimization over JSOP_DEFFUN that avoids requiring a call  
              * object for the outer function's activation.  
              */  
             LOAD_FUNCTION(SLOTNO_LEN);  
             JS_ASSERT(FUN_INTERPRETED(fun));  
             JS_ASSERT(!FUN_FLAT_CLOSURE(fun));  
             obj = FUN_OBJECT(fun);  
   
             if (FUN_NULL_CLOSURE(fun)) {  
                 obj = js_CloneFunctionObject(cx, fun, fp->scopeChain);  
                 if (!obj)  
                     goto error;  
             } else {  
                 parent = js_GetScopeChain(cx, fp);  
                 if (!parent)  
                     goto error;  
   
                 if (OBJ_GET_PARENT(cx, obj) != parent) {  
 #ifdef JS_TRACER  
                     if (TRACE_RECORDER(cx))  
                         js_AbortRecording(cx, "DEFLOCALFUN for closure");  
3029  #endif  #endif
                     obj = js_CloneFunctionObject(cx, fun, parent);  
                     if (!obj)  
                         goto error;  
                 }  
             }  
   
             slot = GET_SLOTNO(regs.pc);  
             TRACE_2(DefLocalFunSetSlot, slot, obj);  
   
             fp->slots[slot] = OBJECT_TO_JSVAL(obj);  
           END_CASE(JSOP_DEFLOCALFUN)  
   
           BEGIN_CASE(JSOP_DEFLOCALFUN_FC)  
             LOAD_FUNCTION(SLOTNO_LEN);  
   
             obj = js_NewFlatClosure(cx, fun);  
             if (!obj)  
                 goto error;  
   
             slot = GET_SLOTNO(regs.pc);  
             TRACE_2(DefLocalFunSetSlot, slot, obj);  
   
             fp->slots[slot] = OBJECT_TO_JSVAL(obj);  
           END_CASE(JSOP_DEFLOCALFUN_FC)  
   
           BEGIN_CASE(JSOP_DEFLOCALFUN_DBGFC)  
             LOAD_FUNCTION(SLOTNO_LEN);  
   
             obj = js_NewDebuggableFlatClosure(cx, fun);  
             if (!obj)  
                 goto error;  
   
             slot = GET_SLOTNO(regs.pc);  
             fp->slots[slot] = OBJECT_TO_JSVAL(obj);  
           END_CASE(JSOP_DEFLOCALFUN_DBGFC)  
   
           BEGIN_CASE(JSOP_LAMBDA)  
             /* Load the specified function object literal. */  
             LOAD_FUNCTION(0);  
             obj = FUN_OBJECT(fun);  
   
             if (FUN_NULL_CLOSURE(fun)) {  
                 obj = js_CloneFunctionObject(cx, fun, fp->scopeChain);  
                 if (!obj)  
                     goto error;  
             } else {  
                 parent = js_GetScopeChain(cx, fp);  
                 if (!parent)  
                     goto error;  
   
                 /* If re-parenting, push a clone of the function object. */  
                 if (OBJ_GET_PARENT(cx, obj) != parent) {  
                     obj = js_CloneFunctionObject(cx, fun, parent);  
                     if (!obj)  
                         goto error;  
                 }  
             }  
   
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_LAMBDA)  
   
           BEGIN_CASE(JSOP_LAMBDA_FC)  
             LOAD_FUNCTION(0);  
   
             obj = js_NewFlatClosure(cx, fun);  
             if (!obj)  
                 goto error;  
   
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_LAMBDA_FC)  
   
           BEGIN_CASE(JSOP_LAMBDA_DBGFC)  
             LOAD_FUNCTION(0);  
   
             obj = js_NewDebuggableFlatClosure(cx, fun);  
             if (!obj)  
                 goto error;  
   
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_LAMBDA_DBGFC)  
   
           BEGIN_CASE(JSOP_CALLEE)  
             PUSH_OPND(OBJECT_TO_JSVAL(fp->callee));  
           END_CASE(JSOP_CALLEE)  
   
 #if JS_HAS_GETTER_SETTER  
           BEGIN_CASE(JSOP_GETTER)  
           BEGIN_CASE(JSOP_SETTER)  
           do_getter_setter:  
             op2 = (JSOp) *++regs.pc;  
             switch (op2) {  
               case JSOP_INDEXBASE:  
                 atoms += GET_INDEXBASE(regs.pc);  
                 regs.pc += JSOP_INDEXBASE_LENGTH - 1;  
                 goto do_getter_setter;  
               case JSOP_INDEXBASE1:  
               case JSOP_INDEXBASE2:  
               case JSOP_INDEXBASE3:  
                 atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;  
                 goto do_getter_setter;  
   
               case JSOP_SETNAME:  
               case JSOP_SETPROP:  
                 LOAD_ATOM(0);  
                 id = ATOM_TO_JSID(atom);  
                 rval = FETCH_OPND(-1);  
                 i = -1;  
                 goto gs_pop_lval;  
   
               case JSOP_SETELEM:  
                 rval = FETCH_OPND(-1);  
                 id = 0;  
                 i = -2;  
               gs_pop_lval:  
                 FETCH_OBJECT(cx, i - 1, lval, obj);  
                 break;  
   
               case JSOP_INITPROP:  
                 JS_ASSERT(regs.sp - StackBase(fp) >= 2);  
                 rval = FETCH_OPND(-1);  
                 i = -1;  
                 LOAD_ATOM(0);  
                 id = ATOM_TO_JSID(atom);  
                 goto gs_get_lval;  
   
               default:  
                 JS_ASSERT(op2 == JSOP_INITELEM);  
   
                 JS_ASSERT(regs.sp - StackBase(fp) >= 3);  
                 rval = FETCH_OPND(-1);  
                 id = 0;  
                 i = -2;  
               gs_get_lval:  
                 lval = FETCH_OPND(i-1);  
                 JS_ASSERT(JSVAL_IS_OBJECT(lval));  
                 obj = JSVAL_TO_OBJECT(lval);  
                 break;  
             }  
   
             /* Ensure that id has a type suitable for use with obj. */  
             if (id == 0)  
                 FETCH_ELEMENT_ID(obj, i, id);  
   
             if (JS_TypeOfValue(cx, rval) != JSTYPE_FUNCTION) {  
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,  
                                      JSMSG_BAD_GETTER_OR_SETTER,  
                                      (op == JSOP_GETTER)  
                                      ? js_getter_str  
                                      : js_setter_str);  
                 goto error;  
             }  
   
             /*  
              * Getters and setters are just like watchpoints from an access  
              * control point of view.  
              */  
             if (!OBJ_CHECK_ACCESS(cx, obj, id, JSACC_WATCH, &rtmp, &attrs))  
                 goto error;  
   
             if (op == JSOP_GETTER) {  
                 getter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);  
                 setter = JS_PropertyStub;  
                 attrs = JSPROP_GETTER;  
             } else {  
                 getter = JS_PropertyStub;  
                 setter = JS_EXTENSION (JSPropertyOp) JSVAL_TO_OBJECT(rval);  
                 attrs = JSPROP_SETTER;  
             }  
             attrs |= JSPROP_ENUMERATE | JSPROP_SHARED;  
   
             /* Check for a readonly or permanent property of the same name. */  
             if (!js_CheckRedeclaration(cx, obj, id, attrs, NULL, NULL))  
                 goto error;  
   
             if (!OBJ_DEFINE_PROPERTY(cx, obj, id, JSVAL_VOID, getter, setter,  
                                      attrs, NULL)) {  
                 goto error;  
             }  
   
             regs.sp += i;  
             if (js_CodeSpec[op2].ndefs)  
                 STORE_OPND(-1, rval);  
             len = js_CodeSpec[op2].length;  
             DO_NEXT_OP(len);  
 #endif /* JS_HAS_GETTER_SETTER */  
   
           BEGIN_CASE(JSOP_HOLE)  
             PUSH_OPND(JSVAL_HOLE);  
           END_CASE(JSOP_HOLE)  
   
           BEGIN_CASE(JSOP_NEWARRAY)  
             len = GET_UINT16(regs.pc);  
             cx->fp->assertValidStackDepth(len);  
             obj = js_NewArrayObject(cx, len, regs.sp - len, JS_TRUE);  
             if (!obj)  
                 goto error;  
             regs.sp -= len - 1;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_NEWARRAY)  
   
           BEGIN_CASE(JSOP_NEWINIT)  
             i = GET_INT8(regs.pc);  
             JS_ASSERT(i == JSProto_Array || i == JSProto_Object);  
             obj = (i == JSProto_Array)  
                   ? js_NewArrayObject(cx, 0, NULL)  
                   : js_NewObject(cx, &js_ObjectClass, NULL, NULL, 0);  
             if (!obj)  
                 goto error;  
             PUSH_OPND(OBJECT_TO_JSVAL(obj));  
             fp->sharpDepth++;  
             CHECK_INTERRUPT_HANDLER();  
           END_CASE(JSOP_NEWINIT)  
   
           BEGIN_CASE(JSOP_ENDINIT)  
             if (--fp->sharpDepth == 0)  
                 fp->sharpArray = NULL;  
   
             /* Re-set the newborn root to the top of this object tree. */  
             JS_ASSERT(regs.sp - StackBase(fp) >= 1);  
             lval = FETCH_OPND(-1);  
             JS_ASSERT(JSVAL_IS_OBJECT(lval));  
             cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(lval);  
           END_CASE(JSOP_ENDINIT)  
   
           BEGIN_CASE(JSOP_INITPROP)  
             /* Load the property's initial value into rval. */  
             JS_ASSERT(regs.sp - StackBase(fp) >= 2);  
             rval = FETCH_OPND(-1);  
   
             /* Load the object being initialized into lval/obj. */  
             lval = FETCH_OPND(-2);  
             obj = JSVAL_TO_OBJECT(lval);  
             JS_ASSERT(OBJ_IS_NATIVE(obj));  
             JS_ASSERT(!OBJ_GET_CLASS(cx, obj)->reserveSlots);  
             JS_ASSERT(!(LOCKED_OBJ_GET_CLASS(obj)->flags &  
                         JSCLASS_SHARE_ALL_PROPERTIES));  
   
             do {  
                 JSScope *scope;  
                 uint32 kshape;  
                 JSPropertyCache *cache;  
                 JSPropCacheEntry *entry;  
   
                 JS_LOCK_OBJ(cx, obj);  
                 scope = OBJ_SCOPE(obj);  
                 JS_ASSERT(!SCOPE_IS_SEALED(scope));  
                 kshape = scope->shape;  
                 cache = &JS_PROPERTY_CACHE(cx);  
                 entry = &cache->table[PROPERTY_CACHE_HASH_PC(regs.pc, kshape)];  
                 PCMETER(cache->pctestentry = entry);  
                 PCMETER(cache->tests++);  
                 PCMETER(cache->initests++);  
   
                 if (entry->kpc == regs.pc &&  
                     entry->kshape == kshape &&  
                     PCVCAP_SHAPE(entry->vcap) == rt->protoHazardShape) {  
                     JS_ASSERT(PCVCAP_TAG(entry->vcap) == 0);  
   
                     PCMETER(cache->pchits++);  
                     PCMETER(cache->inipchits++);  
   
                     JS_ASSERT(PCVAL_IS_SPROP(entry->vword));  
                     sprop = PCVAL_TO_SPROP(entry->vword);  
                     JS_ASSERT(!(sprop->attrs & JSPROP_READONLY));  
   
                     /*  
                      * If this property has a non-stub setter, it must be  
                      * __proto__, __parent__, or another "shared prototype"  
                      * built-in. Force a miss to save code size here and let  
                      * the standard code path take care of business.  
                      */  
                     if (!SPROP_HAS_STUB_SETTER(sprop))  
                         goto do_initprop_miss;  
   
                     if (scope->object != obj) {  
                         scope = js_GetMutableScope(cx, obj);  
                         if (!scope) {  
                             JS_UNLOCK_OBJ(cx, obj);  
                             goto error;  
                         }  
                     }  
   
                     /*  
                      * Detect a repeated property name and force a miss to  
                      * share the strict warning code and cope with complexity  
                      * managed by js_AddScopeProperty.  
                      */  
                     if (sprop->parent != scope->lastProp)  
                         goto do_initprop_miss;  
   
                     /*  
                      * Otherwise this entry must be for a direct property of  
                      * obj, not a proto-property, and there cannot have been  
                      * any deletions of prior properties.  
                      */  
                     JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));  
                     JS_ASSERT(!scope->table ||  
                               !SCOPE_HAS_PROPERTY(scope, sprop));  
   
                     slot = sprop->slot;  
                     JS_ASSERT(slot == scope->freeslot);  
                     if (slot < STOBJ_NSLOTS(obj)) {  
                         ++scope->freeslot;  
                     } else {  
                         if (!js_AllocSlot(cx, obj, &slot)) {  
                             JS_UNLOCK_SCOPE(cx, scope);  
                             goto error;  
                         }  
                         JS_ASSERT(slot == sprop->slot);  
                     }  
   
                     JS_ASSERT(!scope->lastProp ||  
                               scope->shape == scope->lastProp->shape);  
                     if (scope->table) {  
                         JSScopeProperty *sprop2 =  
                             js_AddScopeProperty(cx, scope, sprop->id,  
                                                 sprop->getter, sprop->setter,  
                                                 slot, sprop->attrs,  
                                                 sprop->flags, sprop->shortid);  
                         if (!sprop2) {  
                             js_FreeSlot(cx, obj, slot);  
                             JS_UNLOCK_SCOPE(cx, scope);  
                             goto error;  
                         }  
                         JS_ASSERT(sprop2 == sprop);  
                     } else {  
                         js_LeaveTraceIfGlobalObject(cx, scope->object);  
                         scope->shape = sprop->shape;  
                         ++scope->entryCount;  
                         scope->lastProp = sprop;  
                     }  
   
                     GC_WRITE_BARRIER(cx, scope,  
                                      LOCKED_OBJ_GET_SLOT(obj, slot),  
                                      rval);  
                     TRACE_2(SetPropHit, entry, sprop);  
                     LOCKED_OBJ_SET_SLOT(obj, slot, rval);  
                     JS_UNLOCK_SCOPE(cx, scope);  
                     break;  
                 }  
   
               do_initprop_miss:  
                 PCMETER(cache->inipcmisses++);  
                 JS_UNLOCK_SCOPE(cx, scope);  
   
                 /* Get the immediate property name into id. */  
                 LOAD_ATOM(0);  
                 id = ATOM_TO_JSID(atom);  
   
                 /* Set the property named by obj[id] to rval. */  
                 if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER,  
                                            NULL, NULL)) {  
                     goto error;  
                 }  
   
                 if (!(JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)  
                       ? js_SetPropertyHelper(cx, obj, id, true, &rval)  
                       : js_DefineNativeProperty(cx, obj, id, rval, NULL, NULL,  
                                                 JSPROP_ENUMERATE, 0, 0, NULL,  
                                                 JSDNP_CACHE_RESULT)))  
                     goto error;  
             } while (0);  
   
             /* Common tail for property cache hit and miss cases. */  
             regs.sp--;  
           END_CASE(JSOP_INITPROP);  
   
           BEGIN_CASE(JSOP_INITELEM)  
             /* Pop the element's value into rval. */  
             JS_ASSERT(regs.sp - StackBase(fp) >= 3);  
             rval = FETCH_OPND(-1);  
   
             /* Find the object being initialized at top of stack. */  
             lval = FETCH_OPND(-3);  
             JS_ASSERT(!JSVAL_IS_PRIMITIVE(lval));  
             obj = JSVAL_TO_OBJECT(lval);  
3030    
3031              /* Fetch id now that we have obj. */  /********************** Here we include the operations ***********************/
3032              FETCH_ELEMENT_ID(obj, -2, id);  #include "jsops.cpp"
3033    /*****************************************************************************/
             /*  
              * Check for property redeclaration strict warning (we may be in  
              * an object initialiser, not an array initialiser).  
              */  
             if (!js_CheckRedeclaration(cx, obj, id, JSPROP_INITIALIZER, NULL, NULL))  
                 goto error;  
   
             /*  
              * If rval is a hole, do not call OBJ_DEFINE_PROPERTY. In this case,  
              * obj must be an array, so if the current op is the last element  
              * initialiser, set the array length to one greater than id.  
              */  
             if (rval == JSVAL_HOLE) {  
                 JS_ASSERT(OBJ_IS_ARRAY(cx, obj));  
                 JS_ASSERT(JSID_IS_INT(id));  
                 JS_ASSERT((jsuint) JSID_TO_INT(id) < ARRAY_INIT_LIMIT);  
                 if (js_GetOpcode(cx, script, regs.pc + JSOP_INITELEM_LENGTH) == JSOP_ENDINIT &&  
                     !js_SetLengthProperty(cx, obj, (jsuint) (JSID_TO_INT(id) + 1))) {  
                     goto error;  
                 }  
             } else {  
                 if (!OBJ_DEFINE_PROPERTY(cx, obj, id, rval, NULL, NULL, JSPROP_ENUMERATE, NULL))  
                     goto error;  
             }  
             regs.sp -= 2;  
           END_CASE(JSOP_INITELEM)  
   
 #if JS_HAS_SHARP_VARS  
           BEGIN_CASE(JSOP_DEFSHARP)  
             obj = fp->sharpArray;  
             if (!obj) {  
                 obj = js_NewArrayObject(cx, 0, NULL);  
                 if (!obj)  
                     goto error;  
                 fp->sharpArray = obj;  
             }  
             i = (jsint) GET_UINT16(regs.pc);  
             id = INT_TO_JSID(i);  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_PRIMITIVE(rval)) {  
                 char numBuf[12];  
                 JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);  
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,  
                                      JSMSG_BAD_SHARP_DEF, numBuf);  
                 goto error;  
             }  
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
           END_CASE(JSOP_DEFSHARP)  
   
           BEGIN_CASE(JSOP_USESHARP)  
             i = (jsint) GET_UINT16(regs.pc);  
             id = INT_TO_JSID(i);  
             obj = fp->sharpArray;  
             if (!obj) {  
                 rval = JSVAL_VOID;  
             } else {  
                 if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))  
                     goto error;  
             }  
             if (!JSVAL_IS_OBJECT(rval)) {  
                 char numBuf[12];  
   
                 JS_snprintf(numBuf, sizeof numBuf, "%u", (unsigned) i);  
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,  
                                      JSMSG_BAD_SHARP_USE, numBuf);  
                 goto error;  
             }  
             PUSH_OPND(rval);  
           END_CASE(JSOP_USESHARP)  
 #endif /* JS_HAS_SHARP_VARS */  
   
           BEGIN_CASE(JSOP_GOSUB)  
             PUSH(JSVAL_FALSE);  
             i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUB_LENGTH;  
             PUSH(INT_TO_JSVAL(i));  
             len = GET_JUMP_OFFSET(regs.pc);  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_GOSUBX)  
             PUSH(JSVAL_FALSE);  
             i = PTRDIFF(regs.pc, script->main, jsbytecode) + JSOP_GOSUBX_LENGTH;  
             len = GET_JUMPX_OFFSET(regs.pc);  
             PUSH(INT_TO_JSVAL(i));  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_RETSUB)  
             /* Pop [exception or hole, retsub pc-index]. */  
             rval = POP();  
             lval = POP();  
             JS_ASSERT(JSVAL_IS_BOOLEAN(lval));  
             if (JSVAL_TO_BOOLEAN(lval)) {  
                 /*  
                  * Exception was pending during finally, throw it *before* we  
                  * adjust pc, because pc indexes into script->trynotes.  This  
                  * turns out not to be necessary, but it seems clearer.  And  
                  * it points out a FIXME: 350509, due to Igor Bukanov.  
                  */  
                 cx->throwing = JS_TRUE;  
                 cx->exception = rval;  
                 goto error;  
             }  
             JS_ASSERT(JSVAL_IS_INT(rval));  
             len = JSVAL_TO_INT(rval);  
             regs.pc = script->main;  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_EXCEPTION)  
             JS_ASSERT(cx->throwing);  
             PUSH(cx->exception);  
             cx->throwing = JS_FALSE;  
             CHECK_BRANCH();  
           END_CASE(JSOP_EXCEPTION)  
   
           BEGIN_CASE(JSOP_FINALLY)  
             CHECK_BRANCH();  
           END_CASE(JSOP_FINALLY)  
   
           BEGIN_CASE(JSOP_THROWING)  
             JS_ASSERT(!cx->throwing);  
             cx->throwing = JS_TRUE;  
             cx->exception = POP_OPND();  
           END_CASE(JSOP_THROWING)  
   
           BEGIN_CASE(JSOP_THROW)  
             JS_ASSERT(!cx->throwing);  
             CHECK_BRANCH();  
             cx->throwing = JS_TRUE;  
             cx->exception = POP_OPND();  
             /* let the code at error try to catch the exception. */  
             goto error;  
   
           BEGIN_CASE(JSOP_SETLOCALPOP)  
             /*  
              * The stack must have a block with at least one local slot below  
              * the exception object.  
              */  
             JS_ASSERT((size_t) (regs.sp - StackBase(fp)) >= 2);  
             slot = GET_UINT16(regs.pc);  
             JS_ASSERT(slot + 1 < script->nslots);  
             fp->slots[slot] = POP_OPND();  
           END_CASE(JSOP_SETLOCALPOP)  
   
           BEGIN_CASE(JSOP_IFPRIMTOP)  
             /*  
              * If the top of stack is of primitive type, jump to our target.  
              * Otherwise advance to the next opcode.  
              */  
             JS_ASSERT(regs.sp > StackBase(fp));  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_PRIMITIVE(rval)) {  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 BRANCH(len);  
             }  
           END_CASE(JSOP_IFPRIMTOP)  
3034    
3035            BEGIN_CASE(JSOP_PRIMTOP)  #if !JS_THREADED_INTERP
             JS_ASSERT(regs.sp > StackBase(fp));  
             lval = FETCH_OPND(-1);  
             i = GET_INT8(regs.pc);  
             if (!JSVAL_IS_PRIMITIVE(lval)) {  
                 lval = FETCH_OPND(-2);  
                 js_ReportValueError2(cx, JSMSG_CANT_CONVERT_TO,  
                                      -2, lval, NULL,  
                                      (i == JSTYPE_VOID)  
                                      ? "primitive type"  
                                      : JS_TYPE_STR(i));  
                 goto error;  
             }  
           END_CASE(JSOP_PRIMTOP)  
   
           BEGIN_CASE(JSOP_OBJTOP)  
             lval = FETCH_OPND(-1);  
             if (JSVAL_IS_PRIMITIVE(lval)) {  
                 js_ReportValueError(cx, GET_UINT16(regs.pc), -1, lval, NULL);  
                 goto error;  
             }  
           END_CASE(JSOP_OBJTOP)  
   
           BEGIN_CASE(JSOP_INSTANCEOF)  
             rval = FETCH_OPND(-1);  
             if (JSVAL_IS_PRIMITIVE(rval) ||  
                 !(obj = JSVAL_TO_OBJECT(rval))->map->ops->hasInstance) {  
                 js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,  
                                     -1, rval, NULL);  
                 goto error;  
             }  
             lval = FETCH_OPND(-2);  
             cond = JS_FALSE;  
             if (!obj->map->ops->hasInstance(cx, obj, lval, &cond))  
                 goto error;  
             regs.sp--;  
             STORE_OPND(-1, BOOLEAN_TO_JSVAL(cond));  
           END_CASE(JSOP_INSTANCEOF)  
   
 #if JS_HAS_DEBUGGER_KEYWORD  
           BEGIN_CASE(JSOP_DEBUGGER)  
           {  
             JSTrapHandler handler = cx->debugHooks->debuggerHandler;  
             if (handler) {  
                 switch (handler(cx, script, regs.pc, &rval,  
                                 cx->debugHooks->debuggerHandlerData)) {  
                   case JSTRAP_ERROR:  
                     goto error;  
                   case JSTRAP_CONTINUE:  
                     break;  
                   case JSTRAP_RETURN:  
                     fp->rval = rval;  
                     ok = JS_TRUE;  
                     goto forced_return;  
                   case JSTRAP_THROW:  
                     cx->throwing = JS_TRUE;  
                     cx->exception = rval;  
                     goto error;  
                   default:;  
                 }  
                 CHECK_INTERRUPT_HANDLER();  
             }  
           }  
           END_CASE(JSOP_DEBUGGER)  
 #endif /* JS_HAS_DEBUGGER_KEYWORD */  
   
 #if JS_HAS_XML_SUPPORT  
           BEGIN_CASE(JSOP_DEFXMLNS)  
             rval = POP();  
             if (!js_SetDefaultXMLNamespace(cx, rval))  
                 goto error;  
           END_CASE(JSOP_DEFXMLNS)  
   
           BEGIN_CASE(JSOP_ANYNAME)  
             if (!js_GetAnyName(cx, &rval))  
                 goto error;  
             PUSH_OPND(rval);  
           END_CASE(JSOP_ANYNAME)  
   
           BEGIN_CASE(JSOP_QNAMEPART)  
             LOAD_ATOM(0);  
             PUSH_OPND(ATOM_KEY(atom));  
           END_CASE(JSOP_QNAMEPART)  
   
           BEGIN_CASE(JSOP_QNAMECONST)  
             LOAD_ATOM(0);  
             rval = ATOM_KEY(atom);  
             lval = FETCH_OPND(-1);  
             obj = js_ConstructXMLQNameObject(cx, lval, rval);  
             if (!obj)  
                 goto error;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_QNAMECONST)  
   
           BEGIN_CASE(JSOP_QNAME)  
             rval = FETCH_OPND(-1);  
             lval = FETCH_OPND(-2);  
             obj = js_ConstructXMLQNameObject(cx, lval, rval);  
             if (!obj)  
                 goto error;  
             regs.sp--;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_QNAME)  
   
           BEGIN_CASE(JSOP_TOATTRNAME)  
             rval = FETCH_OPND(-1);  
             if (!js_ToAttributeName(cx, &rval))  
                 goto error;  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_TOATTRNAME)  
   
           BEGIN_CASE(JSOP_TOATTRVAL)  
             rval = FETCH_OPND(-1);  
             JS_ASSERT(JSVAL_IS_STRING(rval));  
             str = js_EscapeAttributeValue(cx, JSVAL_TO_STRING(rval), JS_FALSE);  
             if (!str)  
                 goto error;  
             STORE_OPND(-1, STRING_TO_JSVAL(str));  
           END_CASE(JSOP_TOATTRVAL)  
   
           BEGIN_CASE(JSOP_ADDATTRNAME)  
           BEGIN_CASE(JSOP_ADDATTRVAL)  
             rval = FETCH_OPND(-1);  
             lval = FETCH_OPND(-2);  
             str = JSVAL_TO_STRING(lval);  
             str2 = JSVAL_TO_STRING(rval);  
             str = js_AddAttributePart(cx, op == JSOP_ADDATTRNAME, str, str2);  
             if (!str)  
                 goto error;  
             regs.sp--;  
             STORE_OPND(-1, STRING_TO_JSVAL(str));  
           END_CASE(JSOP_ADDATTRNAME)  
   
           BEGIN_CASE(JSOP_BINDXMLNAME)  
             lval = FETCH_OPND(-1);  
             if (!js_FindXMLProperty(cx, lval, &obj, &id))  
                 goto error;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
             PUSH_OPND(ID_TO_VALUE(id));  
           END_CASE(JSOP_BINDXMLNAME)  
   
           BEGIN_CASE(JSOP_SETXMLNAME)  
             obj = JSVAL_TO_OBJECT(FETCH_OPND(-3));  
             rval = FETCH_OPND(-1);  
             FETCH_ELEMENT_ID(obj, -2, id);  
             if (!OBJ_SET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
             rval = FETCH_OPND(-1);  
             regs.sp -= 2;  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_SETXMLNAME)  
   
           BEGIN_CASE(JSOP_CALLXMLNAME)  
           BEGIN_CASE(JSOP_XMLNAME)  
             lval = FETCH_OPND(-1);  
             if (!js_FindXMLProperty(cx, lval, &obj, &id))  
                 goto error;  
             if (!OBJ_GET_PROPERTY(cx, obj, id, &rval))  
                 goto error;  
             STORE_OPND(-1, rval);  
             if (op == JSOP_CALLXMLNAME)  
                 PUSH_OPND(OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_XMLNAME)  
   
           BEGIN_CASE(JSOP_DESCENDANTS)  
           BEGIN_CASE(JSOP_DELDESC)  
             FETCH_OBJECT(cx, -2, lval, obj);  
             rval = FETCH_OPND(-1);  
             if (!js_GetXMLDescendants(cx, obj, rval, &rval))  
                 goto error;  
   
             if (op == JSOP_DELDESC) {  
                 regs.sp[-1] = rval;          /* set local root */  
                 if (!js_DeleteXMLListElements(cx, JSVAL_TO_OBJECT(rval)))  
                     goto error;  
                 rval = JSVAL_TRUE;      /* always succeed */  
             }  
   
             regs.sp--;  
             STORE_OPND(-1, rval);  
           END_CASE(JSOP_DESCENDANTS)  
   
           BEGIN_CASE(JSOP_FILTER)  
             /*  
              * We push the hole value before jumping to [enditer] so we can  
              * detect the first iteration and direct js_StepXMLListFilter to  
              * initialize filter's state.  
              */  
             PUSH_OPND(JSVAL_HOLE);  
             len = GET_JUMP_OFFSET(regs.pc);  
             JS_ASSERT(len > 0);  
           END_VARLEN_CASE  
   
           BEGIN_CASE(JSOP_ENDFILTER)  
             cond = (regs.sp[-1] != JSVAL_HOLE);  
             if (cond) {  
                 /* Exit the "with" block left from the previous iteration. */  
                 js_LeaveWith(cx);  
             }  
             if (!js_StepXMLListFilter(cx, cond))  
                 goto error;  
             if (regs.sp[-1] != JSVAL_NULL) {  
                 /*  
                  * Decrease sp after EnterWith returns as we use sp[-1] there  
                  * to root temporaries.  
                  */  
                 JS_ASSERT(VALUE_IS_XML(cx, regs.sp[-1]));  
                 if (!js_EnterWith(cx, -2))  
                     goto error;  
                 regs.sp--;  
                 len = GET_JUMP_OFFSET(regs.pc);  
                 JS_ASSERT(len < 0);  
                 BRANCH(len);  
             }  
             regs.sp--;  
           END_CASE(JSOP_ENDFILTER);  
   
           BEGIN_CASE(JSOP_TOXML)  
             rval = FETCH_OPND(-1);  
             obj = js_ValueToXMLObject(cx, rval);  
             if (!obj)  
                 goto error;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_TOXML)  
   
           BEGIN_CASE(JSOP_TOXMLLIST)  
             rval = FETCH_OPND(-1);  
             obj = js_ValueToXMLListObject(cx, rval);  
             if (!obj)  
                 goto error;  
             STORE_OPND(-1, OBJECT_TO_JSVAL(obj));  
           END_CASE(JSOP_TOXMLLIST)  
   
           BEGIN_CASE(JSOP_XMLTAGEXPR)  
             rval = FETCH_OPND(-1);  
             str = js_ValueToString(cx, rval);  
             if (!str)  
                 goto error;  
             STORE_OPND(-1, STRING_TO_JSVAL(str));  
           END_CASE(JSOP_XMLTAGEXPR)  
   
           BEGIN_CASE(JSOP_XMLELTEXPR)  
             rval = FETCH_OPND(-1);  
             if (VALUE_IS_XML(cx, rval)) {  
                 str = js_ValueToXMLString(cx, rval);  
             } else {  
                 str = js_ValueToString(cx, rval);  
                 if (str)  
                     str = js_EscapeElementValue(cx, str);  
             }  
             if (!str)  
                 goto error;  
             STORE_OPND(-1, STRING_TO_JSVAL(str));  
    &nbs