summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/heap-analysis/byteSize-of-string.js')
-rw-r--r--js/src/jit-test/tests/heap-analysis/byteSize-of-string.js87
1 files changed, 70 insertions, 17 deletions
diff --git a/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js b/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js
index aaac0c4f1f..b4cfdffb04 100644
--- a/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js
+++ b/js/src/jit-test/tests/heap-analysis/byteSize-of-string.js
@@ -12,6 +12,7 @@
// stable.
gczeal(0); // Need to control when tenuring happens
+gcparam('semispaceNurseryEnabled', 0);
// Hack to skip this test if strings are not allocated in the nursery.
{
@@ -75,16 +76,20 @@ function tByteSize(str) {
// JSExternalString - limited by MaxStringLength - E
// JSThinInlineString 8 4 16 8 T
// JSFatInlineString 24 12 24 12 F
+// ThinInlineAtom 12 6 20 10 T
+// FatInlineAtom 20 10 20 10 F
// JSExtensibleString - limited by MaxStringLength - X
// Notes:
// - labels are suffixed with A for atoms and N for non-atoms
-// - atoms are 8 bytes larger than non-atoms, to store the atom's hash code.
+// - atoms store a 4 byte hash code, and some add to the size to adjust
// - Nursery-allocated strings require a header that stores the zone.
// Expected sizes based on type of string
const m32 = (getBuildConfiguration("pointer-byte-size") == 4);
-const TA = m32 ? 24 : 32; // ThinInlineString atom, includes a hash value
+const TA = m32 ? 24 : 32; // ThinInlineAtom (includes a hash value)
+const FA = m32 ? 32 : 32; // FatInlineAtom (includes a hash value)
+const NA = m32 ? 24 : 32; // NormalAtom
const TN = m32 ? 16 : 24; // ThinInlineString
const FN = m32 ? 32 : 32; // FatInlineString
const XN = m32 ? 16 : 24; // ExtensibleString, has additional storage buffer
@@ -95,8 +100,8 @@ const EN = m32 ? 16 : 24; // ExternalString
// A function that pads out a tenured size to the nursery size. We store a zone
// pointer in the nursery just before the string (4 bytes on 32-bit, 8 bytes on
// 64-bit), and the string struct itself must be 8-byte aligned (resulting in
-// +4 bytes on 32-bit, +0 bytes on 64-bit). The end result? Nursery strings are
-// 8 bytes larger.
+// +4 bytes on 32-bit, +0 bytes on 64-bit). The end result is that nursery
+// strings are 8 bytes larger.
const Nursery = m32 ? s => s + 4 + 4 : s => s + 8 + 0;
// Latin-1
@@ -130,6 +135,23 @@ assertEq(nByteSize("123456789.123456789.123456789.1"), s(Nursery(
assertEq(nByteSize("123456789.123456789.123456789.12"), s(Nursery(XN)+32,Nursery(XN)+32));
assertEq(nByteSize("123456789.123456789.123456789.123"), s(Nursery(XN)+64,Nursery(XN)+64));
+function Atom(s) { return Object.keys({ [s]: true })[0]; }
+assertEq(byteSize(Atom("1234567")), s(TA, TA));
+assertEq(byteSize(Atom("12345678")), s(TA, FA));
+assertEq(byteSize(Atom("123456789.12")), s(TA, FA));
+assertEq(byteSize(Atom("123456789.123")), s(FA, FA));
+assertEq(byteSize(Atom("123456789.12345")), s(FA, FA));
+assertEq(byteSize(Atom("123456789.123456")), s(FA, FA));
+assertEq(byteSize(Atom("123456789.1234567")), s(FA, FA));
+assertEq(byteSize(Atom("123456789.123456789.")), s(FA, FA));
+assertEq(byteSize(Atom("123456789.123456789.1")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.123")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.1234")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.12345")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.123456789.1")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.123456789.12")), s(NA+32, NA+32));
+assertEq(byteSize(Atom("123456789.123456789.123456789.123")), s(NA+48, NA+48));
+
// Inline char16_t atoms.
// "Impassionate gods have never seen the red that is the Tatsuta River."
// - Ariwara no Narihira
@@ -183,20 +205,43 @@ assertEq(byteSize(rope8), s(Nurser
minorgc();
assertEq(byteSize(rope8), s(RN, RN));
var matches8 = rope8.match(/(de cuyo nombre no quiero acordarme)/);
-assertEq(byteSize(rope8), s(XN + 65536, XN + 65536));
+assertEq(byteSize(rope8), s(XN + 64 * 1024, XN + 64 * 1024));
+var ext8 = rope8; // Stop calling it what it's not (though it'll change again soon.)
// Test extensible strings.
//
// Appending another copy of the fragment should yield another rope.
//
-// Flatting that should turn the original rope into a dependent string, and
+// Flattening that should turn the original rope into a dependent string, and
// yield a new linear string, of the same size as the original.
-rope8a = rope8 + fragment8;
+var rope8a = ext8 + fragment8;
assertEq(byteSize(rope8a), s(Nursery(RN), Nursery(RN)));
rope8a.match(/x/, function() { assertEq(true, false); });
assertEq(byteSize(rope8a), s(Nursery(XN) + 65536, Nursery(XN) + 65536));
+assertEq(byteSize(ext8), s(DN, DN));
+
+// Latin-1 dependent strings in the nursery.
+assertEq(byteSize(ext8.substr(1000, 2000)), s(Nursery(DN), Nursery(DN)));
+assertEq(byteSize(matches8[0]), s(Nursery(DN), Nursery(DN)));
+assertEq(byteSize(matches8[1]), s(Nursery(DN), Nursery(DN)));
+
+// Tenure everything and do it again.
+ext8 = copyString(ext8);
+rope8a = ext8 + fragment8;
+minorgc();
+assertEq(byteSize(rope8a), s(RN, RN));
+rope8a.match(/x/, function() { assertEq(true, false); });
+assertEq(byteSize(rope8a), s(XN + 65536, XN + 65536));
assertEq(byteSize(rope8), s(RN, RN));
+// Latin-1 tenured dependent strings.
+function tenure(s) {
+ minorgc();
+ return s;
+}
+assertEq(byteSize(tenure(rope8.substr(1000, 2000))), s(DN, DN));
+assertEq(byteSize(matches8[0]), s(DN, DN));
+assertEq(byteSize(matches8[1]), s(DN, DN));
// A char16_t rope. This changes size when flattened.
// "From the Heliconian Muses let us begin to sing"
@@ -207,13 +252,11 @@ for (var i = 0; i < 10; i++) // 1024 repetitions
rope16 = rope16 + rope16;
assertEq(byteSize(rope16), s(Nursery(RN), Nursery(RN)));
let matches16 = rope16.match(/(Ἑλικωνιάδων ἀρχώμεθ᾽)/);
-assertEq(byteSize(rope16), s(Nursery(RN) + 131072, Nursery(RN) + 131072));
+assertEq(byteSize(rope16), s(Nursery(XN) + 128 * 1024, Nursery(XN) + 128 * 1024));
+var ext16 = rope16;
-// Latin-1 and char16_t dependent strings.
-assertEq(byteSize(rope8.substr(1000, 2000)), s(Nursery(DN), Nursery(DN)));
-assertEq(byteSize(rope16.substr(1000, 2000)), s(Nursery(DN), Nursery(DN)));
-assertEq(byteSize(matches8[0]), s(Nursery(DN), Nursery(DN)));
-assertEq(byteSize(matches8[1]), s(Nursery(DN), Nursery(DN)));
+// char16_t dependent strings in the nursery.
+assertEq(byteSize(ext16.substr(1000, 2000)), s(Nursery(DN), Nursery(DN)));
assertEq(byteSize(matches16[0]), s(Nursery(DN), Nursery(DN)));
assertEq(byteSize(matches16[1]), s(Nursery(DN), Nursery(DN)));
@@ -221,13 +264,23 @@ assertEq(byteSize(matches16[1]), s(Nurser
//
// Appending another copy of the fragment should yield another rope.
//
-// Flatting that should turn the original rope into a dependent string, and
+// Flattening that should turn the original rope into a dependent string, and
// yield a new linear string, of the some size as the original.
-rope16a = rope16 + fragment16;
+rope16a = ext16 + fragment16;
assertEq(byteSize(rope16a), s(Nursery(RN), Nursery(RN)));
rope16a.match(/x/, function() { assertEq(true, false); });
-assertEq(byteSize(rope16a), s(Nursery(XN) + 131072, Nursery(XN) + 131072));
-assertEq(byteSize(rope16), s(Nursery(XN), Nursery(XN)));
+assertEq(byteSize(rope16a), s(Nursery(XN) + 128 * 1024, Nursery(XN) + 128 * 1024));
+assertEq(byteSize(ext16), s(Nursery(DN), Nursery(DN)));
+
+// Tenure everything and try again. This time it should steal the extensible
+// characters and convert the root into an extensible string using them.
+ext16 = copyString(ext16);
+rope16a = ext16 + fragment16;
+minorgc();
+assertEq(byteSize(rope16a), s(RN, RN));
+rope16a.match(/x/, function() { assertEq(true, false); });
+assertEq(byteSize(rope16a), s(XN + 128 * 1024, XN + 128 * 1024));
+assertEq(byteSize(ext16), s(RN, RN));
// Test external strings.
//