Bug 975589, part 4 - Rename js_GetClassObject -> js::GetBuiltinConstructor and make it never return true without the desired constructor actually existing. r=jwalden.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 10 Mar 2014 16:30:40 -0500
changeset 191075 65e920598d2bda7ac115fb9b856e072eb52128c4
parent 191074 bb4060b72c3882c43b3a2e779c625a7935863eda
child 191076 78f1a88a4048155cb24ae3fa10e4b36f8aa08878
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs975589
milestone30.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 975589, part 4 - Rename js_GetClassObject -> js::GetBuiltinConstructor and make it never return true without the desired constructor actually existing. r=jwalden.
js/src/jit/IonBuilder.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jscompartment.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/jsworkers.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -6113,17 +6113,17 @@ IonBuilder::testSingletonPropertyTypes(M
         // If this is not a known object, a test will be needed.
         *testObject = (obj->type() != MIRType_Object);
         return true;
       }
       default:
         return false;
     }
 
-    JSObject *proto = GetClassPrototypePure(&script()->global(), key);
+    JSObject *proto = GetBuiltinPrototypePure(&script()->global(), key);
     if (proto)
         return testSingletonProperty(proto, name) == singleton;
 
     return false;
 }
 
 // Given an observed type set, annotates the IR as much as possible:
 // (1) If no type information is provided, the value on the top of the stack is
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1347,28 +1347,28 @@ JS_EnumerateStandardClasses(JSContext *c
     return GlobalObject::initStandardClasses(cx, global);
 }
 
 JS_PUBLIC_API(bool)
 JS_GetClassObject(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    return js_GetClassObject(cx, key, objp);
+    return GetBuiltinConstructor(cx, key, objp);
 }
 
 JS_PUBLIC_API(bool)
 JS_GetClassPrototype(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    return js_GetClassPrototype(cx, key, objp);
-}
-
-extern JS_PUBLIC_API(JSProtoKey)
+    return GetBuiltinPrototype(cx, key, objp);
+}
+
+JS_PUBLIC_API(JSProtoKey)
 JS_IdToProtoKey(JSContext *cx, HandleId id)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     if (!JSID_IS_ATOM(id))
         return JSProto_Null;
     RootedString idstr(cx, JSID_TO_STRING(id));
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3175,17 +3175,17 @@ NewArray(ExclusiveContext *cxArg, uint32
             }
         }
     }
 
     RootedObject proto(cxArg, protoArg);
     if (protoArg)
         JS::PoisonPtr(&protoArg);
 
-    if (!proto && !FindProto(cxArg, &ArrayObject::class_, &proto))
+    if (!proto && !GetBuiltinPrototype(cxArg, JSProto_Array, &proto))
         return nullptr;
 
     RootedTypeObject type(cxArg, cxArg->getNewType(&ArrayObject::class_, proto.get()));
     if (!type)
         return nullptr;
 
     JSObject *metadata = nullptr;
     if (!NewObjectMetadata(cxArg, &metadata))
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -348,54 +348,54 @@ JSCompartment::wrap(JSContext *cx, Mutab
     JS_ASSERT(cx->compartment() == this);
     JS_ASSERT_IF(existingArg, existingArg->compartment() == cx->compartment());
     JS_ASSERT_IF(existingArg, IsDeadProxyObject(existingArg));
 
     if (!obj)
         return true;
     AutoDisableProxyCheck adpc(cx->runtime());
 
-    /*
-     * Wrappers should really be parented to the wrapped parent of the wrapped
-     * object, but in that case a wrapped global object would have a nullptr
-     * 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.
-     */
+    // Wrappers should really be parented to the wrapped parent of the wrapped
+    // object, but in that case a wrapped global object would have a nullptr
+    // 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.
     HandleObject global = cx->global();
     RootedObject objGlobal(cx, &obj->global());
     JS_ASSERT(global);
     JS_ASSERT(objGlobal);
 
     JS_ASSERT(!cx->runtime()->isSelfHostingGlobal(global) &&
               !cx->runtime()->isSelfHostingGlobal(objGlobal));
 
     const JSWrapObjectCallbacks *cb = cx->runtime()->wrapObjectCallbacks;
 
     if (obj->compartment() == this)
         return WrapForSameCompartment(cx, obj, cb);
 
-    /* Unwrap the object, but don't unwrap outer windows. */
+    // Unwrap the object, but don't unwrap outer windows.
     unsigned flags = 0;
     obj.set(UncheckedUnwrap(obj, /* stopAtOuter = */ true, &flags));
 
     if (obj->compartment() == this)
         return WrapForSameCompartment(cx, obj, cb);
 
-    /* Translate StopIteration singleton. */
+    // Translate StopIteration singleton.
     if (obj->is<StopIterationObject>()) {
+        // StopIteration isn't a constructor, but it's stored in GlobalObject
+        // as one, out of laziness. Hence the GetBuiltinConstructor call here.
         RootedObject stopIteration(cx);
-        if (!js_GetClassObject(cx, JSProto_StopIteration, &stopIteration))
+        if (!GetBuiltinConstructor(cx, JSProto_StopIteration, &stopIteration))
             return false;
         obj.set(stopIteration);
         return true;
     }
 
-    /* Invoke the prewrap callback. We're a bit worried about infinite
-     * recursion here, so we do a check - see bug 809295. */
+    // Invoke the prewrap callback. We're a bit worried about infinite
+    // recursion here, so we do a check - see bug 809295.
     JS_CHECK_CHROME_RECURSION(cx, return false);
     if (cb->preWrap) {
         obj.set(cb->preWrap(cx, global, obj, flags));
         if (!obj)
             return false;
     }
 
     if (obj->compartment() == this)
@@ -403,47 +403,45 @@ JSCompartment::wrap(JSContext *cx, Mutab
 
 #ifdef DEBUG
     {
         JSObject *outer = GetOuterObject(cx, obj);
         JS_ASSERT(outer && outer == obj);
     }
 #endif
 
-    /* If we already have a wrapper for this value, use it. */
+    // If we already have a wrapper for this value, use it.
     RootedValue key(cx, ObjectValue(*obj));
     if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) {
         obj.set(&p->value().get().toObject());
         JS_ASSERT(obj->is<CrossCompartmentWrapperObject>());
         JS_ASSERT(obj->getParent() == global);
         return true;
     }
 
     RootedObject proto(cx, TaggedProto::LazyProto);
     RootedObject existing(cx, existingArg);
     if (existing) {
-        /* Is it possible to reuse |existing|? */
+        // Is it possible to reuse |existing|?
         if (!existing->getTaggedProto().isLazy() ||
             // Note: don't use is<ObjectProxyObject>() here -- it also matches subclasses!
             existing->getClass() != &ProxyObject::uncallableClass_ ||
             existing->getParent() != global ||
             obj->isCallable())
         {
             existing = nullptr;
         }
     }
 
     obj.set(cb->wrap(cx, existing, obj, proto, global, flags));
     if (!obj)
         return false;
 
-    /*
-     * We maintain the invariant that the key in the cross-compartment wrapper
-     * map is always directly wrapped by the value.
-     */
+    // We maintain the invariant that the key in the cross-compartment wrapper
+    // map is always directly wrapped by the value.
     JS_ASSERT(Wrapper::wrappedObject(obj) == &key.get().toObject());
 
     return putWrapper(cx, key, ObjectValue(*obj));
 }
 
 bool
 JSCompartment::wrapId(JSContext *cx, jsid *idp)
 {
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1999,17 +1999,17 @@ TypeCompartment::addAllocationSiteTypeOb
 
         AllocationSiteTable::Ptr p = cx->compartment()->types.allocationSiteTable->lookup(nkey);
         if (p)
             res = p->value();
     }
 
     if (!res) {
         RootedObject proto(cx);
-        if (!js_GetClassPrototype(cx, key.kind, &proto))
+        if (!GetBuiltinPrototype(cx, key.kind, &proto))
             return nullptr;
 
         Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
         res = newTypeObject(cx, GetClassForProtoKey(key.kind), tagged, OBJECT_FLAG_FROM_ALLOCATION_SITE);
         if (!res)
             return nullptr;
         key.script = keyScript;
     }
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -318,17 +318,17 @@ GetClassForProtoKey(JSProtoKey key)
 /*
  * 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);
-    if (!js_GetClassPrototype(cx, key, &proto))
+    if (!GetBuiltinPrototype(cx, key, &proto))
         return nullptr;
     return cx->getNewType(GetClassForProtoKey(key), proto.get());
 }
 
 /* Get a type object for the immediate allocation site within a native. */
 inline TypeObject *
 GetTypeCallerInitObject(JSContext *cx, JSProtoKey key)
 {
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -736,18 +736,21 @@ js::CreateItrResultObject(JSContext *cx,
 
     return obj;
 }
 
 bool
 js_ThrowStopIteration(JSContext *cx)
 {
     JS_ASSERT(!JS_IsExceptionPending(cx));
+
+    // StopIteration isn't a constructor, but it's stored in GlobalObject
+    // as one, out of laziness. Hence the GetBuiltinConstructor call here.
     RootedObject ctor(cx);
-    if (js_GetClassObject(cx, JSProto_StopIteration, &ctor) && ctor)
+    if (GetBuiltinConstructor(cx, JSProto_StopIteration, &ctor))
         cx->setPendingException(ObjectValue(*ctor));
     return false;
 }
 
 /*** Iterator objects ****************************************************************************/
 
 bool
 js::IteratorConstructor(JSContext *cx, unsigned argc, Value *vp)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2554,17 +2554,17 @@ DefineConstructorAndPrototype(JSContext 
          */
         RootedFunction fun(cx, NewFunction(cx, NullPtr(), constructor, nargs,
                                            JSFunction::NATIVE_CTOR, obj, atom, ctorKind));
         if (!fun)
             goto bad;
 
         /*
          * Set the class object early for standard class constructors. Type
-         * inference may need to access these, and js_GetClassPrototype will
+         * inference may need to access these, and js::GetBuiltinPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
          */
         if (key != JSProto_Null) {
             SetClassObject(obj, key, fun, proto);
             cached = true;
         }
 
         RootedValue value(cx, ObjectValue(*fun));
@@ -2633,26 +2633,24 @@ js_InitClass(JSContext *cx, HandleObject
         return nullptr;
 
     /*
      * All instances of the class will inherit properties from the prototype
      * object we are about to create (in DefineConstructorAndPrototype), which
      * in turn will inherit from protoProto.
      *
      * When initializing a standard class (other than Object), if protoProto is
-     * null, default to the Object prototype object. The engine's internal uses
-     * 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 nullptr
-     * and returning true.
+     * null, default to Object.prototype. The engine's internal uses of
+     * js_InitClass depend on this nicety.
      */
     JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(clasp);
     if (key != JSProto_Null &&
         !protoProto &&
-        !js_GetClassPrototype(cx, JSProto_Object, &protoProto)) {
+        !GetBuiltinPrototype(cx, JSProto_Object, &protoProto))
+    {
         return nullptr;
     }
 
     return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
                                          ps, fs, static_ps, static_fs, ctorp, ctorKind);
 }
 
 /* static */ inline bool
@@ -3240,40 +3238,36 @@ MaybeResolveConstructor(ExclusiveContext
     if (!cxArg->shouldBeJSContext())
         return false;
 
     JSContext *cx = cxArg->asJSContext();
     return GlobalObject::resolveConstructor(cx, global, key);
 }
 
 bool
-js_GetClassObject(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp)
+js::GetBuiltinConstructor(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp)
 {
     MOZ_ASSERT(key != JSProto_Null);
     Rooted<GlobalObject*> global(cx, cx->global());
     if (!MaybeResolveConstructor(cx, global, key))
         return false;
 
-    Value v = global->getConstructor(key);
-    if (v.isObject())
-        objp.set(&v.toObject());
+    objp.set(&global->getConstructor(key).toObject());
     return true;
 }
 
 bool
-js_GetClassPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject protop)
+js::GetBuiltinPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject protop)
 {
     MOZ_ASSERT(key != JSProto_Null);
     Rooted<GlobalObject*> global(cx, cx->global());
     if (!MaybeResolveConstructor(cx, global, key))
         return false;
 
-    Value v = global->getPrototype(key);
-    if (v.isObject())
-        protop.set(&v.toObject());
+    protop.set(&global->getPrototype(key).toObject());
     return true;
 }
 
 static bool
 IsStandardPrototype(JSObject *obj, JSProtoKey key)
 {
     GlobalObject &global = obj->global();
     Value v = global.getPrototype(key);
@@ -3304,36 +3298,29 @@ JS::IdentifyStandardPrototype(JSObject *
 
 JSProtoKey
 JS::IdentifyStandardInstanceOrPrototype(JSObject *obj)
 {
     return JSCLASS_CACHED_PROTO_KEY(obj->getClass());
 }
 
 bool
-js_FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
-{
-    MOZ_ASSERT(clasp);
+js::FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
+{
     JSProtoKey protoKey = GetClassProtoKey(clasp);
-    RootedId id(cx);
     if (protoKey != JSProto_Null) {
         JS_ASSERT(JSProto_Null < protoKey);
         JS_ASSERT(protoKey < JSProto_LIMIT);
-        RootedObject cobj(cx);
-        if (!js_GetClassObject(cx, protoKey, protop))
-            return false;
-        if (cobj)
-            return true;
-        id = NameToId(ClassName(protoKey, cx));
-    } else {
-        JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
-        if (!atom)
-            return false;
-        id = AtomToId(atom);
-    }
+        return GetBuiltinConstructor(cx, protoKey, protop);
+    }
+
+    JSAtom *atom = Atomize(cx, clasp->name, strlen(clasp->name));
+    if (!atom)
+        return false;
+    RootedId id(cx, AtomToId(atom));
 
     RootedObject pobj(cx);
     RootedShape shape(cx);
     if (!LookupPropertyWithFlags(cx, cx->global(), id, 0, &pobj, &shape))
         return false;
     RootedValue v(cx);
     if (shape && pobj->isNative()) {
         if (shape->hasSlot())
@@ -5460,17 +5447,17 @@ js::IsDelegateOfObject(JSContext *cx, Ha
         if (obj2 == protoObj) {
             *result = true;
             return true;
         }
     }
 }
 
 JSObject *
-js::GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey)
+js::GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey)
 {
     JS_ASSERT(JSProto_Null <= protoKey);
     JS_ASSERT(protoKey < JSProto_LIMIT);
 
     if (protoKey != JSProto_Null) {
         const Value &v = global->getPrototype(protoKey);
         if (v.isObject())
             return &v.toObject();
@@ -5479,29 +5466,25 @@ js::GetClassPrototypePure(GlobalObject *
     return nullptr;
 }
 
 /*
  * The first part of this function has been hand-expanded and optimized into
  * NewBuiltinClassInstance in jsobjinlines.h.
  */
 bool
-js_FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
+js::FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp)
 {
     protop.set(nullptr);
     JSProtoKey protoKey = GetClassProtoKey(clasp);
-    if (protoKey != JSProto_Null) {
-        if (!js_GetClassPrototype(cx, protoKey, protop))
-            return false;
-        if (protop)
-            return true;
-    }
+    if (protoKey != JSProto_Null)
+        return GetBuiltinPrototype(cx, protoKey, protop);
 
     RootedObject ctor(cx);
-    if (!js_FindClassObject(cx, &ctor, clasp))
+    if (!FindClassObject(cx, &ctor, clasp))
         return false;
 
     if (ctor && ctor->is<JSFunction>()) {
         RootedValue v(cx);
         if (cx->isJSContext()) {
             if (!JSObject::getProperty(cx->asJSContext(),
                                        ctor, ctor, cx->names().prototype, &v))
             {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1306,16 +1306,45 @@ extern bool
 HasOwnProperty(JSContext *cx, LookupGenericOp lookup,
                typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
                typename MaybeRooted<jsid, allowGC>::HandleType id,
                typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
                typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
 
 typedef JSObject *(*ClassInitializerOp)(JSContext *cx, JS::HandleObject obj);
 
+/* Fast access to builtin constructors and prototypes. */
+bool
+GetBuiltinConstructor(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp);
+
+bool
+GetBuiltinPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp);
+
+const Class *
+ProtoKeyToClass(JSProtoKey key);
+
+JSObject *
+GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey);
+
+extern bool
+SetClassAndProto(JSContext *cx, HandleObject obj,
+                 const Class *clasp, Handle<TaggedProto> proto, bool *succeeded);
+
+/*
+ * Property-lookup-based access to interface and prototype objects for classes.
+ * If the class is built-in (hhas a non-null JSProtoKey), these forward to
+ * GetClass{Object,Prototype}.
+ */
+
+bool
+FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp);
+
+extern bool
+FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp);
+
 } /* namespace js */
 
 /*
  * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
  */
 extern const char js_watch_str[];
 extern const char js_unwatch_str[];
 extern const char js_hasOwnProperty_str[];
@@ -1327,41 +1356,16 @@ extern const char js_defineGetter_str[];
 extern const char js_defineSetter_str[];
 extern const char js_lookupGetter_str[];
 extern const char js_lookupSetter_str[];
 #endif
 
 extern bool
 js_PopulateObject(JSContext *cx, js::HandleObject newborn, js::HandleObject props);
 
-/*
- * Fast access to immutable standard objects (constructors and prototypes).
- */
-extern bool
-js_GetClassObject(js::ExclusiveContext *cx, JSProtoKey key,
-                  js::MutableHandleObject objp);
-
-extern bool
-js_GetClassPrototype(js::ExclusiveContext *cx, JSProtoKey key,
-                     js::MutableHandleObject objp);
-
-/*
- * Property-lookup-based access to interface and prototype objects for classes.
- * If the class is built-in (and has a non-null JSProtoKey), these forward to
- * js_GetClass{Object,Prototype}.
- */
-
-bool
-js_FindClassObject(js::ExclusiveContext *cx, js::MutableHandleObject protop,
-                   const js::Class *clasp);
-
-extern bool
-js_FindClassPrototype(js::ExclusiveContext *cx, js::MutableHandleObject protop,
-                      const js::Class *clasp);
-
 
 namespace js {
 
 extern bool
 DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                   JS::HandleValue descriptor, bool *bp);
 
 extern bool
@@ -1613,26 +1617,16 @@ extern bool
 js_ReportGetterOnlyAssignment(JSContext *cx, bool strict);
 
 extern unsigned
 js_InferFlags(JSContext *cx, unsigned defaultFlags);
 
 
 namespace js {
 
-const Class *
-ProtoKeyToClass(JSProtoKey key);
-
-JSObject *
-GetClassPrototypePure(GlobalObject *global, JSProtoKey protoKey);
-
-extern bool
-SetClassAndProto(JSContext *cx, HandleObject obj,
-                 const Class *clasp, Handle<TaggedProto> proto, bool *succeeded);
-
 extern JSObject *
 NonNullObject(JSContext *cx, const Value &v);
 
 extern const char *
 InformalValueTypeName(const Value &v);
 
 extern bool
 GetFirstArgumentAsObject(JSContext *cx, const CallArgs &args, const char *method,
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -866,20 +866,27 @@ GetClassProtoKey(const js::Class *clasp)
     if (clasp->flags & JSCLASS_IS_ANONYMOUS)
         return JSProto_Object;
     return JSProto_Null;
 }
 
 inline bool
 FindProto(ExclusiveContext *cx, const js::Class *clasp, MutableHandleObject proto)
 {
-    if (!js_FindClassPrototype(cx, proto, clasp))
+    if (!FindClassPrototype(cx, proto, clasp))
         return false;
-    if (!proto && !js_GetClassPrototype(cx, JSProto_Object, proto))
-        return false;
+
+    if (!proto) {
+        // We're looking for the prototype of a class that is currently being
+        // resolved; the global object's resolve hook is on the
+        // stack. js::FindClassPrototype detects this goofy case and returns
+        // true with proto null. Fall back on Object.prototype.
+        JS_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == JSProto_Null);
+        return GetBuiltinPrototype(cx, JSProto_Object, proto);
+    }
     return true;
 }
 
 /*
  * Make an object with the prototype set according to the specified prototype or class:
  *
  * if proto is non-null:
  *   use the specified proto
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -315,29 +315,29 @@ js::StartOffThreadParseScript(JSContext 
     global->zone()->types.inferenceEnabled = cx->typeInferenceEnabled();
     JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
 
     RootedObject obj(cx);
 
     // Initialize all classes needed for parsing while we are still on the main
     // thread. Do this for both the target and the new global so that prototype
     // pointers can be changed infallibly after parsing finishes.
-    if (!js_GetClassObject(cx, JSProto_Function, &obj) ||
-        !js_GetClassObject(cx, JSProto_Array, &obj) ||
-        !js_GetClassObject(cx, JSProto_RegExp, &obj) ||
-        !js_GetClassObject(cx, JSProto_Iterator, &obj))
+    if (!GetBuiltinConstructor(cx, JSProto_Function, &obj) ||
+        !GetBuiltinConstructor(cx, JSProto_Array, &obj) ||
+        !GetBuiltinConstructor(cx, JSProto_RegExp, &obj) ||
+        !GetBuiltinConstructor(cx, JSProto_Iterator, &obj))
     {
         return false;
     }
     {
         AutoCompartment ac(cx, global);
-        if (!js_GetClassObject(cx, JSProto_Function, &obj) ||
-            !js_GetClassObject(cx, JSProto_Array, &obj) ||
-            !js_GetClassObject(cx, JSProto_RegExp, &obj) ||
-            !js_GetClassObject(cx, JSProto_Iterator, &obj))
+        if (!GetBuiltinConstructor(cx, JSProto_Function, &obj) ||
+            !GetBuiltinConstructor(cx, JSProto_Array, &obj) ||
+            !GetBuiltinConstructor(cx, JSProto_RegExp, &obj) ||
+            !GetBuiltinConstructor(cx, JSProto_Iterator, &obj))
         {
             return false;
         }
     }
 
     ScopedJSDeletePtr<ExclusiveContext> workercx(
         cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData *) nullptr,
                                    ThreadSafeContext::Context_Exclusive));
@@ -643,17 +643,17 @@ GlobalWorkerThreadState::finishParseTask
         TaggedProto proto(object->proto());
         if (!proto.isObject())
             continue;
 
         JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
         if (key == JSProto_Null)
             continue;
 
-        JSObject *newProto = GetClassPrototypePure(&parseTask->scopeChain->global(), key);
+        JSObject *newProto = GetBuiltinPrototypePure(&parseTask->scopeChain->global(), key);
         JS_ASSERT(newProto);
 
         object->setProtoUnchecked(newProto);
     }
 
     // Move the parsed script and all its contents into the desired compartment.
     gc::MergeCompartments(parseTask->cx->compartment(), parseTask->scopeChain->compartment());
     parseTask->finish();
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -729,17 +729,17 @@ class TypedArrayObjectTemplate : public 
                  * Rather than hack some crazy solution together, implement
                  * this all using a private helper function, created when
                  * ArrayBufferObject 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);
-                if (!FindProto(cx, fastClass(), &proto))
+                if (!GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(fastClass()), &proto))
                     return nullptr;
 
                 InvokeArgs args(cx);
                 if (!args.init(3))
                     return nullptr;
 
                 args.setCallee(cx->compartment()->maybeGlobal()->createArrayFromBuffer<NativeType>());
                 args.setThis(ObjectValue(*bufobj));