Bug 1431726 part 3 - Replace GetBuiltinPrototype with GlobalObject::getOrCreatePrototype. r=anba
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 20 Jan 2018 15:19:25 +0100
changeset 454426 a937ea520febcc4175e49d5d137bfe48d3d607c2
parent 454425 712f3d9c1cf35d7c26fde310843836a08fa583a7
child 454427 8a7fc4b3a0abcc9586b81188060c5b5b3405b9b5
push id1648
push usermtabara@mozilla.com
push dateThu, 01 Mar 2018 12:45:47 +0000
treeherdermozilla-release@cbb9688c2eeb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersanba
bugs1431726
milestone59.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 1431726 part 3 - Replace GetBuiltinPrototype with GlobalObject::getOrCreatePrototype. r=anba
js/src/builtin/Promise.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jsapi.cpp
js/src/jsarray.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/vm/GlobalObject.h
js/src/vm/Interpreter.cpp
js/src/vm/ObjectGroup.cpp
js/src/vm/TypedArrayObject.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -1574,17 +1574,18 @@ PromiseConstructor(JSContext* cx, unsign
             if (!promiseCtor)
                 return false;
 
             // Promise subclasses don't get the special Xray treatment, so
             // we only need to do the complex wrapping and unwrapping scheme
             // described above for instances of Promise itself.
             if (newTarget == promiseCtor) {
                 needsWrapping = true;
-                if (!GetBuiltinPrototype(cx, JSProto_Promise, &proto))
+                proto = GlobalObject::getOrCreatePromisePrototype(cx, cx->global());
+                if (!proto)
                     return false;
             }
         }
     }
 
     if (needsWrapping) {
         if (!cx->compartment()->wrap(cx, &proto))
             return false;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -5004,20 +5004,20 @@ BaselineCompiler::emit_JSOP_INITHOMEOBJE
 
     return true;
 }
 
 bool
 BaselineCompiler::emit_JSOP_BUILTINPROTO()
 {
     // The builtin prototype is a constant for a given global.
-    RootedObject builtin(cx);
     JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(pc));
     MOZ_ASSERT(key < JSProto_LIMIT);
-    if (!GetBuiltinPrototype(cx, key, &builtin))
+    JSObject* builtin = GlobalObject::getOrCreatePrototype(cx, key);
+    if (!builtin)
         return false;
     frame.push(ObjectValue(*builtin));
     return true;
 }
 
 typedef JSObject* (*ObjectWithProtoOperationFn)(JSContext*, HandleValue);
 static const VMFunction ObjectWithProtoOperationInfo =
     FunctionInfo<ObjectWithProtoOperationFn>(js::ObjectWithProtoOperation,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1231,17 +1231,21 @@ JS_GetClassObject(JSContext* cx, JSProto
     return true;
 }
 
 JS_PUBLIC_API(bool)
 JS_GetClassPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp)
 {
     AssertHeapIsIdle();
     CHECK_REQUEST(cx);
-    return GetBuiltinPrototype(cx, key, objp);
+    JSObject* proto = GlobalObject::getOrCreatePrototype(cx, key);
+    if (!proto)
+        return false;
+    objp.set(proto);
+    return true;
 }
 
 namespace JS {
 
 JS_PUBLIC_API(void)
 ProtoKeyToId(JSContext* cx, JSProtoKey key, MutableHandleId idp)
 {
     idp.set(NameToId(ClassName(key, cx)));
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3788,18 +3788,21 @@ static MOZ_ALWAYS_INLINE ArrayObject*
 NewArray(JSContext* cx, uint32_t length,
          HandleObject protoArg, NewObjectKind newKind = GenericObject)
 {
     gc::AllocKind allocKind = GuessArrayGCKind(length);
     MOZ_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
     allocKind = GetBackgroundAllocKind(allocKind);
 
     RootedObject proto(cx, protoArg);
-    if (!proto && !GetBuiltinPrototype(cx, JSProto_Array, &proto))
-        return nullptr;
+    if (!proto) {
+        proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
+        if (!proto)
+            return nullptr;
+    }
 
     Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
     bool isCachable = NewObjectWithTaggedProtoIsCachable(cx, taggedProto, newKind, &ArrayObject::class_);
     if (isCachable) {
         NewObjectCache& cache = cx->caches().newObjectCache;
         NewObjectCache::EntryIndex entry = -1;
         if (cache.lookupProto(&ArrayObject::class_, proto, allocKind, &entry)) {
             gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -837,34 +837,33 @@ js::NewObjectWithClassProtoCommon(JSCont
     }
 
     // Find the appropriate proto for clasp. Built-in classes have a cached
     // proto on cx->global(); all others get %ObjectPrototype%.
     JSProtoKey protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
     if (protoKey == JSProto_Null)
         protoKey = JSProto_Object;
 
-    RootedObject proto(cx);
-    if (!GetBuiltinPrototype(cx, protoKey, &proto))
+    JSObject* proto = GlobalObject::getOrCreatePrototype(cx, protoKey);
+    if (!proto)
         return nullptr;
 
-    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, clasp, AsTaggedProto(proto)));
+    RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, clasp, TaggedProto(proto)));
     if (!group)
         return nullptr;
 
     JSObject* obj = NewObject(cx, group, allocKind, newKind);
     if (!obj)
         return nullptr;
 
     if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
         NewObjectCache& cache = cx->caches().newObjectCache;
         NewObjectCache::EntryIndex entry = -1;
         cache.lookupGlobal(clasp, global, allocKind, &entry);
-        cache.fillGlobal(entry, clasp, global, allocKind,
-                         &obj->as<NativeObject>());
+        cache.fillGlobal(entry, clasp, global, allocKind, &obj->as<NativeObject>());
     }
 
     return obj;
 }
 
 static bool
 NewObjectWithGroupIsCachable(JSContext* cx, HandleObjectGroup group,
                              NewObjectKind newKind)
@@ -1955,21 +1954,20 @@ js::InitClass(JSContext* cx, HandleObjec
      * 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 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 &&
-        !GetBuiltinPrototype(cx, JSProto_Object, &protoProto))
-    {
-        return nullptr;
+    if (key != JSProto_Null && !protoProto) {
+        protoProto = GlobalObject::getOrCreatePrototype(cx, JSProto_Object);
+        if (!protoProto)
+            return nullptr;
     }
 
     return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
                                          ps, fs, static_ps, static_fs, ctorp, ctorKind);
 }
 
 void
 JSObject::fixupAfterMovingGC()
@@ -2099,28 +2097,16 @@ JSObject::changeToSingleton(JSContext* c
     if (!group)
         return false;
 
     obj->group_ = group;
     return true;
 }
 
 bool
-js::GetBuiltinPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject protop)
-{
-    MOZ_ASSERT(key != JSProto_Null);
-    Handle<GlobalObject*> global = cx->global();
-    if (!GlobalObject::ensureConstructor(cx, global, key))
-        return false;
-
-    protop.set(&global->getPrototype(key).toObject());
-    return true;
-}
-
-bool
 js::IsStandardPrototype(JSObject* obj, JSProtoKey key)
 {
     GlobalObject& global = obj->global();
     Value v = global.getPrototype(key);
     return v.isObject() && obj == &v.toObject();
 }
 
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1027,19 +1027,16 @@ GetThisValueOfLexical(JSObject* env);
 Value
 GetThisValueOfWith(JSObject* env);
 
 /* * */
 
 typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
 
 /* Fast access to builtin constructors and prototypes. */
-bool
-GetBuiltinPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp);
-
 JSObject*
 GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
 
 extern bool
 IsStandardPrototype(JSObject* obj, JSProtoKey key);
 
 } /* namespace js */
 
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -150,16 +150,24 @@ class GlobalObject : public NativeObject
     static JSObject* getOrCreateConstructor(JSContext* cx, JSProtoKey key) {
         MOZ_ASSERT(key != JSProto_Null);
         Handle<GlobalObject*> global = cx->global();
         if (!GlobalObject::ensureConstructor(cx, global, key))
             return nullptr;
         return &global->getConstructor(key).toObject();
     }
 
+    static JSObject* getOrCreatePrototype(JSContext* cx, JSProtoKey key) {
+        MOZ_ASSERT(key != JSProto_Null);
+        Handle<GlobalObject*> global = cx->global();
+        if (!GlobalObject::ensureConstructor(cx, global, key))
+            return nullptr;
+        return &global->getPrototype(key).toObject();
+    }
+
     void setConstructor(JSProtoKey key, const Value& v) {
         MOZ_ASSERT(key <= JSProto_LIMIT);
         setSlot(APPLICATION_SLOTS + key, v);
     }
 
     Value getPrototype(JSProtoKey key) const {
         MOZ_ASSERT(key <= JSProto_LIMIT);
         return getSlot(APPLICATION_SLOTS + JSProto_LIMIT + key);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -4141,20 +4141,20 @@ CASE(JSOP_CHECKCLASSHERITAGE)
 
     if (!CheckClassHeritageOperation(cx, heritage))
         goto error;
 }
 END_CASE(JSOP_CHECKCLASSHERITAGE)
 
 CASE(JSOP_BUILTINPROTO)
 {
-    ReservedRooted<JSObject*> builtin(&rootObject0);
     MOZ_ASSERT(GET_UINT8(REGS.pc) < JSProto_LIMIT);
     JSProtoKey key = static_cast<JSProtoKey>(GET_UINT8(REGS.pc));
-    if (!GetBuiltinPrototype(cx, key, &builtin))
+    JSObject* builtin = GlobalObject::getOrCreatePrototype(cx, key);
+    if (!builtin)
         goto error;
     PUSH_OBJECT(*builtin);
 }
 END_CASE(JSOP_BUILTINPROTO)
 
 CASE(JSOP_FUNWITHPROTO)
 {
     ReservedRooted<JSObject*> proto(&rootObject1, &REGS.sp[-1].toObject());
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -714,20 +714,23 @@ GetClassForProtoKey(JSProtoKey key)
       default:
         MOZ_CRASH("Bad proto key");
     }
 }
 
 /* static */ ObjectGroup*
 ObjectGroup::defaultNewGroup(JSContext* cx, JSProtoKey key)
 {
-    RootedObject proto(cx);
-    if (key != JSProto_Null && !GetBuiltinPrototype(cx, key, &proto))
-        return nullptr;
-    return defaultNewGroup(cx, GetClassForProtoKey(key), TaggedProto(proto.get()));
+    JSObject* proto = nullptr;
+    if (key != JSProto_Null) {
+        proto = GlobalObject::getOrCreatePrototype(cx, key);
+        if (!proto)
+            return nullptr;
+    }
+    return defaultNewGroup(cx, GetClassForProtoKey(key), TaggedProto(proto));
 }
 
 /////////////////////////////////////////////////////////////////////
 // ObjectGroupCompartment ArrayObjectTable
 /////////////////////////////////////////////////////////////////////
 
 struct ObjectGroupCompartment::ArrayObjectKey : public DefaultHasher<ArrayObjectKey>
 {
@@ -839,18 +842,18 @@ ObjectGroup::newArrayObject(JSContext* c
 
     ObjectGroupCompartment::ArrayObjectKey key(elementType);
     DependentAddPtr<ObjectGroupCompartment::ArrayObjectTable> p(cx, *table, key);
 
     RootedObjectGroup group(cx);
     if (p) {
         group = p->value();
     } else {
-        RootedObject proto(cx);
-        if (!GetBuiltinPrototype(cx, JSProto_Array, &proto))
+        JSObject* proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
+        if (!proto)
             return nullptr;
         Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
         group = ObjectGroupCompartment::makeGroup(cx, &ArrayObject::class_, taggedProto);
         if (!group)
             return nullptr;
 
         AddTypePropertyId(cx, group, nullptr, JSID_VOID, elementType);
 
@@ -1162,18 +1165,18 @@ ObjectGroup::newPlainObject(JSContext* c
 
     ObjectGroupCompartment::PlainObjectKey::Lookup lookup(properties, nproperties);
     ObjectGroupCompartment::PlainObjectTable::Ptr p = table->lookup(lookup);
 
     if (!p) {
         if (!CanShareObjectGroup(properties, nproperties))
             return NewPlainObjectWithProperties(cx, properties, nproperties, newKind);
 
-        RootedObject proto(cx);
-        if (!GetBuiltinPrototype(cx, JSProto_Object, &proto))
+        JSObject* proto = GlobalObject::getOrCreatePrototype(cx, JSProto_Object);
+        if (!proto)
             return nullptr;
 
         Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
         RootedObjectGroup group(cx, ObjectGroupCompartment::makeGroup(cx, &PlainObject::class_,
                                                                       tagged));
         if (!group)
             return nullptr;
 
@@ -1411,19 +1414,22 @@ ObjectGroup::allocationSiteGroup(JSConte
             ReportOutOfMemory(cx);
             js_delete(table);
             table = nullptr;
             return nullptr;
         }
     }
 
     RootedScript script(cx, scriptArg);
-    RootedObject proto(cx, protoArg);
-    if (!proto && kind != JSProto_Null && !GetBuiltinPrototype(cx, kind, &proto))
-        return nullptr;
+    JSObject* proto = protoArg;
+    if (!proto && kind != JSProto_Null) {
+        proto = GlobalObject::getOrCreatePrototype(cx, kind);
+        if (!proto)
+            return nullptr;
+    }
 
     Rooted<ObjectGroupCompartment::AllocationSiteKey> key(cx,
         ObjectGroupCompartment::AllocationSiteKey(script, offset, kind, proto));
 
     ObjectGroupCompartment::AllocationSiteTable::AddPtr p = table->lookupForAdd(key);
     if (p)
         return p->value();
 
@@ -1660,18 +1666,18 @@ ObjectGroupCompartment::getStringSplitSt
         return group;
     }
 
     // The following code is a specialized version of the code
     // for ObjectGroup::allocationSiteGroup().
 
     const Class* clasp = GetClassForProtoKey(JSProto_Array);
 
-    RootedObject proto(cx);
-    if (!GetBuiltinPrototype(cx, JSProto_Array, &proto))
+    JSObject* proto = GlobalObject::getOrCreateArrayPrototype(cx, cx->global());
+    if (!proto)
         return nullptr;
     Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
 
     group = makeGroup(cx, clasp, tagged, /* initialFlags = */ 0);
     if (!group)
         return nullptr;
 
     groups.stringSplitStringGroup.set(group);
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -446,18 +446,22 @@ class TypedArrayObjectTemplate : public 
         gc::AllocKind allocKind = buffer
                                   ? GetGCObjectKind(instanceClass())
                                   : AllocKindForLazyBuffer(len * sizeof(NativeType));
 
         // Subclassing mandates that we hand in the proto every time. Most of
         // the time, though, that [[Prototype]] will not be interesting. If
         // it isn't, we can do some more TI optimizations.
         RootedObject checkProto(cx);
-        if (proto && !GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &checkProto))
-            return nullptr;
+        if (proto) {
+            checkProto =
+                GlobalObject::getOrCreatePrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()));
+            if (!checkProto)
+                return nullptr;
+        }
 
         AutoSetNewObjectMetadata metadata(cx);
         Rooted<TypedArrayObject*> obj(cx);
         if (proto && proto != checkProto)
             obj = makeProtoInstance(cx, proto, allocKind);
         else
             obj = makeTypedInstance(cx, len, allocKind);
         if (!obj)
@@ -871,17 +875,19 @@ class TypedArrayObjectTemplate : public 
         uint32_t length;
         if (!computeAndCheckLength(cx, unwrappedBuffer, byteOffset, lengthIndex, &length))
             return nullptr;
 
         // Make sure to get the [[Prototype]] for the created typed array from
         // this compartment.
         RootedObject protoRoot(cx, proto);
         if (!protoRoot) {
-            if (!GetBuiltinPrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()), &protoRoot))
+            protoRoot =
+                GlobalObject::getOrCreatePrototype(cx, JSCLASS_CACHED_PROTO_KEY(instanceClass()));
+            if (!protoRoot)
                 return nullptr;
         }
 
         RootedObject typedArray(cx);
         {
             JSAutoCompartment ac(cx, unwrappedBuffer);
 
             RootedObject wrappedProto(cx, protoRoot);