[maglev] Support Load/StoreDataView for Float64
Bug: v8:7700 Change-Id: Ie6239a5ed51c294252ae980de1b0eccbea1b233a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4017832 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Auto-Submit: Victor Gomes <victorgomes@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#84173}
This commit is contained in:
parent
1a935b3c28
commit
adc29dd514
@ -93,6 +93,15 @@ inline void MaglevAssembler::DefineExceptionHandlerAndLazyDeoptPoint(
|
||||
DefineLazyDeoptPoint(node->lazy_deopt_info());
|
||||
}
|
||||
|
||||
inline void MaglevAssembler::LoadBoundedSizeFromObject(Register result,
|
||||
Register object,
|
||||
int offset) {
|
||||
movq(result, FieldOperand(object, offset));
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
shrq(result, Immediate(kBoundedSizeShift));
|
||||
#endif // V8_ENABLE_SANDBOX
|
||||
}
|
||||
|
||||
// ---
|
||||
// Deferred code handling.
|
||||
// ---
|
||||
|
@ -78,6 +78,9 @@ class MaglevAssembler : public MacroAssembler {
|
||||
inline void PushInput(const Input& input);
|
||||
inline Register FromAnyToRegister(const Input& input, Register scratch);
|
||||
|
||||
inline void LoadBoundedSizeFromObject(Register result, Register object,
|
||||
int offset);
|
||||
|
||||
// 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.
|
||||
|
@ -2605,6 +2605,64 @@ void MaglevGraphBuilder::InlineCallFromRegisters(
|
||||
->SetToBlockAndReturnNext(current_block_);
|
||||
}
|
||||
|
||||
bool MaglevGraphBuilder::TryReduceDataViewPrototypeGetFloat64(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
if (!broker()->dependencies()->DependOnArrayBufferDetachingProtector()) {
|
||||
// TODO(victorgomes): Add checks whether the array has been detached.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(victorgomes): Add data view to known types.
|
||||
ValueNode* receiver = GetTaggedReceiver(args);
|
||||
AddNewNode<CheckInstanceType>({receiver}, CheckType::kCheckHeapObject,
|
||||
JS_DATA_VIEW_TYPE);
|
||||
|
||||
auto offset_register = args.maybe_at(0);
|
||||
ValueNode* offset = offset_register ? GetInt32ElementIndex(*offset_register)
|
||||
: GetInt32Constant(0);
|
||||
AddNewNode<CheckJSDataViewBounds>({receiver, offset},
|
||||
ExternalArrayType::kExternalFloat64Array);
|
||||
|
||||
auto is_little_endian_offset = args.maybe_at(1);
|
||||
ValueNode* is_little_endian = is_little_endian_offset
|
||||
? GetTaggedValue(*is_little_endian_offset)
|
||||
: GetBooleanConstant(false);
|
||||
SetAccumulator(AddNewNode<LoadDoubleDataViewElement>(
|
||||
{receiver, offset, is_little_endian}));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaglevGraphBuilder::TryReduceDataViewPrototypeSetFloat64(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
if (!broker()->dependencies()->DependOnArrayBufferDetachingProtector()) {
|
||||
// TODO(victorgomes): Add checks whether the array has been detached.
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(victorgomes): Add data view to known types.
|
||||
ValueNode* receiver = GetTaggedReceiver(args);
|
||||
AddNewNode<CheckInstanceType>({receiver}, CheckType::kCheckHeapObject,
|
||||
JS_DATA_VIEW_TYPE);
|
||||
|
||||
auto offset_register = args.maybe_at(0);
|
||||
ValueNode* offset = offset_register ? GetInt32ElementIndex(*offset_register)
|
||||
: GetInt32Constant(0);
|
||||
AddNewNode<CheckJSDataViewBounds>({receiver, offset},
|
||||
ExternalArrayType::kExternalFloat64Array);
|
||||
|
||||
auto value_register = args.maybe_at(1);
|
||||
ValueNode* value =
|
||||
value_register ? GetFloat64(*value_register) : GetFloat64Constant(0);
|
||||
|
||||
auto is_little_endian_register = args.maybe_at(2);
|
||||
ValueNode* is_little_endian = is_little_endian_register
|
||||
? GetTaggedValue(*is_little_endian_register)
|
||||
: GetBooleanConstant(false);
|
||||
AddNewNode<StoreDoubleDataViewElement>(
|
||||
{receiver, offset, value, is_little_endian});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MaglevGraphBuilder::TryReduceStringFromCharCode(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
if (args.count() != 1) return false;
|
||||
|
@ -1045,7 +1045,7 @@ class MaglevGraphBuilder {
|
||||
|
||||
int count_with_receiver() const { return count() + 1; }
|
||||
|
||||
const interpreter::Register operator[](size_t i) const {
|
||||
interpreter::Register at(size_t i) const {
|
||||
if (receiver_mode_ != ConvertReceiverMode::kNullOrUndefined) {
|
||||
i++;
|
||||
}
|
||||
@ -1057,6 +1057,13 @@ class MaglevGraphBuilder {
|
||||
return reglist_[i];
|
||||
}
|
||||
|
||||
interpreter::Register operator[](size_t i) const { return at(i); }
|
||||
|
||||
base::Optional<interpreter::Register> maybe_at(int i) const {
|
||||
if (i < count()) return at(i);
|
||||
return {};
|
||||
}
|
||||
|
||||
ConvertReceiverMode receiver_mode() const { return receiver_mode_; }
|
||||
|
||||
CallArguments PopReceiver(ConvertReceiverMode new_receiver_mode) const {
|
||||
@ -1098,6 +1105,8 @@ class MaglevGraphBuilder {
|
||||
const CallArguments& args);
|
||||
|
||||
#define MAGLEV_REDUCED_BUILTIN(V) \
|
||||
V(DataViewPrototypeGetFloat64) \
|
||||
V(DataViewPrototypeSetFloat64) \
|
||||
V(FunctionPrototypeCall) \
|
||||
V(StringFromCharCode) \
|
||||
V(StringPrototypeCharCodeAt)
|
||||
|
@ -122,6 +122,7 @@ class MaglevGraphVerifier {
|
||||
case Opcode::kCheckNumber:
|
||||
case Opcode::kCheckString:
|
||||
case Opcode::kCheckSymbol:
|
||||
case Opcode::kCheckInstanceType:
|
||||
case Opcode::kCheckedInternalizedString:
|
||||
case Opcode::kCheckedObjectToIndex:
|
||||
case Opcode::kConvertReceiver:
|
||||
@ -288,6 +289,7 @@ class MaglevGraphVerifier {
|
||||
}
|
||||
break;
|
||||
case Opcode::kCheckJSArrayBounds:
|
||||
case Opcode::kCheckJSDataViewBounds:
|
||||
case Opcode::kCheckJSObjectElementsBounds:
|
||||
case Opcode::kLoadTaggedElement:
|
||||
case Opcode::kLoadDoubleElement:
|
||||
@ -297,6 +299,19 @@ class MaglevGraphVerifier {
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
||||
break;
|
||||
case Opcode::kLoadDoubleDataViewElement:
|
||||
DCHECK_EQ(node->input_count(), 3);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
||||
CheckValueInputIs(node, 2, ValueRepresentation::kTagged);
|
||||
break;
|
||||
case Opcode::kStoreDoubleDataViewElement:
|
||||
DCHECK_EQ(node->input_count(), 4);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
||||
CheckValueInputIs(node, 2, ValueRepresentation::kFloat64);
|
||||
CheckValueInputIs(node, 3, ValueRepresentation::kTagged);
|
||||
break;
|
||||
case Opcode::kCallBuiltin: {
|
||||
CallBuiltin* call_builtin = node->Cast<CallBuiltin>();
|
||||
auto descriptor =
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "src/maglev/maglev-ir-inl.h"
|
||||
#include "src/maglev/maglev-vreg-allocator.h"
|
||||
#include "src/objects/instance-type.h"
|
||||
#include "src/objects/js-array-buffer.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -1224,6 +1225,27 @@ void CheckSymbol::GenerateCode(MaglevAssembler* masm,
|
||||
void CheckSymbol::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {}
|
||||
|
||||
void CheckInstanceType::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(receiver_input());
|
||||
}
|
||||
void CheckInstanceType::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(receiver_input());
|
||||
if (check_type_ == CheckType::kOmitHeapObjectCheck) {
|
||||
__ AssertNotSmi(object);
|
||||
} else {
|
||||
Condition is_smi = __ CheckSmi(object);
|
||||
__ EmitEagerDeoptIf(is_smi, DeoptimizeReason::kWrongInstanceType, this);
|
||||
}
|
||||
__ LoadMap(kScratchRegister, object);
|
||||
__ CmpInstanceType(kScratchRegister, instance_type());
|
||||
__ EmitEagerDeoptIf(not_equal, DeoptimizeReason::kWrongInstanceType, this);
|
||||
}
|
||||
void CheckInstanceType::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {
|
||||
os << "(" << instance_type() << ")";
|
||||
}
|
||||
|
||||
void CheckString::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(receiver_input());
|
||||
}
|
||||
@ -1396,6 +1418,47 @@ void CheckJSArrayBounds::GenerateCode(MaglevAssembler* masm,
|
||||
__ EmitEagerDeoptIf(above_equal, DeoptimizeReason::kOutOfBounds, this);
|
||||
}
|
||||
|
||||
namespace {
|
||||
int ExternalArrayElementSize(const ExternalArrayType element_type) {
|
||||
switch (element_type) {
|
||||
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
|
||||
case kExternal##Type##Array: \
|
||||
DCHECK_LE(sizeof(ctype), 8); \
|
||||
return sizeof(ctype);
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
||||
default:
|
||||
UNREACHABLE();
|
||||
#undef TYPED_ARRAY_CASE
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void CheckJSDataViewBounds::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(receiver_input());
|
||||
UseRegister(index_input());
|
||||
}
|
||||
void CheckJSDataViewBounds::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(receiver_input());
|
||||
Register index = ToRegister(index_input());
|
||||
Register byte_length = kScratchRegister;
|
||||
if (v8_flags.debug_code) {
|
||||
__ AssertNotSmi(object);
|
||||
__ CmpObjectType(object, JS_DATA_VIEW_TYPE, kScratchRegister);
|
||||
__ Assert(equal, AbortReason::kUnexpectedValue);
|
||||
}
|
||||
__ LoadBoundedSizeFromObject(byte_length, object,
|
||||
JSDataView::kRawByteLengthOffset);
|
||||
int element_size = ExternalArrayElementSize(element_type_);
|
||||
if (element_size > 1) {
|
||||
__ subq(byte_length, Immediate(element_size - 1));
|
||||
__ EmitEagerDeoptIf(negative, DeoptimizeReason::kOutOfBounds, this);
|
||||
}
|
||||
__ cmpl(index, byte_length);
|
||||
__ EmitEagerDeoptIf(above_equal, DeoptimizeReason::kOutOfBounds, this);
|
||||
}
|
||||
|
||||
void CheckJSObjectElementsBounds::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(receiver_input());
|
||||
@ -1719,6 +1782,149 @@ void LoadDoubleElement::GenerateCode(MaglevAssembler* masm,
|
||||
FixedDoubleArray::kHeaderSize));
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool FromConstantToBool(MaglevAssembler* masm, ValueNode* node) {
|
||||
DCHECK(IsConstantNode(node->opcode()));
|
||||
LocalIsolate* local_isolate = masm->isolate()->AsLocalIsolate();
|
||||
switch (node->opcode()) {
|
||||
#define CASE(Name) \
|
||||
case Opcode::k##Name: { \
|
||||
return node->Cast<Name>()->ToBoolean(local_isolate); \
|
||||
}
|
||||
CONSTANT_VALUE_NODE_LIST(CASE)
|
||||
#undef CASE
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void LoadDoubleDataViewElement::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(object_input());
|
||||
UseRegister(index_input());
|
||||
if (is_little_endian_constant()) {
|
||||
UseAny(is_little_endian_input());
|
||||
} else {
|
||||
UseRegister(is_little_endian_input());
|
||||
}
|
||||
set_temporaries_needed(1);
|
||||
DefineAsRegister(vreg_state, this);
|
||||
}
|
||||
void LoadDoubleDataViewElement::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(object_input());
|
||||
Register index = ToRegister(index_input());
|
||||
DoubleRegister result_reg = ToDoubleRegister(result());
|
||||
Register data_pointer = general_temporaries().PopFirst();
|
||||
|
||||
__ AssertNotSmi(object);
|
||||
if (v8_flags.debug_code) {
|
||||
__ CmpObjectType(object, JS_DATA_VIEW_TYPE, kScratchRegister);
|
||||
__ Assert(above_equal, AbortReason::kUnexpectedValue);
|
||||
}
|
||||
|
||||
// Load data pointer.
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
__ LoadSandboxedPointerField(
|
||||
data_pointer, FieldOperand(object, JSDataView::kDataPointerOffset));
|
||||
#else
|
||||
__ movq(data_pointer, FieldOperand(object, JSDataView::kDataPointerOffset));
|
||||
#endif
|
||||
|
||||
if (is_little_endian_constant()) {
|
||||
if (FromConstantToBool(masm, is_little_endian_input().node())) {
|
||||
__ Movsd(result_reg, Operand(data_pointer, index, times_8, 0));
|
||||
} else {
|
||||
__ movq(kScratchRegister, Operand(data_pointer, index, times_8, 0));
|
||||
__ bswapq(kScratchRegister);
|
||||
__ Movq(result_reg, kScratchRegister);
|
||||
}
|
||||
} else {
|
||||
Label done;
|
||||
ZoneLabelRef is_little_endian(masm), is_big_endian(masm);
|
||||
// TODO(leszeks): We're likely to be calling this on an existing boolean --
|
||||
// maybe that's a case we should fast-path here and re-use that boolean
|
||||
// value?
|
||||
__ ToBoolean(ToRegister(is_little_endian_input()), is_little_endian,
|
||||
is_big_endian, true);
|
||||
// x64 is little endian.
|
||||
static_assert(V8_TARGET_LITTLE_ENDIAN == 1);
|
||||
__ bind(*is_little_endian);
|
||||
__ Movsd(result_reg, Operand(data_pointer, index, times_8, 0));
|
||||
__ jmp(&done);
|
||||
// We should swap the bytes if big endian.
|
||||
__ bind(*is_big_endian);
|
||||
__ movq(kScratchRegister, Operand(data_pointer, index, times_8, 0));
|
||||
__ bswapq(kScratchRegister);
|
||||
__ Movq(result_reg, kScratchRegister);
|
||||
__ bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void StoreDoubleDataViewElement::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(object_input());
|
||||
UseRegister(index_input());
|
||||
UseRegister(value_input());
|
||||
if (is_little_endian_constant()) {
|
||||
UseAny(is_little_endian_input());
|
||||
} else {
|
||||
UseRegister(is_little_endian_input());
|
||||
}
|
||||
set_temporaries_needed(1);
|
||||
}
|
||||
void StoreDoubleDataViewElement::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(object_input());
|
||||
Register index = ToRegister(index_input());
|
||||
DoubleRegister value = ToDoubleRegister(value_input());
|
||||
Register data_pointer = general_temporaries().PopFirst();
|
||||
|
||||
__ AssertNotSmi(object);
|
||||
if (v8_flags.debug_code) {
|
||||
__ CmpObjectType(object, JS_DATA_VIEW_TYPE, kScratchRegister);
|
||||
__ Assert(above_equal, AbortReason::kUnexpectedValue);
|
||||
}
|
||||
|
||||
// Load data pointer.
|
||||
#ifdef V8_ENABLE_SANDBOX
|
||||
__ LoadSandboxedPointerField(
|
||||
data_pointer, FieldOperand(object, JSDataView::kDataPointerOffset));
|
||||
#else
|
||||
__ movq(data_pointer, FieldOperand(object, JSDataView::kDataPointerOffset));
|
||||
#endif
|
||||
|
||||
if (is_little_endian_constant()) {
|
||||
if (FromConstantToBool(masm, is_little_endian_input().node())) {
|
||||
__ Movsd(Operand(data_pointer, index, times_8, 0), value);
|
||||
} else {
|
||||
__ Movq(kScratchRegister, value);
|
||||
__ bswapq(kScratchRegister);
|
||||
__ movq(Operand(data_pointer, index, times_8, 0), kScratchRegister);
|
||||
}
|
||||
} else {
|
||||
Label done;
|
||||
ZoneLabelRef is_little_endian(masm), is_big_endian(masm);
|
||||
// TODO(leszeks): We're likely to be calling this on an existing boolean --
|
||||
// maybe that's a case we should fast-path here and re-use that boolean
|
||||
// value?
|
||||
__ ToBoolean(ToRegister(is_little_endian_input()), is_little_endian,
|
||||
is_big_endian, true);
|
||||
// x64 is little endian.
|
||||
static_assert(V8_TARGET_LITTLE_ENDIAN == 1);
|
||||
__ bind(*is_little_endian);
|
||||
__ Movsd(Operand(data_pointer, index, times_8, 0), value);
|
||||
__ jmp(&done);
|
||||
// We should swap the bytes if big endian.
|
||||
__ bind(*is_big_endian);
|
||||
__ Movq(kScratchRegister, value);
|
||||
__ bswapq(kScratchRegister);
|
||||
__ movq(Operand(data_pointer, index, times_8, 0), kScratchRegister);
|
||||
__ bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void StoreDoubleField::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(object_input());
|
||||
UseRegister(value_input());
|
||||
|
@ -154,6 +154,7 @@ class CompactInterpreterFrameState;
|
||||
V(LoadTaggedField) \
|
||||
V(LoadDoubleField) \
|
||||
V(LoadTaggedElement) \
|
||||
V(LoadDoubleDataViewElement) \
|
||||
V(LoadDoubleElement) \
|
||||
V(LoadGlobal) \
|
||||
V(LoadNamedGeneric) \
|
||||
@ -208,6 +209,7 @@ class CompactInterpreterFrameState;
|
||||
V(CheckInt32Condition) \
|
||||
V(CheckJSArrayBounds) \
|
||||
V(CheckJSObjectElementsBounds) \
|
||||
V(CheckJSDataViewBounds) \
|
||||
V(CheckMaps) \
|
||||
V(CheckMapsWithMigration) \
|
||||
V(CheckNumber) \
|
||||
@ -215,11 +217,13 @@ class CompactInterpreterFrameState;
|
||||
V(CheckString) \
|
||||
V(CheckSymbol) \
|
||||
V(CheckValue) \
|
||||
V(CheckInstanceType) \
|
||||
V(DebugBreak) \
|
||||
V(GeneratorStore) \
|
||||
V(JumpLoopPrologue) \
|
||||
V(StoreMap) \
|
||||
V(StoreDoubleField) \
|
||||
V(StoreDoubleDataViewElement) \
|
||||
V(StoreTaggedFieldNoWriteBarrier) \
|
||||
V(StoreTaggedFieldWithWriteBarrier) \
|
||||
V(IncreaseInterruptBudget) \
|
||||
@ -3011,6 +3015,32 @@ class CheckSymbol : public FixedInputNodeT<1, CheckSymbol> {
|
||||
const CheckType check_type_;
|
||||
};
|
||||
|
||||
class CheckInstanceType : public FixedInputNodeT<1, CheckInstanceType> {
|
||||
using Base = FixedInputNodeT<1, CheckInstanceType>;
|
||||
|
||||
public:
|
||||
explicit CheckInstanceType(uint64_t bitfield, CheckType check_type,
|
||||
InstanceType instance_type)
|
||||
: Base(bitfield),
|
||||
check_type_(check_type),
|
||||
instance_type_(instance_type) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
static constexpr int kReceiverIndex = 0;
|
||||
Input& receiver_input() { return input(kReceiverIndex); }
|
||||
|
||||
InstanceType instance_type() const { return instance_type_; }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
|
||||
|
||||
private:
|
||||
const CheckType check_type_;
|
||||
const InstanceType instance_type_;
|
||||
};
|
||||
|
||||
class CheckString : public FixedInputNodeT<1, CheckString> {
|
||||
using Base = FixedInputNodeT<1, CheckString>;
|
||||
|
||||
@ -3063,6 +3093,25 @@ class CheckJSArrayBounds : public FixedInputNodeT<2, CheckJSArrayBounds> {
|
||||
|
||||
public:
|
||||
explicit CheckJSArrayBounds(uint64_t bitfield) : Base(bitfield) {}
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
static constexpr int kReceiverIndex = 0;
|
||||
static constexpr int kIndexIndex = 1;
|
||||
Input& receiver_input() { return input(kReceiverIndex); }
|
||||
Input& index_input() { return input(kIndexIndex); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class CheckJSDataViewBounds : public FixedInputNodeT<2, CheckJSDataViewBounds> {
|
||||
using Base = FixedInputNodeT<2, CheckJSDataViewBounds>;
|
||||
|
||||
public:
|
||||
explicit CheckJSDataViewBounds(uint64_t bitfield,
|
||||
ExternalArrayType element_type)
|
||||
: Base(bitfield), element_type_(element_type) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
@ -3074,6 +3123,9 @@ class CheckJSArrayBounds : public FixedInputNodeT<2, CheckJSArrayBounds> {
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
|
||||
private:
|
||||
ExternalArrayType element_type_;
|
||||
};
|
||||
|
||||
class CheckInt32Condition : public FixedInputNodeT<2, CheckInt32Condition> {
|
||||
@ -3326,6 +3378,59 @@ class LoadDoubleElement : public FixedInputValueNodeT<2, LoadDoubleElement> {
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class LoadDoubleDataViewElement
|
||||
: public FixedInputValueNodeT<3, LoadDoubleDataViewElement> {
|
||||
using Base = FixedInputValueNodeT<3, LoadDoubleDataViewElement>;
|
||||
|
||||
public:
|
||||
explicit LoadDoubleDataViewElement(uint64_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties =
|
||||
OpProperties::Reading() | OpProperties::Float64();
|
||||
|
||||
static constexpr int kObjectIndex = 0;
|
||||
static constexpr int kIndexIndex = 1;
|
||||
static constexpr int kIsLittleEndianIndex = 2;
|
||||
Input& object_input() { return input(kObjectIndex); }
|
||||
Input& index_input() { return input(kIndexIndex); }
|
||||
Input& is_little_endian_input() { return input(kIsLittleEndianIndex); }
|
||||
|
||||
bool is_little_endian_constant() {
|
||||
return IsConstantNode(is_little_endian_input().node()->opcode());
|
||||
}
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class StoreDoubleDataViewElement
|
||||
: public FixedInputNodeT<4, StoreDoubleDataViewElement> {
|
||||
using Base = FixedInputNodeT<4, StoreDoubleDataViewElement>;
|
||||
|
||||
public:
|
||||
explicit StoreDoubleDataViewElement(uint64_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::Writing();
|
||||
|
||||
static constexpr int kObjectIndex = 0;
|
||||
static constexpr int kIndexIndex = 1;
|
||||
static constexpr int kValueIndex = 2;
|
||||
static constexpr int kIsLittleEndianIndex = 3;
|
||||
Input& object_input() { return input(kObjectIndex); }
|
||||
Input& index_input() { return input(kIndexIndex); }
|
||||
Input& value_input() { return input(kValueIndex); }
|
||||
Input& is_little_endian_input() { return input(kIsLittleEndianIndex); }
|
||||
|
||||
bool is_little_endian_constant() {
|
||||
return IsConstantNode(is_little_endian_input().node()->opcode());
|
||||
}
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class StoreDoubleField : public FixedInputNodeT<2, StoreDoubleField> {
|
||||
using Base = FixedInputNodeT<2, StoreDoubleField>;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user