Bug 625199 - remove unnecessary uses of 'parent' that can now use cx->global (r=mrbkap)
authorLuke Wagner <luke@mozilla.com>
Fri, 17 Aug 2012 11:21:57 -0700
changeset 109255 ea32388d45a805c72f179375dc2b763c75454f6d
parent 109254 5e5711c63caa76923b613046d4224e3167399aff
child 109256 986c07b3f3e68af098d7e85fd507a7d4139b4eb3
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs625199
milestone17.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 625199 - remove unnecessary uses of 'parent' that can now use cx->global (r=mrbkap)
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jsexn.cpp
js/src/jsinfer.cpp
js/src/jsinferinlines.h
js/src/jsiter.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/jsprobes.cpp
js/src/jsreflect.cpp
js/src/jstypedarray.cpp
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/shell/js.cpp
js/src/vm/GlobalObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/RegExpStatics-inl.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1783,46 +1783,37 @@ JS_RefreshCrossCompartmentWrappers(JSCon
 {
     RootedObject obj(cx, objArg);
     return RemapAllWrappersForObject(cx, obj, obj);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalObject(JSContext *cx)
 {
-    return cx->globalObject;
+    return cx->maybeDefaultCompartmentObject();
 }
 
 JS_PUBLIC_API(void)
 JS_SetGlobalObject(JSContext *cx, JSRawObject obj)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    cx->globalObject = obj;
-    if (!cx->hasfp())
-        cx->resetCompartment();
+    cx->setDefaultCompartmentObject(obj);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_InitStandardClasses(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
-    /*
-     * JS_SetGlobalObject might or might not change cx's compartment, so call
-     * it before assertSameCompartment. (The API contract is that *after* this,
-     * cx and obj must be in the same compartment.)
-     */
-    if (!cx->globalObject)
-        JS_SetGlobalObject(cx, obj);
-
+    cx->setDefaultCompartmentObjectIfUnset(obj);
     assertSameCompartment(cx, obj);
 
     Rooted<GlobalObject*> global(cx, &obj->global());
     return GlobalObject::initStandardClasses(cx, global);
 }
 
 #define CLASP(name)                 (&name##Class)
 #define TYPED_ARRAY_CLASP(type)     (&TypedArray::classes[TypedArray::type])
@@ -2249,21 +2240,19 @@ JS_GetClassObject(JSContext *cx, JSRawOb
     return true;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JSObject **objp_)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    RootedObject global(cx, cx->compartment->maybeGlobal());
-    if (!global)
-        return false;
+
     RootedObject objp(cx);
-    bool result = js_GetClassPrototype(cx, global, key, &objp);
+    bool result = js_GetClassPrototype(cx, key, &objp);
     *objp_ = objp;
     return result;
 }
 
 JS_PUBLIC_API(JSProtoKey)
 JS_IdentifyClassPrototype(JSContext *cx, JSObject *obj)
 {
     AssertHeapIsIdle(cx);
@@ -2305,17 +2294,17 @@ JS_GetGlobalForCompartmentOrNull(JSConte
     return c->maybeGlobal();
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForScopeChain(JSContext *cx)
 {
     AssertHeapIsIdleOrIterating(cx);
     CHECK_REQUEST(cx);
-    return GetGlobalForScopeChain(cx);
+    return cx->global();
 }
 
 JS_PUBLIC_API(jsval)
 JS_ComputeThis(JSContext *cx, jsval *vp)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, JSValueArray(vp, 2));
     CallReceiver call = CallReceiverFromVp(vp);
@@ -4874,23 +4863,18 @@ JS_PUBLIC_API(JSObject *)
 JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSRawObject parentArg)
 {
     RootedObject funobj(cx, funobjArg);
     RootedObject parent(cx, parentArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);  // XXX no funobj for now
 
-    if (!parent) {
-        if (cx->hasfp())
-            parent = cx->fp()->scopeChain();
-        if (!parent)
-            parent = cx->globalObject;
-        JS_ASSERT(parent);
-    }
+    if (!parent)
+        parent = cx->global();
 
     if (!funobj->isFunction()) {
         ReportIsNotFunction(cx, ObjectValue(*funobj));
         return NULL;
     }
 
     /*
      * If a function was compiled to be lexically nested inside some other
@@ -7296,13 +7280,12 @@ JS_DecodeInterpretedFunction(JSContext *
     return funobj;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetScriptedGlobal(JSContext *cx)
 {
     ScriptFrameIter i(cx);
     if (i.done())
-        return JS_GetGlobalForScopeChain(cx);
-
-    return JS_GetGlobalForFrame(Jsvalify(i.fp()));
-}
-
+        return cx->global();
+    return &i.fp()->global();
+}
+
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3685,60 +3685,57 @@ EnsureNewArrayElements(JSContext *cx, JS
 template<bool allocateCapacity>
 static JS_ALWAYS_INLINE JSObject *
 NewArray(JSContext *cx, uint32_t length, RawObject protoArg)
 {
     gc::AllocKind kind = GuessArrayGCKind(length);
     JS_ASSERT(CanBeFinalizedInBackground(kind, &ArrayClass));
     kind = GetBackgroundAllocKind(kind);
 
-    GlobalObject *parent_ = GetCurrentGlobal(cx);
-
     NewObjectCache &cache = cx->runtime->newObjectCache;
 
     NewObjectCache::EntryIndex entry = -1;
-    if (cache.lookupGlobal(&ArrayClass, parent_, kind, &entry)) {
+    if (cache.lookupGlobal(&ArrayClass, cx->global(), kind, &entry)) {
         JSObject *obj = cache.newObjectFromHit(cx, entry);
         if (obj) {
             /* Fixup the elements pointer and length, which may be incorrect. */
             obj->setFixedElements();
             obj->setArrayLength(cx, length);
             if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
                 return NULL;
             return obj;
         }
     }
 
-    Rooted<GlobalObject*> parent(cx, parent_);
     RootedObject proto(cx, protoArg);
     if (protoArg)
         PoisonPtr(&protoArg);
 
-    if (!proto && !FindProto(cx, &ArrayClass, parent, &proto))
+    if (!proto && !FindProto(cx, &ArrayClass, &proto))
         return NULL;
 
     RootedTypeObject type(cx, proto->getNewType(cx));
     if (!type)
         return NULL;
 
     /*
      * Get a shape with zero fixed slots, regardless of the size class.
      * See JSObject::createDenseArray.
      */
     RootedShape shape(cx, EmptyShape::getInitialShape(cx, &ArrayClass, proto,
-                                                      parent, gc::FINALIZE_OBJECT0));
+                                                      cx->global(), gc::FINALIZE_OBJECT0));
     if (!shape)
         return NULL;
 
     JSObject* obj = JSObject::createDenseArray(cx, kind, shape, type, length);
     if (!obj)
         return NULL;
 
     if (entry != -1)
-        cache.fillGlobal(entry, &ArrayClass, parent, kind, obj);
+        cache.fillGlobal(entry, &ArrayClass, cx->global(), kind, obj);
 
     if (allocateCapacity && !EnsureNewArrayElements(cx, obj, length))
         return NULL;
 
     Probes::createObject(cx, obj);
     return obj;
 }
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -276,22 +276,16 @@ JSRuntime::cloneSelfHostedValueById(JSCo
         return false;
 
     vp->setObjectOrNull(clone);
     DebugOnly<bool> ok = JS_DefinePropertyById(cx, holder, id, *vp, NULL, NULL, 0);
     JS_ASSERT(ok);
     return true;
 }
 
-JSScript *
-js_GetCurrentScript(JSContext *cx)
-{
-    return cx->hasfp() ? cx->fp()->maybeScript() : NULL;
-}
-
 JSContext *
 js::NewContext(JSRuntime *rt, size_t stackChunkSize)
 {
     JS_AbortIfWrongThread(rt);
 
     JSContext *cx = OffTheBooks::new_<JSContext>(rt);
     if (!cx)
         return NULL;
@@ -1061,19 +1055,19 @@ JSContext::JSContext(JSRuntime *rt)
     reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     localeCallbacks(NULL),
     resolvingList(NULL),
     generatingError(false),
 #ifdef DEBUG
     rootingUnnecessary(false),
 #endif
     compartment(NULL),
-    stack(thisDuringConstruction()),  /* depends on cx->thread_ */
+    defaultCompartmentObject_(NULL),
+    stack(thisDuringConstruction()),
     parseMapPool_(NULL),
-    globalObject(NULL),
     sharpObjectMap(thisDuringConstruction()),
     argumentFormatMap(NULL),
     lastMessage(NULL),
     errorReporter(NULL),
     operationCallback(NULL),
     data(NULL),
     data2(NULL),
 #ifdef JS_THREADSAFE
@@ -1147,34 +1141,24 @@ RelaxRootChecksForContext(JSContext *cx)
 }
 
 } /* namespace JS */
 #endif
 
 void
 JSContext::resetCompartment()
 {
-    RootedObject scopeobj(this);
     if (stack.hasfp()) {
-        scopeobj = fp()->scopeChain();
+        compartment = fp()->scopeChain()->compartment();
     } else {
-        scopeobj = globalObject;
-        if (!scopeobj)
+        if (!defaultCompartmentObject_)
             goto error;
-
-        /*
-         * Innerize. Assert, but check anyway, that this succeeds. (It
-         * can only fail due to bugs in the engine or embedding.)
-         */
-        scopeobj = GetInnerObject(this, scopeobj);
-        if (!scopeobj)
-            goto error;
+        compartment = defaultCompartmentObject_->compartment();
     }
 
-    compartment = scopeobj->compartment();
     inferenceEnabled = compartment->types.inferenceEnabled;
 
     if (isExceptionPending())
         wrapPendingException();
     updateJITEnabled();
     return;
 
 error:
@@ -1383,18 +1367,18 @@ JSContext::sizeOfIncludingThis(JSMallocS
 }
 
 void
 JSContext::mark(JSTracer *trc)
 {
     /* Stack frames and slots are traced by StackSpace::mark. */
 
     /* Mark other roots-by-definition in the JSContext. */
-    if (globalObject && !hasRunOption(JSOPTION_UNROOTED_GLOBAL))
-        MarkObjectRoot(trc, &globalObject, "global object");
+    if (defaultCompartmentObject_ && !hasRunOption(JSOPTION_UNROOTED_GLOBAL))
+        MarkObjectRoot(trc, &defaultCompartmentObject_, "default compartment object");
     if (isExceptionPending())
         MarkValueRoot(trc, &exception, "exception");
 
     if (sharpObjectMap.depth > 0)
         js_TraceSharpMap(trc, &sharpObjectMap);
 
     MarkValueRoot(trc, &iterValue, "iterValue");
 }
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1161,16 +1161,28 @@ struct JSContext : js::ContextFriendFiel
     bool                rootingUnnecessary;
 #endif
 
     /* GC heap compartment. */
     JSCompartment       *compartment;
 
     inline void setCompartment(JSCompartment *compartment);
 
+    /*
+     * When no compartments have been explicitly entered, the context's
+     * compartment will be set to the compartment of the "default compartment
+     * object".
+     */
+  private:
+    JSObject *defaultCompartmentObject_;
+  public:
+    inline void setDefaultCompartmentObject(JSObject *obj);
+    inline void setDefaultCompartmentObjectIfUnset(JSObject *obj);
+    JSObject *maybeDefaultCompartmentObject() const { return defaultCompartmentObject_; }
+
     /* Current execution stack. */
     js::ContextStack    stack;
 
     /* Current global. */
     inline js::Handle<js::GlobalObject*> global() const;
 
     /* ContextStack convenience functions */
     inline bool hasfp() const               { return stack.hasfp(); }
@@ -1185,19 +1197,16 @@ struct JSContext : js::ContextFriendFiel
     /* Wrap cx->exception for the current compartment. */
     void wrapPendingException();
 
   private:
     /* Lazily initialized pool of maps used during parse/emit. */
     js::frontend::ParseMapPool *parseMapPool_;
 
   public:
-    /* Top-level object and pointer to top stack frame's scope chain. */
-    JSObject            *globalObject;
-
     /* State for object and array toSource conversion. */
     JSSharpObjectMap    sharpObjectMap;
     js::BusyArraysSet   busyArrays;
 
     /* Argument formatter support for JS_{Convert,Push}Arguments{,VA}. */
     JSArgumentFormatMap *argumentFormatMap;
 
     /* Last message string and log file for debugging. */
@@ -1785,19 +1794,16 @@ extern JSBool
 js_InvokeOperationCallback(JSContext *cx);
 
 extern JSBool
 js_HandleExecutionInterrupt(JSContext *cx);
 
 extern jsbytecode*
 js_GetCurrentBytecodePC(JSContext* cx);
 
-extern JSScript *
-js_GetCurrentScript(JSContext* cx);
-
 /*
  * If the operation callback flag was set, call the operation callback.
  * This macro can run the full GC. Return true if it is OK to continue and
  * false otherwise.
  */
 static MOZ_ALWAYS_INLINE bool
 JS_CHECK_OPERATION_LIMIT(JSContext *cx)
 {
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -129,28 +129,16 @@ struct PreserveRegsGuard
 
     FrameRegs *prevContextRegs;
 
   private:
     JSContext *cx;
     FrameRegs &regs_;
 };
 
-static inline GlobalObject *
-GetGlobalForScopeChain(JSContext *cx)
-{
-    if (cx->hasfp())
-        return &cx->fp()->global();
-
-    JSObject *scope = JS_ObjectToInnerObject(cx, HandleObject::fromMarkedLocation(&cx->globalObject));
-    if (!scope)
-        return NULL;
-    return &scope->asGlobal();
-}
-
 inline GSNCache *
 GetGSNCache(JSContext *cx)
 {
     return &cx->runtime->gsnCache;
 }
 
 #if JS_HAS_XML_SUPPORT
 
@@ -206,22 +194,17 @@ class AutoPtr
 class CompartmentChecker
 {
     JSContext *context;
     JSCompartment *compartment;
 
   public:
     explicit CompartmentChecker(JSContext *cx)
       : context(cx), compartment(cx->compartment)
-    {
-        if (cx->compartment) {
-            GlobalObject *global = GetGlobalForScopeChain(cx);
-            JS_ASSERT(cx->global() == global);
-        }
-    }
+    {}
 
     /*
      * Set a breakpoint here (break js::CompartmentChecker::fail) to debug
      * compartment mismatches.
      */
     static void fail(JSCompartment *c1, JSCompartment *c2) {
         printf("*** Compartment mismatch %p vs. %p\n", (void *) c1, (void *) c2);
         JS_NOT_REACHED("compartment mismatched");
@@ -579,16 +562,32 @@ JSContext::ensureParseMapPool()
 }
 
 inline js::PropertyTree&
 JSContext::propertyTree()
 {
     return compartment->propertyTree;
 }
 
+inline void
+JSContext::setDefaultCompartmentObject(JSObject *obj)
+{
+    defaultCompartmentObject_ = obj;
+
+    if (!hasfp())
+        resetCompartment();
+}
+
+inline void
+JSContext::setDefaultCompartmentObjectIfUnset(JSObject *obj)
+{
+    if (!defaultCompartmentObject_)
+        setDefaultCompartmentObject(obj);
+}
+
 /* Get the current frame, first lazily instantiating stack frames if needed. */
 static inline js::StackFrame *
 js_GetTopStackFrame(JSContext *cx, FrameExpandKind expand)
 {
 #ifdef JS_METHODJIT
     if (expand)
         js::mjit::ExpandInlineFrames(cx->compartment);
 #endif
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -177,37 +177,29 @@ JSCompartment::wrap(JSContext *cx, Value
 
     /*
      * Wrappers should really be parented to the wrapped parent of the wrapped
      * object, but in that case a wrapped global object would have a NULL
      * parent without being a proper global object (JSCLASS_IS_GLOBAL). Instead,
      * we parent all wrappers to the global object in their home compartment.
      * This loses us some transparency, and is generally very cheesy.
      */
-    RootedObject global(cx);
-    if (cx->hasfp()) {
-        global = &cx->fp()->global();
-    } else {
-        global = cx->globalObject;
-        global = JS_ObjectToInnerObject(cx, global);
-        if (!global)
-            return false;
-    }
+    HandleObject global = cx->global();
 
     /* Unwrap incoming objects. */
     if (vp->isObject()) {
         Rooted<JSObject*> obj(cx, &vp->toObject());
 
         if (obj->compartment() == this)
             return WrapForSameCompartment(cx, obj, vp);
 
         /* Translate StopIteration singleton. */
         if (obj->isStopIteration()) {
             RootedValue vvp(cx, *vp);
-            bool result = js_FindClassObject(cx, NullPtr(), JSProto_StopIteration, &vvp);
+            bool result = js_FindClassObject(cx, JSProto_StopIteration, &vvp);
             *vp = vvp;
             return result;
         }
 
         /* Unwrap the object, but don't unwrap outer windows. */
         obj = UnwrapObject(&vp->toObject(), /* stopAtOuter = */ true, &flags);
 
         if (obj->compartment() == this)
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -980,17 +980,17 @@ js_ErrorToException(JSContext *cx, const
     AutoArrayRooter tvr(cx, ArrayLength(tv), tv);
 
     /*
      * Try to get an appropriate prototype by looking up the corresponding
      * exception constructor name in the scope chain of the current context's
      * top stack frame, or in the global object if no frame is active.
      */
     RootedObject errProto(cx);
-    if (!js_GetClassPrototype(cx, NullPtr(), GetExceptionProtoKey(exn), &errProto))
+    if (!js_GetClassPrototype(cx, GetExceptionProtoKey(exn), &errProto))
         return false;
     tv[0] = OBJECT_TO_JSVAL(errProto);
 
     RootedObject errObject(cx, NewObjectWithGivenProto(cx, &ErrorClass, errProto, NULL));
     if (!errObject)
         return false;
     tv[1] = OBJECT_TO_JSVAL(errObject);
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2032,18 +2032,17 @@ TypeCompartment::newAllocationSiteTypeOb
             return NULL;
         }
     }
 
     AllocationSiteTable::AddPtr p = allocationSiteTable->lookupForAdd(key);
     JS_ASSERT(!p);
 
     RootedObject proto(cx);
-    RootedObject global(cx, &key.script->global());
-    if (!js_GetClassPrototype(cx, global, key.kind, &proto, NULL))
+    if (!js_GetClassPrototype(cx, key.kind, &proto, NULL))
         return NULL;
 
     RootedScript keyScript(cx, key.script);
     TypeObject *res = newTypeObject(cx, key.script, key.kind, proto);
     if (!res) {
         cx->compartment->types.setPendingNukeTypes(cx);
         return NULL;
     }
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -354,18 +354,17 @@ struct AutoEnterCompilation
 /*
  * Get the default 'new' object for a given standard class, per the currently
  * active global.
  */
 inline TypeObject *
 GetTypeNewObject(JSContext *cx, JSProtoKey key)
 {
     RootedObject proto(cx);
-    RootedObject null(cx);
-    if (!js_GetClassPrototype(cx, null, key, &proto))
+    if (!js_GetClassPrototype(cx, key, &proto))
         return NULL;
     return proto->getNewType(cx);
 }
 
 /* Get a type object for the immediate allocation site within a native. */
 inline TypeObject *
 GetTypeCallerInitObject(JSContext *cx, JSProtoKey key)
 {
@@ -646,18 +645,17 @@ TypeScript::SlotTypes(JSScript *script, 
     TypeSet *types = script->types->typeArray() + script->nTypeSets + slot;
     return types->toStackTypeSet();
 }
 
 /* static */ inline TypeObject *
 TypeScript::StandardType(JSContext *cx, JSScript *script, JSProtoKey key)
 {
     RootedObject proto(cx);
-    RootedObject global(cx, &script->global());
-    if (!js_GetClassPrototype(cx, global, key, &proto, NULL))
+    if (!js_GetClassPrototype(cx, key, &proto, NULL))
         return NULL;
     return proto->getNewType(cx);
 }
 
 struct AllocationSiteKey {
     JSScript *script;
 
     uint32_t offset : 24;
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -719,17 +719,17 @@ GetIterator(JSContext *cx, HandleObject 
 
 }
 
 JSBool
 js_ThrowStopIteration(JSContext *cx)
 {
     JS_ASSERT(!JS_IsExceptionPending(cx));
     RootedValue v(cx);
-    if (js_FindClassObject(cx, NullPtr(), JSProto_StopIteration, &v))
+    if (js_FindClassObject(cx, JSProto_StopIteration, &v))
         cx->setPendingException(v);
     return JS_FALSE;
 }
 
 /*** Iterator objects ****************************************************************************/
 
 static JSBool
 Iterator(JSContext *cx, unsigned argc, Value *vp)
@@ -845,21 +845,20 @@ Class PropertyIteratorObject::class_ = {
     }
 };
 
 const uint32_t CLOSED_INDEX = UINT32_MAX;
 
 JSObject *
 ElementIteratorObject::create(JSContext *cx, Handle<Value> target)
 {
-    Rooted<GlobalObject*> global(cx, GetCurrentGlobal(cx));
-    Rooted<JSObject*> proto(cx, global->getOrCreateElementIteratorPrototype(cx));
+    Rooted<JSObject*> proto(cx, cx->global()->getOrCreateElementIteratorPrototype(cx));
     if (!proto)
         return NULL;
-    JSObject *iterobj = NewObjectWithGivenProto(cx, &ElementIteratorClass, proto, global);
+    JSObject *iterobj = NewObjectWithGivenProto(cx, &ElementIteratorClass, proto, cx->global());
     if (iterobj) {
         iterobj->setReservedSlot(TargetSlot, target);
         iterobj->setReservedSlot(IndexSlot, Int32Value(0));
     }
     return iterobj;
 }
 
 static bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2416,17 +2416,17 @@ js::NewObjectWithClassProto(JSContext *c
 
     RootedObject parent(cx, parent_);
     RootedObject proto(cx, proto_);
 
     if (CanBeFinalizedInBackground(kind, clasp))
         kind = GetBackgroundAllocKind(kind);
 
     if (!parent)
-        parent = GetCurrentGlobal(cx);
+        parent = cx->global();
 
     /*
      * Use the object cache, except for classes without a cached proto key.
      * On these objects, FindProto will do a dynamic property lookup to get
      * global[className].prototype, where changes to either the className or
      * prototype property would render the cached lookup incorrect. For classes
      * with a proto key, the prototype created during class initialization is
      * stored in an immutable slot on the global (except for ClearScope, which
@@ -2440,17 +2440,17 @@ js::NewObjectWithClassProto(JSContext *c
     if (parent->isGlobal() && protoKey != JSProto_Null) {
         if (cache.lookupGlobal(clasp, &parent->asGlobal(), kind, &entry)) {
             JSObject *obj = cache.newObjectFromHit(cx, entry);
             if (obj)
                 return obj;
         }
     }
 
-    if (!FindProto(cx, clasp, parent, &proto))
+    if (!FindProto(cx, clasp, &proto))
         return NULL;
 
     types::TypeObject *type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
     JSObject *obj = NewObject(cx, clasp, type, parent, kind);
     if (!obj)
@@ -3372,17 +3372,17 @@ bad:
         ClearClassObject(cx, obj, key);
     return NULL;
 }
 
 /*
  * Lazy standard classes need a way to indicate if they have been initialized.
  * Otherwise, when we delete them, we might accidentally recreate them via a
  * lazy initialization. We use the presence of a ctor or proto in the
- * globalObject's slot to indicate that they've been constructed, but this only
+ * global object's slot to indicate that they've been constructed, but this only
  * works for classes which have a proto and ctor. Classes which don't have one
  * can call MarkStandardClassInitializedNoProto(), and we can always check
  * whether a class is initialized by calling IsStandardClassResolved().
  */
 bool
 IsStandardClassResolved(JSObject *obj, js::Class *clasp)
 {
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
@@ -3429,17 +3429,17 @@ js_InitClass(JSContext *cx, HandleObject
      * of js_InitClass depend on this nicety. Note that in
      * js_InitFunctionAndObjectClasses, we specially hack the resolving table
      * and then depend on js_GetClassPrototype here leaving protoProto NULL and
      * returning true.
      */
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
     if (key != JSProto_Null &&
         !protoProto &&
-        !js_GetClassPrototype(cx, obj, JSProto_Object, &protoProto)) {
+        !js_GetClassPrototype(cx, JSProto_Object, &protoProto)) {
         return NULL;
     }
 
     return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
                                          ps, fs, static_ps, static_fs, ctorp, ctorKind);
 }
 
 inline bool
@@ -3888,53 +3888,41 @@ js_IdentifyClassPrototype(JSObject *obj)
     if (v.isObject() && obj == &v.toObject())
         return key;
 
     // False alarm - just an instance.
     return JSProto_Null;
 }
 
 bool
-js_FindClassObject(JSContext *cx, HandleObject start, JSProtoKey protoKey,
-                   MutableHandleValue vp, Class *clasp)
+js_FindClassObject(JSContext *cx, JSProtoKey protoKey, MutableHandleValue vp, Class *clasp)
 {
     RootedId id(cx);
-    RootedObject obj(cx);
-
-    if (start) {
-        obj = &start->global();
-        obj = GetInnerObject(cx, obj);
-    } else {
-        obj = GetGlobalForScopeChain(cx);
-    }
-    if (!obj)
-        return false;
 
     if (protoKey != JSProto_Null) {
         JS_ASSERT(JSProto_Null < protoKey);
         JS_ASSERT(protoKey < JSProto_LIMIT);
         RootedObject cobj(cx);
-        if (!js_GetClassObject(cx, obj, protoKey, &cobj))
+        if (!js_GetClassObject(cx, cx->global(), protoKey, &cobj))
             return false;
         if (cobj) {
             vp.set(ObjectValue(*cobj));
             return JS_TRUE;
         }
         id = NameToId(cx->runtime->atomState.classAtoms[protoKey]);
     } else {
         JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
         if (!atom)
             return false;
         id = AtomToId(atom);
     }
 
-    JS_ASSERT(obj->isNative());
     RootedObject pobj(cx);
     RootedShape shape(cx);
-    if (!LookupPropertyWithFlags(cx, obj, id, 0, &pobj, &shape))
+    if (!LookupPropertyWithFlags(cx, cx->global(), id, 0, &pobj, &shape))
         return false;
     RootedValue v(cx, UndefinedValue());
     if (shape && pobj->isNative()) {
         if (shape->hasSlot()) {
             v = pobj->nativeGetSlot(shape->slot());
             if (v.get().isPrimitive())
                 v.get().setUndefined();
         }
@@ -5299,66 +5287,48 @@ js_IsDelegate(JSContext *cx, JSObject *o
     JSObject *obj2 = &v.toObject();
     while ((obj2 = obj2->getProto()) != NULL) {
         if (obj2 == obj)
             return true;
     }
     return false;
 }
 
+/*
+ * The first part of this function has been hand-expanded and optimized into
+ * NewBuiltinClassInstance in jsobjinlines.h.
+ */
 bool
-js::FindClassPrototype(JSContext *cx, HandleObject scopeobj, JSProtoKey protoKey,
-                       MutableHandleObject protop, Class *clasp)
+js_GetClassPrototype(JSContext *cx, JSProtoKey protoKey, MutableHandleObject protop, Class *clasp)
 {
+    JS_ASSERT(JSProto_Null <= protoKey);
+    JS_ASSERT(protoKey < JSProto_LIMIT);
+
+    if (protoKey != JSProto_Null) {
+        const Value &v = cx->global()->getReservedSlot(JSProto_LIMIT + protoKey);
+        if (v.isObject()) {
+            protop.set(&v.toObject());
+            return true;
+        }
+    }
+
     RootedValue v(cx);
-    if (!js_FindClassObject(cx, scopeobj, protoKey, &v, clasp))
+    if (!js_FindClassObject(cx, protoKey, &v, clasp))
         return false;
 
     if (IsFunctionObject(v)) {
         RootedObject ctor(cx, &v.get().toObject());
         if (!JSObject::getProperty(cx, ctor, ctor, cx->runtime->atomState.classPrototypeAtom, &v))
             return false;
     }
 
     protop.set(v.get().isObject() ? &v.get().toObject() : NULL);
     return true;
 }
 
-/*
- * The first part of this function has been hand-expanded and optimized into
- * NewBuiltinClassInstance in jsobjinlines.h.
- */
-bool
-js_GetClassPrototype(JSContext *cx, HandleObject scopeobj, JSProtoKey protoKey,
-                     MutableHandleObject protop, Class *clasp)
-{
-    JS_ASSERT(JSProto_Null <= protoKey);
-    JS_ASSERT(protoKey < JSProto_LIMIT);
-
-    if (protoKey != JSProto_Null) {
-        GlobalObject *global;
-        if (scopeobj) {
-            global = &scopeobj->global();
-        } else {
-            global = GetCurrentGlobal(cx);
-            if (!global) {
-                protop.set(NULL);
-                return true;
-            }
-        }
-        const Value &v = global->getReservedSlot(JSProto_LIMIT + protoKey);
-        if (v.isObject()) {
-            protop.set(&v.toObject());
-            return true;
-        }
-    }
-
-    return FindClassPrototype(cx, scopeobj, protoKey, protop, clasp);
-}
-
 JSObject *
 PrimitiveToObject(JSContext *cx, const Value &v)
 {
     if (v.isString()) {
         Rooted<JSString*> str(cx, v.toString());
         return StringObject::create(cx, str);
     }
     if (v.isNumber())
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1143,18 +1143,18 @@ js_GetClassObject(JSContext *cx, js::Raw
 extern JSProtoKey
 js_IdentifyClassPrototype(JSObject *obj);
 
 /*
  * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
  * JSProto_Null, clasp must non-null.
  */
 bool
-js_FindClassObject(JSContext *cx, js::HandleObject start, JSProtoKey protoKey,
-                   js::MutableHandleValue vp, js::Class *clasp = NULL);
+js_FindClassObject(JSContext *cx, JSProtoKey protoKey, js::MutableHandleValue vp,
+                   js::Class *clasp = NULL);
 
 // Specialized call for constructing |this| with a known function callee,
 // and a known prototype.
 extern JSObject *
 js_CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto);
 
 // Specialized call for constructing |this| with a known function callee.
 extern JSObject *
@@ -1404,18 +1404,18 @@ js_Object(JSContext *cx, unsigned argc, 
 /*
  * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
  * JSProto_Null, clasp must non-null.
  *
  * If protoKey is constant and scope is non-null, use GlobalObject's prototype
  * methods instead.
  */
 extern JS_FRIEND_API(bool)
-js_GetClassPrototype(JSContext *cx, js::HandleObject scopeobj, JSProtoKey protoKey,
-                     js::MutableHandleObject protop, js::Class *clasp = NULL);
+js_GetClassPrototype(JSContext *cx, JSProtoKey protoKey, js::MutableHandleObject protop,
+                     js::Class *clasp = NULL);
 
 namespace js {
 
 extern bool
 SetProto(JSContext *cx, HandleObject obj, HandleObject proto, bool checkForCycles);
 
 extern JSString *
 obj_toStringHelper(JSContext *cx, JSObject *obj);
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1403,22 +1403,22 @@ GetClassProtoKey(js::Class *clasp)
     if (key != JSProto_Null)
         return key;
     if (clasp->flags & JSCLASS_IS_ANONYMOUS)
         return JSProto_Object;
     return JSProto_Null;
 }
 
 inline bool
-FindProto(JSContext *cx, js::Class *clasp, HandleObject parent, MutableHandleObject proto)
+FindProto(JSContext *cx, js::Class *clasp, MutableHandleObject proto)
 {
     JSProtoKey protoKey = GetClassProtoKey(clasp);
-    if (!js_GetClassPrototype(cx, parent, protoKey, proto, clasp))
+    if (!js_GetClassPrototype(cx, protoKey, proto, clasp))
         return false;
-    if (!proto && !js_GetClassPrototype(cx, parent, JSProto_Object, proto))
+    if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto))
         return false;
     return true;
 }
 
 /*
  * Make an object with the prototype set according to the specified prototype or class:
  *
  * if proto is non-null:
@@ -1458,23 +1458,16 @@ NewBuiltinClassInstance(JSContext *cx, C
 
 inline JSObject *
 NewBuiltinClassInstance(JSContext *cx, Class *clasp)
 {
     gc::AllocKind kind = gc::GetGCObjectKind(clasp);
     return NewBuiltinClassInstance(cx, clasp, kind);
 }
 
-inline GlobalObject *
-GetCurrentGlobal(JSContext *cx)
-{
-    JSObject *scopeChain = (cx->hasfp()) ? cx->fp()->scopeChain() : cx->globalObject;
-    return scopeChain ? &scopeChain->global() : NULL;
-}
-
 bool
 FindClassPrototype(JSContext *cx, HandleObject scope, JSProtoKey protoKey,
                    MutableHandleObject protop, Class *clasp);
 
 /*
  * Create a plain object with the specified type. This bypasses getNewType to
  * avoid losing creation site information for objects made by scripted 'new'.
  */
--- a/js/src/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -191,17 +191,17 @@ Probes::DTraceExitJSFun(JSContext *cx, J
                                FunctionName(cx, fun, &funNameBytes));
 }
 #endif
 
 #ifdef MOZ_ETW
 static void
 current_location(JSContext *cx, int* lineno, char const **filename)
 {
-    JSScript *script = js_GetCurrentScript(cx);
+    JSScript *script = cx->stack.currentScript()
     if (! script) {
         *lineno = -1;
         *filename = "(uninitialized)";
         return;
     }
     *lineno = js_PCToLineNumber(cx, script, js_GetCurrentBytecodePC(cx));
     *filename = ScriptFilename(script);
 }
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -2962,17 +2962,17 @@ ASTSerializer::literal(ParseNode *pn, Va
         break;
 
       case PNK_REGEXP:
       {
         JSObject *re1 = pn->pn_objbox ? pn->pn_objbox->object : NULL;
         LOCAL_ASSERT(re1 && re1->isRegExp());
 
         RootedObject proto(cx);
-        if (!js_GetClassPrototype(cx, cx->fp()->scopeChain(), JSProto_RegExp, &proto))
+        if (!js_GetClassPrototype(cx, JSProto_RegExp, &proto))
             return false;
 
         JSObject *re2 = CloneRegExpObject(cx, re1, proto);
         if (!re2)
             return false;
 
         val.setObject(*re2);
         break;
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -671,31 +671,16 @@ ArrayBufferObject::obj_enumerate(JSConte
 
 JSType
 ArrayBufferObject::obj_typeOf(JSContext *cx, HandleObject obj)
 {
     return JSTYPE_OBJECT;
 }
 
 /*
- * ArrayBufferViews of various sorts
- */
-
-static JSObject *
-GetProtoForClass(JSContext *cx, Class *clasp)
-{
-    // Pass in the proto from this compartment
-    Rooted<GlobalObject*> parent(cx, GetCurrentGlobal(cx));
-    RootedObject proto(cx);
-    if (!FindProto(cx, clasp, parent, &proto))
-        return NULL;
-    return proto;
-}
-
-/*
  * TypedArray
  *
  * The non-templated base class for the specific typed implementations.
  * This class holds all the member variables that are used by
  * the subclasses.
  */
 
 inline bool
@@ -1673,18 +1658,19 @@ class TypedArrayTemplate
                  * origin compartment's view.prototype object).
                  *
                  * Rather than hack some crazy solution together, implement
                  * this all using a private helper function, created when
                  * ArrayBuffer was initialized and cached in the global.  This
                  * reuses all the existing cross-compartment crazy so we don't
                  * have to do anything *uniquely* crazy here.
                  */
-                Rooted<JSObject*> proto(cx, GetProtoForClass(cx, fastClass()));
-                if (!proto)
+
+                Rooted<JSObject*> proto(cx);
+                if (!FindProto(cx, fastClass(), &proto))
                     return NULL;
 
                 InvokeArgsGuard ag;
                 if (!cx->stack.pushInvokeArgs(cx, 3, &ag))
                     return NULL;
 
                 ag.setCallee(cx->compartment->maybeGlobal()->createArrayFromBuffer<NativeType>());
                 ag.setThis(ObjectValue(*bufobj));
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -455,18 +455,17 @@ NewXMLQName(JSContext *cx, JSLinearStrin
 static JSObject *
 NewXMLAttributeName(JSContext *cx, JSLinearString *uri, JSLinearString *prefix,
                     JSAtom *localName)
 {
     /*
      * AttributeName is an internal anonymous class which instances are not
      * exposed to scripts.
      */
-    JSObject *parent = GetGlobalForScopeChain(cx);
-    RootedObject obj(cx, NewObjectWithGivenProto(cx, &AttributeNameClass, NULL, parent));
+    RootedObject obj(cx, NewObjectWithGivenProto(cx, &AttributeNameClass, NULL, cx->global()));
     if (!obj)
         return NULL;
     JS_ASSERT(obj->isQName());
     if (!InitXMLQName(cx, obj, uri, prefix, localName))
         return NULL;
     return obj;
 }
 
@@ -478,17 +477,17 @@ ConstructObjectWithArguments(JSContext *
 
     AutoArrayRooter argtvr(cx, argc, argv);
 
     JSProtoKey protoKey = GetClassProtoKey(clasp);
 
     /* Protect constructor in case a crazy getter for .prototype uproots it. */
     RootedValue value(cx);
     RootedObject null(cx);
-    if (!js_FindClassObject(cx, null, protoKey, &value, clasp))
+    if (!js_FindClassObject(cx, protoKey, &value, clasp))
         return NULL;
 
     Value rval;
     if (!InvokeConstructor(cx, value, argc, argv, &rval))
         return NULL;
 
     /*
      * If the instance's class differs from what was requested, throw a type
@@ -1631,17 +1630,17 @@ fail:
 /*
  * XML helper, object-ops, and library functions.  We start with the helpers,
  * in ECMA-357 order, but merging XML (9.1) and XMLList (9.2) helpers.
  */
 static JSBool
 GetXMLSetting(JSContext *cx, const char *name, jsval *vp)
 {
     RootedValue v(cx);
-    if (!js_FindClassObject(cx, NullPtr(), JSProto_XML, &v))
+    if (!js_FindClassObject(cx, JSProto_XML, &v))
         return JS_FALSE;
     if (v.get().isPrimitive() || !v.get().toObject().isFunction()) {
         *vp = JSVAL_VOID;
         return JS_TRUE;
     }
     RootedObject obj(cx, &v.get().toObject());
     return JS_GetProperty(cx, obj, name, vp);
 }
@@ -1681,18 +1680,17 @@ GetXMLSettingFlags(JSContext *cx, unsign
     return true;
 }
 
 static JSObject *
 GetCurrentScopeChain(JSContext *cx)
 {
     if (cx->hasfp())
         return cx->fp()->scopeChain();
-    RootedObject global(cx, cx->globalObject);
-    return JS_ObjectToInnerObject(cx, global);
+    return cx->global();
 }
 
 static JSXML *
 ParseXMLSource(JSContext *cx, HandleString src)
 {
     jsval nsval;
     JSLinearString *uri;
     size_t urilen, srclen, length, offset, dstlen;
@@ -7302,18 +7300,17 @@ js_NewXMLObject(JSContext *cx, JSXMLClas
     return js_GetXMLObject(cx, xml);
 }
 
 static JSObject *
 NewXMLObject(JSContext *cx, JSXML *xml)
 {
     JSObject *obj;
 
-    JSObject *parent = GetGlobalForScopeChain(cx);
-    obj = NewObjectWithClassProto(cx, &XMLClass, NULL, parent);
+    obj = NewObjectWithClassProto(cx, &XMLClass, NULL, cx->global());
     if (!obj)
         return NULL;
     obj->setPrivate(xml);
     return obj;
 }
 
 JSObject *
 js_GetXMLObject(JSContext *cx, JSXML *xmlArg)
@@ -7642,17 +7639,17 @@ JSString *
 js_ValueToXMLString(JSContext *cx, const Value &v)
 {
     return ToXMLString(cx, v, 0);
 }
 
 JSBool
 js_GetAnyName(JSContext *cx, jsid *idp)
 {
-    JSObject *global = cx->hasfp() ? &cx->fp()->global() : cx->globalObject;
+    JSObject *global = cx->global();
     Value v = global->getReservedSlot(JSProto_AnyName);
     if (v.isUndefined()) {
         RootedObject obj(cx, NewObjectWithGivenProto(cx, &AnyNameClass, NULL, global));
         if (!obj)
             return false;
 
         JS_ASSERT(!obj->getProto());
 
@@ -7912,18 +7909,17 @@ js_StepXMLListFilter(JSContext *cx, JSBo
              * as it may be the only root holding xml.
              */
             sp[-1] = OBJECT_TO_JSVAL(obj);
             list = (JSXML *) obj->getPrivate();
             if (!Append(cx, list, xml))
                 return JS_FALSE;
         }
 
-        JSObject *parent = GetGlobalForScopeChain(cx);
-        filterobj = NewObjectWithGivenProto(cx, &js_XMLFilterClass, NULL, parent);
+        filterobj = NewObjectWithGivenProto(cx, &js_XMLFilterClass, NULL, cx->global());
         if (!filterobj)
             return JS_FALSE;
 
         /*
          * Init all filter fields before setPrivate exposes it to
          * xmlfilter_trace or xmlfilter_finalize.
          */
         filter = cx->new_<JSXMLFilter>(list, &list->xml_kids);
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -5285,17 +5285,17 @@ mjit::Compiler::testSingletonPropertyTyp
         }
         return false;
 
       default:
         return false;
     }
 
     RootedObject proto(cx);
-    if (!js_GetClassPrototype(cx, globalObj, key, &proto, NULL))
+    if (!js_GetClassPrototype(cx, key, &proto, NULL))
         return false;
 
     return testSingletonProperty(proto, id);
 }
 
 bool
 mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
 {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3358,31 +3358,34 @@ DecompileFunction(JSContext *cx, unsigne
 {
     return DecompileFunctionSomehow(cx, argc, vp, JS_DecompileFunction);
 }
 
 static JSBool
 DecompileThisScript(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    JSScript *script = js_GetCurrentScript(cx);
-    JS_ASSERT(script);
+    JSScript *script = NULL;
+    if (!JS_DescribeScriptedCaller(cx, &script, NULL)) {
+        args.rval().setString(cx->runtime->emptyString);
+        return true;
+    }
     JSString *result = JS_DecompileScript(cx, script, "test", 0);
     if (!result)
         return false;
     args.rval().setString(result);
     return true;
 }
 
 static JSBool
 ThisFilename(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    JSScript *script = js_GetCurrentScript(cx);
-    if (!script || !script->filename) {
+    JSScript *script = NULL;
+    if (!JS_DescribeScriptedCaller(cx, &script, NULL) || !script->filename) {
         args.rval().setString(cx->runtime->emptyString);
         return true;
     }
     JSString *filename = JS_NewStringCopyZ(cx, script->filename);
     if (!filename)
         return false;
     args.rval().setString(filename);
     return true;
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -248,19 +248,17 @@ GlobalObject::initFunctionAndObjectClass
 
     /*
      * Calling a function from a cleared global triggers this (yeah, I know).
      * Uncomment this once bug 470510 is fixed (if that bug doesn't remove
      * isCleared entirely).
      */
     // JS_ASSERT(!isCleared());
 
-    /* If cx has no global object, make this the global object. */
-    if (!cx->globalObject)
-        JS_SetGlobalObject(cx, self);
+    cx->setDefaultCompartmentObjectIfUnset(self);
 
     RootedObject objectProto(cx);
 
     /*
      * Create |Object.prototype| first, mirroring CreateBlankProto but for the
      * prototype of the created object.
      */
     objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self);
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -50,17 +50,17 @@ class Debugger;
  *   Various one-off values: ES5 13.2.3's [[ThrowTypeError]], RegExp statics,
  *   the Namespace object for E4X's function::, the original eval for this
  *   global object (implementing |var eval = otherWindow.eval; eval(...)| as an
  *   indirect eval), a bit indicating whether this object has been cleared
  *   (see JS_ClearScope), and a cache for whether eval is allowed (per the
  *   global's Content Security Policy).
  *
  * The first two ranges are necessary to implement js::FindClassObject,
- * js::FindClassPrototype, and spec language speaking in terms of "the original
+ * FindClassPrototype, and spec language speaking in terms of "the original
  * Array prototype object", or "as if by the expression new Array()" referring
  * to the original Array constructor.  The third range stores the (writable and
  * even deletable) Object, Array, &c. properties (although a slot won't be used
  * again if its property is deleted and readded).
  */
 class GlobalObject : public JSObject
 {
     /*
--- a/js/src/vm/RegExpStatics-inl.h
+++ b/js/src/vm/RegExpStatics-inl.h
@@ -261,20 +261,19 @@ RegExpStatics::markFlagsSet(JSContext *c
     /*
      * Flags set on the RegExp function get propagated to constructed RegExp
      * objects, which interferes with optimizations that inline RegExp cloning
      * or avoid cloning entirely. Scripts making this assumption listen to
      * type changes on RegExp.prototype, so mark a state change to trigger
      * recompilation of all such code (when recompiling, a stub call will
      * always be performed).
      */
-    GlobalObject *global = GetGlobalForScopeChain(cx);
-    JS_ASSERT(this == global->getRegExpStatics());
+    JS_ASSERT(this == cx->global()->getRegExpStatics());
 
-    types::MarkTypeObjectFlags(cx, global, types::OBJECT_FLAG_REGEXP_FLAGS_SET);
+    types::MarkTypeObjectFlags(cx, cx->global(), types::OBJECT_FLAG_REGEXP_FLAGS_SET);
 }
 
 inline void
 RegExpStatics::reset(JSContext *cx, JSString *newInput, bool newMultiline)
 {
     aboutToWrite();
     clear();
     pendingInput = newInput;
@@ -282,12 +281,12 @@ RegExpStatics::reset(JSContext *cx, JSSt
     checkInvariants();
 }
 
 } /* namespace js */
 
 inline js::RegExpStatics *
 JSContext::regExpStatics()
 {
-    return js::GetGlobalForScopeChain(this)->getRegExpStatics();
+    return global()->getRegExpStatics();
 }
 
 #endif