[maglev] Support in-heap TypedArrays

Drive-by: fix a bug with TypedArray loads: because we used the output
register as a temporary, if it was actually aliasing with one of the
input registers, the generated code was incorrect.

Bug: v8:7700
Change-Id: Id297f728ca2de13ebc5993cea675900fbfdd7886
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4135884
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#85099}
This commit is contained in:
Darius M 2023-01-04 16:32:52 +01:00 committed by V8 LUCI CQ
parent 05a76791c4
commit 5d3e12941e
6 changed files with 52 additions and 25 deletions

View File

@ -317,6 +317,19 @@ inline MemOperand MaglevAssembler::ToMemOperand(const ValueLocation& location) {
return ToMemOperand(location.operand());
}
inline void MaglevAssembler::BuildTypedArrayDataPointer(Register data_pointer,
Register object) {
DCHECK_NE(data_pointer, object);
LoadExternalPointerField(
data_pointer,
FieldMemOperand(object, JSTypedArray::kExternalPointerOffset));
if (JSTypedArray::kMaxSizeInHeap == 0) return;
UseScratchRegisterScope scope(this);
Register base = scope.AcquireW();
ldr(base, FieldMemOperand(object, JSTypedArray::kBasePointerOffset));
add(data_pointer, data_pointer, base);
}
inline void MaglevAssembler::LoadBoundedSizeFromObject(Register result,
Register object,
int offset) {

View File

@ -1757,7 +1757,7 @@ void LoadSignedIntTypedArrayElement::GenerateCode(
Register object = ToRegister(object_input());
Register index = ToRegister(index_input());
Register result_reg = ToRegister(result());
Register data_pointer = result_reg;
__ AssertNotSmi(object);
if (v8_flags.debug_code) {
UseScratchRegisterScope temps(masm);
@ -1765,10 +1765,11 @@ void LoadSignedIntTypedArrayElement::GenerateCode(
__ CompareObjectType(object, scratch, scratch, JS_TYPED_ARRAY_TYPE);
__ Assert(eq, AbortReason::kUnexpectedValue);
}
UseScratchRegisterScope temps(masm);
Register data_pointer = temps.AcquireX();
int element_size = ElementsKindSize(elements_kind_);
__ LoadExternalPointerField(
data_pointer,
FieldMemOperand(object, JSTypedArray::kExternalPointerOffset));
__ BuildTypedArrayDataPointer(data_pointer, object);
__ Add(data_pointer, data_pointer, Operand(index, LSL, element_size / 2));
__ LoadSignedField(result_reg.W(), MemOperand(data_pointer), element_size);
}
@ -1783,7 +1784,7 @@ void LoadUnsignedIntTypedArrayElement::GenerateCode(
Register object = ToRegister(object_input());
Register index = ToRegister(index_input());
Register result_reg = ToRegister(result());
Register data_pointer = result_reg;
__ AssertNotSmi(object);
if (v8_flags.debug_code) {
UseScratchRegisterScope temps(masm);
@ -1791,10 +1792,11 @@ void LoadUnsignedIntTypedArrayElement::GenerateCode(
__ CompareObjectType(object, scratch, scratch, JS_TYPED_ARRAY_TYPE);
__ Assert(eq, AbortReason::kUnexpectedValue);
}
UseScratchRegisterScope temps(masm);
Register data_pointer = temps.AcquireX();
int element_size = ElementsKindSize(elements_kind_);
__ LoadExternalPointerField(
data_pointer,
FieldMemOperand(object, JSTypedArray::kExternalPointerOffset));
__ BuildTypedArrayDataPointer(data_pointer, object);
__ Add(data_pointer, data_pointer, Operand(index, LSL, element_size / 2));
__ LoadUnsignedField(result_reg.W(), MemOperand(data_pointer), element_size);
}
@ -1820,9 +1822,7 @@ void LoadDoubleTypedArrayElement::GenerateCode(MaglevAssembler* masm,
UseScratchRegisterScope temps(masm);
Register data_pointer = temps.AcquireX();
__ LoadExternalPointerField(
data_pointer,
FieldMemOperand(object, JSTypedArray::kExternalPointerOffset));
__ BuildTypedArrayDataPointer(data_pointer, object);
switch (elements_kind_) {
case FLOAT32_ELEMENTS:
__ Add(data_pointer, data_pointer, Operand(index, LSL, 2));

View File

@ -99,6 +99,8 @@ class MaglevAssembler : public MacroAssembler {
inline void StoreField(MemOperand operand, Register value, int element_size);
inline void ReverseByteOrder(Register value, int element_size);
void BuildTypedArrayDataPointer(Register data_pointer, Register object);
// Warning: Input registers {string} and {index} will be scratched.
// {result} is allowed to alias with one the other 3 input registers.
// {result} is an int32.

View File

@ -2213,11 +2213,6 @@ bool MaglevGraphBuilder::TryBuildElementAccess(
// TODO(victorgomes): Support more elements kind.
ElementsKind elements_kind = access_info.elements_kind();
if (IsTypedArrayElementsKind(elements_kind)) {
if (JSTypedArray::kMaxSizeInHeap != 0) {
// TODO(victorgomes): Support typed array in heap.
// Note that the common config is equal to 0 (for Chrome and Node).
return false;
}
if (elements_kind == BIGUINT64_ELEMENTS ||
elements_kind == BIGINT64_ELEMENTS) {
return false;

View File

@ -189,6 +189,18 @@ inline MemOperand MaglevAssembler::ToMemOperand(const ValueLocation& location) {
return ToMemOperand(location.operand());
}
inline void MaglevAssembler::BuildTypedArrayDataPointer(Register data_pointer,
Register object) {
DCHECK_NE(data_pointer, object);
LoadExternalPointerField(
data_pointer, FieldOperand(object, JSTypedArray::kExternalPointerOffset));
if (JSTypedArray::kMaxSizeInHeap == 0) return;
Register base = kScratchRegister;
movl(base, FieldOperand(object, JSTypedArray::kBasePointerOffset));
addq(data_pointer, base);
}
inline void MaglevAssembler::LoadBoundedSizeFromObject(Register result,
Register object,
int offset) {

View File

@ -1071,21 +1071,23 @@ void LoadSignedIntTypedArrayElement::SetValueLocationConstraints() {
UseRegister(object_input());
UseRegister(index_input());
DefineAsRegister(this);
set_temporaries_needed(1);
}
void LoadSignedIntTypedArrayElement::GenerateCode(
MaglevAssembler* masm, const ProcessingState& state) {
Register object = ToRegister(object_input());
Register index = ToRegister(index_input());
Register result_reg = ToRegister(result());
Register data_pointer = result_reg;
__ AssertNotSmi(object);
if (v8_flags.debug_code) {
__ CmpObjectType(object, JS_TYPED_ARRAY_TYPE, kScratchRegister);
__ Assert(equal, AbortReason::kUnexpectedValue);
}
Register data_pointer = general_temporaries().PopFirst();
__ BuildTypedArrayDataPointer(data_pointer, object);
int element_size = ElementsKindSize(elements_kind_);
__ LoadExternalPointerField(
data_pointer, FieldOperand(object, JSTypedArray::kExternalPointerOffset));
__ LoadSignedField(
result_reg,
Operand(data_pointer, index, ScaleFactorFromInt(element_size), 0),
@ -1096,21 +1098,23 @@ void LoadUnsignedIntTypedArrayElement::SetValueLocationConstraints() {
UseRegister(object_input());
UseRegister(index_input());
DefineAsRegister(this);
set_temporaries_needed(1);
}
void LoadUnsignedIntTypedArrayElement::GenerateCode(
MaglevAssembler* masm, const ProcessingState& state) {
Register object = ToRegister(object_input());
Register index = ToRegister(index_input());
Register result_reg = ToRegister(result());
Register data_pointer = result_reg;
__ AssertNotSmi(object);
if (v8_flags.debug_code) {
__ CmpObjectType(object, JS_TYPED_ARRAY_TYPE, kScratchRegister);
__ Assert(equal, AbortReason::kUnexpectedValue);
}
Register data_pointer = general_temporaries().PopFirst();
int element_size = ElementsKindSize(elements_kind_);
__ LoadExternalPointerField(
data_pointer, FieldOperand(object, JSTypedArray::kExternalPointerOffset));
__ BuildTypedArrayDataPointer(data_pointer, object);
__ LoadUnsignedField(
result_reg,
Operand(data_pointer, index, ScaleFactorFromInt(element_size), 0),
@ -1121,20 +1125,21 @@ void LoadDoubleTypedArrayElement::SetValueLocationConstraints() {
UseRegister(object_input());
UseRegister(index_input());
DefineAsRegister(this);
set_temporaries_needed(1);
}
void LoadDoubleTypedArrayElement::GenerateCode(MaglevAssembler* masm,
const ProcessingState& state) {
Register object = ToRegister(object_input());
Register index = ToRegister(index_input());
DoubleRegister result_reg = ToDoubleRegister(result());
Register data_pointer = kScratchRegister;
__ AssertNotSmi(object);
if (v8_flags.debug_code) {
__ CmpObjectType(object, JS_TYPED_ARRAY_TYPE, kScratchRegister);
__ Assert(equal, AbortReason::kUnexpectedValue);
}
__ LoadExternalPointerField(
data_pointer, FieldOperand(object, JSTypedArray::kExternalPointerOffset));
Register data_pointer = general_temporaries().PopFirst();
__ BuildTypedArrayDataPointer(data_pointer, object);
switch (elements_kind_) {
case FLOAT32_ELEMENTS:
__ Movss(result_reg, Operand(data_pointer, index, times_4, 0));