[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());
|
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.
|
// Deferred code handling.
|
||||||
// ---
|
// ---
|
||||||
|
@ -78,6 +78,9 @@ class MaglevAssembler : public MacroAssembler {
|
|||||||
inline void PushInput(const Input& input);
|
inline void PushInput(const Input& input);
|
||||||
inline Register FromAnyToRegister(const Input& input, Register scratch);
|
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.
|
// Warning: Input registers {string} and {index} will be scratched.
|
||||||
// {result} is allowed to alias with one the other 3 input registers.
|
// {result} is allowed to alias with one the other 3 input registers.
|
||||||
// {result} is an int32.
|
// {result} is an int32.
|
||||||
|
@ -2605,6 +2605,64 @@ void MaglevGraphBuilder::InlineCallFromRegisters(
|
|||||||
->SetToBlockAndReturnNext(current_block_);
|
->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(
|
bool MaglevGraphBuilder::TryReduceStringFromCharCode(
|
||||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||||
if (args.count() != 1) return false;
|
if (args.count() != 1) return false;
|
||||||
|
@ -1045,7 +1045,7 @@ class MaglevGraphBuilder {
|
|||||||
|
|
||||||
int count_with_receiver() const { return count() + 1; }
|
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) {
|
if (receiver_mode_ != ConvertReceiverMode::kNullOrUndefined) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -1057,6 +1057,13 @@ class MaglevGraphBuilder {
|
|||||||
return reglist_[i];
|
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_; }
|
ConvertReceiverMode receiver_mode() const { return receiver_mode_; }
|
||||||
|
|
||||||
CallArguments PopReceiver(ConvertReceiverMode new_receiver_mode) const {
|
CallArguments PopReceiver(ConvertReceiverMode new_receiver_mode) const {
|
||||||
@ -1098,6 +1105,8 @@ class MaglevGraphBuilder {
|
|||||||
const CallArguments& args);
|
const CallArguments& args);
|
||||||
|
|
||||||
#define MAGLEV_REDUCED_BUILTIN(V) \
|
#define MAGLEV_REDUCED_BUILTIN(V) \
|
||||||
|
V(DataViewPrototypeGetFloat64) \
|
||||||
|
V(DataViewPrototypeSetFloat64) \
|
||||||
V(FunctionPrototypeCall) \
|
V(FunctionPrototypeCall) \
|
||||||
V(StringFromCharCode) \
|
V(StringFromCharCode) \
|
||||||
V(StringPrototypeCharCodeAt)
|
V(StringPrototypeCharCodeAt)
|
||||||
|
@ -122,6 +122,7 @@ class MaglevGraphVerifier {
|
|||||||
case Opcode::kCheckNumber:
|
case Opcode::kCheckNumber:
|
||||||
case Opcode::kCheckString:
|
case Opcode::kCheckString:
|
||||||
case Opcode::kCheckSymbol:
|
case Opcode::kCheckSymbol:
|
||||||
|
case Opcode::kCheckInstanceType:
|
||||||
case Opcode::kCheckedInternalizedString:
|
case Opcode::kCheckedInternalizedString:
|
||||||
case Opcode::kCheckedObjectToIndex:
|
case Opcode::kCheckedObjectToIndex:
|
||||||
case Opcode::kConvertReceiver:
|
case Opcode::kConvertReceiver:
|
||||||
@ -288,6 +289,7 @@ class MaglevGraphVerifier {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Opcode::kCheckJSArrayBounds:
|
case Opcode::kCheckJSArrayBounds:
|
||||||
|
case Opcode::kCheckJSDataViewBounds:
|
||||||
case Opcode::kCheckJSObjectElementsBounds:
|
case Opcode::kCheckJSObjectElementsBounds:
|
||||||
case Opcode::kLoadTaggedElement:
|
case Opcode::kLoadTaggedElement:
|
||||||
case Opcode::kLoadDoubleElement:
|
case Opcode::kLoadDoubleElement:
|
||||||
@ -297,6 +299,19 @@ class MaglevGraphVerifier {
|
|||||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||||
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
||||||
break;
|
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: {
|
case Opcode::kCallBuiltin: {
|
||||||
CallBuiltin* call_builtin = node->Cast<CallBuiltin>();
|
CallBuiltin* call_builtin = node->Cast<CallBuiltin>();
|
||||||
auto descriptor =
|
auto descriptor =
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "src/maglev/maglev-ir-inl.h"
|
#include "src/maglev/maglev-ir-inl.h"
|
||||||
#include "src/maglev/maglev-vreg-allocator.h"
|
#include "src/maglev/maglev-vreg-allocator.h"
|
||||||
#include "src/objects/instance-type.h"
|
#include "src/objects/instance-type.h"
|
||||||
|
#include "src/objects/js-array-buffer.h"
|
||||||
|
|
||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -1224,6 +1225,27 @@ void CheckSymbol::GenerateCode(MaglevAssembler* masm,
|
|||||||
void CheckSymbol::PrintParams(std::ostream& os,
|
void CheckSymbol::PrintParams(std::ostream& os,
|
||||||
MaglevGraphLabeller* graph_labeller) const {}
|
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) {
|
void CheckString::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||||
UseRegister(receiver_input());
|
UseRegister(receiver_input());
|
||||||
}
|
}
|
||||||
@ -1396,6 +1418,47 @@ void CheckJSArrayBounds::GenerateCode(MaglevAssembler* masm,
|
|||||||
__ EmitEagerDeoptIf(above_equal, DeoptimizeReason::kOutOfBounds, this);
|
__ 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(
|
void CheckJSObjectElementsBounds::AllocateVreg(
|
||||||
MaglevVregAllocationState* vreg_state) {
|
MaglevVregAllocationState* vreg_state) {
|
||||||
UseRegister(receiver_input());
|
UseRegister(receiver_input());
|
||||||
@ -1719,6 +1782,149 @@ void LoadDoubleElement::GenerateCode(MaglevAssembler* masm,
|
|||||||
FixedDoubleArray::kHeaderSize));
|
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) {
|
void StoreDoubleField::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||||
UseRegister(object_input());
|
UseRegister(object_input());
|
||||||
UseRegister(value_input());
|
UseRegister(value_input());
|
||||||
|
@ -154,6 +154,7 @@ class CompactInterpreterFrameState;
|
|||||||
V(LoadTaggedField) \
|
V(LoadTaggedField) \
|
||||||
V(LoadDoubleField) \
|
V(LoadDoubleField) \
|
||||||
V(LoadTaggedElement) \
|
V(LoadTaggedElement) \
|
||||||
|
V(LoadDoubleDataViewElement) \
|
||||||
V(LoadDoubleElement) \
|
V(LoadDoubleElement) \
|
||||||
V(LoadGlobal) \
|
V(LoadGlobal) \
|
||||||
V(LoadNamedGeneric) \
|
V(LoadNamedGeneric) \
|
||||||
@ -208,6 +209,7 @@ class CompactInterpreterFrameState;
|
|||||||
V(CheckInt32Condition) \
|
V(CheckInt32Condition) \
|
||||||
V(CheckJSArrayBounds) \
|
V(CheckJSArrayBounds) \
|
||||||
V(CheckJSObjectElementsBounds) \
|
V(CheckJSObjectElementsBounds) \
|
||||||
|
V(CheckJSDataViewBounds) \
|
||||||
V(CheckMaps) \
|
V(CheckMaps) \
|
||||||
V(CheckMapsWithMigration) \
|
V(CheckMapsWithMigration) \
|
||||||
V(CheckNumber) \
|
V(CheckNumber) \
|
||||||
@ -215,11 +217,13 @@ class CompactInterpreterFrameState;
|
|||||||
V(CheckString) \
|
V(CheckString) \
|
||||||
V(CheckSymbol) \
|
V(CheckSymbol) \
|
||||||
V(CheckValue) \
|
V(CheckValue) \
|
||||||
|
V(CheckInstanceType) \
|
||||||
V(DebugBreak) \
|
V(DebugBreak) \
|
||||||
V(GeneratorStore) \
|
V(GeneratorStore) \
|
||||||
V(JumpLoopPrologue) \
|
V(JumpLoopPrologue) \
|
||||||
V(StoreMap) \
|
V(StoreMap) \
|
||||||
V(StoreDoubleField) \
|
V(StoreDoubleField) \
|
||||||
|
V(StoreDoubleDataViewElement) \
|
||||||
V(StoreTaggedFieldNoWriteBarrier) \
|
V(StoreTaggedFieldNoWriteBarrier) \
|
||||||
V(StoreTaggedFieldWithWriteBarrier) \
|
V(StoreTaggedFieldWithWriteBarrier) \
|
||||||
V(IncreaseInterruptBudget) \
|
V(IncreaseInterruptBudget) \
|
||||||
@ -3011,6 +3015,32 @@ class CheckSymbol : public FixedInputNodeT<1, CheckSymbol> {
|
|||||||
const CheckType check_type_;
|
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> {
|
class CheckString : public FixedInputNodeT<1, CheckString> {
|
||||||
using Base = FixedInputNodeT<1, CheckString>;
|
using Base = FixedInputNodeT<1, CheckString>;
|
||||||
|
|
||||||
@ -3063,6 +3093,25 @@ class CheckJSArrayBounds : public FixedInputNodeT<2, CheckJSArrayBounds> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CheckJSArrayBounds(uint64_t bitfield) : Base(bitfield) {}
|
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();
|
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||||
|
|
||||||
@ -3074,6 +3123,9 @@ class CheckJSArrayBounds : public FixedInputNodeT<2, CheckJSArrayBounds> {
|
|||||||
void AllocateVreg(MaglevVregAllocationState*);
|
void AllocateVreg(MaglevVregAllocationState*);
|
||||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ExternalArrayType element_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CheckInt32Condition : public FixedInputNodeT<2, CheckInt32Condition> {
|
class CheckInt32Condition : public FixedInputNodeT<2, CheckInt32Condition> {
|
||||||
@ -3326,6 +3378,59 @@ class LoadDoubleElement : public FixedInputValueNodeT<2, LoadDoubleElement> {
|
|||||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
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> {
|
class StoreDoubleField : public FixedInputNodeT<2, StoreDoubleField> {
|
||||||
using Base = FixedInputNodeT<2, StoreDoubleField>;
|
using Base = FixedInputNodeT<2, StoreDoubleField>;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user