[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:
parent
05a76791c4
commit
5d3e12941e
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user