diff options
Diffstat (limited to 'deps/v8/src/builtins/bigint.tq')
-rw-r--r-- | deps/v8/src/builtins/bigint.tq | 427 |
1 files changed, 210 insertions, 217 deletions
diff --git a/deps/v8/src/builtins/bigint.tq b/deps/v8/src/builtins/bigint.tq index 02dca7543ef..d52de7f84ea 100644 --- a/deps/v8/src/builtins/bigint.tq +++ b/deps/v8/src/builtins/bigint.tq @@ -23,225 +23,218 @@ Convert<BigInt, MutableBigInt>(i: MutableBigInt): BigInt { namespace bigint { - const kPositiveSign: uint32 = 0; - const kNegativeSign: uint32 = 1; +const kPositiveSign: uint32 = 0; +const kNegativeSign: uint32 = 1; + +extern macro BigIntBuiltinsAssembler::CppAbsoluteAddAndCanonicalize( + MutableBigInt, BigIntBase, BigIntBase): void; +extern macro BigIntBuiltinsAssembler::CppAbsoluteSubAndCanonicalize( + MutableBigInt, BigIntBase, BigIntBase): void; +extern macro BigIntBuiltinsAssembler::CppAbsoluteCompare( + BigIntBase, BigIntBase): int32; + +extern macro BigIntBuiltinsAssembler::ReadBigIntSign(BigIntBase): uint32; +extern macro BigIntBuiltinsAssembler::ReadBigIntLength(BigIntBase): intptr; +extern macro BigIntBuiltinsAssembler::WriteBigIntSignAndLength( + MutableBigInt, uint32, intptr): void; + +extern macro CodeStubAssembler::AllocateBigInt(intptr): MutableBigInt; +extern macro CodeStubAssembler::StoreBigIntDigit( + MutableBigInt, intptr, uintptr): void; +extern macro CodeStubAssembler::LoadBigIntDigit(BigIntBase, intptr): uintptr; + +macro IsCanonicalized(bigint: BigIntBase): bool { + const length = ReadBigIntLength(bigint); + + if (length == 0) { + return ReadBigIntSign(bigint) == kPositiveSign; + } + + return LoadBigIntDigit(bigint, length - 1) != 0; +} + +macro InvertSign(sign: uint32): uint32 { + return sign == kPositiveSign ? kNegativeSign : kPositiveSign; +} + +macro AllocateEmptyBigIntNoThrow(implicit context: Context)( + sign: uint32, length: intptr): MutableBigInt labels BigIntTooBig { + if (length > kBigIntMaxLength) { + goto BigIntTooBig; + } + const result: MutableBigInt = AllocateBigInt(length); + + WriteBigIntSignAndLength(result, sign, length); + return result; +} + +macro AllocateEmptyBigInt(implicit context: Context)( + sign: uint32, length: intptr): MutableBigInt { + try { + return AllocateEmptyBigIntNoThrow(sign, length) otherwise BigIntTooBig; + } label BigIntTooBig { + ThrowRangeError(MessageTemplate::kBigIntTooBig); + } +} + +macro MutableBigIntAbsoluteCompare(x: BigIntBase, y: BigIntBase): int32 { + return CppAbsoluteCompare(x, y); +} + +macro MutableBigIntAbsoluteSub(implicit context: Context)( + x: BigInt, y: BigInt, resultSign: uint32): BigInt { + const xlength = ReadBigIntLength(x); + const ylength = ReadBigIntLength(y); + const xsign = ReadBigIntSign(x); + + assert(MutableBigIntAbsoluteCompare(x, y) >= 0); + if (xlength == 0) { + assert(ylength == 0); + return x; + } + + if (ylength == 0) { + return resultSign == xsign ? x : BigIntUnaryMinus(x); + } + + const result = AllocateEmptyBigInt(resultSign, xlength); + CppAbsoluteSubAndCanonicalize(result, x, y); + return Convert<BigInt>(result); +} + +macro MutableBigIntAbsoluteAdd(implicit context: Context)( + xBigint: BigInt, yBigint: BigInt, + resultSign: uint32): BigInt labels BigIntTooBig { + let xlength = ReadBigIntLength(xBigint); + let ylength = ReadBigIntLength(yBigint); + + let x = xBigint; + let y = yBigint; + if (xlength < ylength) { + // Swap x and y so that x is longer. + x = yBigint; + y = xBigint; + const tempLength = xlength; + xlength = ylength; + ylength = tempLength; + } + + // case: 0n + 0n + if (xlength == 0) { + assert(ylength == 0); + return x; + } + + // case: x + 0n + if (ylength == 0) { + return resultSign == ReadBigIntSign(x) ? x : BigIntUnaryMinus(x); + } - extern macro BigIntBuiltinsAssembler::CppAbsoluteAddAndCanonicalize( - MutableBigInt, BigIntBase, BigIntBase): void; - extern macro BigIntBuiltinsAssembler::CppAbsoluteSubAndCanonicalize( - MutableBigInt, BigIntBase, BigIntBase): void; - extern macro BigIntBuiltinsAssembler::CppAbsoluteCompare( - BigIntBase, BigIntBase): int32; - - extern macro BigIntBuiltinsAssembler::ReadBigIntSign(BigIntBase): uint32; - extern macro BigIntBuiltinsAssembler::ReadBigIntLength(BigIntBase): intptr; - extern macro BigIntBuiltinsAssembler::WriteBigIntSignAndLength( - MutableBigInt, uint32, intptr): void; + // case: x + y + const result = AllocateEmptyBigIntNoThrow(resultSign, xlength + 1) + otherwise BigIntTooBig; + CppAbsoluteAddAndCanonicalize(result, x, y); + return Convert<BigInt>(result); +} + +macro BigIntAddImpl(implicit context: Context)(x: BigInt, y: BigInt): BigInt + labels BigIntTooBig { + const xsign = ReadBigIntSign(x); + const ysign = ReadBigIntSign(y); + if (xsign == ysign) { + // x + y == x + y + // -x + -y == -(x + y) + return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; + } + + // x + -y == x - y == -(y - x) + // -x + y == y - x == -(x - y) + if (MutableBigIntAbsoluteCompare(x, y) >= 0) { + return MutableBigIntAbsoluteSub(x, y, xsign); + } + return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); +} + +builtin BigIntAddNoThrow(implicit context: Context)( + x: BigInt, y: BigInt): Numeric { + try { + return BigIntAddImpl(x, y) otherwise BigIntTooBig; + } label BigIntTooBig { + // Smi sentinal is used to signal BigIntTooBig exception. + return Convert<Smi>(0); + } +} + +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; + + return BigIntAddImpl(x, y) otherwise BigIntTooBig; + } label MixedTypes { + ThrowTypeError(MessageTemplate::kBigIntMixedTypes); + } label BigIntTooBig { + ThrowRangeError(MessageTemplate::kBigIntTooBig); + } +} + +macro BigIntSubtractImpl(implicit context: Context)( + x: BigInt, y: BigInt): BigInt labels BigIntTooBig { + const xsign = ReadBigIntSign(x); + const ysign = ReadBigIntSign(y); + if (xsign != ysign) { + // x - (-y) == x + y + // (-x) - y == -(x + y) + return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; + } - extern macro CodeStubAssembler::AllocateBigInt(intptr): MutableBigInt; - extern macro CodeStubAssembler::StoreBigIntDigit( - MutableBigInt, intptr, uintptr): void; - extern macro CodeStubAssembler::LoadBigIntDigit(BigIntBase, intptr): uintptr; - - macro IsCanonicalized(bigint: BigIntBase): bool { - const length = ReadBigIntLength(bigint); - - if (length == 0) { - return ReadBigIntSign(bigint) == kPositiveSign; - } - - return LoadBigIntDigit(bigint, length - 1) != 0; - } - - macro InvertSign(sign: uint32): uint32 { - return sign == kPositiveSign ? kNegativeSign : kPositiveSign; - } - - macro AllocateEmptyBigIntNoThrow(implicit context: Context)( - sign: uint32, length: intptr): MutableBigInt labels BigIntTooBig { - if (length > kBigIntMaxLength) { - goto BigIntTooBig; - } - const result: MutableBigInt = AllocateBigInt(length); - - WriteBigIntSignAndLength(result, sign, length); - return result; - } - - macro AllocateEmptyBigInt(implicit context: Context)( - sign: uint32, length: intptr): MutableBigInt { - try { - return AllocateEmptyBigIntNoThrow(sign, length) otherwise BigIntTooBig; - } - label BigIntTooBig { - ThrowRangeError(MessageTemplate::kBigIntTooBig); - } - } - - macro MutableBigIntAbsoluteCompare(x: BigIntBase, y: BigIntBase): int32 { - return CppAbsoluteCompare(x, y); - } - - macro MutableBigIntAbsoluteSub(implicit context: Context)( - x: BigInt, y: BigInt, resultSign: uint32): BigInt { - const xlength = ReadBigIntLength(x); - const ylength = ReadBigIntLength(y); - const xsign = ReadBigIntSign(x); - - assert(MutableBigIntAbsoluteCompare(x, y) >= 0); - if (xlength == 0) { - assert(ylength == 0); - return x; - } - - if (ylength == 0) { - return resultSign == xsign ? x : BigIntUnaryMinus(x); - } - - const result = AllocateEmptyBigInt(resultSign, xlength); - CppAbsoluteSubAndCanonicalize(result, x, y); - return Convert<BigInt>(result); - } - - macro MutableBigIntAbsoluteAdd(implicit context: Context)( - xBigint: BigInt, yBigint: BigInt, - resultSign: uint32): BigInt labels BigIntTooBig { - let xlength = ReadBigIntLength(xBigint); - let ylength = ReadBigIntLength(yBigint); - - let x = xBigint; - let y = yBigint; - if (xlength < ylength) { - // Swap x and y so that x is longer. - x = yBigint; - y = xBigint; - const tempLength = xlength; - xlength = ylength; - ylength = tempLength; - } - - // case: 0n + 0n - if (xlength == 0) { - assert(ylength == 0); - return x; - } - - // case: x + 0n - if (ylength == 0) { - return resultSign == ReadBigIntSign(x) ? x : BigIntUnaryMinus(x); - } - - // case: x + y - const result = AllocateEmptyBigIntNoThrow(resultSign, xlength + 1) - otherwise BigIntTooBig; - CppAbsoluteAddAndCanonicalize(result, x, y); - return Convert<BigInt>(result); - } - - macro BigIntAddImpl(implicit context: Context)(x: BigInt, y: BigInt): BigInt - labels BigIntTooBig { - const xsign = ReadBigIntSign(x); - const ysign = ReadBigIntSign(y); - if (xsign == ysign) { - // x + y == x + y - // -x + -y == -(x + y) - return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; - } - - // x + -y == x - y == -(y - x) - // -x + y == y - x == -(x - y) - if (MutableBigIntAbsoluteCompare(x, y) >= 0) { - return MutableBigIntAbsoluteSub(x, y, xsign); - } - return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); - } - - builtin BigIntAddNoThrow(implicit context: Context)(x: BigInt, y: BigInt): - Numeric { - try { - return BigIntAddImpl(x, y) otherwise BigIntTooBig; - } - label BigIntTooBig { - // Smi sentinal is used to signal BigIntTooBig exception. - return Convert<Smi>(0); - } - } - - 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; - - return BigIntAddImpl(x, y) otherwise BigIntTooBig; - } - label MixedTypes { - ThrowTypeError(MessageTemplate::kBigIntMixedTypes); - } - label BigIntTooBig { - ThrowRangeError(MessageTemplate::kBigIntTooBig); - } - } - - macro BigIntSubtractImpl(implicit context: Context)(x: BigInt, y: BigInt): - BigInt labels BigIntTooBig { - const xsign = ReadBigIntSign(x); - const ysign = ReadBigIntSign(y); - if (xsign != ysign) { - // x - (-y) == x + y - // (-x) - y == -(x + y) - return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; - } - - // x - y == -(y - x) - // (-x) - (-y) == y - x == -(x - y) - if (MutableBigIntAbsoluteCompare(x, y) >= 0) { - return MutableBigIntAbsoluteSub(x, y, xsign); - } - return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); - } - - builtin BigIntSubtractNoThrow(implicit context: - Context)(x: BigInt, y: BigInt): Numeric { - try { - return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; - } - label BigIntTooBig { - // Smi sentinal is used to signal BigIntTooBig exception. - return Convert<Smi>(0); - } - } - - 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; - - return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; - } - label MixedTypes { - ThrowTypeError(MessageTemplate::kBigIntMixedTypes); - } - label BigIntTooBig { - ThrowRangeError(MessageTemplate::kBigIntTooBig); - } - } - - builtin BigIntUnaryMinus(implicit context: Context)(bigint: BigInt): BigInt { - const length = ReadBigIntLength(bigint); - - // There is no -0n. - if (length == 0) { - return bigint; - } - - const result = - AllocateEmptyBigInt(InvertSign(ReadBigIntSign(bigint)), length); - for (let i: intptr = 0; i < length; ++i) { - StoreBigIntDigit(result, i, LoadBigIntDigit(bigint, i)); - } - return Convert<BigInt>(result); + // x - y == -(y - x) + // (-x) - (-y) == y - x == -(x - y) + if (MutableBigIntAbsoluteCompare(x, y) >= 0) { + return MutableBigIntAbsoluteSub(x, y, xsign); } + return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); +} + +builtin BigIntSubtractNoThrow(implicit context: Context)( + x: BigInt, y: BigInt): Numeric { + try { + return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; + } label BigIntTooBig { + // Smi sentinal is used to signal BigIntTooBig exception. + return Convert<Smi>(0); + } +} + +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; + + return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; + } label MixedTypes { + ThrowTypeError(MessageTemplate::kBigIntMixedTypes); + } label BigIntTooBig { + ThrowRangeError(MessageTemplate::kBigIntTooBig); + } +} + +builtin BigIntUnaryMinus(implicit context: Context)(bigint: BigInt): BigInt { + const length = ReadBigIntLength(bigint); + + // There is no -0n. + if (length == 0) { + return bigint; + } + + const result = + AllocateEmptyBigInt(InvertSign(ReadBigIntSign(bigint)), length); + for (let i: intptr = 0; i < length; ++i) { + StoreBigIntDigit(result, i, LoadBigIntDigit(bigint, i)); + } + return Convert<BigInt>(result); +} } // namespace bigint |