Commit 589f5264 authored by Santiago Aboy Solanes's avatar Santiago Aboy Solanes Committed by V8 LUCI CQ

[compiler] Do StringRef::GetCharAsStringOrUndefined concurrently

We can reuse part of ConcurrentLookupIterator::TryGetOwnConstantElement
to read a char from a string concurrently.

Bug: v8:7790, v8:11012
Change-Id: Iaa75e0cdb457963e89e6bbbdb79766502286cc2d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3097277
Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76318}
parent 31a91cb8
......@@ -2069,11 +2069,24 @@ ObjectRef MapRef::GetFieldType(InternalIndex descriptor_index) const {
base::Optional<ObjectRef> StringRef::GetCharAsStringOrUndefined(
uint32_t index, SerializationPolicy policy) const {
// TODO(solanes, neis, v8:7790, v8:11012): Re-enable this optimization for
// concurrent inlining when we have the infrastructure to safely do so.
if (broker()->is_concurrent_inlining()) return base::nullopt;
CHECK_EQ(data_->kind(), ObjectDataKind::kUnserializedHeapObject);
return GetOwnElementFromHeap(broker(), object(), index, true);
if (broker()->is_concurrent_inlining()) {
String maybe_char;
auto result = ConcurrentLookupIterator::TryGetOwnChar(
&maybe_char, broker()->isolate(), broker()->local_isolate(), *object(),
index);
if (result == ConcurrentLookupIterator::kGaveUp) {
TRACE_BROKER_MISSING(broker(), "StringRef::GetCharAsStringOrUndefined on "
<< *this << " at index " << index);
return {};
}
DCHECK_EQ(result, ConcurrentLookupIterator::kPresent);
return TryMakeRef(broker(), maybe_char);
}
CHECK_EQ(data_->kind(), ObjectDataKind::kUnserializedHeapObject);
return GetOwnElementFromHeap(broker(), object(), index, true);
}
bool StringRef::SupportedStringKind() const {
......
......@@ -1473,34 +1473,9 @@ ConcurrentLookupIterator::TryGetOwnConstantElement(
JSPrimitiveWrapper js_value = JSPrimitiveWrapper::cast(holder);
String wrapped_string = String::cast(js_value.value());
// The access guard below protects string accesses related to internalized
// strings.
// TODO(jgruber): Support other string kinds.
Map wrapped_string_map = wrapped_string.map(isolate, kAcquireLoad);
InstanceType wrapped_type = wrapped_string_map.instance_type();
if (!(InstanceTypeChecker::IsInternalizedString(wrapped_type)) ||
InstanceTypeChecker::IsThinString(wrapped_type)) {
return kGaveUp;
}
const uint32_t length = static_cast<uint32_t>(wrapped_string.length());
if (index >= length) return kGaveUp;
uint16_t charcode;
{
SharedStringAccessGuardIfNeeded access_guard(local_isolate);
charcode = wrapped_string.Get(static_cast<int>(index));
}
if (charcode > unibrow::Latin1::kMaxChar) return kGaveUp;
Object value = isolate->factory()->single_character_string_cache()->get(
charcode, kRelaxedLoad);
if (value == ReadOnlyRoots(isolate).undefined_value()) return kGaveUp;
*result_out = value;
return kPresent;
return ConcurrentLookupIterator::TryGetOwnChar(
static_cast<String*>(result_out), isolate, local_isolate,
wrapped_string, index);
} else {
DCHECK(!IsFrozenElementsKind(elements_kind));
DCHECK(!IsDictionaryElementsKind(elements_kind));
......@@ -1511,6 +1486,40 @@ ConcurrentLookupIterator::TryGetOwnConstantElement(
UNREACHABLE();
}
// static
ConcurrentLookupIterator::Result ConcurrentLookupIterator::TryGetOwnChar(
String* result_out, Isolate* isolate, LocalIsolate* local_isolate,
String string, size_t index) {
DisallowGarbageCollection no_gc;
// The access guard below protects string accesses related to internalized
// strings.
// TODO(jgruber): Support other string kinds.
Map string_map = string.map(isolate, kAcquireLoad);
InstanceType type = string_map.instance_type();
if (!(InstanceTypeChecker::IsInternalizedString(type)) ||
InstanceTypeChecker::IsThinString(type)) {
return kGaveUp;
}
const uint32_t length = static_cast<uint32_t>(string.length());
if (index >= length) return kGaveUp;
uint16_t charcode;
{
SharedStringAccessGuardIfNeeded access_guard(local_isolate);
charcode = string.Get(static_cast<int>(index));
}
if (charcode > unibrow::Latin1::kMaxChar) return kGaveUp;
Object value = isolate->factory()->single_character_string_cache()->get(
charcode, kRelaxedLoad);
if (value == ReadOnlyRoots(isolate).undefined_value()) return kGaveUp;
*result_out = String::cast(value);
return kPresent;
}
// static
base::Optional<PropertyCell> ConcurrentLookupIterator::TryGetPropertyCell(
Isolate* isolate, LocalIsolate* local_isolate,
......
......@@ -345,6 +345,13 @@ class ConcurrentLookupIterator final : public AllStatic {
JSObject holder, FixedArrayBase elements, ElementsKind elements_kind,
size_t index);
// Implements the own data property lookup for the specialized case of
// strings.
V8_EXPORT_PRIVATE static Result TryGetOwnChar(String* result_out,
Isolate* isolate,
LocalIsolate* local_isolate,
String string, size_t index);
// This method reimplements the following sequence in a concurrent setting:
//
// LookupIterator it(holder, isolate, name, LookupIterator::OWN);
......
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