Commit 90a39679 authored by Joyee Cheung's avatar Joyee Cheung Committed by V8 LUCI CQ

[string] handle strings sliced from externalized one-byte strings

...in Runtime_StringToArray.

When a string is sliced from an externalized two-byte string that has
only one-byte chars, String::IsFlat() and
should not call ToOneByteVector() on it and instead we should use

String: :IsOneByteRepresentation() can both be true, while
FlatContent: :IsOneByte() returns false. In this case we
String: :Get() to get the individual characters.
Bug: chromium:1350270
Change-Id: I735408602072279f09b32e1997c97b2900942bdd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3813070Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Cr-Commit-Position: refs/heads/main@{#82268}
parent 5c9c1d75
......@@ -276,22 +276,32 @@ RUNTIME_FUNCTION(Runtime_StringToArray) {
static_cast<int>(std::min(static_cast<uint32_t>(s->length()), limit));
Handle<FixedArray> elements = isolate->factory()->NewFixedArray(length);
bool elements_are_initialized = false;
if (s->IsFlat() && s->IsOneByteRepresentation()) {
DisallowGarbageCollection no_gc;
String::FlatContent content = s->GetFlatContent(no_gc);
// Use pre-initialized single characters.
base::Vector<const uint8_t> chars = content.ToOneByteVector();
FixedArray one_byte_table =
isolate->heap()->single_character_string_table();
for (int i = 0; i < length; ++i) {
Object value = one_byte_table.get(chars[i]);
DCHECK(value.IsString());
DCHECK(ReadOnlyHeap::Contains(HeapObject::cast(value)));
// The single-character strings are in RO space so it should
// be safe to skip the write barriers.
elements->set(i, value, SKIP_WRITE_BARRIER);
// Use pre-initialized single characters to intialize all the elements.
// This can be false if the string is sliced from an externalized
// two-byte string that has only one-byte chars, in that case we will do
// a LookupSingleCharacterStringFromCode for each of the characters.
if (content.IsOneByte()) {
base::Vector<const uint8_t> chars = content.ToOneByteVector();
FixedArray one_byte_table =
isolate->heap()->single_character_string_table();
for (int i = 0; i < length; ++i) {
Object value = one_byte_table.get(chars[i]);
DCHECK(value.IsString());
DCHECK(ReadOnlyHeap::Contains(HeapObject::cast(value)));
// The single-character strings are in RO space so it should
// be safe to skip the write barriers.
elements->set(i, value, SKIP_WRITE_BARRIER);
}
elements_are_initialized = true;
}
} else {
}
if (!elements_are_initialized) {
for (int i = 0; i < length; ++i) {
Handle<Object> str =
isolate->factory()->LookupSingleCharacterStringFromCode(s->Get(i));
......
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-externalize-string
let str1 = "external string turned into two byte";
let str2 = str1.substring(1);
try {
// Turn the string to a two-byte external string, so that the sliced
// string looks like one-byte, but its parent is actually two-byte.
externalizeString(str1, true);
} catch (e) { }
assertEquals(
["x", "t", "e", "r", "n", "a", "l", " ",
"s", "t", "r", "i", "n", "g", " ",
"t", "u", "r", "n", "e", "d", " ",
"i", "n", "t", "o", " ",
"t", "w", "o", " ",
"b", "y", "t", "e"], str2.split(""));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment