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 105294 ea32388d45a805c72f179375dc2b763c75454f6d
parent 105293 5e5711c63caa76923b613046d4224e3167399aff
child 105295 986c07b3f3e68af098d7e85fd507a7d4139b4eb3
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersmrbkap
bugs625199
milestone17.0a1
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