Bug 1201850 - Don't elide stack check when getelem/setelem caches are used. r=bhackett
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 19 Sep 2015 20:00:16 +0200
changeset 296027 123761e37f2722014766a0c225bd2e15623519f9
parent 296026 0ad4ca92e9a909763f054fee3d111f8274d00b61
child 296028 9bdb6d48a34e1bbf0aaf468e44e71544e26adf7d
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1201850
milestone43.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 1201850 - Don't elide stack check when getelem/setelem caches are used. r=bhackett
js/src/jit-test/tests/ion/bug1201850.js
js/src/jit/IonCaches.cpp
js/src/jit/Lowering.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1201850.js
@@ -0,0 +1,10 @@
+// |jit-test| error: too much recursion
+var tokenCodes = {
+    get finally() {
+        if (tokenCodes[arr[i]] !== i) {}
+    }
+};
+var arr = ['finally'];
+for (var i = 0; i < arr.length; i++) {
+    if (tokenCodes[arr[i]] !== i) {}
+}
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3411,16 +3411,17 @@ GetElementIC::attachGetProp(JSContext* c
 
     if (canCache == GetPropertyIC::CanAttachReadSlot) {
         // OK to attach.
     } else if (canCache == GetPropertyIC::CanAttachCallGetter) {
         if (!output().hasValue()) {
             JitSpew(JitSpew_IonIC, "GETELEM uncacheable property");
             return true;
         }
+        MOZ_ASSERT(monitoredResult());
     } else if (obj->is<UnboxedPlainObject>()) {
         MOZ_ASSERT(canCache == GetPropertyIC::CanAttachNone);
         const UnboxedLayout::Property* property =
             obj->as<UnboxedPlainObject>().layout().lookup(name);
         if (property) {
             // OK to attach.
         } else {
             UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando();
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -3298,16 +3298,19 @@ LIRGenerator::visitSetPropertyPolymorphi
     }
 }
 
 void
 LIRGenerator::visitGetElementCache(MGetElementCache* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
 
+    if (ins->monitoredResult())
+        gen->setPerformsCall(); // See visitGetPropertyCache.
+
     if (ins->type() == MIRType_Value) {
         MOZ_ASSERT(ins->index()->type() == MIRType_Value);
         LGetElementCacheV* lir = new(alloc()) LGetElementCacheV(useRegister(ins->object()));
         useBox(lir, LGetElementCacheV::Index, ins->index());
         defineBox(lir, ins);
         assignSafepoint(lir, ins);
     } else {
         MOZ_ASSERT(ins->index()->type() == MIRType_Int32);
@@ -3514,16 +3517,18 @@ LIRGenerator::visitSetPropertyCache(MSet
 }
 
 void
 LIRGenerator::visitSetElementCache(MSetElementCache* ins)
 {
     MOZ_ASSERT(ins->object()->type() == MIRType_Object);
     MOZ_ASSERT(ins->index()->type() == MIRType_Value);
 
+    gen->setPerformsCall(); // See visitSetPropertyCache.
+
     // Due to lack of registers on x86, we reuse the object register as a
     // temporary. This register may be used in a 1-byte store, which on x86
     // again has constraints; thus the use of |useByteOpRegister| over
     // |useRegister| below.
     LInstruction* lir;
     if (ins->value()->type() == MIRType_Value) {
         LDefinition tempF32 = hasUnaliasedDouble() ? tempFloat32() : LDefinition::BogusTemp();
         lir = new(alloc()) LSetElementCacheV(useByteOpRegister(ins->object()), tempToUnbox(),