[turbofan] Fix missing checks for UnsignedBigInt64
Output of type UnsignedBigInt64 can be out of the range of small BigInts. This CL inserts necessary conversion and checks for it. Bug: chromium:1371935, v8:9407 Change-Id: I2553679452caa63111b97c89d072dd5fcc98aa7c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3939668 Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Commit-Queue: Qifan Pan <panq@google.com> Cr-Commit-Position: refs/heads/main@{#83661}
This commit is contained in:
parent
aa388de13d
commit
b3e243c53b
@ -103,6 +103,7 @@ class EffectControlLinearizer {
|
||||
Node* LowerCheckedUint32ToTaggedSigned(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedUint64Bounds(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedUint64ToInt32(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedUint64ToInt64(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedUint64ToTaggedSigned(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedFloat64ToInt32(Node* node, Node* frame_state);
|
||||
Node* LowerCheckedFloat64ToInt64(Node* node, Node* frame_state);
|
||||
@ -1002,6 +1003,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
||||
case IrOpcode::kCheckString:
|
||||
result = LowerCheckString(node, frame_state);
|
||||
break;
|
||||
case IrOpcode::kCheckedUint64ToInt64:
|
||||
result = LowerCheckedUint64ToInt64(node, frame_state);
|
||||
break;
|
||||
case IrOpcode::kCheckBigInt:
|
||||
result = LowerCheckBigInt(node, frame_state);
|
||||
break;
|
||||
@ -2563,6 +2567,18 @@ Node* EffectControlLinearizer::LowerCheckedUint64ToInt32(Node* node,
|
||||
return __ TruncateInt64ToInt32(value);
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerCheckedUint64ToInt64(Node* node,
|
||||
Node* frame_state) {
|
||||
Node* value = node->InputAt(0);
|
||||
const CheckParameters& params = CheckParametersOf(node->op());
|
||||
|
||||
Node* check = __ Uint64LessThanOrEqual(
|
||||
value, __ Uint64Constant(std::numeric_limits<int64_t>::max()));
|
||||
__ DeoptimizeIfNot(DeoptimizeReason::kLostPrecision, params.feedback(), check,
|
||||
frame_state);
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerCheckedUint64ToTaggedSigned(
|
||||
Node* node, Node* frame_state) {
|
||||
Node* value = node->InputAt(0);
|
||||
|
@ -288,6 +288,7 @@
|
||||
V(CheckedUint32ToTaggedSigned) \
|
||||
V(CheckedUint64Bounds) \
|
||||
V(CheckedUint64ToInt32) \
|
||||
V(CheckedUint64ToInt64) \
|
||||
V(CheckedUint64ToTaggedSigned) \
|
||||
V(CheckedFloat64ToInt32) \
|
||||
V(CheckedFloat64ToInt64) \
|
||||
|
@ -496,12 +496,15 @@ Node* RepresentationChanger::GetTaggedPointerRepresentationFor(
|
||||
// for TaggedSigned output representation.
|
||||
op = simplified()->CheckedTaggedToTaggedPointer(use_info.feedback());
|
||||
} else if (IsAnyTagged(output_rep)) {
|
||||
if (output_type.Is(Type::BigInt())) {
|
||||
return node;
|
||||
}
|
||||
if (use_info.type_check() == TypeCheckKind::kBigInt) {
|
||||
if (output_type.Is(Type::BigInt())) {
|
||||
return node;
|
||||
}
|
||||
op = simplified()->CheckBigInt(use_info.feedback());
|
||||
} else if (use_info.type_check() == TypeCheckKind::kBigInt64) {
|
||||
if (output_type.Is(Type::SignedBigInt64())) {
|
||||
return node;
|
||||
}
|
||||
op = simplified()->CheckBigInt64(use_info.feedback());
|
||||
} else {
|
||||
return TypeError(node, output_rep, output_type,
|
||||
@ -1254,9 +1257,17 @@ Node* RepresentationChanger::GetWord64RepresentationFor(
|
||||
}
|
||||
} else if (output_rep == MachineRepresentation::kWord64) {
|
||||
DCHECK(TypeCheckIsBigInt(use_info.type_check()));
|
||||
if (output_type.Is(Type::BigInt())) {
|
||||
if (output_type.Is(Type::UnsignedBigInt64()) &&
|
||||
use_info.type_check() == TypeCheckKind::kBigInt64) {
|
||||
op = simplified()->CheckedUint64ToInt64(use_info.feedback());
|
||||
} else if ((output_type.Is(Type::BigInt()) &&
|
||||
use_info.type_check() == TypeCheckKind::kBigInt) ||
|
||||
(output_type.Is(Type::SignedBigInt64()) &&
|
||||
use_info.type_check() == TypeCheckKind::kBigInt64)) {
|
||||
return node;
|
||||
} else {
|
||||
DCHECK(output_type != Type::BigInt() ||
|
||||
use_info.type_check() != TypeCheckKind::kBigInt64);
|
||||
Node* unreachable = InsertUnconditionalDeopt(
|
||||
use_node, DeoptimizeReason::kNotABigInt, use_info.feedback());
|
||||
return jsgraph()->graph()->NewNode(
|
||||
|
@ -432,6 +432,7 @@ void SimplifiedLoweringVerifier::VisitNode(Node* node,
|
||||
CASE(CheckedUint32ToTaggedSigned)
|
||||
CASE(CheckedUint64Bounds)
|
||||
CASE(CheckedUint64ToInt32)
|
||||
CASE(CheckedUint64ToInt64)
|
||||
CASE(CheckedUint64ToTaggedSigned)
|
||||
CASE(CheckedFloat64ToInt64)
|
||||
CASE(CheckedTaggedSignedToInt32)
|
||||
|
@ -850,6 +850,7 @@ bool operator==(CheckMinusZeroParameters const& lhs,
|
||||
V(CheckedUint32ToInt32, 1, 1) \
|
||||
V(CheckedUint32ToTaggedSigned, 1, 1) \
|
||||
V(CheckedUint64ToInt32, 1, 1) \
|
||||
V(CheckedUint64ToInt64, 1, 1) \
|
||||
V(CheckedUint64ToTaggedSigned, 1, 1)
|
||||
|
||||
#define CHECKED_BOUNDS_OP_LIST(V) \
|
||||
|
@ -940,6 +940,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
const Operator* CheckedUint32ToInt32(const FeedbackSource& feedback);
|
||||
const Operator* CheckedUint32ToTaggedSigned(const FeedbackSource& feedback);
|
||||
const Operator* CheckedUint64ToInt32(const FeedbackSource& feedback);
|
||||
const Operator* CheckedUint64ToInt64(const FeedbackSource& feedback);
|
||||
const Operator* CheckedUint64ToTaggedSigned(const FeedbackSource& feedback);
|
||||
|
||||
const Operator* ConvertReceiver(ConvertReceiverMode);
|
||||
|
@ -1516,6 +1516,7 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
|
||||
case IrOpcode::kCheckedUint32ToTaggedSigned:
|
||||
case IrOpcode::kCheckedUint64Bounds:
|
||||
case IrOpcode::kCheckedUint64ToInt32:
|
||||
case IrOpcode::kCheckedUint64ToInt64:
|
||||
case IrOpcode::kCheckedUint64ToTaggedSigned:
|
||||
case IrOpcode::kCheckedFloat64ToInt32:
|
||||
case IrOpcode::kCheckedFloat64ToInt64:
|
||||
|
24
test/mjsunit/regress/regress-1371935.js
Normal file
24
test/mjsunit/regress/regress-1371935.js
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --turbofan --no-always-turbofan
|
||||
|
||||
function f(a, b, c) {
|
||||
// CheckBigInt64 is required if the type of input is UnsignedBigInt64
|
||||
// because its value can be out of the range of SignedBigInt64.
|
||||
let t = BigInt.asUintN(64, a + b);
|
||||
// The addition is speculated as CheckedBigInt64Add and triggers the deopt
|
||||
// for the large value coming in through <t>.
|
||||
return t + c;
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(f);
|
||||
assertEquals(12n, f(9n, 2n, 1n));
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
assertEquals(12n, f(9n, 2n, 1n));
|
||||
assertOptimized(f);
|
||||
assertEquals(2n ** 64n, f(1n, -2n, 1n));
|
||||
if (%Is64Bit()) {
|
||||
assertUnoptimized(f);
|
||||
}
|
Loading…
Reference in New Issue
Block a user