Bug 1078871 - Relax assertions when creating dependent strings, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 08 Oct 2014 06:30:28 -0700
changeset 209348 2a12b3e698c9a1abbb26d0ee8adf39843482a290
parent 209347 2ae98c304c5e2c12d82227d894eca96511dd3eb4
child 209349 5830312dbcb46915c6c3369a7e73b618655197f8
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjandem
bugs1078871
milestone35.0a1
Bug 1078871 - Relax assertions when creating dependent strings, r=jandem.
js/src/jit-test/tests/basic/bug1078871.js
js/src/vm/String-inl.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug1078871.js
@@ -0,0 +1,44 @@
+
+// Robert Jenkins' 32 bit integer hash function
+var seed = 100;
+Math.random = function() {
+   seed = (seed + 0x7ed55d16) + (seed<<12);
+   seed = (seed ^ 0xc761c23c) ^ (seed>>19);
+   seed = (seed + 0x165667b1) + (seed<<5);
+   seed = (seed + 0xd3a2646c) ^ (seed<<9);
+   seed = (seed + 0xfd7046c5) + (seed<<3);
+   seed = (seed ^ 0xb55a4f09) ^ (seed>>16);
+   seed = Math.abs(seed | 0);
+   return seed / 0xffffffff * 2;
+}
+
+function tangle(n, m) {
+  function rand(n) {
+    return Math.floor(Math.random() * n);
+  }
+
+  var arr = [];
+  for (var i = 0; i < n; i++)
+    arr[i] = String.fromCharCode(65 + rand(26));
+  for (var i = 0; i < m; i++) {
+    var j = rand(n);
+    switch (rand(2)) {
+      case 0: {
+        var s = arr[rand(n)];
+        var b = rand(s.length);
+        var e = b + rand(s.length - b);
+        if (e - b > 1)
+          arr[j] = s.substring(b, e);
+      }
+      break;
+      case 1: {
+        arr[j] = arr[rand(n)] + arr[rand(n)];
+      }
+    }
+    uneval(arr[j]);
+  }
+
+  return arr;
+}
+
+tangle(10, 500);
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -155,25 +155,26 @@ JSDependentString::init(js::ThreadSafeCo
     d.s.u3.base = base;
     js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u3.base));
 }
 
 MOZ_ALWAYS_INLINE JSLinearString *
 JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_t start,
                         size_t length)
 {
-    /* Try to avoid long chains of dependent strings. */
+    /*
+     * Try to avoid long chains of dependent strings. We can't avoid these
+     * entirely, however, due to how ropes are flattened.
+     */
     if (baseArg->isDependent()) {
         start += baseArg->asDependent().baseOffset();
         baseArg = baseArg->asDependent().base();
     }
-    MOZ_ASSERT(!baseArg->isDependent());
 
     MOZ_ASSERT(start + length <= baseArg->length());
-    MOZ_ASSERT(baseArg->isFlat());
 
     /*
      * Do not create a string dependent on inline chars from another string,
      * both to avoid the awkward moving-GC hazard this introduces and because it
      * is more efficient to immediately undepend here.
      */
     bool useFatInline = baseArg->hasTwoByteChars()
                         ? JSFatInlineString::twoByteLengthFits(length)