Bug 1006899 - Prevent stack iterations while recovering allocations. r=bhackett, a=sledru
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Tue, 22 Jul 2014 06:04:03 -0700
changeset 208163 b801d912ea0e
parent 208160 6a87b4799b21
child 208164 794d229b5125
push id3749
push userryanvm@gmail.com
push date2014-07-23 15:03 +0000
treeherdermozilla-beta@b801d912ea0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett, sledru
bugs1006899
milestone32.0
Bug 1006899 - Prevent stack iterations while recovering allocations. r=bhackett, a=sledru
js/src/jit-test/tests/ion/bug1006899.js
js/src/jit/Recover.cpp
js/src/jsobjinlines.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1006899.js
@@ -0,0 +1,16 @@
+
+this.__defineGetter__("x",
+  function() {
+    return this;
+  }
+);
+function callback(obj) {}
+setObjectMetadataCallback(callback);
+evaluate("\
+var { ArrayType, StructType, uint32 } = TypedObject;\
+  var L = 1024;\
+  var Matrix = uint32.array(L, 2);\
+  var matrix = new Matrix();\
+  for (var i = 0; i < L; i++)\
+    matrix[i][0] = x;\
+", { compileAndGo : true });
--- a/js/src/jit/Recover.cpp
+++ b/js/src/jit/Recover.cpp
@@ -472,16 +472,20 @@ RNewObject::RNewObject(CompactBufferRead
 
 bool
 RNewObject::recover(JSContext *cx, SnapshotIterator &iter) const
 {
     RootedObject templateObject(cx, &iter.read().toObject());
     RootedValue result(cx);
     JSObject *resultObject = nullptr;
 
+    // Use AutoEnterAnalysis to avoid invoking the object metadata callback
+    // while bailing out, which could try to walk the stack.
+    types::AutoEnterAnalysis enter(cx);
+
     // See CodeGenerator::visitNewObjectVMCall
     if (templateObjectIsClassPrototype_)
         resultObject = NewInitObjectWithClassPrototype(cx, templateObject);
     else
         resultObject = NewInitObject(cx, templateObject);
 
     if (!resultObject)
         return false;
@@ -504,16 +508,20 @@ RNewDerivedTypedObject::RNewDerivedTyped
 
 bool
 RNewDerivedTypedObject::recover(JSContext *cx, SnapshotIterator &iter) const
 {
     Rooted<SizedTypeDescr *> descr(cx, &iter.read().toObject().as<SizedTypeDescr>());
     Rooted<TypedObject *> owner(cx, &iter.read().toObject().as<TypedObject>());
     int32_t offset = iter.read().toInt32();
 
+    // Use AutoEnterAnalysis to avoid invoking the object metadata callback
+    // while bailing out, which could try to walk the stack.
+    types::AutoEnterAnalysis enter(cx);
+
     JSObject *obj = TypedObject::createDerived(cx, descr, owner, offset);
     if (!obj)
         return false;
 
     RootedValue result(cx, ObjectValue(*obj));
     iter.storeInstructionResult(result);
     return true;
 }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -1015,17 +1015,18 @@ IsObjectWithClass(const Value &v, ESClas
     RootedObject obj(cx, &v.toObject());
     return ObjectClassIs(obj, classValue, cx);
 }
 
 static MOZ_ALWAYS_INLINE bool
 NewObjectMetadata(ExclusiveContext *cxArg, JSObject **pmetadata)
 {
     // The metadata callback is invoked before each created object, except when
-    // analysis/compilation is active, to avoid recursion.
+    // analysis/compilation is active, to avoid recursion.  It is also skipped
+    // when we allocate objects during a bailout, to prevent stack iterations.
     JS_ASSERT(!*pmetadata);
     if (JSContext *cx = cxArg->maybeJSContext()) {
         if (MOZ_UNLIKELY((size_t)cx->compartment()->hasObjectMetadataCallback()) &&
             !cx->compartment()->activeAnalysis)
         {
             // Use AutoEnterAnalysis to prohibit both any GC activity under the
             // callback, and any reentering of JS via Invoke() etc.
             types::AutoEnterAnalysis enter(cx);