Commit 362eddde authored by Marja Hölttä's avatar Marja Hölttä Committed by V8 LUCI CQ

[rab/gsab] Add RAB / GSAB support to KeyedStoreIC

Existing tests already exercise KeyedStoreIC; this CL makes them
take the fast path instead of the slow path.

Bug: v8:11111
Change-Id: I13b84650ae37abe1a8a46d53c9a9b7104bed31de
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2910315
Commit-Queue: Marja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74706}
parent f2dbf318
......@@ -244,20 +244,20 @@ void HandlerBuiltinsAssembler::DispatchByElementsKind(
Switch(elements_kind, &if_unknown_type, elements_kinds, elements_kind_labels,
arraysize(elements_kinds));
#define ELEMENTS_KINDS_CASE(KIND) \
BIND(&if_##KIND); \
{ \
if (!FLAG_enable_sealed_frozen_elements_kind && \
IsAnyNonextensibleElementsKindUnchecked(KIND)) { \
/* Disable support for frozen or sealed elements kinds. */ \
Unreachable(); \
} else if (!handle_typed_elements_kind && \
IsTypedArrayElementsKind(KIND)) { \
Unreachable(); \
} else { \
case_function(KIND); \
Goto(&next); \
} \
#define ELEMENTS_KINDS_CASE(KIND) \
BIND(&if_##KIND); \
{ \
if (!FLAG_enable_sealed_frozen_elements_kind && \
IsAnyNonextensibleElementsKindUnchecked(KIND)) { \
/* Disable support for frozen or sealed elements kinds. */ \
Unreachable(); \
} else if (!handle_typed_elements_kind && \
IsTypedArrayOrRabGsabTypedArrayElementsKind(KIND)) { \
Unreachable(); \
} else { \
case_function(KIND); \
Goto(&next); \
} \
}
ELEMENTS_KINDS(ELEMENTS_KINDS_CASE)
#undef ELEMENTS_KINDS_CASE
......
......@@ -10834,6 +10834,14 @@ void CodeStubAssembler::EmitElementStoreTypedArray(
TNode<Context> context, TVariable<Object>* maybe_converted_value) {
Label done(this), update_value_and_bailout(this, Label::kDeferred);
bool is_rab_gsab = false;
if (IsRabGsabTypedArrayElementsKind(elements_kind)) {
is_rab_gsab = true;
// For the rest of the function, use the corresponding non-RAB/GSAB
// ElementsKind.
elements_kind = GetCorrespondingNonRabGsabElementsKind(elements_kind);
}
TNode<TValue> converted_value =
PrepareValueForWriteToTypedArray<TValue>(value, elements_kind, context);
......@@ -10842,16 +10850,23 @@ void CodeStubAssembler::EmitElementStoreTypedArray(
// the buffer is not alive or move the elements.
// TODO(ishell): introduce DisallowGarbageCollectionCode scope here.
// Check if buffer has been detached.
// Check if buffer has been detached. (For RAB / GSAB this is part of loading
// the length, so no additional check is needed.)
TNode<JSArrayBuffer> buffer = LoadJSArrayBufferViewBuffer(typed_array);
if (maybe_converted_value) {
if (!is_rab_gsab) {
GotoIf(IsDetachedBuffer(buffer), &update_value_and_bailout);
} else {
GotoIf(IsDetachedBuffer(buffer), bailout);
}
// Bounds check.
TNode<UintPtrT> length = LoadJSTypedArrayLength(typed_array);
TNode<UintPtrT> length;
if (is_rab_gsab) {
length = LoadVariableLengthJSTypedArrayLength(
typed_array, buffer,
store_mode == STORE_IGNORE_OUT_OF_BOUNDS ? &done
: &update_value_and_bailout);
} else {
length = LoadJSTypedArrayLength(typed_array);
}
if (store_mode == STORE_IGNORE_OUT_OF_BOUNDS) {
// Skip the store if we write beyond the length or
......@@ -10866,19 +10881,21 @@ void CodeStubAssembler::EmitElementStoreTypedArray(
StoreElement(data_ptr, elements_kind, key, converted_value);
Goto(&done);
BIND(&update_value_and_bailout);
// We already prepared the incoming value for storing into a typed array.
// This might involve calling ToNumber in some cases. We shouldn't call
// ToNumber again in the runtime so pass the converted value to the runtime.
// The prepared value is an untagged value. Convert it to a tagged value
// to pass it to runtime. It is not possible to do the detached buffer check
// before we prepare the value, since ToNumber can detach the ArrayBuffer.
// The spec specifies the order of these operations.
if (maybe_converted_value != nullptr) {
EmitElementStoreTypedArrayUpdateValue(value, elements_kind, converted_value,
maybe_converted_value);
if (!is_rab_gsab || store_mode != STORE_IGNORE_OUT_OF_BOUNDS) {
BIND(&update_value_and_bailout);
// We already prepared the incoming value for storing into a typed array.
// This might involve calling ToNumber in some cases. We shouldn't call
// ToNumber again in the runtime so pass the converted value to the runtime.
// The prepared value is an untagged value. Convert it to a tagged value
// to pass it to runtime. It is not possible to do the detached buffer check
// before we prepare the value, since ToNumber can detach the ArrayBuffer.
// The spec specifies the order of these operations.
if (maybe_converted_value != nullptr) {
EmitElementStoreTypedArrayUpdateValue(
value, elements_kind, converted_value, maybe_converted_value);
}
Goto(bailout);
}
Goto(bailout);
BIND(&done);
}
......@@ -10889,12 +10906,6 @@ void CodeStubAssembler::EmitElementStore(
TNode<Context> context, TVariable<Object>* maybe_converted_value) {
CSA_ASSERT(this, Word32BinaryNot(IsJSProxy(object)));
// TODO(v8:11111): Fast path for RAB / GSAB backed TypedArrays.
if (IsRabGsabTypedArrayElementsKind(elements_kind)) {
GotoIf(Int32TrueConstant(), bailout);
return;
}
TNode<FixedArrayBase> elements = LoadElements(object);
if (!(IsSmiOrObjectElementsKind(elements_kind) ||
IsSealedElementsKind(elements_kind) ||
......@@ -10909,7 +10920,7 @@ void CodeStubAssembler::EmitElementStore(
// TODO(rmcilroy): TNodify the converted value once this funciton and
// StoreElement are templated based on the type elements_kind type.
if (IsTypedArrayElementsKind(elements_kind)) {
if (IsTypedArrayOrRabGsabTypedArrayElementsKind(elements_kind)) {
TNode<JSTypedArray> typed_array = CAST(object);
switch (elements_kind) {
case UINT8_ELEMENTS:
......@@ -10919,22 +10930,33 @@ void CodeStubAssembler::EmitElementStore(
case UINT32_ELEMENTS:
case INT32_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
case RAB_GSAB_UINT8_ELEMENTS:
case RAB_GSAB_INT8_ELEMENTS:
case RAB_GSAB_UINT16_ELEMENTS:
case RAB_GSAB_INT16_ELEMENTS:
case RAB_GSAB_UINT32_ELEMENTS:
case RAB_GSAB_INT32_ELEMENTS:
case RAB_GSAB_UINT8_CLAMPED_ELEMENTS:
EmitElementStoreTypedArray<Word32T>(typed_array, intptr_key, value,
elements_kind, store_mode, bailout,
context, maybe_converted_value);
break;
case FLOAT32_ELEMENTS:
case RAB_GSAB_FLOAT32_ELEMENTS:
EmitElementStoreTypedArray<Float32T>(typed_array, intptr_key, value,
elements_kind, store_mode, bailout,
context, maybe_converted_value);
break;
case FLOAT64_ELEMENTS:
case RAB_GSAB_FLOAT64_ELEMENTS:
EmitElementStoreTypedArray<Float64T>(typed_array, intptr_key, value,
elements_kind, store_mode, bailout,
context, maybe_converted_value);
break;
case BIGINT64_ELEMENTS:
case BIGUINT64_ELEMENTS:
case RAB_GSAB_BIGINT64_ELEMENTS:
case RAB_GSAB_BIGUINT64_ELEMENTS:
EmitElementStoreTypedArray<BigInt>(typed_array, intptr_key, value,
elements_kind, store_mode, bailout,
context, maybe_converted_value);
......
......@@ -2083,10 +2083,10 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
} else if (receiver_map->has_fast_elements() ||
receiver_map->has_sealed_elements() ||
receiver_map->has_nonextensible_elements() ||
receiver_map->has_typed_array_elements()) {
receiver_map->has_typed_array_or_rab_gsab_typed_array_elements()) {
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
code = CodeFactory::StoreFastElementIC(isolate(), store_mode).code();
if (receiver_map->has_typed_array_elements()) {
if (receiver_map->has_typed_array_or_rab_gsab_typed_array_elements()) {
return code;
}
} else if (IsStoreInArrayLiteralICKind(kind())) {
......@@ -2097,9 +2097,7 @@ Handle<Object> KeyedStoreIC::StoreElementHandler(
// TODO(jgruber): Update counter name.
TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
DCHECK(DICTIONARY_ELEMENTS == receiver_map->elements_kind() ||
receiver_map->has_frozen_elements() ||
receiver_map->has_rab_gsab_typed_array_elements());
// TODO(v8:11111): Add fast paths for RAB / GSAB.
receiver_map->has_frozen_elements());
code = StoreHandler::StoreSlow(isolate(), store_mode);
}
......@@ -2205,7 +2203,8 @@ KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, size_t index) {
if (allow_growth) {
return STORE_AND_GROW_HANDLE_COW;
}
if (receiver->map().has_typed_array_elements() && oob_access) {
if (receiver->map().has_typed_array_or_rab_gsab_typed_array_elements() &&
oob_access) {
return STORE_IGNORE_OUT_OF_BOUNDS;
}
return receiver->elements().IsCowArray() ? STORE_HANDLE_COW : STANDARD_STORE;
......
......@@ -333,6 +333,14 @@ inline ElementsKind GetCorrespondingRabGsabElementsKind(
FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
}
inline ElementsKind GetCorrespondingNonRabGsabElementsKind(
ElementsKind typed_array_kind) {
DCHECK(IsRabGsabTypedArrayElementsKind(typed_array_kind));
return ElementsKind(typed_array_kind -
FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
}
inline bool UnionElementsKindUptoPackedness(ElementsKind* a_out,
ElementsKind b) {
// Assert that the union of two ElementKinds can be computed via std::max.
......
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