aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/bigint.tq
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/bigint.tq')
-rw-r--r--deps/v8/src/builtins/bigint.tq206
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