From 1224fc8eead9195e5464e223717d967040b26172 Mon Sep 17 00:00:00 2001 From: Reece Wilson Date: Tue, 28 Feb 2023 03:08:49 +0000 Subject: [PATCH] [+] EMCAScript: implicit upcast of expressions involving u64s [+] Massive performance boost in dealing with expressions consisting of non-literal/const bigints (1 out of 2) [*] Updated source url map Last aurora commit: b8f6b544 --- src/builtins/builtins-bigint.tq | 159 +++++++++++++++++++++-------- src/codegen/code-stub-assembler.cc | 55 +++++++--- src/codegen/code-stub-assembler.h | 15 +-- src/ic/binary-op-assembler.cc | 151 +++++++++++++++++++++++---- src/ic/unary-op-assembler.cc | 2 +- src/runtime/runtime-bigint.cc | 30 +++++- src/torque/source-positions.h | 5 +- 7 files changed, 324 insertions(+), 93 deletions(-) diff --git a/src/builtins/builtins-bigint.tq b/src/builtins/builtins-bigint.tq index c8748c70bb..11bd7e9a17 100644 --- a/src/builtins/builtins-bigint.tq +++ b/src/builtins/builtins-bigint.tq @@ -58,8 +58,12 @@ extern macro BigIntBuiltinsAssembler::WriteBigIntSignAndLength( extern macro CodeStubAssembler::AllocateBigInt(intptr): MutableBigInt; extern macro CodeStubAssembler::StoreBigIntDigit( MutableBigInt, intptr, uintptr): void; +extern macro CodeStubAssembler::SetBigInt( + MutableBigInt, Smi, bool): void; extern macro CodeStubAssembler::LoadBigIntDigit(BigIntBase, intptr): uintptr; +extern runtime ToBigIntConvertNumber(Context, Object): BigInt; + macro IsCanonicalized(bigint: BigIntBase): bool { const length = ReadBigIntLength(bigint); @@ -74,6 +78,30 @@ macro InvertSign(sign: uint32): uint32 { return sign == kPositiveSign ? kNegativeSign : kPositiveSign; } +macro NormalizeWord(implicit context: Context)( + n: Numeric): BigInt { + try { + return Cast(n) otherwise NotBigInt; + } label NotBigInt { + try { + const ssWord : Smi = Cast(n) otherwise NotSmi; + const bSign : bool = SmiUntag(ssWord) <= 0; + const iSign : uint32 = bSign ? kNegativeSign : kPositiveSign; + const mbiRet : MutableBigInt = AllocateBigInt(1); + + WriteBigIntSignAndLength(mbiRet, + iSign, + 1 /* SMI = x < 2^32, where digit_t = uintptr_t, 2 ^ (1 * sizeof(uintptr_t)) > x*/); + + SetBigInt(mbiRet, ssWord, bSign); + + return Convert(mbiRet); + } label NotSmi { + return ToBigIntConvertNumber(context, n); + } + } +} + macro AllocateEmptyBigIntNoThrow(implicit context: Context)( sign: uint32, length: intptr): MutableBigInt labels BigIntTooBig { if (length > kBigIntMaxLength) { @@ -173,8 +201,11 @@ macro BigIntAddImpl(implicit context: Context)(x: BigInt, y: BigInt): BigInt } builtin BigIntAddNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntAddImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinal is used to signal BigIntTooBig exception. @@ -185,11 +216,11 @@ builtin BigIntAddNoThrow(implicit context: Context)( builtin BigIntAdd(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntAddImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -215,8 +246,11 @@ macro BigIntSubtractImpl(implicit context: Context)( } builtin BigIntSubtractNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { +xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinal is used to signal BigIntTooBig exception. @@ -227,11 +261,11 @@ builtin BigIntSubtractNoThrow(implicit context: Context)( builtin BigIntSubtract(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -268,8 +302,11 @@ macro BigIntMultiplyImpl(implicit context: Context)(x: BigInt, y: BigInt): } builtin BigIntMultiplyNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntMultiplyImpl(x, y) otherwise BigIntTooBig, TerminationRequested; } label BigIntTooBig { @@ -284,12 +321,12 @@ builtin BigIntMultiplyNoThrow(implicit context: Context)( builtin BigIntMultiply(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntMultiplyImpl(x, y) otherwise BigIntTooBig, TerminationRequested; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -337,8 +374,11 @@ macro BigIntDivideImpl(implicit context: Context)(x: BigInt, y: BigInt): } builtin BigIntDivideNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntDivideImpl(x, y) otherwise BigIntDivZero, TerminationRequested; } label BigIntDivZero { // Smi sentinel 0 is used to signal BigIntDivZero exception. @@ -352,11 +392,11 @@ builtin BigIntDivideNoThrow(implicit context: Context)( builtin BigIntDivide(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntDivideImpl(x, y) otherwise BigIntDivZero, TerminationRequested; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntDivZero { ThrowRangeError(MessageTemplate::kBigIntDivZero); @@ -399,8 +439,11 @@ macro BigIntModulusImpl(implicit context: Context)(x: BigInt, y: BigInt): } builtin BigIntModulusNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntModulusImpl(x, y) otherwise BigIntDivZero, TerminationRequested; } label BigIntDivZero { @@ -415,12 +458,12 @@ builtin BigIntModulusNoThrow(implicit context: Context)( builtin BigIntModulus(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntModulusImpl(x, y) otherwise BigIntDivZero, TerminationRequested; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntDivZero { ThrowRangeError(MessageTemplate::kBigIntDivZero); @@ -473,8 +516,11 @@ macro BigIntBitwiseAndImpl(implicit context: Context)( } builtin BigIntBitwiseAndNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntBitwiseAndImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinel 0 is used to signal BigIntTooBig exception. @@ -485,11 +531,11 @@ builtin BigIntBitwiseAndNoThrow(implicit context: Context)( builtin BigIntBitwiseAnd(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntBitwiseAndImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -539,18 +585,21 @@ macro BigIntBitwiseOrImpl(implicit context: Context)( } builtin BigIntBitwiseOrNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntBitwiseOrImpl(x, y); } builtin BigIntBitwiseOr(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntBitwiseOrImpl(x, y); - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } } @@ -601,8 +650,11 @@ macro BigIntBitwiseXorImpl(implicit context: Context)( } builtin BigIntBitwiseXorNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntBitwiseXorImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinel 0 is used to signal BigIntTooBig exception. @@ -613,11 +665,11 @@ builtin BigIntBitwiseXorNoThrow(implicit context: Context)( builtin BigIntBitwiseXor(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntBitwiseXorImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -733,8 +785,11 @@ macro BigIntShiftRightImpl(implicit context: Context)( } builtin BigIntShiftLeftNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntShiftLeftImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinel 0 is used to signal BigIntTooBig exception. @@ -745,11 +800,11 @@ builtin BigIntShiftLeftNoThrow(implicit context: Context)( builtin BigIntShiftLeft(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntShiftLeftImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); @@ -757,8 +812,11 @@ builtin BigIntShiftLeft(implicit context: Context)( } builtin BigIntShiftRightNoThrow(implicit context: Context)( - x: BigInt, y: BigInt): Numeric { + xNum: Numeric, yNum: Numeric): Numeric { try { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + return BigIntShiftRightImpl(x, y) otherwise BigIntTooBig; } label BigIntTooBig { // Smi sentinel 0 is used to signal BigIntTooBig exception. @@ -769,18 +827,21 @@ builtin BigIntShiftRightNoThrow(implicit context: Context)( builtin BigIntShiftRight(implicit context: Context)( xNum: Numeric, yNum: Numeric): BigInt { try { - const x = Cast(xNum) otherwise MixedTypes; - const y = Cast(yNum) otherwise MixedTypes; + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntShiftRightImpl(x, y) otherwise BigIntTooBig; - } label MixedTypes { + } label _MixedTypes { ThrowTypeError(MessageTemplate::kBigIntMixedTypes); } label BigIntTooBig { ThrowRangeError(MessageTemplate::kBigIntTooBig); } } -builtin BigIntEqual(implicit context: Context)(x: BigInt, y: BigInt): Boolean { +builtin BigIntEqual(implicit context: Context)(xNum: Numeric, yNum: Numeric): Boolean { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); + if (ReadBigIntSign(x) != ReadBigIntSign(y)) { return False; } @@ -836,22 +897,30 @@ macro BigIntCompare(implicit context: Context)(x: BigInt, y: BigInt): intptr { } builtin BigIntLessThan(implicit context: Context)( - x: BigInt, y: BigInt): Boolean { + xNum: Numeric, yNum: Numeric): Boolean { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntCompare(x, y) < 0 ? True : False; } builtin BigIntGreaterThan(implicit context: Context)( - x: BigInt, y: BigInt): Boolean { + xNum: Numeric, yNum: Numeric): Boolean { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntCompare(x, y) > 0 ? True : False; } builtin BigIntLessThanOrEqual(implicit context: Context)( - x: BigInt, y: BigInt): Boolean { + xNum: Numeric, yNum: Numeric): Boolean { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntCompare(x, y) <= 0 ? True : False; } builtin BigIntGreaterThanOrEqual(implicit context: Context)( - x: BigInt, y: BigInt): Boolean { + xNum: Numeric, yNum: Numeric): Boolean { + const x = NormalizeWord(xNum); + const y = NormalizeWord(yNum); return BigIntCompare(x, y) >= 0 ? True : False; } diff --git a/src/codegen/code-stub-assembler.cc b/src/codegen/code-stub-assembler.cc index 7d47afa2c9..e138e8cc07 100644 --- a/src/codegen/code-stub-assembler.cc +++ b/src/codegen/code-stub-assembler.cc @@ -3625,6 +3625,32 @@ TNode CodeStubAssembler::LoadBigIntBitfield(TNode bigint) { LoadObjectField(bigint, BigInt::kBitfieldOffset)); } +void CodeStubAssembler::SetBigInt(TNode bigint, TNode digit, + TNode bFlip) { + + Label trCondition(this), frCondition(this), epilogue(this); + + auto ret = ChangeInt32ToIntPtr(SmiToInt32(digit)); + + Branch(bFlip, &trCondition, &frCondition); + + BIND(&trCondition); + { + StoreObjectFieldNoWriteBarrier(bigint, BigInt::kDigitsOffset, + Unsigned(IntPtrAdd(WordNot(ret), IntPtrConstant(1)))); + Goto(&epilogue); + } + + BIND(&frCondition); + { + StoreObjectFieldNoWriteBarrier(bigint, BigInt::kDigitsOffset, + Unsigned(ret)); + Goto(&epilogue); + } + + BIND(&epilogue); +} + TNode CodeStubAssembler::LoadBigIntDigit(TNode bigint, intptr_t digit_index) { CHECK_LE(0, digit_index); @@ -5717,7 +5743,7 @@ TNode CodeStubAssembler::TruncateTaggedToWord32(TNode context, void CodeStubAssembler::TaggedToWord32OrBigInt( TNode context, TNode value, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint) { + TVariable* var_maybe_bigint) { TaggedToWord32OrBigIntImpl( context, value, if_number, var_word32, IsKnownTaggedPointer::kNo, if_bigint, if_bigint64, var_maybe_bigint); @@ -5729,7 +5755,7 @@ void CodeStubAssembler::TaggedToWord32OrBigInt( void CodeStubAssembler::TaggedToWord32OrBigIntWithFeedback( TNode context, TNode value, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint, TVariable* var_feedback) { + TVariable* var_maybe_bigint, TVariable* var_feedback) { TaggedToWord32OrBigIntImpl( context, value, if_number, var_word32, IsKnownTaggedPointer::kNo, if_bigint, if_bigint64, var_maybe_bigint, var_feedback); @@ -5741,7 +5767,7 @@ void CodeStubAssembler::TaggedToWord32OrBigIntWithFeedback( void CodeStubAssembler::TaggedPointerToWord32OrBigIntWithFeedback( TNode context, TNode pointer, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint, TVariable* var_feedback) { + TVariable* var_maybe_bigint, TVariable* var_feedback) { TaggedToWord32OrBigIntImpl( context, pointer, if_number, var_word32, IsKnownTaggedPointer::kYes, if_bigint, if_bigint64, var_maybe_bigint, var_feedback); @@ -5752,7 +5778,7 @@ void CodeStubAssembler::TaggedToWord32OrBigIntImpl( TNode context, TNode value, Label* if_number, TVariable* var_word32, IsKnownTaggedPointer is_known_tagged_pointer, Label* if_bigint, - Label* if_bigint64, TVariable* var_maybe_bigint, + Label* if_bigint64, TVariable* var_maybe_bigint, TVariable* var_feedback) { // We might need to loop after conversion. TVARIABLE(Object, var_value, value); @@ -7995,6 +8021,8 @@ TNode CodeStubAssembler::ToBigInt(TNode context, Goto(&done); BIND(&if_throw); + //result = CallBuiltin(Builtin::kBigInt, context(), + // var_left_bigint.value(), var_right_bigint.value()); ThrowTypeError(context, MessageTemplate::kBigIntFromObject, input); BIND(&done); @@ -8025,9 +8053,9 @@ TNode CodeStubAssembler::ToBigIntConvertNumber(TNode context, void CodeStubAssembler::TaggedToBigInt(TNode context, TNode value, - Label* if_not_bigint, Label* if_bigint, + Label* if_invalid, Label* if_bigint, Label* if_bigint64, - TVariable* var_bigint, + TVariable* var_bigint, TVariable* var_feedback) { Label done(this), is_smi(this), is_heapnumber(this), maybe_bigint64(this), is_bigint(this), is_oddball(this); @@ -8047,18 +8075,20 @@ void CodeStubAssembler::TaggedToBigInt(TNode context, TNode numeric_value = CAST( CallBuiltin(Builtin::kNonNumberToNumeric, context, heap_object_value)); OverwriteFeedback(var_feedback, BinaryOperationFeedback::kAny); - GotoIf(TaggedIsSmi(numeric_value), if_not_bigint); - GotoIfNot(IsBigInt(CAST(numeric_value)), if_not_bigint); - *var_bigint = CAST(numeric_value); + GotoIf(TaggedIsSmi(numeric_value), if_invalid); + GotoIfNot(IsBigInt(CAST(numeric_value)), if_invalid); + *var_bigint = numeric_value; Goto(if_bigint); BIND(&is_smi); OverwriteFeedback(var_feedback, BinaryOperationFeedback::kSignedSmall); - Goto(if_not_bigint); + *var_bigint = CAST(value); + Goto(if_bigint); BIND(&is_heapnumber); OverwriteFeedback(var_feedback, BinaryOperationFeedback::kNumber); - Goto(if_not_bigint); + *var_bigint = CAST(value); + Goto(if_bigint); if (Is64() && if_bigint64) { BIND(&maybe_bigint64); @@ -8074,8 +8104,9 @@ void CodeStubAssembler::TaggedToBigInt(TNode context, Goto(if_bigint); BIND(&is_oddball); + *var_bigint = SmiConstant(0); OverwriteFeedback(var_feedback, BinaryOperationFeedback::kNumberOrOddball); - Goto(if_not_bigint); + Goto(if_bigint); } // ES#sec-touint32 diff --git a/src/codegen/code-stub-assembler.h b/src/codegen/code-stub-assembler.h index 166e0d3576..722fb91fec 100644 --- a/src/codegen/code-stub-assembler.h +++ b/src/codegen/code-stub-assembler.h @@ -1893,7 +1893,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler void StoreBigIntDigit(TNode bigint, TNode digit_index, TNode digit); - TNode LoadBigIntBitfield(TNode bigint); + void SetBigInt(TNode bigint, TNode digit, + TNode bFlip); + + TNode LoadBigIntBitfield(TNode bigint); TNode LoadBigIntDigit(TNode bigint, intptr_t digit_index); TNode LoadBigIntDigit(TNode bigint, TNode digit_index); @@ -2433,17 +2436,17 @@ class V8_EXPORT_PRIVATE CodeStubAssembler void TaggedToWord32OrBigInt(TNode context, TNode value, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint); + TVariable* var_maybe_bigint); void TaggedToWord32OrBigIntWithFeedback(TNode context, TNode value, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint, + TVariable* var_maybe_bigint, TVariable* var_feedback); void TaggedPointerToWord32OrBigIntWithFeedback( TNode context, TNode pointer, Label* if_number, TVariable* var_word32, Label* if_bigint, Label* if_bigint64, - TVariable* var_maybe_bigint, TVariable* var_feedback); + TVariable* var_maybe_bigint, TVariable* var_feedback); TNode TruncateNumberToWord32(TNode value); // Truncate the floating point value of a HeapNumber to an Int32. @@ -2474,7 +2477,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler void TaggedToBigInt(TNode context, TNode value, Label* if_not_bigint, Label* if_bigint, - Label* if_bigint64, TVariable* var_bigint, + Label* if_bigint64, TVariable* var_bigint, TVariable* var_feedback); // Ensures that {var_shared_value} is shareable across Isolates, and throws if @@ -4325,7 +4328,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler IsKnownTaggedPointer is_known_tagged_pointer, Label* if_bigint = nullptr, Label* if_bigint64 = nullptr, - TVariable* var_maybe_bigint = nullptr, + TVariable* var_maybe_bigint = nullptr, TVariable* var_feedback = nullptr); // Low-level accessors for Descriptor arrays. diff --git a/src/ic/binary-op-assembler.cc b/src/ic/binary-op-assembler.cc index a1dfbe49d8..24d6961aa1 100644 --- a/src/ic/binary-op-assembler.cc +++ b/src/ic/binary-op-assembler.cc @@ -788,7 +788,7 @@ TNode BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback( TVARIABLE(Smi, var_right_feedback); TVARIABLE(Word32T, var_left_word32); TVARIABLE(Word32T, var_right_word32); - TVARIABLE(BigInt, var_left_bigint); + TVARIABLE(Numeric, var_left_bigint); Label done(this); Label if_left_number(this), do_number_op(this); Label if_left_bigint(this), if_left_bigint64(this); @@ -800,11 +800,15 @@ TNode BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback( &var_left_bigint, slot ? &var_left_feedback : nullptr); BIND(&if_left_number); - TaggedToWord32OrBigIntWithFeedback( - context(), right, &do_number_op, &var_right_word32, - &if_left_number_right_bigint, nullptr, nullptr, - slot ? &var_right_feedback : nullptr); + { + TaggedToWord32OrBigIntWithFeedback( + context(), right, &do_number_op, &var_right_word32, + &if_left_number_right_bigint, + nullptr, nullptr, slot ? &var_right_feedback : nullptr); + } + // SMI of X &^| bigint Y should remain a throw + // Logically, it does not make sense for the right hand operand to be greater than the lefthand BIND(&if_left_number_right_bigint); { if (slot) { @@ -835,17 +839,17 @@ TNode BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback( // BigInt cases. { - TVARIABLE(BigInt, var_right_bigint); + TVARIABLE(Numeric, var_right_bigint); Label if_both_bigint(this), if_both_bigint64(this); - Label if_bigint_mix(this, Label::kDeferred); + Label if_invalid(this, Label::kDeferred); BIND(&if_left_bigint); - TaggedToBigInt(context(), right, &if_bigint_mix, &if_both_bigint, nullptr, + TaggedToBigInt(context(), right, &if_invalid, &if_both_bigint, nullptr, &var_right_bigint, slot ? &var_right_feedback : nullptr); if (IsBigInt64OpSupported(this, bitwise_op)) { BIND(&if_left_bigint64); - TaggedToBigInt(context(), right, &if_bigint_mix, &if_both_bigint, + TaggedToBigInt(context(), right, &if_invalid, &if_both_bigint, &if_both_bigint64, &var_right_bigint, slot ? &var_right_feedback : nullptr); @@ -860,8 +864,12 @@ TNode BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback( TVARIABLE(UintPtrT, left_raw); TVARIABLE(UintPtrT, right_raw); - BigIntToRawBytes(var_left_bigint.value(), &left_raw, &left_raw); - BigIntToRawBytes(var_right_bigint.value(), &right_raw, &right_raw); + + BigIntToRawBytes(UncheckedCast(var_left_bigint.value()), + &left_raw, &left_raw); + + BigIntToRawBytes(UncheckedCast(var_right_bigint.value()), + &right_raw, &right_raw); switch (bitwise_op) { case Operation::kBitwiseAnd: { @@ -995,14 +1003,14 @@ TNode BinaryOpAssembler::Generate_BitwiseBinaryOpWithOptionalFeedback( } } - BIND(&if_bigint_mix); + BIND(&if_invalid); { if (slot) { // Ensure that the feedback is updated before we throw. UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), (*maybe_feedback_vector)(), *slot, update_feedback_mode); } - ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes); + ThrowTypeError(context(), MessageTemplate::kBigIntFromNumber); } } @@ -1020,11 +1028,12 @@ BinaryOpAssembler::Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback( TVARIABLE(Object, result); TVARIABLE(Smi, var_left_feedback); TVARIABLE(Word32T, var_left_word32); - TVARIABLE(BigInt, var_left_bigint); + TVARIABLE(Numeric, var_left_bigint); TVARIABLE(Smi, feedback); // Check if the {lhs} is a Smi or a HeapObject. - Label if_lhsissmi(this), if_lhsisnotsmi(this, Label::kDeferred); - Label do_number_op(this), if_bigint_mix(this), done(this); + Label if_lhsissmi(this), if_lhsisnotsmi(this); + Label do_number_op(this), if_bigint_mix(this), done(this), done2(this), + mixedBigInt(this); Branch(TaggedIsSmi(left), &if_lhsissmi, &if_lhsisnotsmi); @@ -1065,18 +1074,118 @@ BinaryOpAssembler::Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback( BIND(&if_bigint_mix); { - if (slot) { - // Ensure that the feedback is updated before we throw. - UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), - (*maybe_feedback_vector)(), *slot, update_feedback_mode); + Goto(&mixedBigInt); + } + } + + BIND(&mixedBigInt); + { + if (slot) { + // Ensure that the feedback is updated even if the runtime call below + // would throw. + feedback = SmiOr(var_left_feedback.value(), right_smi); + UpdateFeedback(feedback.value(), (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + + switch (bitwise_op) { + case Operation::kBitwiseAnd: { + result = CallBuiltin(Builtin::kBigIntBitwiseAndNoThrow, context(), + var_left_bigint.value(), right_smi); + // Check for sentinel that signals BigIntTooBig exception. + GotoIfNot(TaggedIsSmi(result.value()), &done2); + + if (slot) { + // Update feedback to prevent deopt loop. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + ThrowRangeError(context(), MessageTemplate::kBigIntTooBig); + break; } - ThrowTypeError(context(), MessageTemplate::kBigIntMixedTypes); + case Operation::kBitwiseOr: { + result = CallBuiltin(Builtin::kBigIntBitwiseOrNoThrow, context(), + var_left_bigint.value(), right_smi); + // Check for sentinel that signals BigIntTooBig exception. + GotoIfNot(TaggedIsSmi(result.value()), &done2); + + if (slot) { + // Update feedback to prevent deopt loop. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + ThrowRangeError(context(), MessageTemplate::kBigIntTooBig); + break; + } + case Operation::kBitwiseXor: { + result = CallBuiltin(Builtin::kBigIntBitwiseXorNoThrow, context(), + var_left_bigint.value(), right_smi); + // Check for sentinel that signals BigIntTooBig exception. + GotoIfNot(TaggedIsSmi(result.value()), &done2); + + if (slot) { + // Update feedback to prevent deopt loop. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + ThrowRangeError(context(), MessageTemplate::kBigIntTooBig); + break; + } + case Operation::kShiftLeft: { + result = CallBuiltin(Builtin::kBigIntShiftLeftNoThrow, context(), + var_left_bigint.value(), right_smi); + // Check for sentinel that signals BigIntTooBig exception. + GotoIfNot(TaggedIsSmi(result.value()), &done2); + + if (slot) { + // Update feedback to prevent deopt loop. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + ThrowRangeError(context(), MessageTemplate::kBigIntTooBig); + break; + } + case Operation::kShiftRight: { + result = CallBuiltin(Builtin::kBigIntShiftRightNoThrow, context(), + var_left_bigint.value(), right_smi); + // Check for sentinel that signals BigIntTooBig exception. + GotoIfNot(TaggedIsSmi(result.value()), &done2); + + if (slot) { + // Update feedback to prevent deopt loop. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + ThrowRangeError(context(), MessageTemplate::kBigIntTooBig); + break; + } + case Operation::kShiftRightLogical: { + if (slot) { + // Ensure that the feedback is updated before we throw. + UpdateFeedback(SmiConstant(BinaryOperationFeedback::kAny), + (*maybe_feedback_vector)(), *slot, + update_feedback_mode); + } + // BigInt does not support logical right shift. + ThrowTypeError(context(), MessageTemplate::kBigIntShr); + break; + } + default: + UNREACHABLE(); } } BIND(&done); UpdateFeedback(feedback.value(), (*maybe_feedback_vector)(), *slot, update_feedback_mode); + Goto(&done2); + + BIND(&done2); return result.value(); } diff --git a/src/ic/unary-op-assembler.cc b/src/ic/unary-op-assembler.cc index fe3dc599ca..0571558ee3 100644 --- a/src/ic/unary-op-assembler.cc +++ b/src/ic/unary-op-assembler.cc @@ -25,7 +25,7 @@ class UnaryOpAssemblerImpl final : public CodeStubAssembler { // mechanism). TVARIABLE(Word32T, var_word32); TVARIABLE(Smi, var_feedback); - TVARIABLE(BigInt, var_bigint); + TVARIABLE(Numeric, var_bigint); TVARIABLE(Object, var_result); Label if_number(this), if_bigint(this, Label::kDeferred), out(this); TaggedToWord32OrBigIntWithFeedback(context, value, &if_number, &var_word32, diff --git a/src/runtime/runtime-bigint.cc b/src/runtime/runtime-bigint.cc index f64d9e5b1a..0d62eb2e0d 100644 --- a/src/runtime/runtime-bigint.cc +++ b/src/runtime/runtime-bigint.cc @@ -121,12 +121,32 @@ RUNTIME_FUNCTION(Runtime_BigIntBinaryOp) { int opcode = args.smi_value_at(2); Operation op = static_cast(opcode); - if (!left_obj->IsBigInt() || !right_obj->IsBigInt()) { - THROW_NEW_ERROR_RETURN_FAILURE( - isolate, NewTypeError(MessageTemplate::kBigIntMixedTypes)); + Handle left ; + Handle right; + + if (!left_obj->IsBigInt()) { + auto mebi = BigInt::FromObject(isolate, left_obj); + if (mebi.is_null()) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kBigIntMixedTypes)); + } + left = mebi.ToHandleChecked(); } - Handle left(Handle::cast(left_obj)); - Handle right(Handle::cast(right_obj)); + else { + left = Handle::cast(left_obj); + } + + if (!right_obj->IsBigInt()) { + auto mebi = BigInt::FromObject(isolate, right_obj); + if (mebi.is_null()) { + THROW_NEW_ERROR_RETURN_FAILURE( + isolate, NewTypeError(MessageTemplate::kBigIntMixedTypes)); + } + right = mebi.ToHandleChecked(); + } else { + right = Handle::cast(right_obj); + } + MaybeHandle result; switch (op) { case Operation::kAdd: diff --git a/src/torque/source-positions.h b/src/torque/source-positions.h index 32f60e06e0..a9f878a439 100644 --- a/src/torque/source-positions.h +++ b/src/torque/source-positions.h @@ -109,10 +109,9 @@ inline std::string PositionAsString(SourcePosition pos) { } inline std::ostream& operator<<(std::ostream& out, SourcePosition pos) { - return out << "https://source.chromium.org/chromium/chromium/src/+/main:v8/" + return out << "https://gitea.reece.sx/AuroraMiddleware/v8/src/branch/master/" << SourceFileMap::PathFromV8Root(pos.source) - << "?l=" << (pos.start.line + 1) - << "&c=" << (pos.start.column + 1); + << "#L" << (pos.start.line + 1); } } // namespace torque