Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo, a=sledru
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 26 Aug 2015 11:02:15 -0400
changeset 289049 a8b96fe39d92f422cc5491e993955c430ce29329
parent 289048 e3cc78bb5f7316a3066a815e8262a1193e67e0b2
child 289050 c03eb276968912168fe1ad0e818a5aea5fe8570e
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo, sledru
bugs1183153
milestone42.0a2
Bug 1183153 - Give generator function groups the correct builtin prototype. r=Waldo, a=sledru
js/src/jsobj.cpp
js/src/jsobj.h
js/src/vm/HelperThreads.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2026,18 +2026,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
@@ -1073,16 +1073,19 @@ GetBuiltinPrototype(ExclusiveContext* cx
 
 JSObject*
 GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
 
 extern bool
 SetClassAndProto(JSContext* cx, HandleObject obj,
                  const Class* clasp, Handle<TaggedProto> proto);
 
+extern bool
+IsStandardPrototype(JSObject* obj, JSProtoKey key);
+
 } /* 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[];
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -915,17 +915,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 (!EnsureConstructor(cx, global, JSProto_Object) ||
         !EnsureConstructor(cx, global, JSProto_Array) ||
         !EnsureConstructor(cx, global, JSProto_Function) ||
         !EnsureConstructor(cx, global, JSProto_RegExp) ||
-        !EnsureConstructor(cx, global, JSProto_Iterator))
+        !EnsureConstructor(cx, global, JSProto_Iterator) ||
+        !EnsureConstructor(cx, global, JSProto_GeneratorFunction))
     {
         LeaveParseTaskZone(rt, parseTask);
         return nullptr;
     }
 
     mergeParseTaskCompartment(rt, parseTask, global, cx->compartment());
 
     if (!parseTask->finish(cx))
@@ -979,21 +980,28 @@ GlobalHelperThreadState::mergeParseTaskC
          iter.next())
     {
         ObjectGroup* group = iter.get<ObjectGroup>();
         TaggedProto proto(group->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;
+        }
         MOZ_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);
         MOZ_ASSERT(newProto);
 
         group->setProtoUnchecked(TaggedProto(newProto));
     }
 
     // Move the parsed script and all its contents into the desired compartment.