bug 686017 - avoid Cell::arenaHeader() on fast paths. r=bhackett1024
authorIgor Bukanov <igor@mir2.org>
Tue, 16 Aug 2011 12:27:34 +0200
changeset 76883 f3908eb901515fa929450bd31b7393ceccf98d6d
parent 76882 cdf7e50630fc4360b9f3f501d86cf896b99ec1f6
child 76884 b991feb93d32ea9c9d8a6b711125d185ce9f6ca3
child 76886 91906f4106817c721391921e60a591ff49788921
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersbhackett1024
bugs686017
milestone9.0a1
bug 686017 - avoid Cell::arenaHeader() on fast paths. r=bhackett1024
js/src/jsanalyze.h
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsemit.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgcinlines.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jspropertycache.cpp
js/src/jsregexpinlines.h
js/src/jsscope.cpp
js/src/jsscope.h
js/src/jsscopeinlines.h
js/src/jsscript.cpp
js/src/jstracer.cpp
js/src/jswatchpoint.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/StubCalls.cpp
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -1026,31 +1026,31 @@ class ScriptAnalysis
         return array + which;
     }
     types::TypeSet *pushedTypes(const jsbytecode *pc, uint32 which) {
         return pushedTypes(pc - script->code, which);
     }
 
     bool hasPushedTypes(const jsbytecode *pc) { return getCode(pc).pushedTypes != NULL; }
 
-    types::TypeBarrier *typeBarriers(uint32 offset) {
+    types::TypeBarrier *typeBarriers(JSContext *cx, uint32 offset) {
         if (getCode(offset).typeBarriers)
-            pruneTypeBarriers(offset);
+            pruneTypeBarriers(cx, offset);
         return getCode(offset).typeBarriers;
     }
-    types::TypeBarrier *typeBarriers(const jsbytecode *pc) {
-        return typeBarriers(pc - script->code);
+    types::TypeBarrier *typeBarriers(JSContext *cx, const jsbytecode *pc) {
+        return typeBarriers(cx, pc - script->code);
     }
     void addTypeBarrier(JSContext *cx, const jsbytecode *pc,
                         types::TypeSet *target, types::Type type);
     void addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc,
                                  types::TypeSet *target, JSObject *singleton, jsid singletonId);
 
     /* Remove obsolete type barriers at the given offset. */
-    void pruneTypeBarriers(uint32 offset);
+    void pruneTypeBarriers(JSContext *cx, uint32 offset);
 
     /*
      * Remove still-active type barriers at the given offset. If 'all' is set,
      * then all barriers are removed, otherwise only those deemed excessive
      * are removed.
      */
     void breakTypeBarriers(JSContext *cx, uint32 offset, bool all);
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1796,17 +1796,17 @@ JS_EnumerateStandardClasses(JSContext *c
     assertSameCompartment(cx, obj);
     rt = cx->runtime;
 
     /*
      * Check whether we need to bind 'undefined' and define it if so.
      * Since ES5 15.1.1.3 undefined can't be deleted.
      */
     atom = rt->atomState.typeAtoms[JSTYPE_VOID];
-    if (!obj->nativeContains(ATOM_TO_JSID(atom)) &&
+    if (!obj->nativeContains(cx, ATOM_TO_JSID(atom)) &&
         !obj->defineProperty(cx, ATOM_TO_JSID(atom), UndefinedValue(),
                              PropertyStub, StrictPropertyStub,
                              JSPROP_PERMANENT | JSPROP_READONLY)) {
         return JS_FALSE;
     }
 
     /* Initialize any classes that have not been initialized yet. */
     for (i = 0; standard_class_atoms[i].init; i++) {
@@ -1872,17 +1872,17 @@ AddAtomToArray(JSContext *cx, JSAtom *at
     *ip = i + 1;
     return ida;
 }
 
 static JSIdArray *
 EnumerateIfResolved(JSContext *cx, JSObject *obj, JSAtom *atom, JSIdArray *ida,
                     jsint *ip, JSBool *foundp)
 {
-    *foundp = obj->nativeContains(ATOM_TO_JSID(atom));
+    *foundp = obj->nativeContains(cx, ATOM_TO_JSID(atom));
     if (*foundp)
         ida = AddAtomToArray(cx, atom, ida, ip);
     return ida;
 }
 
 JS_PUBLIC_API(JSIdArray *)
 JS_EnumerateResolvedStandardClasses(JSContext *cx, JSObject *obj, JSIdArray *ida)
 {
@@ -3342,17 +3342,17 @@ JS_AlreadyHasOwnPropertyById(JSContext *
         if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED | JSRESOLVE_DETECTING,
                                 &obj2, &prop)) {
             return JS_FALSE;
         }
         *foundp = (obj == obj2);
         return JS_TRUE;
     }
 
-    *foundp = obj->nativeContains(id);
+    *foundp = obj->nativeContains(cx, id);
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32 index, JSBool *foundp)
 {
     CHECK_REQUEST(cx);
     jsid id;
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -342,17 +342,17 @@ JSObject::arrayGetOwnDataElement(JSConte
         return true;
     }
 
     JSBool hole;
     jsid id;
     if (!IndexToId(cx, this, i, &hole, &id))
         return false;
 
-    const Shape *shape = nativeLookup(id);
+    const Shape *shape = nativeLookup(cx, id);
     if (!shape || !shape->isDataDescriptor())
         vp->setMagic(JS_ARRAY_HOLE);
     else
         *vp = getSlot(shape->slot);
     return true;
 }
 
 /*
@@ -1099,17 +1099,17 @@ Class js::SlowArrayClass = {
     ResolveStub,
     ConvertStub
 };
 
 static bool
 AddLengthProperty(JSContext *cx, JSObject *obj)
 {
     const jsid lengthId = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
-    JS_ASSERT(!obj->nativeLookup(lengthId));
+    JS_ASSERT(!obj->nativeLookup(cx, lengthId));
 
     return obj->addProperty(cx, lengthId, array_length_getter, array_length_setter,
                             SHAPE_INVALID_SLOT, JSPROP_PERMANENT | JSPROP_SHARED, 0, 0);
 }
 
 /*
  * Convert an array object from fast-and-dense to slow-and-flexible.
  */
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -1713,17 +1713,17 @@ js_LexicalLookup(JSTreeContext *tc, JSAt
 
         /* Skip "maybe scope" statements that don't contain let bindings. */
         if (!(stmt->flags & SIF_SCOPE))
             continue;
 
         JSObject *obj = stmt->blockBox->object;
         JS_ASSERT(obj->isStaticBlock());
 
-        const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom));
+        const Shape *shape = obj->nativeLookup(tc->parser->context, ATOM_TO_JSID(atom));
         if (shape) {
             JS_ASSERT(shape->hasShortID());
 
             if (slotp) {
                 JS_ASSERT(obj->getSlot(JSSLOT_BLOCK_DEPTH).isInt32());
                 *slotp = obj->getSlot(JSSLOT_BLOCK_DEPTH).toInt32() + shape->shortid;
             }
             return stmt;
@@ -1774,17 +1774,17 @@ LookupCompileTimeConstant(JSContext *cx,
              */
             if (cg->inFunction()) {
                 if (cg->bindings.hasBinding(cx, atom))
                     break;
             } else {
                 JS_ASSERT(cg->compileAndGo());
                 obj = cg->scopeChain();
 
-                const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom));
+                const Shape *shape = obj->nativeLookup(cx, ATOM_TO_JSID(atom));
                 if (shape) {
                     /*
                      * We're compiling code that will be executed immediately,
                      * not re-executed against a different scope chain and/or
                      * variable object.  Therefore we can get constant values
                      * from our variable object here.
                      */
                     if (!shape->writable() && !shape->configurable() &&
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -1202,17 +1202,17 @@ StackFrame::getValidCalleeObject(JSConte
                  * While a non-native object is responsible for handling its
                  * entire prototype chain, notable non-natives including dense
                  * and typed arrays have native prototypes, so keep going.
                  */
                 if (!thisp->isNative())
                     continue;
 
                 if (thisp->hasMethodBarrier()) {
-                    const Shape *shape = thisp->nativeLookup(ATOM_TO_JSID(fun->methodAtom()));
+                    const Shape *shape = thisp->nativeLookup(cx, ATOM_TO_JSID(fun->methodAtom()));
                     if (shape) {
                         /*
                          * Two cases follow: the method barrier was not crossed
                          * yet, so we cross it here; the method barrier *was*
                          * crossed but after the call, in which case we fetch
                          * and validate the cloned (unjoined) funobj from the
                          * method property's slot.
                          *
@@ -2308,21 +2308,21 @@ LookupInterpretedFunctionPrototype(JSCon
 #ifdef DEBUG
     JSFunction *fun = funobj->getFunctionPrivate();
     JS_ASSERT(fun->isInterpreted());
     JS_ASSERT(!fun->isFunctionPrototype());
     JS_ASSERT(!funobj->isBoundFunction());
 #endif
 
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
-    const Shape *shape = funobj->nativeLookup(id);
+    const Shape *shape = funobj->nativeLookup(cx, id);
     if (!shape) {
         if (!ResolveInterpretedFunctionPrototype(cx, funobj))
             return NULL;
-        shape = funobj->nativeLookup(id);
+        shape = funobj->nativeLookup(cx, id);
     }
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(shape->isDataDescriptor());
     JS_ASSERT(shape->hasSlot());
     JS_ASSERT(!shape->isMethod());
     return shape;
 }
 
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -321,19 +321,19 @@ IsNativeFunction(const js::Value &v, Nat
  * TODO: a per-thread shape-based cache would be faster and simpler.
  */
 static JS_ALWAYS_INLINE bool
 ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid, Native native)
 {
     JS_ASSERT(obj->getClass() == clasp);
 
     Value v;
-    if (!HasDataProperty(obj, methodid, &v)) {
+    if (!HasDataProperty(cx, obj, methodid, &v)) {
         JSObject *proto = obj->getProto();
-        if (!proto || proto->getClass() != clasp || !HasDataProperty(proto, methodid, &v))
+        if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, proto, methodid, &v))
             return false;
     }
 
     return js::IsNativeFunction(v, native);
 }
 
 extern JS_ALWAYS_INLINE bool
 SameTraceType(const Value &lhs, const Value &rhs)
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -138,16 +138,25 @@ GetGCObjectKind(size_t numSlots, bool is
          * other objects. Arrays do not use their fixed slots anymore when
          * they have a slots array, while other objects will continue to do so.
          */
         return isArray ? FINALIZE_OBJECT0 : FINALIZE_OBJECT16;
     }
     return slotsToThingKind[numSlots];
 }
 
+static inline AllocKind
+GetGCObjectFixedSlotsKind(size_t numFixedSlots)
+{
+    extern AllocKind slotsToThingKind[];
+
+    JS_ASSERT(numFixedSlots < SLOTS_TO_THING_KIND_LIMIT);
+    return slotsToThingKind[numFixedSlots];
+}
+
 static inline bool
 IsBackgroundAllocKind(AllocKind kind)
 {
     JS_ASSERT(kind <= FINALIZE_OBJECT_LAST);
     return kind % 2 == 1;
 }
 
 static inline AllocKind
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -751,38 +751,38 @@ public:
 void
 TypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target, FilterKind filter)
 {
     add(cx, ArenaNew<TypeConstraintFilterPrimitive>(cx->compartment->pool, target, filter));
 }
 
 /* If id is a normal slotful 'own' property of an object, get its shape. */
 static inline const Shape *
-GetSingletonShape(JSObject *obj, jsid id)
-{
-    const Shape *shape = obj->nativeLookup(id);
+GetSingletonShape(JSContext *cx, JSObject *obj, jsid id)
+{
+    const Shape *shape = obj->nativeLookup(cx, id);
     if (shape && shape->hasDefaultGetterOrIsMethod() && shape->slot != SHAPE_INVALID_SLOT)
         return shape;
     return NULL;
 }
 
 void
-ScriptAnalysis::pruneTypeBarriers(uint32 offset)
+ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32 offset)
 {
     TypeBarrier **pbarrier = &getCode(offset).typeBarriers;
     while (*pbarrier) {
         TypeBarrier *barrier = *pbarrier;
         if (barrier->target->hasType(barrier->type)) {
             /* Barrier is now obsolete, it can be removed. */
             *pbarrier = barrier->next;
             continue;
         }
         if (barrier->singleton) {
             JS_ASSERT(barrier->type.isPrimitive(JSVAL_TYPE_UNDEFINED));
-            const Shape *shape = GetSingletonShape(barrier->singleton, barrier->singletonId);
+            const Shape *shape = GetSingletonShape(cx, barrier->singleton, barrier->singletonId);
             if (shape && !barrier->singleton->nativeGetSlot(shape->slot).isUndefined()) {
                 /*
                  * When we analyzed the script the singleton had an 'own'
                  * property which was undefined (probably a 'var' variable
                  * added to a global object), but now it is defined. The only
                  * way it can become undefined again is if an explicit assign
                  * or deletion on the property occurs, which will update the
                  * type set for the property directly and trigger construction
@@ -800,17 +800,17 @@ ScriptAnalysis::pruneTypeBarriers(uint32
  * Cheesy limit on the number of objects we will tolerate in an observed type
  * set before refusing to add new type barriers for objects.
  * :FIXME: this heuristic sucks, and doesn't handle calls.
  */
 static const uint32 BARRIER_OBJECT_LIMIT = 10;
 
 void ScriptAnalysis::breakTypeBarriers(JSContext *cx, uint32 offset, bool all)
 {
-    pruneTypeBarriers(offset);
+    pruneTypeBarriers(cx, offset);
 
     TypeBarrier **pbarrier = &getCode(offset).typeBarriers;
     while (*pbarrier) {
         TypeBarrier *barrier = *pbarrier;
         if (barrier->target->hasType(barrier->type) ) {
             /*
              * Barrier is now obsolete, it can be removed. This is not
              * redundant with the pruneTypeBarriers() call above, as breaking
@@ -999,17 +999,17 @@ PropertyAccess(JSContext *cx, JSScript *
             types->addSubsetBarrier(cx, script, pc, target);
             if (object->singleton && !JSID_IS_VOID(id)) {
                 /*
                  * Add a singleton type barrier on the object if it has an
                  * 'own' property which is currently undefined. We'll be able
                  * to remove the barrier after the property becomes defined,
                  * even if no undefined value is ever observed at pc.
                  */
-                const Shape *shape = GetSingletonShape(object->singleton, id);
+                const Shape *shape = GetSingletonShape(cx, object->singleton, id);
                 if (shape && object->singleton->nativeGetSlot(shape->slot).isUndefined())
                     script->analysis()->addSingletonTypeBarrier(cx, pc, target, object->singleton, id);
             }
         } else {
             types->addSubset(cx, target);
         }
     }
 }
@@ -2723,17 +2723,17 @@ TypeObject::addProperty(JSContext *cx, j
             /* Go through all shapes on the object to get integer-valued properties. */
             const Shape *shape = singleton->lastProperty();
             while (!JSID_IS_EMPTY(shape->propid)) {
                 if (JSID_IS_VOID(MakeTypeId(cx, shape->propid)))
                     UpdatePropertyType(cx, &base->types, singleton, shape, true);
                 shape = shape->previous();
             }
         } else {
-            const Shape *shape = singleton->nativeLookup(id);
+            const Shape *shape = singleton->nativeLookup(cx, id);
             if (shape)
                 UpdatePropertyType(cx, &base->types, singleton, shape, false);
         }
     }
 
     *pprop = base;
 
     InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3750,19 +3750,19 @@ BEGIN_CASE(JSOP_SETMETHOD)
              * can call NATIVE_SET only for a direct or proto-setter hit.
              */
             if (!entry->adding()) {
                 if (entry->vcapTag() == 0 ||
                     ((obj2 = obj->getProto()) && obj2->shape() == entry->vshape()))
                 {
 #ifdef DEBUG
                     if (entry->directHit()) {
-                        JS_ASSERT(obj->nativeContains(*shape));
+                        JS_ASSERT(obj->nativeContains(cx, *shape));
                     } else {
-                        JS_ASSERT(obj2->nativeContains(*shape));
+                        JS_ASSERT(obj2->nativeContains(cx, *shape));
                         JS_ASSERT(entry->vcapTag() == 1);
                         JS_ASSERT(entry->kshape != entry->vshape());
                         JS_ASSERT(!shape->hasSlot());
                     }
 #endif
 
                     PCMETER(cache->pchits++);
                     PCMETER(cache->setpchits++);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3112,17 +3112,17 @@ JS_DEFINE_CALLINFO_3(extern, OBJECT, js_
 
 JSObject * FASTCALL
 js_CreateThisFromTrace(JSContext *cx, JSObject *ctor, uintN protoSlot)
 {
 #ifdef DEBUG
     JS_ASSERT(ctor->isFunction());
     JS_ASSERT(ctor->getFunctionPrivate()->isInterpreted());
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.classPrototypeAtom);
-    const Shape *shape = ctor->nativeLookup(id);
+    const Shape *shape = ctor->nativeLookup(cx, id);
     JS_ASSERT(shape->slot == protoSlot);
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(!shape->isMethod());
 #endif
 
     JSObject *parent = ctor->getParent();
     JSObject *proto;
     const Value &protov = ctor->getSlot(protoSlot);
@@ -4110,17 +4110,17 @@ DefineStandardSlot(JSContext *cx, JSObje
          * reserved slot. Otherwise, go through the normal property path.
          */
         JS_ASSERT(obj->isGlobal());
         JS_ASSERT(obj->isNative());
 
         if (!obj->ensureClassReservedSlots(cx))
             return false;
 
-        const Shape *shape = obj->nativeLookup(id);
+        const Shape *shape = obj->nativeLookup(cx, id);
         if (!shape) {
             uint32 slot = 2 * JSProto_LIMIT + key;
             if (!js_SetReservedSlot(cx, obj, slot, v))
                 return false;
             if (!obj->addProperty(cx, id, PropertyStub, StrictPropertyStub, slot, attrs, 0, 0))
                 return false;
             AddTypePropertyId(cx, obj, id, v);
 
@@ -4960,17 +4960,17 @@ PurgeProtoChain(JSContext *cx, JSObject 
 {
     const Shape *shape;
 
     while (obj) {
         if (!obj->isNative()) {
             obj = obj->getProto();
             continue;
         }
-        shape = obj->nativeLookup(id);
+        shape = obj->nativeLookup(cx, id);
         if (shape) {
             PCMETER(JS_PROPERTY_CACHE(cx).pcpurges++);
             obj->shadowingShapeChange(cx, *shape);
 
             if (!obj->getParent()) {
                 /*
                  * All scope chains end in a global object, so this will change
                  * the global shape. jstracer.cpp assumes that the global shape
@@ -5199,17 +5199,17 @@ DefineNativeProperty(JSContext *cx, JSOb
 
             JSObject *funobj = &value.toObject();
             if (funobj->getFunctionPrivate() == funobj) {
                 flags |= Shape::METHOD;
                 getter = CastAsPropertyOp(funobj);
             }
         }
 
-        if (const Shape *existingShape = obj->nativeLookup(id)) {
+        if (const Shape *existingShape = obj->nativeLookup(cx, id)) {
             if (existingShape->hasSlot())
                 AbortRecordingIfUnexpectedGlobalWrite(cx, obj, existingShape->slot);
 
             if (existingShape->isMethod() &&
                 ObjectValue(existingShape->methodObject()) == valueCopy)
             {
                 /*
                  * Redefining an existing shape-memoized method object without
@@ -5351,17 +5351,17 @@ CallResolveOp(JSContext *cx, JSObject *s
         }
         obj = obj2;
     } else {
         if (!resolve(cx, obj, id))
             return false;
     }
 
     if (!obj->nativeEmpty()) {
-        if (const Shape *shape = obj->nativeLookup(id)) {
+        if (const Shape *shape = obj->nativeLookup(cx, id)) {
             *objp = obj;
             *propp = (JSProperty *) shape;
         }
     }
 
     return true;
 }
 
@@ -5370,17 +5370,17 @@ LookupPropertyWithFlagsInline(JSContext 
                               JSObject **objp, JSProperty **propp)
 {
     /* We should not get string indices which aren't already integers here. */
     JS_ASSERT(id == js_CheckForStringIndex(id));
 
     /* Search scopes starting with obj and following the prototype link. */
     JSObject *start = obj;
     while (true) {
-        const Shape *shape = obj->nativeLookup(id);
+        const Shape *shape = obj->nativeLookup(cx, id);
         if (shape) {
             *objp = obj;
             *propp = (JSProperty *) shape;
             return true;
         }
 
         /* Try obj's class resolve hook if id was not found in obj's scope. */
         if (obj->getClass()->resolve != JS_ResolveStub) {
@@ -5665,17 +5665,17 @@ js_NativeGetInline(JSContext *cx, JSObje
     }
 
     sample = cx->runtime->propertyRemovals;
     if (!shape->get(cx, receiver, obj, pobj, vp))
         return false;
 
     if (pobj->containsSlot(slot) &&
         (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
-         pobj->nativeContains(*shape))) {
+         pobj->nativeContains(cx, *shape))) {
         if (!pobj->methodWriteBarrier(cx, *shape, *vp))
             return false;
         pobj->nativeSetSlot(slot, *vp);
     }
 
     /* Record values produced by shapes without a default getter. */
     AddTypePropertyId(cx, obj, shape->propid, *vp);
 
@@ -5732,17 +5732,17 @@ js_NativeSet(JSContext *cx, JSObject *ob
     if (!shape->set(cx, obj, strict, vp))
         return false;
     
     JS_ASSERT_IF(!obj->inDictionaryMode(), shape->slot == slot);
     slot = shape->slot;
 
     if (obj->containsSlot(slot) &&
         (JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
-         obj->nativeContains(*shape))) {
+         obj->nativeContains(cx, *shape))) {
         if (!added) {
             AbortRecordingIfUnexpectedGlobalWrite(cx, obj, slot);
             if (!obj->methodWriteBarrier(cx, *shape, *vp))
                 return false;
         }
         obj->setSlot(slot, *vp);
     }
 
@@ -6343,19 +6343,19 @@ js_DeleteProperty(JSContext *cx, JSObjec
     }
 
     return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
 }
 
 namespace js {
 
 bool
-HasDataProperty(JSObject *obj, jsid methodid, Value *vp)
-{
-    if (const Shape *shape = obj->nativeLookup(methodid)) {
+HasDataProperty(JSContext *cx, JSObject *obj, jsid methodid, Value *vp)
+{
+    if (const Shape *shape = obj->nativeLookup(cx, methodid)) {
         if (shape->hasDefaultGetterOrIsMethod() && obj->containsSlot(shape->slot)) {
             *vp = obj->nativeGetSlot(shape->slot);
             return true;
         }
     }
 
     return false;
 }
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -420,21 +420,21 @@ struct JSObject : js::gc::Cell {
 
 #ifdef DEBUG
     void checkShapeConsistency();
 #endif
 
   public:
     inline const js::Shape *lastProperty() const;
 
-    inline js::Shape **nativeSearch(jsid id, bool adding = false);
-    inline const js::Shape *nativeLookup(jsid id);
+    inline js::Shape **nativeSearch(JSContext *cx, jsid id, bool adding = false);
+    inline const js::Shape *nativeLookup(JSContext *cx, jsid id);
 
-    inline bool nativeContains(jsid id);
-    inline bool nativeContains(const js::Shape &shape);
+    inline bool nativeContains(JSContext *cx, jsid id);
+    inline bool nativeContains(JSContext *cx, const js::Shape &shape);
 
     enum {
         DELEGATE                  =       0x01,
         SYSTEM                    =       0x02,
         NOT_EXTENSIBLE            =       0x04,
         BRANDED                   =       0x08,
         GENERIC                   =       0x10,
         METHOD_BARRIER            =       0x20,
@@ -1979,17 +1979,17 @@ js_SetNativeAttributes(JSContext *cx, JS
 
 namespace js {
 
 /*
  * If obj has an already-resolved data property for methodid, return true and
  * store the property value in *vp.
  */
 extern bool
-HasDataProperty(JSObject *obj, jsid methodid, js::Value *vp);
+HasDataProperty(JSContext *cx, JSObject *obj, jsid methodid, js::Value *vp);
 
 extern JSBool
 CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
             js::Value *vp, uintN *attrsp);
 
 } /* namespace js */
 
 extern bool
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -138,17 +138,17 @@ JSObject::getProperty(JSContext *cx, JSO
 {
     js::PropertyIdOp op = getOps()->getProperty;
     if (op) {
         if (!op(cx, this, receiver, id, vp))
             return false;
     } else {
         if (!js_GetProperty(cx, this, receiver, id, vp))
             return false;
-        JS_ASSERT_IF(!hasSingletonType() && nativeContains(js_CheckForStringIndex(id)),
+        JS_ASSERT_IF(!hasSingletonType() && nativeContains(cx, js_CheckForStringIndex(id)),
                      js::types::TypeHasProperty(cx, type(), id, *vp));
     }
     return true;
 }
 
 inline JSBool
 JSObject::getProperty(JSContext *cx, jsid id, js::Value *vp)
 {
@@ -248,17 +248,17 @@ JSObject::setBlockOwnShape(JSContext *cx
  * Property read barrier for deferred cloning of compiler-created function
  * objects optimized as typically non-escaping, ad-hoc methods in obj.
  */
 inline const js::Shape *
 JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp)
 {
     JS_ASSERT(canHaveMethodBarrier());
     JS_ASSERT(hasMethodBarrier());
-    JS_ASSERT(nativeContains(shape));
+    JS_ASSERT(nativeContains(cx, shape));
     JS_ASSERT(shape.isMethod());
     JS_ASSERT(shape.methodObject() == vp->toObject());
     JS_ASSERT(shape.writable());
     JS_ASSERT(shape.slot != SHAPE_INVALID_SLOT);
     JS_ASSERT(shape.hasDefaultSetter());
     JS_ASSERT(!isGlobal());  /* i.e. we are not changing the global shape */
 
     JSObject *funobj = &vp->toObject();
@@ -1002,38 +1002,38 @@ JSObject::clearOwnShape()
 inline void
 JSObject::setOwnShape(uint32 s)
 {
     flags |= OWN_SHAPE;
     objShape = s;
 }
 
 inline js::Shape **
-JSObject::nativeSearch(jsid id, bool adding)
+JSObject::nativeSearch(JSContext *cx, jsid id, bool adding)
 {
-    return js::Shape::search(compartment()->rt, &lastProp, id, adding);
+    return js::Shape::search(cx, &lastProp, id, adding);
 }
 
 inline const js::Shape *
-JSObject::nativeLookup(jsid id)
+JSObject::nativeLookup(JSContext *cx, jsid id)
 {
     JS_ASSERT(isNative());
-    return SHAPE_FETCH(nativeSearch(id));
+    return SHAPE_FETCH(nativeSearch(cx, id));
 }
 
 inline bool
-JSObject::nativeContains(jsid id)
+JSObject::nativeContains(JSContext *cx, jsid id)
 {
-    return nativeLookup(id) != NULL;
+    return nativeLookup(cx, id) != NULL;
 }
 
 inline bool
-JSObject::nativeContains(const js::Shape &shape)
+JSObject::nativeContains(JSContext *cx, const js::Shape &shape)
 {
-    return nativeLookup(shape.propid) == &shape;
+    return nativeLookup(cx, shape.propid) == &shape;
 }
 
 inline const js::Shape *
 JSObject::lastProperty() const
 {
     JS_ASSERT(isNative());
     JS_ASSERT(!JSID_IS_VOID(lastProp->propid));
     return lastProp;
@@ -1562,17 +1562,22 @@ NewObjectWithClassProto(JSContext *cx, C
 
 /* Make an object with pregenerated shape from a NEWOBJECT bytecode. */
 static inline JSObject *
 CopyInitializerObject(JSContext *cx, JSObject *baseobj, types::TypeObject *type)
 {
     JS_ASSERT(baseobj->getClass() == &ObjectClass);
     JS_ASSERT(!baseobj->inDictionaryMode());
 
-    JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, baseobj->getAllocKind());
+    gc::AllocKind kind = gc::GetGCObjectFixedSlotsKind(baseobj->numFixedSlots());
+#ifdef JS_THREADSAFE
+    kind = gc::GetBackgroundAllocKind(kind);
+#endif
+    JS_ASSERT(kind == baseobj->getAllocKind());
+    JSObject *obj = NewBuiltinClassInstance(cx, &ObjectClass, kind);
 
     if (!obj || !obj->ensureSlots(cx, baseobj->numSlots()))
         return NULL;
 
     obj->setType(type);
     obj->flags = baseobj->flags;
     obj->lastProp = baseobj->lastProp;
     obj->objShape = baseobj->objShape;
@@ -1584,17 +1589,17 @@ inline bool
 DefineConstructorAndPrototype(JSContext *cx, GlobalObject *global,
                               JSProtoKey key, JSObject *ctor, JSObject *proto)
 {
     JS_ASSERT(!global->nativeEmpty()); /* reserved slots already allocated */
     JS_ASSERT(ctor);
     JS_ASSERT(proto);
 
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.classAtoms[key]);
-    JS_ASSERT(!global->nativeLookup(id));
+    JS_ASSERT(!global->nativeLookup(cx, id));
 
     /* Set these first in case AddTypePropertyId looks for this class. */
     global->setSlot(key, ObjectValue(*ctor));
     global->setSlot(key + JSProto_LIMIT, ObjectValue(*proto));
 
     types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
     if (!global->addDataProperty(cx, id, key + JSProto_LIMIT * 2, 0)) {
         global->setSlot(key, UndefinedValue());
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -65,17 +65,17 @@ PropertyCache::fill(JSContext *cx, JSObj
         PCMETER(disfills++);
         return JS_NO_PROP_CACHE_FILL;
     }
 
     /*
      * Check for fill from js_SetPropertyHelper where the setter removed shape
      * from pobj (via unwatch or delete, e.g.).
      */
-    if (!pobj->nativeContains(*shape)) {
+    if (!pobj->nativeContains(cx, *shape)) {
         PCMETER(oddfills++);
         return JS_NO_PROP_CACHE_FILL;
     }
 
     /*
      * Dictionary-mode objects have unique shapes, so there is no way to cache
      * a prediction of the next shape when adding.
      */
@@ -394,17 +394,17 @@ PropertyCache::fullTest(JSContext *cx, j
     }
 
     if (matchShape(cx, pobj, vcap >> PCVCAP_TAGBITS)) {
 #ifdef DEBUG
         JSAtom *atom = GetAtomFromBytecode(cx, pc, op, cs);
         jsid id = ATOM_TO_JSID(atom);
 
         id = js_CheckForStringIndex(id);
-        JS_ASSERT(pobj->nativeContains(id));
+        JS_ASSERT(pobj->nativeContains(cx, id));
 #endif
         *pobjp = pobj;
         return NULL;
     }
 
     PCMETER(vcapmisses++);
     return GetAtomFromBytecode(cx, pc, op, cs);
 }
--- a/js/src/jsregexpinlines.h
+++ b/js/src/jsregexpinlines.h
@@ -778,27 +778,27 @@ JSObject::initRegExp(JSContext *cx, js::
             *shapep = assignInitialRegExpShape(cx);
             if (!*shapep)
                 return false;
         }
         setLastProperty(*shapep);
         JS_ASSERT(!nativeEmpty());
     }
 
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.lastIndexAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.lastIndexAtom))->slot ==
               JSObject::JSSLOT_REGEXP_LAST_INDEX);
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.sourceAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.sourceAtom))->slot ==
               JSObject::JSSLOT_REGEXP_SOURCE);
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.globalAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.globalAtom))->slot ==
               JSObject::JSSLOT_REGEXP_GLOBAL);
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.ignoreCaseAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.ignoreCaseAtom))->slot ==
               JSObject::JSSLOT_REGEXP_IGNORE_CASE);
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.multilineAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.multilineAtom))->slot ==
               JSObject::JSSLOT_REGEXP_MULTILINE);
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.stickyAtom))->slot ==
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.stickyAtom))->slot ==
               JSObject::JSSLOT_REGEXP_STICKY);
 
     setPrivate(re);
     zeroRegExpLastIndex();
     setRegExpSource(re->getSource());
     setRegExpGlobal(re->global());
     setRegExpIgnoreCase(re->ignoreCase());
     setRegExpMultiline(re->multiline());
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -165,19 +165,20 @@ PropertyTable::init(JSRuntime *rt, Shape
          */
         if (!SHAPE_FETCH(spp))
             SHAPE_STORE_PRESERVING_COLLISION(spp, &shape);
     }
     return true;
 }
 
 bool
-Shape::hashify(JSRuntime *rt)
+Shape::hashify(JSContext *cx)
 {
     JS_ASSERT(!hasTable());
+    JSRuntime *rt = cx->runtime;
     PropertyTable *table = rt->new_<PropertyTable>(entryCount());
     if (!table)
         return false;
 
     if (!table->init(rt, this)) {
         rt->free_(table);
         return false;
     }
@@ -361,17 +362,17 @@ Shape::getChild(JSContext *cx, const js:
                     ++table->entryCount;
                 SHAPE_STORE_PRESERVING_COLLISION(spp, newShape);
 
                 /* Hand the table off from oldShape to newShape. */
                 oldShape->setTable(NULL);
                 newShape->setTable(table);
             } else {
                 if (!newShape->hasTable())
-                    newShape->hashify(cx->runtime);
+                    newShape->hashify(cx);
             }
             return newShape;
         }
 
         return NULL;
     }
 
     if ((*listp)->entryCount() >= PropertyTree::MAX_HEIGHT) {
@@ -488,17 +489,17 @@ Shape::newDictionaryList(JSContext *cx, 
         childp = &dprop->parent;
         shape = shape->parent;
     }
 
     *listp = root;
     root->listp = listp;
 
     JS_ASSERT(root->inDictionary());
-    root->hashify(cx->runtime);
+    root->hashify(cx);
     return root;
 }
 
 bool
 JSObject::toDictionaryMode(JSContext *cx)
 {
     JS_ASSERT(!inDictionaryMode());
 
@@ -630,17 +631,17 @@ JSObject::addProperty(JSContext *cx, jsi
     if (!isExtensible()) {
         reportNotExtensible(cx);
         return NULL;
     }
 
     NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter);
 
     /* Search for id with adding = true in order to claim its entry. */
-    Shape **spp = nativeSearch(id, true);
+    Shape **spp = nativeSearch(cx, id, true);
     JS_ASSERT(!SHAPE_FETCH(spp));
     return addPropertyInternal(cx, id, getter, setter, slot, attrs, flags, shortid, spp);
 }
 
 const Shape *
 JSObject::addPropertyInternal(JSContext *cx, jsid id,
                               PropertyOp getter, StrictPropertyOp setter,
                               uint32 slot, uintN attrs,
@@ -649,17 +650,17 @@ JSObject::addPropertyInternal(JSContext 
 {
     JS_ASSERT_IF(inDictionaryMode(), !lastProp->frozen());
 
     PropertyTable *table = NULL;
     if (!inDictionaryMode()) {
         if (lastProp->entryCount() >= PropertyTree::MAX_HEIGHT) {
             if (!toDictionaryMode(cx))
                 return NULL;
-            spp = nativeSearch(id, true);
+            spp = nativeSearch(cx, id, true);
             table = lastProp->getTable();
         }
     } else if (lastProp->hasTable()) {
         table = lastProp->getTable();
         if (table->needsToGrow()) {
             if (!table->grow(cx))
                 return NULL;
 
@@ -737,17 +738,17 @@ JSObject::putProperty(JSContext *cx, jsi
         if (!Shape::newDictionaryList(cx, &lastProp))
             return NULL;
         JS_ASSERT(!lastProp->frozen());
     }
 
     NormalizeGetterAndSetter(cx, this, id, attrs, flags, getter, setter);
 
     /* Search for id in order to claim its entry if table has been allocated. */
-    Shape **spp = nativeSearch(id, true);
+    Shape **spp = nativeSearch(cx, id, true);
     Shape *shape = SHAPE_FETCH(spp);
     if (!shape) {
         /*
          * You can't add properties to a non-extensible object, but you can change
          * attributes of properties in such objects.
          */
         if (!isExtensible()) {
             reportNotExtensible(cx);
@@ -783,17 +784,17 @@ JSObject::putProperty(JSContext *cx, jsi
     /*
      * Overwriting a non-last property requires switching to dictionary mode.
      * The shape tree is shared immutable, and we can't removeProperty and then
      * addPropertyInternal because a failure under add would lose data.
      */
     if (shape != lastProp && !inDictionaryMode()) {
         if (!toDictionaryMode(cx))
             return NULL;
-        spp = nativeSearch(shape->propid);
+        spp = nativeSearch(cx, shape->propid);
         shape = SHAPE_FETCH(spp);
     }
 
     /*
      * Now that we have passed the lastProp->frozen() check at the top of this
      * method, and the non-last-property conditioning just above, we are ready
      * to overwrite.
      *
@@ -888,17 +889,17 @@ JSObject::putProperty(JSContext *cx, jsi
 }
 
 const Shape *
 JSObject::changeProperty(JSContext *cx, const Shape *shape, uintN attrs, uintN mask,
                          PropertyOp getter, StrictPropertyOp setter)
 {
     JS_ASSERT_IF(inDictionaryMode(), !lastProp->frozen());
     JS_ASSERT(!JSID_IS_VOID(shape->propid));
-    JS_ASSERT(nativeContains(*shape));
+    JS_ASSERT(nativeContains(cx, *shape));
 
     attrs |= shape->attrs & mask;
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
     JS_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
               !(attrs & JSPROP_SHARED));
 
     /* Don't allow method properties to be changed to have a getter. */
@@ -959,17 +960,17 @@ JSObject::changeProperty(JSContext *cx, 
         Shape child(shape->propid, getter, setter, shape->slot, attrs, shape->flags,
                     shape->shortid);
 
         newShape = getChildProperty(cx, shape->parent, child);
 #ifdef DEBUG
         if (newShape) {
             JS_ASSERT(newShape == lastProp);
             if (newShape->hasTable()) {
-                Shape **spp = nativeSearch(shape->propid);
+                Shape **spp = nativeSearch(cx, shape->propid);
                 JS_ASSERT(SHAPE_FETCH(spp) == newShape);
             }
         }
 #endif
     } else {
         /*
          * Let JSObject::putProperty handle this |overwriting| case, including
          * the conservation of shape->slot (if it's valid). We must not call
@@ -984,34 +985,34 @@ JSObject::changeProperty(JSContext *cx, 
 
     CHECK_SHAPE_CONSISTENCY(this);
     return newShape;
 }
 
 bool
 JSObject::removeProperty(JSContext *cx, jsid id)
 {
-    Shape **spp = nativeSearch(id);
+    Shape **spp = nativeSearch(cx, id);
     Shape *shape = SHAPE_FETCH(spp);
     if (!shape)
         return true;
 
     /* First, if shape is unshared and not has a slot, free its slot number. */
     bool addedToFreelist = false;
     bool hadSlot = shape->hasSlot();
     if (hadSlot) {
         addedToFreelist = freeSlot(cx, shape->slot);
         JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
     }
 
     /* If shape is not the last property added, switch to dictionary mode. */
     if (shape != lastProp && !inDictionaryMode()) {
         if (!toDictionaryMode(cx))
             return false;
-        spp = nativeSearch(shape->propid);
+        spp = nativeSearch(cx, shape->propid);
         shape = SHAPE_FETCH(spp);
     }
 
     /*
      * A dictionary-mode object owns mutable, unique shapes on a non-circular
      * doubly linked list, optionally hashed by lastProp->table. So we can edit
      * the list and hash in place.
      */
@@ -1031,17 +1032,17 @@ JSObject::removeProperty(JSContext *cx, 
 #ifdef DEBUG
                 /*
                  * Check the consistency of the table but limit the number of
                  * checks not to alter significantly the complexity of the
                  * delete in debug builds, see bug 534493.
                  */
                 const Shape *aprop = lastProp;
                 for (int n = 50; --n >= 0 && aprop->parent; aprop = aprop->parent)
-                    JS_ASSERT_IF(aprop != shape, nativeContains(*aprop));
+                    JS_ASSERT_IF(aprop != shape, nativeContains(cx, *aprop));
 #endif
             }
         }
 
         /*
          * Remove shape from its non-circular doubly linked list, setting this
          * object's OWN_SHAPE flag so the updateShape(cx) further below will
          * generate a fresh shape id for this object, distinct from the id of
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -362,27 +362,27 @@ struct Shape : public js::gc::Cell
         mutable js::KidsPointer kids;   /* null, single child, or a tagged ptr
                                            to many-kids data structure */
         mutable js::Shape **listp;      /* dictionary list starting at lastProp
                                            has a double-indirect back pointer,
                                            either to shape->parent if not last,
                                            else to obj->lastProp */
     };
 
-    static inline js::Shape **search(JSRuntime *rt, js::Shape **startp, jsid id,
+    static inline js::Shape **search(JSContext *cx, js::Shape **startp, jsid id,
                                      bool adding = false);
     static js::Shape *newDictionaryShape(JSContext *cx, const js::Shape &child, js::Shape **listp);
     static js::Shape *newDictionaryList(JSContext *cx, js::Shape **listp);
 
     inline void removeFromDictionary(JSObject *obj) const;
     inline void insertIntoDictionary(js::Shape **dictp);
 
     js::Shape *getChild(JSContext *cx, const js::Shape &child, js::Shape **listp);
 
-    bool hashify(JSRuntime *rt);
+    bool hashify(JSContext *cx);
 
     void setTable(js::PropertyTable *t) const {
         JS_ASSERT_IF(t && t->freelist != SHAPE_INVALID_SLOT, t->freelist < slotSpan);
         table = t;
     }
 
     /*
      * Setter for parent. The challenge is to maintain JSObjectMap::slotSpan in
@@ -699,24 +699,24 @@ extern uint32
 js_GenerateShape(JSRuntime *rt);
 
 extern uint32
 js_GenerateShape(JSContext *cx);
 
 namespace js {
 
 JS_ALWAYS_INLINE js::Shape **
-Shape::search(JSRuntime *rt, js::Shape **startp, jsid id, bool adding)
+Shape::search(JSContext *cx, js::Shape **startp, jsid id, bool adding)
 {
     js::Shape *start = *startp;
     if (start->hasTable())
         return start->getTable()->search(id, adding);
 
     if (start->numLinearSearches == PropertyTable::MAX_LINEAR_SEARCHES) {
-        if (start->hashify(rt))
+        if (start->hashify(cx))
             return start->getTable()->search(id, adding);
         /* OOM!  Don't increment numLinearSearches, to keep hasTable() false. */
         JS_ASSERT(!start->hasTable());
     } else {
         JS_ASSERT(start->numLinearSearches < PropertyTable::MAX_LINEAR_SEARCHES);
         start->numLinearSearches++;
     }
 
--- a/js/src/jsscopeinlines.h
+++ b/js/src/jsscopeinlines.h
@@ -159,17 +159,17 @@ StringObject::init(JSContext *cx, JSStri
         setLastProperty(*shapep);
     } else {
         *shapep = assignInitialShape(cx);
         if (!*shapep)
             return false;
     }
     JS_ASSERT(*shapep == lastProperty());
     JS_ASSERT(!nativeEmpty());
-    JS_ASSERT(nativeLookup(ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))->slot == LENGTH_SLOT);
+    JS_ASSERT(nativeLookup(cx, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom))->slot == LENGTH_SLOT);
 
     setStringThis(str);
     return true;
 }
 
 inline
 Shape::Shape(jsid propid, js::PropertyOp getter, js::StrictPropertyOp setter, uint32 slot,
              uintN attrs, uintN flags, intN shortid, uint32 shapeid, uint32 slotSpan)
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -83,17 +83,17 @@ namespace js {
 
 BindingKind
 Bindings::lookup(JSContext *cx, JSAtom *name, uintN *indexp) const
 {
     if (!lastBinding)
         return NONE;
 
     Shape *shape =
-        SHAPE_FETCH(Shape::search(cx->runtime, const_cast<Shape **>(&lastBinding),
+        SHAPE_FETCH(Shape::search(cx, const_cast<Shape **>(&lastBinding),
                     ATOM_TO_JSID(name)));
     if (!shape)
         return NONE;
 
     if (indexp)
         *indexp = shape->shortid;
 
     if (shape->getter() == GetCallArg)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11551,17 +11551,17 @@ TraceRecorder::callNative(uintN argc, JS
                  * that RegExp.prototype.test() hasn't been changed;  we check this.
                  */
                 if (!CallResultEscapes(cx->regs().pc)) {
                     JSObject* proto;
                     /* Get RegExp.prototype.test and check it hasn't been changed. */
                     if (js_GetClassPrototype(cx, NULL, JSProto_RegExp, &proto)) {
                         Value pval;
                         jsid id = ATOM_TO_JSID(cx->runtime->atomState.testAtom);
-                        if (HasDataProperty(proto, id, &pval) &&
+                        if (HasDataProperty(cx, proto, id, &pval) &&
                             IsNativeFunction(pval, js_regexp_test))
                         {
                             vp[0] = pval;
                             funobj = &pval.toObject();
                             fun = funobj->getFunctionPrivate();
                             native = js_regexp_test;
                         }
                     }
@@ -12060,17 +12060,17 @@ TraceRecorder::record_JSOP_GETPROP()
 static bool
 SafeLookup(JSContext *cx, JSObject* obj, jsid id, JSObject** pobjp, const Shape** shapep)
 {
     do {
         // Avoid non-native lookupProperty hooks.
         if (obj->getOps()->lookupProperty)
             return false;
 
-        if (const Shape *shape = obj->nativeLookup(id)) {
+        if (const Shape *shape = obj->nativeLookup(cx, id)) {
             *pobjp = obj;
             *shapep = shape;
             return true;
         }
 
         // Avoid resolve hooks.
         if (obj->getClass()->resolve != JS_ResolveStub)
             return false;
@@ -12131,17 +12131,17 @@ JS_DEFINE_CALLINFO_4(static, BOOL_FAIL, 
 
 /* Emit a specialized, inlined copy of js_NativeSet. */
 JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::nativeSet(JSObject* obj, LIns* obj_ins, const Shape* shape,
                          const Value &v, LIns* v_ins)
 {
     uint32 slot = shape->slot;
     JS_ASSERT((slot != SHAPE_INVALID_SLOT) == shape->hasSlot());
-    JS_ASSERT_IF(shape->hasSlot(), obj->nativeContains(*shape));
+    JS_ASSERT_IF(shape->hasSlot(), obj->nativeContains(cx, *shape));
 
     /*
      * We do not trace assignment to properties that have both a non-default
      * setter and a slot, for several reasons.
      *
      * First, that would require sampling rt->propertyRemovals before and after
      * (see js_NativeSet), and even more code to handle the case where the two
      * samples differ. A mere guard is not enough, because you can't just bail
@@ -12176,17 +12176,17 @@ TraceRecorder::nativeSet(JSObject* obj, 
     }
 
     if (slot != SHAPE_INVALID_SLOT) {
         if (obj->brandedOrHasMethodBarrier()) {
             if (obj == globalObj) {
                 // Because the trace is type-specialized to the global object's
                 // slots, no run-time check is needed. Avoid recording a global
                 // shape change, though.
-                JS_ASSERT(obj->nativeContains(*shape));
+                JS_ASSERT(obj->nativeContains(cx, *shape));
                 if (IsFunctionObject(obj->getSlot(slot)))
                     RETURN_STOP("can't trace set of function-valued global property");
             } else {
                 // Setting a function-valued property might need to rebrand the
                 // object. Call the method write barrier. Note that even if the
                 // property is not function-valued now, it might be on trace.
                 enterDeepBailCall();
                 LIns* args[] = {box_value_into_alloc(v, v_ins), w.immi(slot), obj_ins, cx_ins};
@@ -12516,17 +12516,17 @@ TraceRecorder::recordInitPropertyOp(jsby
 
     JSAtom* atom = atoms[GET_INDEX(cx->regs().pc)];
     jsid id = js_CheckForStringIndex(ATOM_TO_JSID(atom));
 
     // If obj already has this property (because JSOP_NEWOBJECT already set its
     // shape or because the id appears more than once in the initializer), just
     // set it. The existing property can't be an accessor property: we wouldn't
     // get here, as JSOP_SETTER can't be recorded.
-    if (const Shape* shape = obj->nativeLookup(id)) {
+    if (const Shape* shape = obj->nativeLookup(cx, id)) {
         // Don't assign a bare (non-cloned) function to an ordinary or method
         // property. The opposite case, assigning some other value to a method,
         // is OK. nativeSet emits code that trips the write barrier.
         if (op == JSOP_INITMETHOD)
             RETURN_STOP("initmethod: property exists");
         JS_ASSERT(shape->isDataDescriptor());
         JS_ASSERT(shape->hasSlot());
         JS_ASSERT(shape->hasDefaultSetter());
@@ -14174,17 +14174,17 @@ TraceRecorder::propTail(JSObject* obj, L
     JS_ASSERT(!(cs.format & JOF_SET));
 
     const Shape* shape;
     uint32 slot;
     bool isMethod;
 
     if (pcval.isShape()) {
         shape = pcval.toShape();
-        JS_ASSERT(obj2->nativeContains(*shape));
+        JS_ASSERT(obj2->nativeContains(cx, *shape));
 
         if (setflags && !shape->hasDefaultSetter())
             RETURN_STOP("non-stub setter");
         if (setflags && !shape->writable())
             RETURN_STOP("writing to a readonly property");
         if (!shape->hasDefaultGetterOrIsMethod()) {
             if (slotp)
                 RETURN_STOP("can't trace non-stub getter for this opcode");
--- a/js/src/jswatchpoint.cpp
+++ b/js/src/jswatchpoint.cpp
@@ -139,30 +139,30 @@ WatchpointMap::triggerWatchpoint(JSConte
     /* Copy the entry, since GC would invalidate p. */
     JSWatchPointHandler handler = p->value.handler;
     JSObject *closure = p->value.closure;
 
     /* Determine the property's old value. */
     Value old;
     old.setUndefined();
     if (obj->isNative()) {
-        if (const Shape *shape = obj->nativeLookup(id)) {
+        if (const Shape *shape = obj->nativeLookup(cx, id)) {
             uint32 slot = shape->slot;
             if (obj->containsSlot(slot)) {
                 if (shape->isMethod()) {
                     /*
                      * The existing watched property is a method. Trip
                      * the method read barrier in order to avoid
                      * passing an uncloned function object to the
                      * handler.
                      */
                     Value method = ObjectValue(shape->methodObject());
                     if (!obj->methodReadBarrier(cx, *shape, &method))
                         return false;
-                    shape = obj->nativeLookup(id);
+                    shape = obj->nativeLookup(cx, id);
                     JS_ASSERT(shape->isDataDescriptor());
                     JS_ASSERT(!shape->isMethod());
                     old = method;
                 } else {
                     old = obj->nativeGetSlot(slot);
                 }
             }
         }
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -254,17 +254,17 @@ mjit::Compiler::scanInlineCalls(uint32 i
         if (!code)
             continue;
 
         /* :XXX: Not yet inlining 'new' calls. */
         if (JSOp(*pc) != JSOP_CALL)
             continue;
 
         /* Not inlining at monitored call sites or those with type barriers. */
-        if (code->monitoredTypes || code->monitoredTypesReturn || analysis->typeBarriers(pc) != NULL)
+        if (code->monitoredTypes || code->monitoredTypesReturn || analysis->typeBarriers(cx, pc) != NULL)
             continue;
 
         uint32 argc = GET_ARGC(pc);
         types::TypeSet *calleeTypes = analysis->poppedTypes(pc, argc + 1);
 
         if (calleeTypes->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT)
             continue;
 
@@ -5922,17 +5922,17 @@ mjit::Compiler::jsop_getgname(uint32 ind
         if (!propertyTypes)
             return;
 
         /*
          * If we are accessing a defined global which is a normal data property
          * then bake its address into the jitcode and guard against future
          * reallocation of the global object's slots.
          */
-        const js::Shape *shape = globalObj->nativeLookup(ATOM_TO_JSID(atom));
+        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(atom));
         if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
             Value *value = &globalObj->getSlotRef(shape->slot);
             if (!value->isUndefined() &&
                 !propertyTypes->isOwnProperty(cx, globalObj->getType(cx), true)) {
                 watchGlobalReallocation();
                 RegisterID reg = frame.allocReg();
                 masm.move(ImmPtr(value), reg);
 
@@ -6145,17 +6145,17 @@ mjit::Compiler::jsop_setgname(JSAtom *at
          * Note: object branding is disabled when inference is enabled. With
          * branding there is no way to ensure that a non-function property
          * can't get a function later and cause the global object to become
          * branded, requiring a shape change if it changes again.
          */
         types::TypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
         if (!types)
             return;
-        const js::Shape *shape = globalObj->nativeLookup(ATOM_TO_JSID(atom));
+        const js::Shape *shape = globalObj->nativeLookup(cx, ATOM_TO_JSID(atom));
         if (shape && !shape->isMethod() && shape->hasDefaultSetter() &&
             shape->writable() && shape->hasSlot() &&
             !types->isOwnProperty(cx, globalObj->getType(cx), true)) {
             watchGlobalReallocation();
             Value *value = &globalObj->getSlotRef(shape->slot);
             RegisterID reg = frame.allocReg();
             masm.move(ImmPtr(value), reg);
             frame.storeTo(frame.peek(-1), Address(reg), popGuaranteed);
@@ -7236,17 +7236,17 @@ mjit::Compiler::hasTypeBarriers(jsbyteco
     if (!cx->typeInferenceEnabled())
         return false;
 
 #if 0
     /* Stress test. */
     return js_CodeSpec[*pc].format & JOF_TYPESET;
 #endif
 
-    return analysis->typeBarriers(pc) != NULL;
+    return analysis->typeBarriers(cx, pc) != NULL;
 }
 
 void
 mjit::Compiler::pushSyncedEntry(uint32 pushed)
 {
     frame.pushSynced(knownPushedType(pushed));
 }
 
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -82,17 +82,17 @@ PatchGetFallback(VMFrame &f, ic::GetGlob
 
 void JS_FASTCALL
 ic::GetGlobalName(VMFrame &f, ic::GetGlobalNameIC *ic)
 {
     JSObject *obj = f.fp()->scopeChain().getGlobal();
     JSAtom *atom = f.script()->getAtom(GET_INDEX(f.pc()));
     jsid id = ATOM_TO_JSID(atom);
 
-    const Shape *shape = obj->nativeLookup(id);
+    const Shape *shape = obj->nativeLookup(f.cx, id);
     if (!shape ||
         !shape->hasDefaultGetterOrIsMethod() ||
         !shape->hasSlot())
     {
         if (shape)
             PatchGetFallback(f, ic);
         stubs::GetGlobalName(f);
         return;
@@ -317,17 +317,17 @@ UpdateSetGlobalName(VMFrame &f, ic::SetG
 }
 
 void JS_FASTCALL
 ic::SetGlobalName(VMFrame &f, ic::SetGlobalNameIC *ic)
 {
     JSObject *obj = f.fp()->scopeChain().getGlobal();
     JSScript *script = f.script();
     JSAtom *atom = script->getAtom(GET_INDEX(f.pc()));
-    const Shape *shape = obj->nativeLookup(ATOM_TO_JSID(atom));
+    const Shape *shape = obj->nativeLookup(f.cx, ATOM_TO_JSID(atom));
 
     LookupStatus status = UpdateSetGlobalName(f, ic, obj, shape);
     if (status == Lookup_Error)
         THROW();
 
     if (ic->usePropertyCache)
         STRICT_VARIANT(stubs::SetGlobalName)(f, atom);
     else
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -177,19 +177,19 @@ stubs::SetName(VMFrame &f, JSAtom *origA
              * can call NATIVE_SET only for a direct or proto-setter hit.
              */
             if (!entry->adding()) {
                 if (entry->vcapTag() == 0 ||
                     ((obj2 = obj->getProto()) && obj2->shape() == entry->vshape()))
                 {
 #ifdef DEBUG
                     if (entry->directHit()) {
-                        JS_ASSERT(obj->nativeContains(*shape));
+                        JS_ASSERT(obj->nativeContains(cx, *shape));
                     } else {
-                        JS_ASSERT(obj2->nativeContains(*shape));
+                        JS_ASSERT(obj2->nativeContains(cx, *shape));
                         JS_ASSERT(entry->vcapTag() == 1);
                         JS_ASSERT(entry->kshape != entry->vshape());
                         JS_ASSERT(!shape->hasSlot());
                     }
 #endif
 
                     PCMETER(cache->pchits++);
                     PCMETER(cache->setpchits++);