Bug 1511412 - Fix an issue with incremental sweeping and ICScript. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 30 Nov 2018 19:59:04 +0000
changeset 505460 847bc008e00b9348a07b87b4c8063782c1d7ab11
parent 505459 65511560940f5ac446b1cb4e76d5dcba74a3bf85
child 505461 22425b629a9d1484ebda8b03bb0cf3019305207f
child 505490 3a4e05f965e943f4e1181a4270dacc98a491cac8
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1511412
milestone65.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 1511412 - Fix an issue with incremental sweeping and ICScript. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D13566
js/src/gc/Zone.cpp
js/src/jit-test/tests/gc/bug1511412.js
js/src/jit/BaselineIC.h
js/src/jit/BaselineJIT.cpp
--- a/js/src/gc/Zone.cpp
+++ b/js/src/gc/Zone.cpp
@@ -254,17 +254,17 @@ void Zone::discardJitCode(FreeOp* fop, b
       script->maybeReleaseTypes();
     }
 
     // The optimizedStubSpace will be purged below so make sure ICScript
     // doesn't point into it. We do this after (potentially) releasing types
     // because TypeScript contains the ICScript* and there's no need to
     // purge stubs if we just destroyed the Typescript.
     if (discardBaselineCode && script->hasICScript()) {
-      script->icScript()->purgeOptimizedStubs(script->zone());
+      script->icScript()->purgeOptimizedStubs(script);
     }
   }
 
   /*
    * When scripts contains pointers to nursery things, the store buffer
    * can contain entries that point into the optimized stub space. Since
    * this method can be called outside the context of a GC, this situation
    * could result in us trying to mark invalid store buffer entries.
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug1511412.js
@@ -0,0 +1,17 @@
+Object.defineProperty(this, "fuzzutils", {
+      value: {
+          orig_evaluate: evaluate,
+          evaluate: function(c, o) {
+              if (!o) {
+                  o = {};
+              }
+              o.catchTermination = true;
+              return fuzzutils.orig_evaluate(c, o);
+          },
+      }
+  });
+  gczeal(21, 10);
+  fuzzutils.evaluate(`
+enableShellAllocationMetadataBuilder();
+function test() {}
+`);
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -340,17 +340,17 @@ class ICScript {
     MOZ_ASSERT(index < numICEntries());
     return icEntryList()[index];
   }
 
   void noteAccessedGetter(uint32_t pcOffset);
   void noteHasDenseAdd(uint32_t pcOffset);
 
   void trace(JSTracer* trc);
-  void purgeOptimizedStubs(Zone* zone);
+  void purgeOptimizedStubs(JSScript* script);
 
   ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset);
   ICEntry* maybeICEntryFromPCOffset(uint32_t pcOffset,
                                     ICEntry* prevLookedUpEntry);
 
   ICEntry& icEntryFromPCOffset(uint32_t pcOffset);
   ICEntry& icEntryFromPCOffset(uint32_t pcOffset, ICEntry* prevLookedUpEntry);
 };
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -1009,17 +1009,29 @@ void BaselineScript::toggleProfilerInstr
     flags_ |= uint32_t(PROFILER_INSTRUMENTATION_ON);
   } else {
     Assembler::ToggleToJmp(enterToggleLocation);
     Assembler::ToggleToJmp(exitToggleLocation);
     flags_ &= ~uint32_t(PROFILER_INSTRUMENTATION_ON);
   }
 }
 
-void ICScript::purgeOptimizedStubs(Zone* zone) {
+void ICScript::purgeOptimizedStubs(JSScript* script) {
+  MOZ_ASSERT(script->icScript() == this);
+
+  Zone* zone = script->zone();
+  if (zone->isGCSweeping() && IsAboutToBeFinalizedDuringSweep(*script)) {
+    // We're sweeping and the script is dead. Don't purge optimized stubs
+    // because (1) accessing CacheIRStubInfo pointers in ICStubs is invalid
+    // because we may have swept them already when we started (incremental)
+    // sweeping and (2) it's unnecessary because this script will be finalized
+    // soon anyway.
+    return;
+  }
+
   JitSpew(JitSpew_BaselineIC, "Purging optimized stubs");
 
   for (size_t i = 0; i < numICEntries(); i++) {
     ICEntry& entry = icEntry(i);
     ICStub* lastStub = entry.firstStub();
     while (lastStub->next()) {
       lastStub = lastStub->next();
     }