[+] 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
This commit is contained in:
Reece Wilson 2023-02-28 03:08:49 +00:00
parent b8f6b544b0
commit 1224fc8eea
7 changed files with 324 additions and 93 deletions

View File

@ -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<BigInt>(n) otherwise NotBigInt;
} label NotBigInt {
try {
const ssWord : Smi = Cast<Smi>(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<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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<BigInt>(xNum) otherwise MixedTypes;
const y = Cast<BigInt>(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;
}

View File

@ -3625,6 +3625,32 @@ TNode<Word32T> CodeStubAssembler::LoadBigIntBitfield(TNode<BigInt> bigint) {
LoadObjectField<Uint32T>(bigint, BigInt::kBitfieldOffset));
}
void CodeStubAssembler::SetBigInt(TNode<BigInt> bigint, TNode<Smi> digit,
TNode<BoolT> 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<UintPtrT> CodeStubAssembler::LoadBigIntDigit(TNode<BigInt> bigint,
intptr_t digit_index) {
CHECK_LE(0, digit_index);
@ -5717,7 +5743,7 @@ TNode<Word32T> CodeStubAssembler::TruncateTaggedToWord32(TNode<Context> context,
void CodeStubAssembler::TaggedToWord32OrBigInt(
TNode<Context> context, TNode<Object> value, Label* if_number,
TVariable<Word32T>* var_word32, Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint) {
TVariable<Numeric>* var_maybe_bigint) {
TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumeric>(
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> context, TNode<Object> value, Label* if_number,
TVariable<Word32T>* var_word32, Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint, TVariable<Smi>* var_feedback) {
TVariable<Numeric>* var_maybe_bigint, TVariable<Smi>* var_feedback) {
TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumeric>(
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> context, TNode<HeapObject> pointer, Label* if_number,
TVariable<Word32T>* var_word32, Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint, TVariable<Smi>* var_feedback) {
TVariable<Numeric>* var_maybe_bigint, TVariable<Smi>* var_feedback) {
TaggedToWord32OrBigIntImpl<Object::Conversion::kToNumeric>(
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> context, TNode<Object> value, Label* if_number,
TVariable<Word32T>* var_word32,
IsKnownTaggedPointer is_known_tagged_pointer, Label* if_bigint,
Label* if_bigint64, TVariable<BigInt>* var_maybe_bigint,
Label* if_bigint64, TVariable<Numeric>* var_maybe_bigint,
TVariable<Smi>* var_feedback) {
// We might need to loop after conversion.
TVARIABLE(Object, var_value, value);
@ -7995,6 +8021,8 @@ TNode<BigInt> CodeStubAssembler::ToBigInt(TNode<Context> 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<BigInt> CodeStubAssembler::ToBigIntConvertNumber(TNode<Context> context,
void CodeStubAssembler::TaggedToBigInt(TNode<Context> context,
TNode<Object> value,
Label* if_not_bigint, Label* if_bigint,
Label* if_invalid, Label* if_bigint,
Label* if_bigint64,
TVariable<BigInt>* var_bigint,
TVariable<Numeric>* var_bigint,
TVariable<Smi>* 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> context,
TNode<Numeric> 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> 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

View File

@ -1893,7 +1893,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
void StoreBigIntDigit(TNode<BigInt> bigint, TNode<IntPtrT> digit_index,
TNode<UintPtrT> digit);
TNode<Word32T> LoadBigIntBitfield(TNode<BigInt> bigint);
void SetBigInt(TNode<BigInt> bigint, TNode<Smi> digit,
TNode<BoolT> bFlip);
TNode<Word32T> LoadBigIntBitfield(TNode<BigInt> bigint);
TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, intptr_t digit_index);
TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint,
TNode<IntPtrT> digit_index);
@ -2433,17 +2436,17 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
void TaggedToWord32OrBigInt(TNode<Context> context, TNode<Object> value,
Label* if_number, TVariable<Word32T>* var_word32,
Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint);
TVariable<Numeric>* var_maybe_bigint);
void TaggedToWord32OrBigIntWithFeedback(TNode<Context> context,
TNode<Object> value, Label* if_number,
TVariable<Word32T>* var_word32,
Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint,
TVariable<Numeric>* var_maybe_bigint,
TVariable<Smi>* var_feedback);
void TaggedPointerToWord32OrBigIntWithFeedback(
TNode<Context> context, TNode<HeapObject> pointer, Label* if_number,
TVariable<Word32T>* var_word32, Label* if_bigint, Label* if_bigint64,
TVariable<BigInt>* var_maybe_bigint, TVariable<Smi>* var_feedback);
TVariable<Numeric>* var_maybe_bigint, TVariable<Smi>* var_feedback);
TNode<Int32T> TruncateNumberToWord32(TNode<Number> 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> context, TNode<Object> value,
Label* if_not_bigint, Label* if_bigint,
Label* if_bigint64, TVariable<BigInt>* var_bigint,
Label* if_bigint64, TVariable<Numeric>* var_bigint,
TVariable<Smi>* 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<BigInt>* var_maybe_bigint = nullptr,
TVariable<Numeric>* var_maybe_bigint = nullptr,
TVariable<Smi>* var_feedback = nullptr);
// Low-level accessors for Descriptor arrays.

View File

@ -788,7 +788,7 @@ TNode<Object> 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<Object> 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<Object> 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<Object> 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<BigInt>(var_left_bigint.value()),
&left_raw, &left_raw);
BigIntToRawBytes(UncheckedCast<BigInt>(var_right_bigint.value()),
&right_raw, &right_raw);
switch (bitwise_op) {
case Operation::kBitwiseAnd: {
@ -995,14 +1003,14 @@ TNode<Object> 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();
}

View File

@ -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,

View File

@ -121,12 +121,32 @@ RUNTIME_FUNCTION(Runtime_BigIntBinaryOp) {
int opcode = args.smi_value_at(2);
Operation op = static_cast<Operation>(opcode);
if (!left_obj->IsBigInt() || !right_obj->IsBigInt()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kBigIntMixedTypes));
Handle<BigInt> left ;
Handle<BigInt> 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<BigInt> left(Handle<BigInt>::cast(left_obj));
Handle<BigInt> right(Handle<BigInt>::cast(right_obj));
else {
left = Handle<BigInt>::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<BigInt>::cast(right_obj);
}
MaybeHandle<BigInt> result;
switch (op) {
case Operation::kAdd:

View File

@ -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