[maglev] Float64 bitwise ops as truncation + Int32
Implement truncating bitwise ops (ops that treat their input as a number truncated to int32) for Float64 representation, by adding truncation operations for Float64 and tagged Number. Bug: v8:7700 Change-Id: I36f423ba8d5332e8eb8c3d6357bbaed7ea4bbb37 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4013685 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#84182}
This commit is contained in:
parent
246d04486c
commit
2adc620152
@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/codegen/interface-descriptors-inl.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/maglev/maglev-assembler-inl.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
|
||||
@ -348,6 +349,30 @@ void MaglevAssembler::ToBoolean(Register value, ZoneLabelRef is_true,
|
||||
}
|
||||
}
|
||||
|
||||
void MaglevAssembler::TruncateDoubleToInt32(Register dst, DoubleRegister src) {
|
||||
ZoneLabelRef done(this);
|
||||
|
||||
Cvttsd2siq(dst, src);
|
||||
// Check whether the Cvt overflowed.
|
||||
cmpq(dst, Immediate(1));
|
||||
JumpToDeferredIf(
|
||||
overflow,
|
||||
[](MaglevAssembler* masm, DoubleRegister src, Register dst,
|
||||
ZoneLabelRef done) {
|
||||
// Push the double register onto the stack as an input argument.
|
||||
__ AllocateStackSpace(kDoubleSize);
|
||||
__ Movsd(MemOperand(rsp, 0), src);
|
||||
__ CallBuiltin(Builtin::kDoubleToI);
|
||||
// DoubleToI sets the result on the stack, pop the result off the stack.
|
||||
// Avoid using `pop` to not mix implicit and explicit rsp updates.
|
||||
__ movl(dst, MemOperand(rsp, 0));
|
||||
__ addq(rsp, Immediate(kDoubleSize));
|
||||
__ jmp(*done);
|
||||
},
|
||||
src, dst, done);
|
||||
bind(*done);
|
||||
}
|
||||
|
||||
} // namespace maglev
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -119,6 +119,8 @@ class MaglevAssembler : public MacroAssembler {
|
||||
void ToBoolean(Register value, ZoneLabelRef is_true, ZoneLabelRef is_false,
|
||||
bool fallthrough_when_true);
|
||||
|
||||
void TruncateDoubleToInt32(Register dst, DoubleRegister src);
|
||||
|
||||
inline void DefineLazyDeoptPoint(LazyDeoptInfo* info);
|
||||
inline void DefineExceptionHandlerPoint(NodeBase* node);
|
||||
inline void DefineExceptionHandlerAndLazyDeoptPoint(NodeBase* node);
|
||||
|
@ -230,6 +230,23 @@ template <Operation kOperation>
|
||||
using GenericNodeForOperation =
|
||||
typename NodeForOperationHelper<kOperation>::generic_type;
|
||||
|
||||
// Bitwise operations truncate their input to an Int32, which means we can be
|
||||
// less strict on conversions of their inputs.
|
||||
template <Operation kOperation>
|
||||
bool BinaryOperationTruncatesInputsToInt32() {
|
||||
switch (kOperation) {
|
||||
case Operation::kBitwiseAnd:
|
||||
case Operation::kBitwiseOr:
|
||||
case Operation::kBitwiseXor:
|
||||
case Operation::kShiftLeft:
|
||||
case Operation::kShiftRight:
|
||||
case Operation::kShiftRightLogical:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(victorgomes): Remove this once all operations have fast paths.
|
||||
template <Operation kOperation>
|
||||
bool BinaryOperationHasInt32FastPath() {
|
||||
@ -252,7 +269,7 @@ bool BinaryOperationHasInt32FastPath() {
|
||||
case Operation::kGreaterThan:
|
||||
case Operation::kGreaterThanOrEqual:
|
||||
return true;
|
||||
default:
|
||||
case Operation::kExponentiate:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -414,9 +431,16 @@ ValueNode* MaglevGraphBuilder::TryFoldInt32BinaryOperation(ValueNode* left,
|
||||
|
||||
template <Operation kOperation>
|
||||
void MaglevGraphBuilder::BuildInt32BinaryOperationNode() {
|
||||
// Truncating Int32 nodes treat their input as a signed int32 regardless
|
||||
// of whether it's really signed or not, so we allow Uint32 by loading a
|
||||
// Word32 value.
|
||||
static const bool inputs_are_truncated =
|
||||
BinaryOperationTruncatesInputsToInt32<kOperation>();
|
||||
// TODO(v8:7700): Do constant folding.
|
||||
ValueNode* left = LoadRegisterInt32(0);
|
||||
ValueNode* right = GetAccumulatorInt32();
|
||||
ValueNode* left =
|
||||
inputs_are_truncated ? LoadRegisterWord32(0) : LoadRegisterInt32(0);
|
||||
ValueNode* right =
|
||||
inputs_are_truncated ? GetAccumulatorWord32() : GetAccumulatorInt32();
|
||||
|
||||
if (ValueNode* result =
|
||||
TryFoldInt32BinaryOperation<kOperation>(left, right)) {
|
||||
@ -428,13 +452,67 @@ void MaglevGraphBuilder::BuildInt32BinaryOperationNode() {
|
||||
}
|
||||
|
||||
template <Operation kOperation>
|
||||
void MaglevGraphBuilder::BuildInt32BinarySmiOperationNode() {
|
||||
void MaglevGraphBuilder::BuildTruncatingInt32BinaryOperationNodeForNumber() {
|
||||
DCHECK(BinaryOperationTruncatesInputsToInt32<kOperation>());
|
||||
// TODO(v8:7700): Do constant folding.
|
||||
ValueNode* left = GetAccumulatorInt32();
|
||||
ValueNode* left;
|
||||
ValueNode* right;
|
||||
if (IsRegisterEqualToAccumulator(0)) {
|
||||
left = right = GetTruncatedWord32FromNumber(
|
||||
current_interpreter_frame_.get(iterator_.GetRegisterOperand(0)));
|
||||
} else {
|
||||
left = GetTruncatedWord32FromNumber(
|
||||
current_interpreter_frame_.get(iterator_.GetRegisterOperand(0)));
|
||||
right =
|
||||
GetTruncatedWord32FromNumber(current_interpreter_frame_.accumulator());
|
||||
}
|
||||
|
||||
if (ValueNode* result =
|
||||
TryFoldInt32BinaryOperation<kOperation>(left, right)) {
|
||||
SetAccumulator(result);
|
||||
return;
|
||||
}
|
||||
SetAccumulator(AddNewInt32BinaryOperationNode<kOperation>({left, right}));
|
||||
}
|
||||
|
||||
template <Operation kOperation>
|
||||
void MaglevGraphBuilder::BuildInt32BinarySmiOperationNode() {
|
||||
// Truncating Int32 nodes treat their input as a signed int32 regardless
|
||||
// of whether it's really signed or not, so we allow Uint32 by loading a
|
||||
// Word32 value.
|
||||
static const bool inputs_are_truncated =
|
||||
BinaryOperationTruncatesInputsToInt32<kOperation>();
|
||||
// TODO(v8:7700): Do constant folding.
|
||||
ValueNode* left =
|
||||
inputs_are_truncated ? GetAccumulatorWord32() : GetAccumulatorInt32();
|
||||
int32_t constant = iterator_.GetImmediateOperand(0);
|
||||
if (base::Optional<int>(constant) == Int32Identity<kOperation>()) {
|
||||
// If the constant is the unit of the operation, it already has the right
|
||||
// value, so we can just return.
|
||||
// value, so just return.
|
||||
return;
|
||||
}
|
||||
if (ValueNode* result =
|
||||
TryFoldInt32BinaryOperation<kOperation>(left, constant)) {
|
||||
SetAccumulator(result);
|
||||
return;
|
||||
}
|
||||
ValueNode* right = GetInt32Constant(constant);
|
||||
SetAccumulator(AddNewInt32BinaryOperationNode<kOperation>({left, right}));
|
||||
}
|
||||
|
||||
template <Operation kOperation>
|
||||
void MaglevGraphBuilder::BuildTruncatingInt32BinarySmiOperationNodeForNumber() {
|
||||
DCHECK(BinaryOperationTruncatesInputsToInt32<kOperation>());
|
||||
// TODO(v8:7700): Do constant folding.
|
||||
ValueNode* left =
|
||||
GetTruncatedWord32FromNumber(current_interpreter_frame_.accumulator());
|
||||
int32_t constant = iterator_.GetImmediateOperand(0);
|
||||
if (base::Optional<int>(constant) == Int32Identity<kOperation>()) {
|
||||
// If the constant is the unit of the operation, it already has the right
|
||||
// value, so use the truncated value (if not just a conversion) and return.
|
||||
if (!left->properties().is_conversion()) {
|
||||
current_interpreter_frame_.set_accumulator(left);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ValueNode* result =
|
||||
@ -475,26 +553,20 @@ void MaglevGraphBuilder::VisitBinaryOperation() {
|
||||
FeedbackNexus nexus = FeedbackNexusForOperand(1);
|
||||
switch (nexus.GetBinaryOperationFeedback()) {
|
||||
case BinaryOperationHint::kNone:
|
||||
EmitUnconditionalDeopt(
|
||||
return EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForBinaryOperation);
|
||||
return;
|
||||
case BinaryOperationHint::kSignedSmall:
|
||||
if (BinaryOperationHasInt32FastPath<kOperation>()) {
|
||||
BuildInt32BinaryOperationNode<kOperation>();
|
||||
return;
|
||||
return BuildInt32BinaryOperationNode<kOperation>();
|
||||
}
|
||||
break;
|
||||
case BinaryOperationHint::kSignedSmallInputs:
|
||||
case BinaryOperationHint::kNumber:
|
||||
if (BinaryOperationHasFloat64FastPath<kOperation>()) {
|
||||
BuildFloat64BinaryOperationNode<kOperation>();
|
||||
return;
|
||||
// } else if (BinaryOperationHasInt32FastPath<kOperation>()) {
|
||||
// // Fall back to int32 fast path if there is one (this will be the
|
||||
// case
|
||||
// // for operations that deal with bits rather than numbers).
|
||||
// BuildInt32BinaryOperationNode<kOperation>();
|
||||
// return;
|
||||
return BuildFloat64BinaryOperationNode<kOperation>();
|
||||
} else if (BinaryOperationHasInt32FastPath<kOperation>() &&
|
||||
BinaryOperationTruncatesInputsToInt32<kOperation>()) {
|
||||
return BuildTruncatingInt32BinaryOperationNodeForNumber<kOperation>();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -509,26 +581,21 @@ void MaglevGraphBuilder::VisitBinarySmiOperation() {
|
||||
FeedbackNexus nexus = FeedbackNexusForOperand(1);
|
||||
switch (nexus.GetBinaryOperationFeedback()) {
|
||||
case BinaryOperationHint::kNone:
|
||||
EmitUnconditionalDeopt(
|
||||
return EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForBinaryOperation);
|
||||
return;
|
||||
case BinaryOperationHint::kSignedSmall:
|
||||
if (BinaryOperationHasInt32FastPath<kOperation>()) {
|
||||
BuildInt32BinarySmiOperationNode<kOperation>();
|
||||
return;
|
||||
return BuildInt32BinarySmiOperationNode<kOperation>();
|
||||
}
|
||||
break;
|
||||
case BinaryOperationHint::kSignedSmallInputs:
|
||||
case BinaryOperationHint::kNumber:
|
||||
if (BinaryOperationHasFloat64FastPath<kOperation>()) {
|
||||
BuildFloat64BinarySmiOperationNode<kOperation>();
|
||||
return;
|
||||
// } else if (BinaryOperationHasInt32FastPath<kOperation>()) {
|
||||
// // Fall back to int32 fast path if there is one (this will be the
|
||||
// case
|
||||
// // for operations that deal with bits rather than numbers).
|
||||
// BuildInt32BinarySmiOperationNode<kOperation>();
|
||||
// return;
|
||||
return BuildFloat64BinarySmiOperationNode<kOperation>();
|
||||
} else if (BinaryOperationHasInt32FastPath<kOperation>() &&
|
||||
BinaryOperationTruncatesInputsToInt32<kOperation>()) {
|
||||
return BuildTruncatingInt32BinarySmiOperationNodeForNumber<
|
||||
kOperation>();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "src/maglev/maglev-graph-labeller.h"
|
||||
#include "src/maglev/maglev-graph-printer.h"
|
||||
#include "src/maglev/maglev-graph.h"
|
||||
#include "src/maglev/maglev-interpreter-frame-state.h"
|
||||
#include "src/maglev/maglev-ir.h"
|
||||
#include "src/utils/memcopy.h"
|
||||
|
||||
@ -706,6 +707,53 @@ class MaglevGraphBuilder {
|
||||
return node;
|
||||
}
|
||||
|
||||
ValueNode* GetTruncatedWord32FromNumber(ValueNode* value) {
|
||||
switch (value->properties().value_representation()) {
|
||||
case ValueRepresentation::kTagged: {
|
||||
if (SmiConstant* constant = value->TryCast<SmiConstant>()) {
|
||||
return GetInt32Constant(constant->value().value());
|
||||
}
|
||||
NodeInfo* node_info = known_node_aspects().GetOrCreateInfoFor(value);
|
||||
if (node_info->int32_alternative == nullptr) {
|
||||
NodeType old_type;
|
||||
EnsureType(value, NodeType::kNumber, &old_type);
|
||||
if (NodeTypeIsSmi(old_type)) {
|
||||
node_info->int32_alternative = AddNewNode<UnsafeSmiUntag>({value});
|
||||
} else {
|
||||
// TODO(leszeks): Cache this value somehow.
|
||||
return AddNewNode<CheckedNumberToWord32>({value});
|
||||
}
|
||||
}
|
||||
return node_info->int32_alternative;
|
||||
}
|
||||
case ValueRepresentation::kFloat64:
|
||||
// TODO(leszeks): Cache this value somehow.
|
||||
return AddNewNode<TruncateFloat64ToWord32>({value});
|
||||
case ValueRepresentation::kInt32:
|
||||
case ValueRepresentation::kUint32:
|
||||
// Already good.
|
||||
return value;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ValueNode* GetWord32(ValueNode* value) {
|
||||
switch (value->properties().value_representation()) {
|
||||
case ValueRepresentation::kTagged:
|
||||
case ValueRepresentation::kFloat64:
|
||||
return GetInt32(value);
|
||||
case ValueRepresentation::kInt32:
|
||||
case ValueRepresentation::kUint32:
|
||||
// Both Int32 and Uint32 are valid Word32 values.
|
||||
return value;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ValueNode* GetWord32(interpreter::Register reg) {
|
||||
return GetWord32(current_interpreter_frame_.get(reg));
|
||||
}
|
||||
|
||||
ValueNode* GetInt32(ValueNode* value) {
|
||||
switch (value->properties().value_representation()) {
|
||||
case ValueRepresentation::kTagged: {
|
||||
@ -788,6 +836,10 @@ class MaglevGraphBuilder {
|
||||
return GetInt32(interpreter::Register::virtual_accumulator());
|
||||
}
|
||||
|
||||
ValueNode* GetAccumulatorWord32() {
|
||||
return GetWord32(interpreter::Register::virtual_accumulator());
|
||||
}
|
||||
|
||||
ValueNode* GetAccumulatorFloat64() {
|
||||
return GetFloat64(interpreter::Register::virtual_accumulator());
|
||||
}
|
||||
@ -806,6 +858,10 @@ class MaglevGraphBuilder {
|
||||
return GetInt32(iterator_.GetRegisterOperand(operand_index));
|
||||
}
|
||||
|
||||
ValueNode* LoadRegisterWord32(int operand_index) {
|
||||
return GetWord32(iterator_.GetRegisterOperand(operand_index));
|
||||
}
|
||||
|
||||
ValueNode* LoadRegisterFloat64(int operand_index) {
|
||||
return GetFloat64(iterator_.GetRegisterOperand(operand_index));
|
||||
}
|
||||
@ -1299,6 +1355,10 @@ class MaglevGraphBuilder {
|
||||
template <Operation kOperation>
|
||||
void BuildInt32BinarySmiOperationNode();
|
||||
template <Operation kOperation>
|
||||
void BuildTruncatingInt32BinaryOperationNodeForNumber();
|
||||
template <Operation kOperation>
|
||||
void BuildTruncatingInt32BinarySmiOperationNodeForNumber();
|
||||
template <Operation kOperation>
|
||||
void BuildFloat64BinaryOperationNode();
|
||||
template <Operation kOperation>
|
||||
void BuildFloat64BinarySmiOperationNode();
|
||||
|
@ -75,6 +75,22 @@ class MaglevGraphVerifier {
|
||||
}
|
||||
}
|
||||
|
||||
void CheckValueInputIsWord32(NodeBase* node, int i) {
|
||||
ValueNode* input = node->input(i).node();
|
||||
ValueRepresentation got = input->properties().value_representation();
|
||||
if (got != ValueRepresentation::kInt32 &&
|
||||
got != ValueRepresentation::kUint32) {
|
||||
std::ostringstream str;
|
||||
str << "Type representation error: node ";
|
||||
if (graph_labeller_) {
|
||||
str << "#" << graph_labeller_->NodeId(node) << " : ";
|
||||
}
|
||||
str << node->opcode() << " (input @" << i << " = " << input->opcode()
|
||||
<< ") type " << got << " is not Word32 (Int32 or Uint32)";
|
||||
FATAL("%s", str.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Process(NodeBase* node, const ProcessingState& state) {
|
||||
switch (node->opcode()) {
|
||||
case Opcode::kAbort:
|
||||
@ -128,6 +144,7 @@ class MaglevGraphVerifier {
|
||||
case Opcode::kCheckInstanceType:
|
||||
case Opcode::kCheckedInternalizedString:
|
||||
case Opcode::kCheckedObjectToIndex:
|
||||
case Opcode::kCheckedNumberToWord32:
|
||||
case Opcode::kConvertReceiver:
|
||||
case Opcode::kConvertHoleToUndefined:
|
||||
// TODO(victorgomes): Can we check that the input is Boolean?
|
||||
@ -173,6 +190,7 @@ class MaglevGraphVerifier {
|
||||
case Opcode::kFloat64Box:
|
||||
case Opcode::kHoleyFloat64Box:
|
||||
case Opcode::kCheckedTruncateFloat64ToInt32:
|
||||
case Opcode::kTruncateFloat64ToWord32:
|
||||
DCHECK_EQ(node->input_count(), 1);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kFloat64);
|
||||
break;
|
||||
@ -240,14 +258,8 @@ class MaglevGraphVerifier {
|
||||
case Opcode::kInt32SubtractWithOverflow:
|
||||
case Opcode::kInt32MultiplyWithOverflow:
|
||||
case Opcode::kInt32DivideWithOverflow:
|
||||
// case Opcode::kInt32ExponentiateWithOverflow:
|
||||
case Opcode::kInt32ModulusWithOverflow:
|
||||
case Opcode::kInt32BitwiseAnd:
|
||||
case Opcode::kInt32BitwiseOr:
|
||||
case Opcode::kInt32BitwiseXor:
|
||||
case Opcode::kInt32ShiftLeft:
|
||||
case Opcode::kInt32ShiftRight:
|
||||
case Opcode::kInt32ShiftRightLogical:
|
||||
// case Opcode::kInt32ExponentiateWithOverflow:
|
||||
case Opcode::kInt32Equal:
|
||||
case Opcode::kInt32StrictEqual:
|
||||
case Opcode::kInt32LessThan:
|
||||
@ -260,6 +272,16 @@ class MaglevGraphVerifier {
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kInt32);
|
||||
CheckValueInputIs(node, 1, ValueRepresentation::kInt32);
|
||||
break;
|
||||
case Opcode::kInt32BitwiseAnd:
|
||||
case Opcode::kInt32BitwiseOr:
|
||||
case Opcode::kInt32BitwiseXor:
|
||||
case Opcode::kInt32ShiftLeft:
|
||||
case Opcode::kInt32ShiftRight:
|
||||
case Opcode::kInt32ShiftRightLogical:
|
||||
DCHECK_EQ(node->input_count(), 2);
|
||||
CheckValueInputIsWord32(node, 0);
|
||||
CheckValueInputIsWord32(node, 1);
|
||||
break;
|
||||
case Opcode::kBranchIfReferenceCompare:
|
||||
DCHECK_EQ(node->input_count(), 2);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kTagged);
|
||||
|
@ -3191,7 +3191,7 @@ void CheckedFloat64Unbox::GenerateCode(MaglevAssembler* masm,
|
||||
Register value = ToRegister(input());
|
||||
Label is_not_smi, done;
|
||||
// Check if Smi.
|
||||
__ JumpIfNotSmi(value, &is_not_smi);
|
||||
__ JumpIfNotSmi(value, &is_not_smi, Label::kNear);
|
||||
// If Smi, convert to Float64.
|
||||
__ SmiToInt32(value);
|
||||
__ Cvtlsi2sd(ToDoubleRegister(result()), value);
|
||||
@ -3201,7 +3201,7 @@ void CheckedFloat64Unbox::GenerateCode(MaglevAssembler* masm,
|
||||
// not the same as the output register or the function does not call a
|
||||
// builtin. So, we recover the Smi value here.
|
||||
__ SmiTag(value);
|
||||
__ jmp(&done);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&is_not_smi);
|
||||
// Check if HeapNumber, deopt otherwise.
|
||||
__ CompareRoot(FieldOperand(value, HeapObject::kMapOffset),
|
||||
@ -3212,6 +3212,33 @@ void CheckedFloat64Unbox::GenerateCode(MaglevAssembler* masm,
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
void CheckedNumberToWord32::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(input());
|
||||
DefineSameAsFirst(vreg_state, this);
|
||||
}
|
||||
void CheckedNumberToWord32::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
Register value = ToRegister(input());
|
||||
Register result_reg = ToRegister(result());
|
||||
DCHECK_EQ(value, result_reg);
|
||||
Label is_not_smi, done;
|
||||
// Check if Smi.
|
||||
__ JumpIfNotSmi(value, &is_not_smi, Label::kNear);
|
||||
// If Smi, convert to Int32.
|
||||
__ SmiToInt32(value);
|
||||
__ jmp(&done, Label::kNear);
|
||||
__ bind(&is_not_smi);
|
||||
// Check if HeapNumber, deopt otherwise.
|
||||
__ CompareRoot(FieldOperand(value, HeapObject::kMapOffset),
|
||||
RootIndex::kHeapNumberMap);
|
||||
__ EmitEagerDeoptIf(not_equal, DeoptimizeReason::kNotANumber, this);
|
||||
auto double_value = kScratchDoubleReg;
|
||||
__ Movsd(double_value, FieldOperand(value, HeapNumber::kValueOffset));
|
||||
__ TruncateDoubleToInt32(result_reg, double_value);
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
void LogicalNot::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(value());
|
||||
DefineAsRegister(vreg_state, this);
|
||||
@ -3642,6 +3669,16 @@ void CheckedTruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm,
|
||||
__ bind(&check_done);
|
||||
}
|
||||
|
||||
void TruncateFloat64ToWord32::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(input());
|
||||
DefineAsRegister(vreg_state, this);
|
||||
}
|
||||
void TruncateFloat64ToWord32::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
__ TruncateDoubleToInt32(ToRegister(result()), ToDoubleRegister(input()));
|
||||
}
|
||||
|
||||
void Phi::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
// Phi inputs are processed in the post-process, once loop phis' inputs'
|
||||
// v-regs are allocated.
|
||||
|
@ -177,10 +177,12 @@ class CompactInterpreterFrameState;
|
||||
V(UnsafeSmiUntag) \
|
||||
V(CheckedInternalizedString) \
|
||||
V(CheckedObjectToIndex) \
|
||||
V(CheckedNumberToWord32) \
|
||||
V(CheckedUint32ToInt32) \
|
||||
V(ChangeInt32ToFloat64) \
|
||||
V(ChangeUint32ToFloat64) \
|
||||
V(CheckedTruncateFloat64ToInt32) \
|
||||
V(TruncateFloat64ToWord32) \
|
||||
V(Float64Box) \
|
||||
V(HoleyFloat64Box) \
|
||||
V(CheckedFloat64Unbox) \
|
||||
@ -2107,6 +2109,22 @@ class CheckedTruncateFloat64ToInt32
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class TruncateFloat64ToWord32
|
||||
: public FixedInputValueNodeT<1, TruncateFloat64ToWord32> {
|
||||
using Base = FixedInputValueNodeT<1, TruncateFloat64ToWord32>;
|
||||
|
||||
public:
|
||||
explicit TruncateFloat64ToWord32(uint64_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::Int32();
|
||||
|
||||
Input& input() { return Node::input(0); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class CheckedFloat64Unbox
|
||||
: public FixedInputValueNodeT<1, CheckedFloat64Unbox> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedFloat64Unbox>;
|
||||
@ -2125,6 +2143,23 @@ class CheckedFloat64Unbox
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class CheckedNumberToWord32
|
||||
: public FixedInputValueNodeT<1, CheckedNumberToWord32> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedNumberToWord32>;
|
||||
|
||||
public:
|
||||
explicit CheckedNumberToWord32(uint64_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties =
|
||||
OpProperties::EagerDeopt() | OpProperties::Int32();
|
||||
|
||||
Input& input() { return Node::input(0); }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevAssembler*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
};
|
||||
|
||||
class LogicalNot : public FixedInputValueNodeT<1, LogicalNot> {
|
||||
using Base = FixedInputValueNodeT<1, LogicalNot>;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user