Commit f21ae185 authored by Qifan Pan's avatar Qifan Pan Committed by V8 LUCI CQ

[turbofan] Collect feedback for BigInt64 in addition

Collect feedback for BigInt64 in interpreter and change the runtime
for BigInt64 addition.

Bug: v8:9407
Change-Id: Ic69ba2c1f5ada998ac5ee3279e8296efe084d600
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3909809
Commit-Queue: Qifan Pan <panq@google.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83419}
parent 8e50bdb8
...@@ -6868,6 +6868,26 @@ TNode<BoolT> CodeStubAssembler::IsBigInt(TNode<HeapObject> object) { ...@@ -6868,6 +6868,26 @@ TNode<BoolT> CodeStubAssembler::IsBigInt(TNode<HeapObject> object) {
return IsBigIntInstanceType(LoadInstanceType(object)); return IsBigIntInstanceType(LoadInstanceType(object));
} }
void CodeStubAssembler::GotoIfLargeBigInt(TNode<BigInt> bigint,
Label* true_label) {
// Small BigInts are BigInts in the range [-2^63 + 1, 2^63 - 1] so that they
// can fit in 64-bit registers. Excluding -2^63 from the range makes the check
// simpler and faster. The other BigInts are seen as "large".
// TODO(panq): We might need to reevaluate of the range of small BigInts.
DCHECK(Is64());
Label false_label(this);
TNode<Uint32T> length =
DecodeWord32<BigIntBase::LengthBits>(LoadBigIntBitfield(bigint));
GotoIf(Word32Equal(length, Uint32Constant(0)), &false_label);
GotoIfNot(Word32Equal(length, Uint32Constant(1)), true_label);
Branch(WordEqual(UintPtrConstant(0),
WordAnd(LoadBigIntDigit(bigint, 0),
UintPtrConstant(static_cast<uintptr_t>(
1ULL << (sizeof(uintptr_t) * 8 - 1))))),
&false_label, true_label);
Bind(&false_label);
}
TNode<BoolT> CodeStubAssembler::IsPrimitiveInstanceType( TNode<BoolT> CodeStubAssembler::IsPrimitiveInstanceType(
TNode<Int32T> instance_type) { TNode<Int32T> instance_type) {
return Int32LessThanOrEqual(instance_type, return Int32LessThanOrEqual(instance_type,
......
...@@ -772,6 +772,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -772,6 +772,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
void GotoIfNumber(TNode<Object> value, Label* is_number); void GotoIfNumber(TNode<Object> value, Label* is_number);
TNode<Number> SmiToNumber(TNode<Smi> v) { return v; } TNode<Number> SmiToNumber(TNode<Smi> v) { return v; }
// BigInt operations.
void GotoIfLargeBigInt(TNode<BigInt> bigint, Label* true_label);
TNode<Number> BitwiseOp(TNode<Word32T> left32, TNode<Word32T> right32, TNode<Number> BitwiseOp(TNode<Word32T> left32, TNode<Word32T> right32,
Operation bitwise_op); Operation bitwise_op);
TNode<Number> BitwiseSmiOp(TNode<Smi> left32, TNode<Smi> right32, TNode<Number> BitwiseSmiOp(TNode<Smi> left32, TNode<Smi> right32,
......
...@@ -1620,7 +1620,7 @@ inline uint32_t ObjectHash(Address address) { ...@@ -1620,7 +1620,7 @@ inline uint32_t ObjectHash(Address address) {
// //
// kSignedSmall -> kSignedSmallInputs -> kNumber -> kNumberOrOddball -> kAny // kSignedSmall -> kSignedSmallInputs -> kNumber -> kNumberOrOddball -> kAny
// kString -> kAny // kString -> kAny
// kBigInt -> kAny // kBigInt64 -> kBigInt -> kAny
// //
// Technically we wouldn't need the separation between the kNumber and the // Technically we wouldn't need the separation between the kNumber and the
// kNumberOrOddball values here, since for binary operations, we always // kNumberOrOddball values here, since for binary operations, we always
...@@ -1637,7 +1637,8 @@ class BinaryOperationFeedback { ...@@ -1637,7 +1637,8 @@ class BinaryOperationFeedback {
kNumber = 0x7, kNumber = 0x7,
kNumberOrOddball = 0xF, kNumberOrOddball = 0xF,
kString = 0x10, kString = 0x10,
kBigInt = 0x20, kBigInt64 = 0x20,
kBigInt = 0x60,
kAny = 0x7F kAny = 0x7F
}; };
}; };
......
...@@ -17,7 +17,8 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback( ...@@ -17,7 +17,8 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred), Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
check_rhsisoddball(this, Label::kDeferred), check_rhsisoddball(this, Label::kDeferred),
call_with_oddball_feedback(this), call_with_any_feedback(this), call_with_oddball_feedback(this), call_with_any_feedback(this),
call_add_stub(this), end(this), bigint(this, Label::kDeferred); call_add_stub(this), end(this), bigint(this, Label::kDeferred),
bigint64(this);
TVARIABLE(Float64T, var_fadd_lhs); TVARIABLE(Float64T, var_fadd_lhs);
TVARIABLE(Float64T, var_fadd_rhs); TVARIABLE(Float64T, var_fadd_rhs);
TVARIABLE(Smi, var_type_feedback); TVARIABLE(Smi, var_type_feedback);
...@@ -158,7 +159,16 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback( ...@@ -158,7 +159,16 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
Goto(&call_with_any_feedback); Goto(&call_with_any_feedback);
BIND(&lhs_is_bigint); BIND(&lhs_is_bigint);
Branch(IsBigInt(rhs_heap_object), &bigint, &call_with_any_feedback); {
GotoIfNot(IsBigInt(rhs_heap_object), &call_with_any_feedback);
if (Is64()) {
GotoIfLargeBigInt(CAST(lhs), &bigint);
GotoIfLargeBigInt(CAST(rhs), &bigint);
Goto(&bigint64);
} else {
Goto(&bigint);
}
}
BIND(&lhs_is_string); BIND(&lhs_is_string);
{ {
...@@ -191,6 +201,30 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback( ...@@ -191,6 +201,30 @@ TNode<Object> BinaryOpAssembler::Generate_AddWithFeedback(
Goto(&call_with_any_feedback); Goto(&call_with_any_feedback);
} }
if (Is64()) {
BIND(&bigint64);
{
// Both {lhs} and {rhs} are of BigInt type and can fit in 64-bit
// registers.
Label if_overflow(this);
TVARIABLE(UintPtrT, lhs_raw);
TVARIABLE(UintPtrT, rhs_raw);
BigIntToRawBytes(CAST(lhs), &lhs_raw, &lhs_raw);
BigIntToRawBytes(CAST(rhs), &rhs_raw, &rhs_raw);
var_result = BigIntFromInt64(
TryIntPtrAdd(UncheckedCast<IntPtrT>(lhs_raw.value()),
UncheckedCast<IntPtrT>(rhs_raw.value()), &if_overflow));
var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt64);
UpdateFeedback(var_type_feedback.value(), maybe_feedback_vector(),
slot_id, update_feedback_mode);
Goto(&end);
BIND(&if_overflow);
Goto(&bigint);
}
}
BIND(&bigint); BIND(&bigint);
{ {
// Both {lhs} and {rhs} are of BigInt type. // Both {lhs} and {rhs} are of BigInt type.
......
...@@ -320,6 +320,7 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) { ...@@ -320,6 +320,7 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
case BinaryOperationFeedback::kString: case BinaryOperationFeedback::kString:
return BinaryOperationHint::kString; return BinaryOperationHint::kString;
case BinaryOperationFeedback::kBigInt: case BinaryOperationFeedback::kBigInt:
case BinaryOperationFeedback::kBigInt64:
return BinaryOperationHint::kBigInt; return BinaryOperationHint::kBigInt;
default: default:
return BinaryOperationHint::kAny; return BinaryOperationHint::kAny;
......
...@@ -377,7 +377,10 @@ TEST_F(InterpreterTest, InterpreterBinaryOpsBigInt) { ...@@ -377,7 +377,10 @@ TEST_F(InterpreterTest, InterpreterBinaryOpsBigInt) {
if (tester.HasFeedbackMetadata()) { if (tester.HasFeedbackMetadata()) {
MaybeObject feedback = callable.vector().Get(slot); MaybeObject feedback = callable.vector().Get(slot);
CHECK(feedback->IsSmi()); CHECK(feedback->IsSmi());
CHECK_EQ(BinaryOperationFeedback::kBigInt, feedback->ToSmi().value()); // TODO(panq): Create a standalone unit test for kBigInt64.
CHECK(BinaryOperationFeedback::kBigInt64 ==
feedback->ToSmi().value() ||
BinaryOperationFeedback::kBigInt == feedback->ToSmi().value());
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment