[maglev] Add a checked Float64->Int32 node
This can happen when we have a load from a double field of a value that canonicalises to a Smi, and we then use that Smi value in Smi-feedback arithmetic. Bug: v8:7700 Fixed: v8:13282 Change-Id: I6d8245b8393f7595c3442985087ebb8e806061eb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3890999 Auto-Submit: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Linke <jgruber@chromium.org> Cr-Commit-Position: refs/heads/main@{#83210}
This commit is contained in:
parent
1628c9052f
commit
e6a08cd985
@ -682,8 +682,6 @@ class MaglevGraphBuilder {
|
||||
case ValueRepresentation::kInt32:
|
||||
return value;
|
||||
case ValueRepresentation::kFloat64:
|
||||
// We should not be able to request an Int32 from a Float64 input,
|
||||
// unless it's an unboxing of a tagged value or a conversion from int32.
|
||||
if (value->Is<CheckedFloat64Unbox>()) {
|
||||
// TODO(leszeks): Maybe convert the CheckedFloat64Unbox to
|
||||
// ChangeInt32ToFloat64 with this CheckedSmiUntag as the input.
|
||||
@ -692,7 +690,7 @@ class MaglevGraphBuilder {
|
||||
} else if (value->Is<ChangeInt32ToFloat64>()) {
|
||||
return value->input(0).node();
|
||||
}
|
||||
UNREACHABLE();
|
||||
return AddNewConversionNode<CheckedTruncateFloat64ToInt32>(reg, value);
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -152,6 +152,7 @@ class MaglevGraphVerifier {
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kInt32);
|
||||
break;
|
||||
case Opcode::kFloat64Box:
|
||||
case Opcode::kCheckedTruncateFloat64ToInt32:
|
||||
DCHECK_EQ(node->input_count(), 1);
|
||||
CheckValueInputIs(node, 0, ValueRepresentation::kFloat64);
|
||||
break;
|
||||
|
@ -2839,6 +2839,40 @@ void ChangeInt32ToFloat64::GenerateCode(MaglevAssembler* masm,
|
||||
__ Cvtlsi2sd(ToDoubleRegister(result()), ToRegister(input()));
|
||||
}
|
||||
|
||||
void CheckedTruncateFloat64ToInt32::AllocateVreg(
|
||||
MaglevVregAllocationState* vreg_state) {
|
||||
UseRegister(input());
|
||||
DefineAsRegister(vreg_state, this);
|
||||
}
|
||||
void CheckedTruncateFloat64ToInt32::GenerateCode(MaglevAssembler* masm,
|
||||
const ProcessingState& state) {
|
||||
DoubleRegister input_reg = ToDoubleRegister(input());
|
||||
Register result_reg = ToRegister(result());
|
||||
DoubleRegister converted_back = kScratchDoubleReg;
|
||||
|
||||
// Convert the input float64 value to int32.
|
||||
__ Cvttsd2si(result_reg, input_reg);
|
||||
// Convert that int32 value back to float64.
|
||||
__ Cvtlsi2sd(converted_back, result_reg);
|
||||
// Check that the result of the float64->int32->float64 is equal to the input
|
||||
// (i.e. that the conversion didn't truncate.
|
||||
__ Ucomisd(input_reg, converted_back);
|
||||
__ EmitEagerDeoptIf(not_equal, DeoptimizeReason::kNotInt32, this);
|
||||
|
||||
// Check if {input} is -0.
|
||||
Label check_done;
|
||||
__ cmpl(result_reg, Immediate(0));
|
||||
__ j(not_equal, &check_done);
|
||||
|
||||
// In case of 0, we need to check the high bits for the IEEE -0 pattern.
|
||||
Register high_word32_of_input = kScratchRegister;
|
||||
__ Pextrd(high_word32_of_input, input_reg, 1);
|
||||
__ cmpl(high_word32_of_input, Immediate(0));
|
||||
__ EmitEagerDeoptIf(less, DeoptimizeReason::kNotInt32, this);
|
||||
|
||||
__ bind(&check_done);
|
||||
}
|
||||
|
||||
void Phi::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
// Phi inputs are processed in the post-process, once loop phis' inputs'
|
||||
// v-regs are allocated.
|
||||
|
@ -117,68 +117,69 @@ class CompactInterpreterFrameState;
|
||||
V(RootConstant) \
|
||||
V(SmiConstant)
|
||||
|
||||
#define VALUE_NODE_LIST(V) \
|
||||
V(Call) \
|
||||
V(CallBuiltin) \
|
||||
V(CallRuntime) \
|
||||
V(CallWithSpread) \
|
||||
V(Construct) \
|
||||
V(ConstructWithSpread) \
|
||||
V(CreateEmptyArrayLiteral) \
|
||||
V(CreateArrayLiteral) \
|
||||
V(CreateShallowArrayLiteral) \
|
||||
V(CreateObjectLiteral) \
|
||||
V(CreateEmptyObjectLiteral) \
|
||||
V(CreateShallowObjectLiteral) \
|
||||
V(CreateFunctionContext) \
|
||||
V(CreateClosure) \
|
||||
V(FastCreateClosure) \
|
||||
V(CreateRegExpLiteral) \
|
||||
V(DeleteProperty) \
|
||||
V(ForInPrepare) \
|
||||
V(ForInNext) \
|
||||
V(GeneratorRestoreRegister) \
|
||||
V(GetIterator) \
|
||||
V(GetSecondReturnedValue) \
|
||||
V(GetTemplateObject) \
|
||||
V(InitialValue) \
|
||||
V(LoadTaggedField) \
|
||||
V(LoadDoubleField) \
|
||||
V(LoadTaggedElement) \
|
||||
V(LoadDoubleElement) \
|
||||
V(LoadGlobal) \
|
||||
V(LoadNamedGeneric) \
|
||||
V(LoadNamedFromSuperGeneric) \
|
||||
V(SetNamedGeneric) \
|
||||
V(DefineNamedOwnGeneric) \
|
||||
V(StoreInArrayLiteralGeneric) \
|
||||
V(StoreGlobal) \
|
||||
V(GetKeyedGeneric) \
|
||||
V(SetKeyedGeneric) \
|
||||
V(DefineKeyedOwnGeneric) \
|
||||
V(Phi) \
|
||||
V(RegisterInput) \
|
||||
V(CheckedSmiTag) \
|
||||
V(CheckedSmiUntag) \
|
||||
V(CheckedInternalizedString) \
|
||||
V(ChangeInt32ToFloat64) \
|
||||
V(Float64Box) \
|
||||
V(CheckedFloat64Unbox) \
|
||||
V(LogicalNot) \
|
||||
V(SetPendingMessage) \
|
||||
V(ToBooleanLogicalNot) \
|
||||
V(TaggedEqual) \
|
||||
V(TaggedNotEqual) \
|
||||
V(TestInstanceOf) \
|
||||
V(TestUndetectable) \
|
||||
V(TestTypeOf) \
|
||||
V(ToName) \
|
||||
V(ToNumberOrNumeric) \
|
||||
V(ToObject) \
|
||||
V(ToString) \
|
||||
CONSTANT_VALUE_NODE_LIST(V) \
|
||||
INT32_OPERATIONS_NODE_LIST(V) \
|
||||
FLOAT64_OPERATIONS_NODE_LIST(V) \
|
||||
#define VALUE_NODE_LIST(V) \
|
||||
V(Call) \
|
||||
V(CallBuiltin) \
|
||||
V(CallRuntime) \
|
||||
V(CallWithSpread) \
|
||||
V(Construct) \
|
||||
V(ConstructWithSpread) \
|
||||
V(CreateEmptyArrayLiteral) \
|
||||
V(CreateArrayLiteral) \
|
||||
V(CreateShallowArrayLiteral) \
|
||||
V(CreateObjectLiteral) \
|
||||
V(CreateEmptyObjectLiteral) \
|
||||
V(CreateShallowObjectLiteral) \
|
||||
V(CreateFunctionContext) \
|
||||
V(CreateClosure) \
|
||||
V(FastCreateClosure) \
|
||||
V(CreateRegExpLiteral) \
|
||||
V(DeleteProperty) \
|
||||
V(ForInPrepare) \
|
||||
V(ForInNext) \
|
||||
V(GeneratorRestoreRegister) \
|
||||
V(GetIterator) \
|
||||
V(GetSecondReturnedValue) \
|
||||
V(GetTemplateObject) \
|
||||
V(InitialValue) \
|
||||
V(LoadTaggedField) \
|
||||
V(LoadDoubleField) \
|
||||
V(LoadTaggedElement) \
|
||||
V(LoadDoubleElement) \
|
||||
V(LoadGlobal) \
|
||||
V(LoadNamedGeneric) \
|
||||
V(LoadNamedFromSuperGeneric) \
|
||||
V(SetNamedGeneric) \
|
||||
V(DefineNamedOwnGeneric) \
|
||||
V(StoreInArrayLiteralGeneric) \
|
||||
V(StoreGlobal) \
|
||||
V(GetKeyedGeneric) \
|
||||
V(SetKeyedGeneric) \
|
||||
V(DefineKeyedOwnGeneric) \
|
||||
V(Phi) \
|
||||
V(RegisterInput) \
|
||||
V(CheckedSmiTag) \
|
||||
V(CheckedSmiUntag) \
|
||||
V(CheckedInternalizedString) \
|
||||
V(ChangeInt32ToFloat64) \
|
||||
V(CheckedTruncateFloat64ToInt32) \
|
||||
V(Float64Box) \
|
||||
V(CheckedFloat64Unbox) \
|
||||
V(LogicalNot) \
|
||||
V(SetPendingMessage) \
|
||||
V(ToBooleanLogicalNot) \
|
||||
V(TaggedEqual) \
|
||||
V(TaggedNotEqual) \
|
||||
V(TestInstanceOf) \
|
||||
V(TestUndetectable) \
|
||||
V(TestTypeOf) \
|
||||
V(ToName) \
|
||||
V(ToNumberOrNumeric) \
|
||||
V(ToObject) \
|
||||
V(ToString) \
|
||||
CONSTANT_VALUE_NODE_LIST(V) \
|
||||
INT32_OPERATIONS_NODE_LIST(V) \
|
||||
FLOAT64_OPERATIONS_NODE_LIST(V) \
|
||||
GENERIC_OPERATIONS_NODE_LIST(V)
|
||||
|
||||
#define GAP_MOVE_NODE_LIST(V) \
|
||||
@ -1746,6 +1747,22 @@ class ChangeInt32ToFloat64
|
||||
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
|
||||
};
|
||||
|
||||
class CheckedTruncateFloat64ToInt32
|
||||
: public FixedInputValueNodeT<1, CheckedTruncateFloat64ToInt32> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedTruncateFloat64ToInt32>;
|
||||
|
||||
public:
|
||||
explicit CheckedTruncateFloat64ToInt32(uint64_t bitfield) : Base(bitfield) {}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt() |
|
||||
OpProperties::Int32() |
|
||||
OpProperties::ConversionNode();
|
||||
|
||||
Input& input() { return Node::input(0); }
|
||||
|
||||
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
|
||||
};
|
||||
|
||||
class CheckedFloat64Unbox
|
||||
: public FixedInputValueNodeT<1, CheckedFloat64Unbox> {
|
||||
using Base = FixedInputValueNodeT<1, CheckedFloat64Unbox>;
|
||||
|
Loading…
Reference in New Issue
Block a user