stringbuffer-6.js (3752B)
1 // Test that long strings allocated by rope flattening have a string buffer. 2 3 gczeal(0); 4 5 // Must match sizeof(mozilla::StringBuffer) 6 const StringBufferSizeInBytes = 8; 7 8 function checkRefCount(s, expected) { 9 // stringRepresentation and the bufferRefCount field aren't available in 10 // all builds. 11 if (getBuildConfiguration("debug")) { 12 finishBackgroundFree(); 13 var repr = JSON.parse(stringRepresentation(s)); 14 assertEq(repr.bufferRefCount, expected); 15 } 16 } 17 function checkExtensibleCapacity(s, expected) { 18 if (getBuildConfiguration("debug")) { 19 var repr = JSON.parse(stringRepresentation(s)); 20 assertEq(repr.capacity, expected); 21 } 22 } 23 24 function testBasicLatin1() { 25 var s1 = ensureLinearString("a".repeat(1000)); 26 var s2 = ensureLinearString("b".repeat(1000)); 27 var flattened1 = ensureLinearString(newRope(s1, s2)); 28 checkRefCount(flattened1, 1); 29 // Test that the string's capacity + StringBuffer + null terminator fills up 30 // a jemalloc bucket of 2048 bytes. 31 var expectedCapacity = 2048 - StringBufferSizeInBytes - 1 /* null terminator */; 32 checkExtensibleCapacity(flattened1, expectedCapacity); 33 34 // Move string buffer to flattened2 and turn flattened into a dependent string. 35 var flattened2 = ensureLinearString(flattened1 + "abcdef"); 36 checkRefCount(flattened1, undefined); 37 checkRefCount(flattened2, 1); 38 assertEq(flattened2.length, 2006); 39 40 // Share the StringBuffer with another JS string. 41 var sharedBuffer = newString(flattened2, {shareStringBuffer: true}); 42 checkRefCount(flattened2, 2); 43 44 // Because there are now multiple references, we don't use the extensible buffer. 45 var flattened3 = ensureLinearString(flattened2 + "abcdef"); 46 checkRefCount(flattened2, 2); 47 checkRefCount(flattened3, 1); 48 checkExtensibleCapacity(flattened3, expectedCapacity); 49 } 50 testBasicLatin1(); 51 52 function testBasicTwoByte() { 53 var s1 = ensureLinearString("\u1234".repeat(500)); 54 var s2 = ensureLinearString("\u1256".repeat(500)); 55 var flattened1 = ensureLinearString(newRope(s1, s2)); 56 checkRefCount(flattened1, 1); 57 // Test that the string's capacity + StringBuffer + null terminator fills up 58 // a jemalloc bucket of 2048 bytes. 59 var expectedCapacity = 1024 - StringBufferSizeInBytes / 2 - 1 /* null terminator */; 60 checkExtensibleCapacity(flattened1, expectedCapacity); 61 62 // Move string buffer to flattened2 and turn flattened into a dependent string. 63 var flattened2 = ensureLinearString(flattened1 + "abcdef"); 64 checkRefCount(flattened1, undefined); 65 checkRefCount(flattened2, 1); 66 assertEq(flattened2.length, 1006); 67 68 // Share the StringBuffer with another JS string. 69 var sharedBuffer = newString(flattened2, {shareStringBuffer: true}); 70 checkRefCount(flattened2, 2); 71 72 // Because there are now multiple references, we don't use the extensible buffer. 73 var flattened3 = ensureLinearString(flattened2 + "abcdef"); 74 checkRefCount(flattened2, 2); 75 checkRefCount(flattened3, 1); 76 checkExtensibleCapacity(flattened3, expectedCapacity); 77 } 78 testBasicTwoByte(); 79 80 function testBufferTransfer(fromNursery, toNursery) { 81 var s1 = ensureLinearString("a".repeat(1000)); 82 var s2 = ensureLinearString("b".repeat(1000)); 83 var flattened1 = ensureLinearString(newRope(s1, s2, {nursery: fromNursery})); 84 checkRefCount(flattened1, 1); 85 86 var flattened2 = ensureLinearString(newRope(flattened1, "abcdef", {nursery: toNursery})); 87 checkRefCount(flattened1, undefined); 88 checkRefCount(flattened2, 1); 89 gc(); 90 checkRefCount(flattened2, 1); 91 } 92 testBufferTransfer(false, false); 93 testBufferTransfer(false, true); 94 testBufferTransfer(true, false); 95 testBufferTransfer(true, true);