Bug 962449 - Make various getOrCreate methods static to efficiently fix hazards. r=Waldo
authorBobby Holley <bobbyholley@gmail.com>
Fri, 31 Jan 2014 14:51:42 -0800
changeset 182486 290a8f35944160917f1fb03a19bb7e09ac5f5667
parent 182485 8c206e77eb64ed7671ced59ddf599c4af79351ed
child 182487 26bc2b4b1605a091d4740514ebf5bc995bdce479
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs962449
milestone29.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 962449 - Make various getOrCreate methods static to efficiently fix hazards. r=Waldo
js/src/builtin/MapObject.cpp
js/src/frontend/Parser.cpp
js/src/jit/BaselineIC.cpp
js/src/jsapi.cpp
js/src/jsfun.cpp
js/src/jsiter.cpp
js/src/json.cpp
js/src/vm/Debugger.cpp
js/src/vm/ErrorObject.cpp
js/src/vm/GlobalObject.h
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/SelfHosting.cpp
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -892,17 +892,17 @@ MapIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     JS_ASSERT(i == MapObject::Keys || i == MapObject::Values || i == MapObject::Entries);
     return MapObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initMapIteratorProto(JSContext *cx, Handle<GlobalObject *> global)
 {
-    JSObject *base = global->getOrCreateIteratorPrototype(cx);
+    JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
     if (!base)
         return false;
     Rooted<JSObject*> proto(cx,
         NewObjectWithGivenProto(cx, &MapIteratorObject::class_, base, global));
     if (!proto)
         return false;
     proto->setSlot(MapIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, MapIteratorObject::methods))
@@ -911,17 +911,17 @@ GlobalObject::initMapIteratorProto(JSCon
     return true;
 }
 
 MapIteratorObject *
 MapIteratorObject::create(JSContext *cx, HandleObject mapobj, ValueMap *data,
                           MapObject::IteratorKind kind)
 {
     Rooted<GlobalObject *> global(cx, &mapobj->global());
-    Rooted<JSObject*> proto(cx, global->getOrCreateMapIteratorPrototype(cx));
+    Rooted<JSObject*> proto(cx, GlobalObject::getOrCreateMapIteratorPrototype(cx, global));
     if (!proto)
         return nullptr;
 
     ValueMap::Range *range = cx->new_<ValueMap::Range>(data->all());
     if (!range)
         return nullptr;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &class_, proto, global);
@@ -1487,17 +1487,17 @@ SetIteratorObject::kind() const
     int32_t i = getSlot(KindSlot).toInt32();
     JS_ASSERT(i == SetObject::Values || i == SetObject::Entries);
     return SetObject::IteratorKind(i);
 }
 
 bool
 GlobalObject::initSetIteratorProto(JSContext *cx, Handle<GlobalObject*> global)
 {
-    JSObject *base = global->getOrCreateIteratorPrototype(cx);
+    JSObject *base = GlobalObject::getOrCreateIteratorPrototype(cx, global);
     if (!base)
         return false;
     RootedObject proto(cx, NewObjectWithGivenProto(cx, &SetIteratorObject::class_, base, global));
     if (!proto)
         return false;
     proto->setSlot(SetIteratorObject::RangeSlot, PrivateValue(nullptr));
     if (!JS_DefineFunctions(cx, proto, SetIteratorObject::methods))
         return false;
@@ -1505,17 +1505,17 @@ GlobalObject::initSetIteratorProto(JSCon
     return true;
 }
 
 SetIteratorObject *
 SetIteratorObject::create(JSContext *cx, HandleObject setobj, ValueSet *data,
                           SetObject::IteratorKind kind)
 {
     Rooted<GlobalObject *> global(cx, &setobj->global());
-    Rooted<JSObject*> proto(cx, global->getOrCreateSetIteratorPrototype(cx));
+    Rooted<JSObject*> proto(cx, GlobalObject::getOrCreateSetIteratorPrototype(cx, global));
     if (!proto)
         return nullptr;
 
     ValueSet::Range *range = cx->new_<ValueSet::Range>(data->all());
     if (!range)
         return nullptr;
 
     JSObject *iterobj = NewObjectWithGivenProto(cx, &class_, proto, global);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1968,17 +1968,17 @@ Parser<ParseHandler>::functionDef(Handle
         return pn;
 
     RootedObject proto(context);
     if (generatorKind == StarGenerator) {
         // If we are off the main thread, the generator meta-objects have
         // already been created by js::StartOffThreadParseScript, so cx will not
         // be necessary.
         JSContext *cx = context->maybeJSContext();
-        proto = context->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
+        proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, context->global());
         if (!proto)
             return null();
     }
     RootedFunction fun(context, newFunction(pc, funName, kind, proto));
     if (!fun)
         return null();
 
     // Speculatively parse using the directives of the parent parsing context.
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -6234,26 +6234,27 @@ static bool
 TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
                               ICGetProp_Fallback *stub, HandlePropertyName name, HandleValue val,
                               HandleValue res, bool *attached)
 {
     JS_ASSERT(!*attached);
 
     JSValueType primitiveType;
     RootedObject proto(cx);
+    Rooted<GlobalObject*> global(cx, &script->global());
     if (val.isString()) {
         primitiveType = JSVAL_TYPE_STRING;
-        proto = script->global().getOrCreateStringPrototype(cx);
+        proto = GlobalObject::getOrCreateStringPrototype(cx, global);
     } else if (val.isNumber()) {
         primitiveType = JSVAL_TYPE_DOUBLE;
-        proto = script->global().getOrCreateNumberPrototype(cx);
+        proto = GlobalObject::getOrCreateNumberPrototype(cx, global);
     } else {
         JS_ASSERT(val.isBoolean());
         primitiveType = JSVAL_TYPE_BOOLEAN;
-        proto = script->global().getOrCreateBooleanPrototype(cx);
+        proto = GlobalObject::getOrCreateBooleanPrototype(cx, global);
     }
     if (!proto)
         return false;
 
     // Instantiate this property, for use during Ion compilation.
     RootedId id(cx, NameToId(name));
     if (IsIonEnabled(cx))
         types::EnsureTrackPropertyTypes(cx, proto, id);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1377,17 +1377,18 @@ JS_GetFunctionPrototype(JSContext *cx, H
     return forObj->global().getOrCreateFunctionPrototype(cx);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetArrayPrototype(JSContext *cx, HandleObject forObj)
 {
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, forObj);
-    return forObj->global().getOrCreateArrayPrototype(cx);
+    Rooted<GlobalObject*> global(cx, &forObj->global());
+    return GlobalObject::getOrCreateArrayPrototype(cx, global);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
     return &obj->global();
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -203,19 +203,20 @@ ResolveInterpretedFunctionPrototype(JSCo
     JS_ASSERT(!IsInternalFunctionObject(obj));
     JS_ASSERT(!obj->isBoundFunction());
 
     // Make the prototype object an instance of Object with the same parent as
     // the function object itself, unless the function is an ES6 generator.  In
     // that case, per the 15 July 2013 ES6 draft, section 15.19.3, its parent is
     // the GeneratorObjectPrototype singleton.
     bool isStarGenerator = obj->as<JSFunction>().isStarGenerator();
+    Rooted<GlobalObject*> global(cx, &obj->global());
     JSObject *objProto;
     if (isStarGenerator)
-        objProto = obj->global().getOrCreateStarGeneratorObjectPrototype(cx);
+        objProto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
     else
         objProto = obj->global().getOrCreateObjectPrototype(cx);
     if (!objProto)
         return nullptr;
     const Class *clasp = &JSObject::class_;
 
     RootedObject proto(cx, NewObjectWithGivenProto(cx, clasp, objProto, nullptr, SingletonObject));
     if (!proto)
@@ -391,17 +392,17 @@ js::XDRInterpretedFunction(XDRState<mode
     }
 
     if (!xdr->codeUint32(&firstword))
         return false;
 
     if (mode == XDR_DECODE) {
         JSObject *proto = nullptr;
         if (firstword & IsStarGenerator) {
-            proto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
+            proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
             if (!proto)
                 return false;
         }
         fun = NewFunctionWithProto(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED,
                                    NullPtr(), NullPtr(), proto,
                                    JSFunction::FinalizeKind, TenuredObject);
         if (!fun)
             return false;
@@ -439,17 +440,17 @@ template bool
 js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleObject);
 
 JSObject *
 js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
 {
     /* NB: Keep this in sync with XDRInterpretedFunction. */
     JSObject *cloneProto = nullptr;
     if (srcFun->isStarGenerator()) {
-        cloneProto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
+        cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
     RootedFunction clone(cx, NewFunctionWithProto(cx, NullPtr(), nullptr, 0,
                                                   JSFunction::INTERPRETED, NullPtr(), NullPtr(),
                                                   cloneProto, JSFunction::FinalizeKind,
                                                   TenuredObject));
     if (!clone)
@@ -1649,17 +1650,17 @@ FunctionConstructor(JSContext *cx, unsig
      * NB: (new Function) is not lexically closed by its caller, it's just an
      * anonymous function in the top-level scope that its constructor inhabits.
      * Thus 'var x = 42; f = new Function("return x"); print(f())' prints 42,
      * and so would a call to f from another top-level's script or function.
      */
     RootedAtom anonymousAtom(cx, cx->names().anonymous);
     JSObject *proto = nullptr;
     if (isStarGenerator) {
-        proto = global->getOrCreateStarGeneratorFunctionPrototype(cx);
+        proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global);
         if (!proto)
             return false;
     }
     RootedFunction fun(cx, NewFunctionWithProto(cx, js::NullPtr(), nullptr, 0,
                                                 JSFunction::INTERPRETED_LAMBDA, global,
                                                 anonymousAtom, proto,
                                                 JSFunction::FinalizeKind, TenuredObject));
     if (!fun)
@@ -1771,17 +1772,17 @@ js::CloneFunctionObject(JSContext *cx, H
                          !types::UseNewTypeForClone(fun);
 
     if (!useSameScript && fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
         return nullptr;
 
     NewObjectKind newKind = useSameScript ? newKindArg : SingletonObject;
     JSObject *cloneProto = nullptr;
     if (fun->isStarGenerator()) {
-        cloneProto = cx->global()->getOrCreateStarGeneratorFunctionPrototype(cx);
+        cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
     JSObject *cloneobj = NewObjectWithClassProto(cx, &JSFunction::class_, cloneProto,
                                                  SkipScopeParent(parent), allocKind, newKind);
     if (!cloneobj)
         return nullptr;
     RootedFunction clone(cx, &cloneobj->as<JSFunction>());
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1546,24 +1546,24 @@ js_NewGenerator(JSContext *cx, const Fra
         RootedValue pval(cx);
         RootedObject fun(cx, stackfp->fun());
         // FIXME: This would be faster if we could avoid doing a lookup to get
         // the prototype for the instance.  Bug 906600.
         if (!JSObject::getProperty(cx, fun, fun, cx->names().prototype, &pval))
             return nullptr;
         JSObject *proto = pval.isObject() ? &pval.toObject() : nullptr;
         if (!proto) {
-            proto = global->getOrCreateStarGeneratorObjectPrototype(cx);
+            proto = GlobalObject::getOrCreateStarGeneratorObjectPrototype(cx, global);
             if (!proto)
                 return nullptr;
         }
         obj = NewObjectWithGivenProto(cx, &StarGeneratorObject::class_, proto, global);
     } else {
         JS_ASSERT(stackfp->script()->isLegacyGenerator());
-        JSObject *proto = global->getOrCreateLegacyGeneratorObjectPrototype(cx);
+        JSObject *proto = GlobalObject::getOrCreateLegacyGeneratorObjectPrototype(cx, global);
         if (!proto)
             return nullptr;
         obj = NewObjectWithGivenProto(cx, &LegacyGeneratorObject::class_, proto, global);
     }
     if (!obj)
         return nullptr;
 
     /* Load and compute stack slot counts. */
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -865,17 +865,17 @@ js_InitJSONClass(JSContext *cx, HandleOb
 {
     Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
 
     /*
      * JSON requires that Boolean.prototype.valueOf be created and stashed in a
      * reserved slot on the global object; see js::BooleanGetPrimitiveValueSlow
      * called from PreprocessValue above.
      */
-    if (!global->getOrCreateBooleanPrototype(cx))
+    if (!GlobalObject::getOrCreateBooleanPrototype(cx, global))
         return nullptr;
 
     RootedObject proto(cx, obj->as<GlobalObject>().getOrCreateObjectPrototype(cx));
     RootedObject JSON(cx, NewObjectWithClassProto(cx, &JSONClass, proto, global, SingletonObject));
     if (!JSON)
         return nullptr;
 
     if (!JS_DefineProperty(cx, global, js_JSON_str, OBJECT_TO_JSVAL(JSON),
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4201,19 +4201,18 @@ DebuggerFrame_getArguments(JSContext *cx
         JS_ASSERT(argumentsv.isObjectOrNull());
         args.rval().set(argumentsv);
         return true;
     }
 
     RootedObject argsobj(cx);
     if (frame.hasArgs()) {
         /* Create an arguments object. */
-        Rooted<GlobalObject*> global(cx);
-        global = &args.callee().global();
-        JSObject *proto = global->getOrCreateArrayPrototype(cx);
+        Rooted<GlobalObject*> global(cx, &args.callee().global());
+        JSObject *proto = GlobalObject::getOrCreateArrayPrototype(cx, global);
         if (!proto)
             return false;
         argsobj = NewObjectWithGivenProto(cx, &DebuggerArguments_class, proto, global);
         if (!argsobj)
             return false;
         SetReservedSlot(argsobj, JSSLOT_DEBUGARGUMENTS_FRAME, ObjectValue(*thisobj));
 
         JS_ASSERT(frame.numActualArgs() <= 0x7fffffff);
--- a/js/src/vm/ErrorObject.cpp
+++ b/js/src/vm/ErrorObject.cpp
@@ -82,17 +82,17 @@ js::ErrorObject::init(JSContext *cx, Han
     return true;
 }
 
 /* static */ ErrorObject *
 js::ErrorObject::create(JSContext *cx, JSExnType errorType, HandleString stack,
                         HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
                         ScopedJSFreePtr<JSErrorReport> *report, HandleString message)
 {
-    Rooted<JSObject*> proto(cx, cx->global()->getOrCreateCustomErrorPrototype(cx, errorType));
+    Rooted<JSObject*> proto(cx, GlobalObject::getOrCreateCustomErrorPrototype(cx, cx->global(), errorType));
     if (!proto)
         return nullptr;
 
     Rooted<ErrorObject*> errObject(cx);
     {
         JSObject* obj = NewObjectWithGivenProto(cx, &ErrorObject::class_, proto, nullptr);
         if (!obj)
             return nullptr;
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -333,76 +333,72 @@ class GlobalObject : public JSObject
         if (functionObjectClassesInitialized())
             return &getPrototype(JSProto_Function).toObject();
         Rooted<GlobalObject*> self(cx, this);
         if (!initFunctionAndObjectClasses(cx))
             return nullptr;
         return &self->getPrototype(JSProto_Function).toObject();
     }
 
-    JSObject *getOrCreateArrayPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_Array))
+    static JSObject *getOrCreateArrayPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_Array))
             return nullptr;
-        return &self->getPrototype(JSProto_Array).toObject();
+        return &global->getPrototype(JSProto_Array).toObject();
     }
 
     JSObject *maybeGetArrayPrototype() {
         if (arrayClassInitialized())
             return &getPrototype(JSProto_Array).toObject();
         return nullptr;
     }
 
-    JSObject *getOrCreateBooleanPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_Boolean))
+    static JSObject *getOrCreateBooleanPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_Boolean))
             return nullptr;
-        return &self->getPrototype(JSProto_Boolean).toObject();
+        return &global->getPrototype(JSProto_Boolean).toObject();
     }
 
-    JSObject *getOrCreateNumberPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_Number))
+    static JSObject *getOrCreateNumberPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_Number))
             return nullptr;
-        return &self->getPrototype(JSProto_Number).toObject();
+        return &global->getPrototype(JSProto_Number).toObject();
     }
 
-    JSObject *getOrCreateStringPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_String))
+    static JSObject *getOrCreateStringPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_String))
             return nullptr;
-        return &self->getPrototype(JSProto_String).toObject();
+        return &global->getPrototype(JSProto_String).toObject();
     }
 
-    JSObject *getOrCreateRegExpPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_RegExp))
+    static JSObject *getOrCreateRegExpPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_RegExp))
             return nullptr;
-        return &self->getPrototype(JSProto_RegExp).toObject();
+        return &global->getPrototype(JSProto_RegExp).toObject();
     }
 
     JSObject *maybeGetRegExpPrototype() {
         if (regexpClassInitialized())
             return &getPrototype(JSProto_RegExp).toObject();
         return nullptr;
     }
 
-    JSObject *getOrCreateArrayBufferPrototype(JSContext *cx) {
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, JSProto_ArrayBuffer))
+    static JSObject *getOrCreateArrayBufferPrototype(JSContext *cx, Handle<GlobalObject*> global) {
+        if (!global->ensureConstructor(cx, JSProto_ArrayBuffer))
             return nullptr;
-        return &self->getPrototype(JSProto_ArrayBuffer).toObject();
+        return &global->getPrototype(JSProto_ArrayBuffer).toObject();
     }
 
-    JSObject *getOrCreateCustomErrorPrototype(JSContext *cx, JSExnType exnType) {
+    static JSObject *getOrCreateCustomErrorPrototype(JSContext *cx,
+                                                     Handle<GlobalObject*> global,
+                                                     JSExnType exnType)
+    {
         JSProtoKey key = GetExceptionProtoKey(exnType);
-        Rooted<GlobalObject*> self(cx, this);
-        if (!ensureConstructor(cx, key))
+        if (!global->ensureConstructor(cx, key))
             return nullptr;
-        return &self->getPrototype(key).toObject();
+        return &global->getPrototype(key).toObject();
     }
 
     JSObject *getOrCreateIntlObject(JSContext *cx) {
         return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_Intl, initIntlObject);
     }
 
     JSObject *getOrCreateTypedObjectModule(JSContext *cx) {
         return getOrCreateObject(cx, APPLICATION_SLOTS + JSProto_TypedObject, initTypedObjectModule);
@@ -468,64 +464,82 @@ class GlobalObject : public JSObject
         uint32_t fixed = numFixedSlotsForCompilation();
         AutoThreadSafeAccess ts(this);
         if (slot < fixed)
             return fixedSlots()[slot];
         return slots[slot - fixed];
     }
 
   public:
-    JSObject *getOrCreateIteratorPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateIteratorPrototype(JSContext *cx,
+                                                  Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator).toObject();
+        return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_Iterator).toObject();
     }
 
-    JSObject *getOrCreateArrayIteratorPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateArrayIteratorPrototype(JSContext *cx,
+                                                       Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(ARRAY_ITERATOR_PROTO).toObject();
+        return &global->getSlot(ARRAY_ITERATOR_PROTO).toObject();
     }
 
-    JSObject *getOrCreateStringIteratorPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateStringIteratorPrototype(JSContext *cx,
+                                                        Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(STRING_ITERATOR_PROTO).toObject();
+        return &global->getSlot(STRING_ITERATOR_PROTO).toObject();
     }
 
-    JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx,
+                                                               Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(LEGACY_GENERATOR_OBJECT_PROTO).toObject();
+        return &global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).toObject();
     }
 
-    JSObject *getOrCreateStarGeneratorObjectPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateStarGeneratorObjectPrototype(JSContext *cx,
+                                                             Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(STAR_GENERATOR_OBJECT_PROTO).toObject();
+        return &global->getSlot(STAR_GENERATOR_OBJECT_PROTO).toObject();
     }
 
-    JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateStarGeneratorFunctionPrototype(JSContext *cx,
+                                                               Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_GeneratorFunction).toObject();
+        return &global->getSlot(APPLICATION_SLOTS + JSProto_LIMIT + JSProto_GeneratorFunction).toObject();
     }
 
-    JSObject *getOrCreateStarGeneratorFunction(JSContext *cx) {
-        if (!ensureConstructor(cx, JSProto_Iterator))
+    static JSObject *getOrCreateStarGeneratorFunction(JSContext *cx,
+                                                      Handle<GlobalObject*> global)
+    {
+        if (!global->ensureConstructor(cx, JSProto_Iterator))
             return nullptr;
-        return &getSlot(APPLICATION_SLOTS + JSProto_GeneratorFunction).toObject();
+        return &global->getSlot(APPLICATION_SLOTS + JSProto_GeneratorFunction).toObject();
     }
 
-    JSObject *getOrCreateMapIteratorPrototype(JSContext *cx) {
-        return getOrCreateObject(cx, MAP_ITERATOR_PROTO, initMapIteratorProto);
+    static JSObject *getOrCreateMapIteratorPrototype(JSContext *cx,
+                                                     Handle<GlobalObject*> global)
+    {
+        return global->getOrCreateObject(cx, MAP_ITERATOR_PROTO, initMapIteratorProto);
     }
 
-    JSObject *getOrCreateSetIteratorPrototype(JSContext *cx) {
-        return getOrCreateObject(cx, SET_ITERATOR_PROTO, initSetIteratorProto);
+    static JSObject *getOrCreateSetIteratorPrototype(JSContext *cx,
+                                                     Handle<GlobalObject*> global)
+    {
+        return global->getOrCreateObject(cx, SET_ITERATOR_PROTO, initSetIteratorProto);
     }
 
     JSObject *getOrCreateDataViewPrototype(JSContext *cx) {
         Rooted<GlobalObject*> self(cx, this);
         if (!ensureConstructor(cx, JSProto_DataView))
             return nullptr;
         return &self->getPrototype(JSProto_DataView).toObject();
     }
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -108,24 +108,24 @@ GuardFunApplyArgumentsOptimization(JSCon
  * problem to the value at |spindex| on the stack.
  */
 MOZ_ALWAYS_INLINE JSObject *
 ValuePropertyBearer(JSContext *cx, StackFrame *fp, HandleValue v, int spindex)
 {
     if (v.isObject())
         return &v.toObject();
 
-    GlobalObject &global = fp->global();
+    Rooted<GlobalObject*> global(cx, &fp->global());
 
     if (v.isString())
-        return global.getOrCreateStringPrototype(cx);
+        return GlobalObject::getOrCreateStringPrototype(cx, global);
     if (v.isNumber())
-        return global.getOrCreateNumberPrototype(cx);
+        return GlobalObject::getOrCreateNumberPrototype(cx, global);
     if (v.isBoolean())
-        return global.getOrCreateBooleanPrototype(cx);
+        return GlobalObject::getOrCreateBooleanPrototype(cx, global);
 
     JS_ASSERT(v.isNull() || v.isUndefined());
     js_ReportIsNullOrUndefined(cx, spindex, v, NullPtr());
     return nullptr;
 }
 
 inline bool
 GetLengthProperty(const Value &lval, MutableHandleValue vp)
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -237,22 +237,23 @@ GetPropertyOperation(JSContext *cx, Stac
             vp.setInt32(fp->numActualArgs());
             return true;
         }
 
         if (GetLengthProperty(lval, vp))
             return true;
     }
 
+    Rooted<GlobalObject*> global(cx, &fp->global());
     RootedId id(cx, NameToId(script->getName(pc)));
     RootedObject obj(cx);
 
     /* Optimize (.1).toString(). */
     if (lval.isNumber() && id == NameToId(cx->names().toString)) {
-        JSObject *proto = fp->global().getOrCreateNumberPrototype(cx);
+        JSObject *proto = GlobalObject::getOrCreateNumberPrototype(cx, global);
         if (!proto)
             return false;
         if (ClassMethodIsNative(cx, proto, &NumberObject::class_, id, js_num_toString))
             obj = proto;
     }
 
     if (!obj) {
         obj = ToObjectFromStack(cx, lval);
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -464,31 +464,31 @@ js::intrinsic_IsPackedArray(JSContext *c
 }
 
 static bool
 intrinsic_GetIteratorPrototype(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() == 0);
 
-    JSObject *obj = cx->global()->getOrCreateIteratorPrototype(cx);
+    JSObject *obj = GlobalObject::getOrCreateIteratorPrototype(cx, cx->global());
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
 static bool
 intrinsic_NewArrayIterator(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() == 0);
 
-    RootedObject proto(cx, cx->global()->getOrCreateArrayIteratorPrototype(cx));
+    RootedObject proto(cx, GlobalObject::getOrCreateArrayIteratorPrototype(cx, cx->global()));
     if (!proto)
         return false;
 
     JSObject *obj = NewObjectWithGivenProto(cx, proto->getClass(), proto, cx->global());
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
@@ -507,17 +507,17 @@ intrinsic_IsArrayIterator(JSContext *cx,
 }
 
 static bool
 intrinsic_NewStringIterator(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() == 0);
 
-    RootedObject proto(cx, cx->global()->getOrCreateStringIteratorPrototype(cx));
+    RootedObject proto(cx, GlobalObject::getOrCreateStringIteratorPrototype(cx, cx->global()));
     if (!proto)
         return false;
 
     JSObject *obj = NewObjectWithGivenProto(cx, &StringIteratorObject::class_, proto, cx->global());
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);