Bug 1212343 - Propagate OOM from SafepointWriter r=nbp
☠☠ backed out by bf388a8e620b ☠ ☠
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 08 Oct 2015 17:48:53 +0100
changeset 266962 ab9dbd4c1ec40988c1cedc031a12c89b2feaf25e
parent 266961 e04c59fd01c4b07898f805938e131afb3d71f7e5
child 266963 1f46ca0a518a0a9be083fa93877731b1c38ed5ba
push id29504
push usercbook@mozilla.com
push dateFri, 09 Oct 2015 09:43:23 +0000
treeherdermozilla-central@d01dd42e654b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1212343
milestone44.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 1212343 - Propagate OOM from SafepointWriter r=nbp
js/src/jit-test/tests/gc/oomInArrayProtoTest.js
js/src/jit/CodeGenerator.cpp
js/src/jit/Safepoints.h
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/jit/shared/CodeGenerator-shared.h
js/src/vm/TypeInference.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/oomInArrayProtoTest.js
@@ -0,0 +1,24 @@
+load(libdir + 'oomTest.js');
+
+function arrayProtoOutOfRange() {
+    function f(obj) {
+        return typeof obj[15];
+    }
+
+    function test() {
+        var a = [1, 2];
+        a.__proto__ = {15: 1337};
+        var b = [1, 2, 3, 4];
+
+        for (var i = 0; i < 1000; i++) {
+            var r = f(i % 2 ? a : b);
+            assertEq(r, i % 2 ? "number" : "undefined");
+        }
+    }
+
+    test();
+    test();
+    test();
+}
+
+oomTest(arrayProtoOutOfRange);
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8005,17 +8005,18 @@ CodeGenerator::link(JSContext* cx, Compi
         script->incWarmUpCounter(warmUpCount - script->getWarmUpCount());
 
     uint32_t argumentSlots = (gen->info().nargs() + 1) * sizeof(Value);
     uint32_t scriptFrameSize = frameClass_ == FrameSizeClass::None()
                            ? frameDepth_
                            : FrameSizeClass::FromDepth(frameDepth_).frameSize();
 
     // We encode safepoints after the OSI-point offsets have been determined.
-    encodeSafepoints();
+    if (!encodeSafepoints())
+        return false;
 
     AutoDiscardIonCode discardIonCode(cx, &recompileInfo);
 
     IonScript* ionScript =
       IonScript::New(cx, recompileInfo,
                      graph.totalSlotCount(), argumentSlots, scriptFrameSize,
                      snapshots_.listSize(), snapshots_.RVATableSize(),
                      recovers_.size(), bailouts_.length(), graph.numConstants(),
--- a/js/src/jit/Safepoints.h
+++ b/js/src/jit/Safepoints.h
@@ -52,16 +52,19 @@ class SafepointWriter
     void encode(LSafepoint* safepoint);
 
     size_t size() const {
         return stream_.length();
     }
     const uint8_t* buffer() const {
         return stream_.buffer();
     }
+    bool oom() const {
+        return stream_.oom();
+    }
 };
 
 class SafepointReader
 {
     CompactBufferReader stream_;
     uint32_t frameSlots_;
     uint32_t argumentSlots_;
     uint32_t currentSlotChunk_;
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -621,29 +621,31 @@ CodeGeneratorShared::assignBailoutId(LSn
         return false;
 
     unsigned bailoutId = bailouts_.length();
     snapshot->setBailoutId(bailoutId);
     JitSpew(JitSpew_IonSnapshots, "Assigned snapshot bailout id %u", bailoutId);
     return bailouts_.append(snapshot->snapshotOffset());
 }
 
-void
+bool
 CodeGeneratorShared::encodeSafepoints()
 {
     for (SafepointIndex& index : safepointIndices_) {
         LSafepoint* safepoint = index.safepoint();
 
         if (!safepoint->encoded()) {
             safepoint->fixupOffset(&masm);
             safepoints_.encode(safepoint);
         }
 
         index.resolve();
     }
+
+    return !safepoints_.oom();
 }
 
 bool
 CodeGeneratorShared::createNativeToBytecodeScriptList(JSContext* cx)
 {
     js::Vector<JSScript*, 0, SystemAllocPolicy> scriptList;
     InlineScriptTree* tree = gen->info().inlineScriptTree();
     for (;;) {
--- a/js/src/jit/shared/CodeGenerator-shared.h
+++ b/js/src/jit/shared/CodeGenerator-shared.h
@@ -298,17 +298,17 @@ class CodeGeneratorShared : public LElem
 
     // Attempts to assign a BailoutId to a snapshot, if one isn't already set.
     // If the bailout table is full, this returns false, which is not a fatal
     // error (the code generator may use a slower bailout mechanism).
     bool assignBailoutId(LSnapshot* snapshot);
 
     // Encode all encountered safepoints in CG-order, and resolve |indices| for
     // safepoint offsets.
-    void encodeSafepoints();
+    bool encodeSafepoints();
 
     // Fixup offsets of native-to-bytecode map.
     bool createNativeToBytecodeScriptList(JSContext* cx);
     bool generateCompactNativeToBytecodeMap(JSContext* cx, JitCode* code);
     void verifyCompactNativeToBytecodeMap(JitCode* code);
 
     bool generateCompactTrackedOptimizationsMap(JSContext* cx, JitCode* code,
                                                 IonTrackedTypeVector* allTypes);
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -4333,17 +4333,18 @@ TypeZone::beginSweep(FreeOp* fop, bool r
     // index for remaining live outputs.
     if (compilerOutputs) {
         CompilerOutputVector* newCompilerOutputs = nullptr;
         for (size_t i = 0; i < compilerOutputs->length(); i++) {
             CompilerOutput& output = (*compilerOutputs)[i];
             if (output.isValid()) {
                 JSScript* script = output.script();
                 if (IsAboutToBeFinalizedUnbarriered(&script)) {
-                    script->ionScript()->recompileInfoRef() = RecompileInfo();
+                    if (script->hasIonScript())
+                        script->ionScript()->recompileInfoRef() = RecompileInfo();
                     output.invalidate();
                 } else {
                     CompilerOutput newOutput(script);
 
                     if (!newCompilerOutputs)
                         newCompilerOutputs = js_new<CompilerOutputVector>();
                     if (newCompilerOutputs && newCompilerOutputs->append(newOutput)) {
                         output.setSweepIndex(newCompilerOutputs->length() - 1);