Bug 1055219. r=terrence, a=abillings
authorTerrence Cole <terrence@mozilla.com>
Tue, 19 Aug 2014 13:35:20 -0700
changeset 208342 7c7145e95cb5
parent 208341 90b5e0b87666
child 208343 ec5427a8e674
push id3831
push userryanvm@gmail.com
push date2014-08-19 22:04 +0000
treeherdermozilla-beta@7c7145e95cb5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, abillings
bugs1055219
milestone32.0
Bug 1055219. r=terrence, a=abillings
js/src/jit-test/tests/gc/bug-1055219.js
js/src/jsinfer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1055219.js
@@ -0,0 +1,5 @@
+gczeal(13);
+function A() {};
+A.prototype = [];
+function B() {};
+B.prototype = new A();
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3850,16 +3850,36 @@ class NewTypeObjectsSetRef : public Buff
 
         TypeObjectWithNewScriptSet::Ptr p = set->lookup(TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), newFunction));
         JS_ASSERT(p);  // newTypeObjects set must still contain original entry.
 
         set->rekeyAs(TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(prior), TaggedProto(proto), newFunction),
                      TypeObjectWithNewScriptSet::Lookup(clasp, TaggedProto(proto), newFunction), *p);
     }
 };
+
+static void
+TypeObjectTablePostBarrier(ExclusiveContext *cx, TypeObjectWithNewScriptSet *table,
+                           const Class *clasp, TaggedProto proto, JSFunction *fun)
+{
+    JS_ASSERT_IF(fun, !IsInsideNursery(fun));
+
+    if (!proto.isObject())
+        return;
+
+    if (!cx->isJSContext()) {
+        JS_ASSERT(!IsInsideNursery(proto.toObject()));
+        return;
+    }
+
+    if (IsInsideNursery(proto.toObject())) {
+        StoreBuffer &sb = cx->asJSContext()->runtime()->gc.storeBuffer;
+        sb.putGeneric(NewTypeObjectsSetRef(table, clasp, proto.toObject(), fun));
+    }
+}
 #endif
 
 TypeObject *
 ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction *fun)
 {
     JS_ASSERT_IF(fun, proto.isObject());
     JS_ASSERT_IF(proto.isObject(), isInsideCurrentCompartment(proto.toObject()));
 
@@ -3908,20 +3928,17 @@ ExclusiveContext::getNewType(const Class
     TypeObject *type = compartment()->types.newTypeObject(this, clasp, protoRoot, initialFlags);
     if (!type)
         return nullptr;
 
     if (!newTypeObjects.add(p, TypeObjectWithNewScriptEntry(type, fun)))
         return nullptr;
 
 #ifdef JSGC_GENERATIONAL
-    if (proto.isObject() && hasNursery() && IsInsideNursery(proto.toObject())) {
-        asJSContext()->runtime()->gc.storeBuffer.putGeneric(
-            NewTypeObjectsSetRef(&newTypeObjects, clasp, proto.toObject(), fun));
-    }
+    TypeObjectTablePostBarrier(this, &newTypeObjects, clasp, proto, fun);
 #endif
 
     if (proto.isObject()) {
         RootedObject obj(this, proto.toObject());
 
         if (fun)
             CheckNewScriptProperties(asJSContext(), type, fun);
 
@@ -4000,16 +4017,20 @@ ExclusiveContext::getSingletonType(const
     Rooted<TaggedProto> protoRoot(this, proto);
     TypeObject *type = compartment()->types.newTypeObject(this, clasp, protoRoot);
     if (!type)
         return nullptr;
 
     if (!table.add(p, TypeObjectWithNewScriptEntry(type, nullptr)))
         return nullptr;
 
+#ifdef JSGC_GENERATIONAL
+    TypeObjectTablePostBarrier(this, &table, clasp, proto, nullptr);
+#endif
+
     type->initSingleton((JSObject *) TypeObject::LAZY_SINGLETON);
     MOZ_ASSERT(type->singleton(), "created type must be a proper singleton");
 
     return type;
 }
 
 /////////////////////////////////////////////////////////////////////
 // Tracing