Bug 1252329 - Fix interaction between AutoClearTypeInferenceStateOnOOM and compacting GC. r=terrence, a=ritu
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 08 Mar 2016 10:15:09 +0000
changeset 325920 834fed3f42db37b6427d1140a6e32a3cb6af1ed9
parent 325919 89d0d3749675100aab0c87782f94100dcb2563ae
child 325921 b91e9c497db9007877d1c0b9661e486591af8d9d
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, ritu
bugs1252329
milestone47.0a2
Bug 1252329 - Fix interaction between AutoClearTypeInferenceStateOnOOM and compacting GC. r=terrence, a=ritu * * * Bug 1252329 - Fix test bustage on opt builds r=me
js/src/jit-test/tests/gc/bug-1252329.js
js/src/vm/ObjectGroup.cpp
js/src/vm/TypeInference.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1252329.js
@@ -0,0 +1,34 @@
+// |jit-test| allow-oom
+
+if (helperThreadCount() == 0 || !('oomAfterAllocations' in this))
+    quit();
+
+var lfcode = new Array();
+lfcode.push("5");
+lfcode.push(`
+gczeal(8, 2);
+try {
+    [new String, y]
+} catch (e) {}
+oomAfterAllocations(50);
+try {
+    (5).replace(r, () => {});
+} catch (x) {}
+`);
+while (true) {
+  var file = lfcode.shift(); if (file == undefined) { break; }
+  loadFile(file)
+}
+function loadFile(lfVarx) {
+    if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
+        switch (lfRunTypeId) {
+            case 5:
+                var lfGlobal = newGlobal();
+                for (lfLocal in this) {}
+                lfGlobal.offThreadCompileScript(lfVarx);
+                lfGlobal.runOffThreadScript();
+        }
+    } else if (!isNaN(lfVarx)) {
+        lfRunTypeId = parseInt(lfVarx);
+    }
+}
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1803,32 +1803,38 @@ ObjectGroupCompartment::fixupNewTableAft
 {
     /*
      * Each entry's hash depends on the object's prototype and we can't tell
      * whether that has been moved or not in sweepNewObjectGroupTable().
      */
     if (table && table->initialized()) {
         for (NewTable::Enum e(*table); !e.empty(); e.popFront()) {
             NewEntry entry = e.front();
+            ObjectGroup* group = entry.group.unbarrieredGet();
+
             bool needRekey = false;
             if (IsForwarded(entry.group.unbarrieredGet())) {
-                entry.group.set(Forwarded(entry.group.unbarrieredGet()));
+                group = Forwarded(entry.group.unbarrieredGet());
+                entry.group.set(group);
                 needRekey = true;
             }
-            TaggedProto proto = entry.group.unbarrieredGet()->proto();
+            TaggedProto proto = group->proto();
             if (proto.isObject() && IsForwarded(proto.toObject())) {
                 proto = TaggedProto(Forwarded(proto.toObject()));
+                // Update the group's proto here so that we are able to lookup
+                // entries in this table before all object pointers are updated.
+                group->proto() = proto;
                 needRekey = true;
             }
             if (entry.associated && IsForwarded(entry.associated)) {
                 entry.associated = Forwarded(entry.associated);
                 needRekey = true;
             }
             if (needRekey) {
-                const Class* clasp = entry.group.unbarrieredGet()->clasp();
+                const Class* clasp = group->clasp();
                 if (entry.associated && entry.associated->is<JSFunction>())
                     clasp = nullptr;
                 NewEntry::Lookup lookup(clasp, proto, entry.associated);
                 e.rekeyFront(lookup, entry);
             }
         }
     }
 }
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -2907,22 +2907,25 @@ ObjectGroup::detachNewScript(bool writeB
     // analyzed, remove it from the newObjectGroups table so that it will not be
     // produced by calling 'new' on the associated function anymore.
     // The TypeNewScript is not actually destroyed.
     TypeNewScript* newScript = anyNewScript();
     MOZ_ASSERT(newScript);
 
     if (newScript->analyzed()) {
         ObjectGroupCompartment& objectGroups = newScript->function()->compartment()->objectGroups;
+        TaggedProto proto = this->proto();
+        if (proto.isObject() && IsForwarded(proto.toObject()))
+            proto = TaggedProto(Forwarded(proto.toObject()));
+        JSObject* associated = MaybeForwarded(newScript->function());
         if (replacement) {
             MOZ_ASSERT(replacement->newScript()->function() == newScript->function());
-            objectGroups.replaceDefaultNewGroup(nullptr, proto(), newScript->function(),
-                                                replacement);
+            objectGroups.replaceDefaultNewGroup(nullptr, proto, associated, replacement);
         } else {
-            objectGroups.removeDefaultNewGroup(nullptr, proto(), newScript->function());
+            objectGroups.removeDefaultNewGroup(nullptr, proto, associated);
         }
     } else {
         MOZ_ASSERT(!replacement);
     }
 
     if (this->newScript())
         setAddendum(Addendum_None, nullptr, writeBarrier);
     else