Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo, a=2.1s+
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 26 Aug 2015 11:02:15 -0400
changeset 222381 9ef38fe25fc7
parent 222380 5e80c7eefb66
child 222382 59f9e3fb09ef
push id241
push userryanvm@gmail.com
push dateTue, 01 Sep 2015 03:10:14 +0000
treeherdermozilla-b2g34_v2_1s@9ef38fe25fc7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo, 2
bugs1183153
milestone34.0
Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo, a=2.1s+
js/src/jsobj.cpp
js/src/jsobj.h
js/src/vm/HelperThreads.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -3675,18 +3675,18 @@ js::GetBuiltinPrototype(ExclusiveContext
     Rooted<GlobalObject*> global(cx, cx->global());
     if (!MaybeResolveConstructor(cx, global, key))
         return false;
 
     protop.set(&global->getPrototype(key).toObject());
     return true;
 }
 
-static bool
-IsStandardPrototype(JSObject* obj, JSProtoKey key)
+bool
+js::IsStandardPrototype(JSObject* obj, JSProtoKey key)
 {
     GlobalObject& global = obj->global();
     Value v = global.getPrototype(key);
     return v.isObject() && obj == &v.toObject();
 }
 
 JSProtoKey
 JS::IdentifyStandardInstance(JSObject* obj)
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1294,16 +1294,19 @@ GetBuiltinPrototype(ExclusiveContext* cx
 
 JSObject*
 GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
 
 extern bool
 SetClassAndProto(JSContext* cx, HandleObject obj,
                  const Class* clasp, Handle<TaggedProto> proto, bool* succeeded);
 
+extern bool
+IsStandardPrototype(JSObject* obj, JSProtoKey key);
+
 /*
  * 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);
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -729,17 +729,18 @@ GlobalHelperThreadState::finishParseTask
 
     // Make sure we have all the constructors we need for the prototype
     // remapping below, since we can't GC while that's happening.
     Rooted<GlobalObject*> global(cx, &cx->global()->as<GlobalObject>());
     if (!GlobalObject::ensureConstructor(cx, global, JSProto_Object) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_Array) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_Function) ||
         !GlobalObject::ensureConstructor(cx, global, JSProto_RegExp) ||
-        !GlobalObject::ensureConstructor(cx, global, JSProto_Iterator))
+        !GlobalObject::ensureConstructor(cx, global, JSProto_Iterator) ||
+        !GlobalObject::ensureConstructor(cx, global, JSProto_GeneratorFunction))
     {
         LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
 
     LeaveParseTaskZone(rt, parseTask);
 
     // Point the prototypes of any objects in the script's compartment to refer
@@ -751,21 +752,28 @@ GlobalHelperThreadState::finishParseTask
          iter.next())
     {
         types::TypeObject* object = iter.get<types::TypeObject>();
         TaggedProto proto(object->proto());
         if (!proto.isObject())
             continue;
 
         JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
-        if (key == JSProto_Null)
-            continue;
+        if (key == JSProto_Null) {
+            // Generator functions don't have Function.prototype as prototype
+            // but a different function object, so IdentifyStandardPrototype
+            // doesn't work. Just special-case it here.
+            if (IsStandardPrototype(proto.toObject(), JSProto_GeneratorFunction))
+                key = JSProto_GeneratorFunction;
+            else
+                continue;
+        }
         JS_ASSERT(key == JSProto_Object || key == JSProto_Array ||
                   key == JSProto_Function || key == JSProto_RegExp ||
-                  key == JSProto_Iterator);
+                  key == JSProto_Iterator || key == JSProto_GeneratorFunction);
 
         JSObject* newProto = GetBuiltinPrototypePure(global, key);
         JS_ASSERT(newProto);
 
         object->setProtoUnchecked(TaggedProto(newProto));
     }
 
     // Move the parsed script and all its contents into the desired compartment.