diff options
Diffstat (limited to 'deps/v8/src/builtins/bigint.tq')
-rw-r--r-- | deps/v8/src/builtins/bigint.tq | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/deps/v8/src/builtins/bigint.tq b/deps/v8/src/builtins/bigint.tq new file mode 100644 index 0000000000..a1b1cb6780 --- /dev/null +++ b/deps/v8/src/builtins/bigint.tq @@ -0,0 +1,206 @@ +// Copyright 2019 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. + +#include 'src/builtins/builtins-bigint-gen.h' + +// TODO(nicohartmann): Discuss whether types used by multiple builtins should be +// in global namespace +@noVerifier +extern class BigIntBase extends HeapObject generates 'TNode<BigInt>' { +} + +type BigInt extends BigIntBase; + +@noVerifier +@hasSameInstanceTypeAsParent +extern class MutableBigInt extends BigIntBase generates 'TNode<BigInt>' { +} + +Convert<BigInt, MutableBigInt>(i: MutableBigInt): BigInt { + assert(bigint::IsCanonicalized(i)); + return %RawDownCast<BigInt>(Convert<BigIntBase>(i)); +} + +namespace bigint { + + 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; + + @export // Silence unused warning. + // TODO(szuend): Remove @export once macros that are only used in + // asserts are no longer detected as unused. + 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(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(kBigIntMixedTypes); + } + label BigIntTooBig { + ThrowRangeError(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 |