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 id21150
push usereakhgari@mozilla.com
push dateMon, 12 Sep 2011 13:46:25 +0000
treeherdermozilla-central@b991feb93d32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett1024
bugs686017
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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++);