v8/test/mjsunit/string-externalize.js
Benedikt Meurer 683cf6f43b [cleanup] Remove obsolete "one byte data hint" for strings.
In the early days of Chrome when we used WebKit there was no support for
ASCII strings on the C++ side, so we put a hint onto these two-byte
strings that said "string only contains one byte data", such that
internally in V8 when these were involved in string operations, we could
instead create the *cheaper* one byte strings.

Nowadays Blink properly supports one-byte string representations and
this additional hint only comes with overhead, since we check it in
quite a few places (i.e. on the hot path for string concatenation), plus
we end up consuming more memory due to the additional string maps.
Removing the hint also frees one bit in the InstanceType zoo for
strings.

This alone improves performance on the `bench-dom-serialize.js` test case
by around **3%**.

Tbr: mstarzinger@chromium.org
Bug: v8:6622, v8:8834, v8:8939
Cq-Include-Trybots: luci.chromium.try:linux-blink-rel
Change-Id: I0753f2859cee7b5a37b6f0da64d8ec39fcb044ff
Doc: https://bit.ly/fast-string-concatenation-in-javascript
Reviewed-on: https://chromium-review.googlesource.com/c/1498478
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60006}
2019-03-04 14:04:02 +00:00

104 lines
3.8 KiB
JavaScript

// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-externalize-string --expose-gc --allow-natives-syntax
var size = 1024;
function dont_inline() { return "A"; }
%NeverOptimizeFunction(dont_inline);
function dont_inline2() { return "\u1234"; }
%NeverOptimizeFunction(dont_inline2);
function test() {
var str = "";
// Build an ascii cons string.
for (var i = 0; i < size; i++) {
str += String.fromCharCode(i & 0x7f);
}
assertTrue(isOneByteString(str));
var twoByteExternalWithOneByteData =
"AAAA" + dont_inline();
externalizeString(twoByteExternalWithOneByteData, true /* force two-byte */);
assertFalse(isOneByteString(twoByteExternalWithOneByteData));
var realTwoByteExternalString =
"\u1234\u1234\u1234\u1234" + dont_inline2();
externalizeString(realTwoByteExternalString);
assertFalse(isOneByteString(realTwoByteExternalString));
assertFalse(isOneByteString(["a", twoByteExternalWithOneByteData].join("")));
var str1 = str + twoByteExternalWithOneByteData;
assertFalse(isOneByteString(str1));
// Force flattening of the string.
var old_length = str1.length - twoByteExternalWithOneByteData.length;
for (var i = 0; i < old_length; i++) {
assertEquals(String.fromCharCode(i & 0x7f), str1[i]);
}
for (var i = old_length; i < str1.length; i++) {
assertEquals("A", str1[i]);
}
// Flattened string should still be two-byte.
assertFalse(isOneByteString(str1));
// Lower-casing an ascii string should produce two-byte.
assertFalse(isOneByteString(str1.toLowerCase()));
assertFalse(isOneByteString(["a", realTwoByteExternalString].join("")));
// Appending a real two-byte string should produce a two-byte cons.
var str2 = str + realTwoByteExternalString;
assertFalse(isOneByteString(str2));
// Force flattening of the string.
old_length = str2.length - realTwoByteExternalString.length;
for (var i = 0; i < old_length; i++) {
assertEquals(String.fromCharCode(i & 0x7f), str2[i]);
}
for (var i = old_length; i < str.length; i++) {
assertEquals("\u1234", str2[i]);
}
// Flattened string should still be two-byte.
assertFalse(isOneByteString(str2));
}
// Run the test many times to ensure IC-s don't break things.
for (var i = 0; i < 10; i++) {
test();
}
// Clean up string to make Valgrind happy.
gc();
gc();