11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include 'src/builtins/builtins-bigint-gen.h' 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cinamespace bigint { 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst kPositiveSign: uint32 = 0; 101cb0ef41Sopenharmony_ciconst kNegativeSign: uint32 = 1; 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::CppAbsoluteAddAndCanonicalize( 131cb0ef41Sopenharmony_ci MutableBigInt, BigIntBase, BigIntBase): void; 141cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::CppAbsoluteSubAndCanonicalize( 151cb0ef41Sopenharmony_ci MutableBigInt, BigIntBase, BigIntBase): void; 161cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::CppAbsoluteCompare( 171cb0ef41Sopenharmony_ci BigIntBase, BigIntBase): int32; 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::ReadBigIntSign(BigIntBase): uint32; 201cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::ReadBigIntLength(BigIntBase): intptr; 211cb0ef41Sopenharmony_ciextern macro BigIntBuiltinsAssembler::WriteBigIntSignAndLength( 221cb0ef41Sopenharmony_ci MutableBigInt, uint32, intptr): void; 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciextern macro CodeStubAssembler::AllocateBigInt(intptr): MutableBigInt; 251cb0ef41Sopenharmony_ciextern macro CodeStubAssembler::StoreBigIntDigit( 261cb0ef41Sopenharmony_ci MutableBigInt, intptr, uintptr): void; 271cb0ef41Sopenharmony_ciextern macro CodeStubAssembler::LoadBigIntDigit(BigIntBase, intptr): uintptr; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cimacro IsCanonicalized(bigint: BigIntBase): bool { 301cb0ef41Sopenharmony_ci const length = ReadBigIntLength(bigint); 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci if (length == 0) { 331cb0ef41Sopenharmony_ci return ReadBigIntSign(bigint) == kPositiveSign; 341cb0ef41Sopenharmony_ci } 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci return LoadBigIntDigit(bigint, length - 1) != 0; 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_cimacro InvertSign(sign: uint32): uint32 { 401cb0ef41Sopenharmony_ci return sign == kPositiveSign ? kNegativeSign : kPositiveSign; 411cb0ef41Sopenharmony_ci} 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cimacro AllocateEmptyBigIntNoThrow(implicit context: Context)( 441cb0ef41Sopenharmony_ci sign: uint32, length: intptr): MutableBigInt labels BigIntTooBig { 451cb0ef41Sopenharmony_ci if (length > kBigIntMaxLength) { 461cb0ef41Sopenharmony_ci goto BigIntTooBig; 471cb0ef41Sopenharmony_ci } 481cb0ef41Sopenharmony_ci const result: MutableBigInt = AllocateBigInt(length); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci WriteBigIntSignAndLength(result, sign, length); 511cb0ef41Sopenharmony_ci return result; 521cb0ef41Sopenharmony_ci} 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cimacro AllocateEmptyBigInt(implicit context: Context)( 551cb0ef41Sopenharmony_ci sign: uint32, length: intptr): MutableBigInt { 561cb0ef41Sopenharmony_ci try { 571cb0ef41Sopenharmony_ci return AllocateEmptyBigIntNoThrow(sign, length) otherwise BigIntTooBig; 581cb0ef41Sopenharmony_ci } label BigIntTooBig { 591cb0ef41Sopenharmony_ci ThrowRangeError(MessageTemplate::kBigIntTooBig); 601cb0ef41Sopenharmony_ci } 611cb0ef41Sopenharmony_ci} 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_cimacro MutableBigIntAbsoluteCompare(x: BigIntBase, y: BigIntBase): int32 { 641cb0ef41Sopenharmony_ci return CppAbsoluteCompare(x, y); 651cb0ef41Sopenharmony_ci} 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_cimacro MutableBigIntAbsoluteSub(implicit context: Context)( 681cb0ef41Sopenharmony_ci x: BigInt, y: BigInt, resultSign: uint32): BigInt { 691cb0ef41Sopenharmony_ci const xlength = ReadBigIntLength(x); 701cb0ef41Sopenharmony_ci const ylength = ReadBigIntLength(y); 711cb0ef41Sopenharmony_ci const xsign = ReadBigIntSign(x); 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci dcheck(MutableBigIntAbsoluteCompare(x, y) >= 0); 741cb0ef41Sopenharmony_ci if (xlength == 0) { 751cb0ef41Sopenharmony_ci dcheck(ylength == 0); 761cb0ef41Sopenharmony_ci return x; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci if (ylength == 0) { 801cb0ef41Sopenharmony_ci return resultSign == xsign ? x : BigIntUnaryMinus(x); 811cb0ef41Sopenharmony_ci } 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci const result = AllocateEmptyBigInt(resultSign, xlength); 841cb0ef41Sopenharmony_ci CppAbsoluteSubAndCanonicalize(result, x, y); 851cb0ef41Sopenharmony_ci return Convert<BigInt>(result); 861cb0ef41Sopenharmony_ci} 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_cimacro MutableBigIntAbsoluteAdd(implicit context: Context)( 891cb0ef41Sopenharmony_ci xBigint: BigInt, yBigint: BigInt, 901cb0ef41Sopenharmony_ci resultSign: uint32): BigInt labels BigIntTooBig { 911cb0ef41Sopenharmony_ci let xlength = ReadBigIntLength(xBigint); 921cb0ef41Sopenharmony_ci let ylength = ReadBigIntLength(yBigint); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci let x = xBigint; 951cb0ef41Sopenharmony_ci let y = yBigint; 961cb0ef41Sopenharmony_ci if (xlength < ylength) { 971cb0ef41Sopenharmony_ci // Swap x and y so that x is longer. 981cb0ef41Sopenharmony_ci x = yBigint; 991cb0ef41Sopenharmony_ci y = xBigint; 1001cb0ef41Sopenharmony_ci const tempLength = xlength; 1011cb0ef41Sopenharmony_ci xlength = ylength; 1021cb0ef41Sopenharmony_ci ylength = tempLength; 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci // case: 0n + 0n 1061cb0ef41Sopenharmony_ci if (xlength == 0) { 1071cb0ef41Sopenharmony_ci dcheck(ylength == 0); 1081cb0ef41Sopenharmony_ci return x; 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci // case: x + 0n 1121cb0ef41Sopenharmony_ci if (ylength == 0) { 1131cb0ef41Sopenharmony_ci return resultSign == ReadBigIntSign(x) ? x : BigIntUnaryMinus(x); 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci // case: x + y 1171cb0ef41Sopenharmony_ci const result = AllocateEmptyBigIntNoThrow(resultSign, xlength + 1) 1181cb0ef41Sopenharmony_ci otherwise BigIntTooBig; 1191cb0ef41Sopenharmony_ci CppAbsoluteAddAndCanonicalize(result, x, y); 1201cb0ef41Sopenharmony_ci return Convert<BigInt>(result); 1211cb0ef41Sopenharmony_ci} 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_cimacro BigIntAddImpl(implicit context: Context)(x: BigInt, y: BigInt): BigInt 1241cb0ef41Sopenharmony_ci labels BigIntTooBig { 1251cb0ef41Sopenharmony_ci const xsign = ReadBigIntSign(x); 1261cb0ef41Sopenharmony_ci const ysign = ReadBigIntSign(y); 1271cb0ef41Sopenharmony_ci if (xsign == ysign) { 1281cb0ef41Sopenharmony_ci // x + y == x + y 1291cb0ef41Sopenharmony_ci // -x + -y == -(x + y) 1301cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci // x + -y == x - y == -(y - x) 1341cb0ef41Sopenharmony_ci // -x + y == y - x == -(x - y) 1351cb0ef41Sopenharmony_ci if (MutableBigIntAbsoluteCompare(x, y) >= 0) { 1361cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteSub(x, y, xsign); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); 1391cb0ef41Sopenharmony_ci} 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_cibuiltin BigIntAddNoThrow(implicit context: Context)( 1421cb0ef41Sopenharmony_ci x: BigInt, y: BigInt): Numeric { 1431cb0ef41Sopenharmony_ci try { 1441cb0ef41Sopenharmony_ci return BigIntAddImpl(x, y) otherwise BigIntTooBig; 1451cb0ef41Sopenharmony_ci } label BigIntTooBig { 1461cb0ef41Sopenharmony_ci // Smi sentinal is used to signal BigIntTooBig exception. 1471cb0ef41Sopenharmony_ci return Convert<Smi>(0); 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci} 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_cibuiltin BigIntAdd(implicit context: Context)( 1521cb0ef41Sopenharmony_ci xNum: Numeric, yNum: Numeric): BigInt { 1531cb0ef41Sopenharmony_ci try { 1541cb0ef41Sopenharmony_ci const x = Cast<BigInt>(xNum) otherwise MixedTypes; 1551cb0ef41Sopenharmony_ci const y = Cast<BigInt>(yNum) otherwise MixedTypes; 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci return BigIntAddImpl(x, y) otherwise BigIntTooBig; 1581cb0ef41Sopenharmony_ci } label MixedTypes { 1591cb0ef41Sopenharmony_ci ThrowTypeError(MessageTemplate::kBigIntMixedTypes); 1601cb0ef41Sopenharmony_ci } label BigIntTooBig { 1611cb0ef41Sopenharmony_ci ThrowRangeError(MessageTemplate::kBigIntTooBig); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_cimacro BigIntSubtractImpl(implicit context: Context)( 1661cb0ef41Sopenharmony_ci x: BigInt, y: BigInt): BigInt labels BigIntTooBig { 1671cb0ef41Sopenharmony_ci const xsign = ReadBigIntSign(x); 1681cb0ef41Sopenharmony_ci const ysign = ReadBigIntSign(y); 1691cb0ef41Sopenharmony_ci if (xsign != ysign) { 1701cb0ef41Sopenharmony_ci // x - (-y) == x + y 1711cb0ef41Sopenharmony_ci // (-x) - y == -(x + y) 1721cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteAdd(x, y, xsign) otherwise BigIntTooBig; 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci // x - y == -(y - x) 1761cb0ef41Sopenharmony_ci // (-x) - (-y) == y - x == -(x - y) 1771cb0ef41Sopenharmony_ci if (MutableBigIntAbsoluteCompare(x, y) >= 0) { 1781cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteSub(x, y, xsign); 1791cb0ef41Sopenharmony_ci } 1801cb0ef41Sopenharmony_ci return MutableBigIntAbsoluteSub(y, x, InvertSign(xsign)); 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_cibuiltin BigIntSubtractNoThrow(implicit context: Context)( 1841cb0ef41Sopenharmony_ci x: BigInt, y: BigInt): Numeric { 1851cb0ef41Sopenharmony_ci try { 1861cb0ef41Sopenharmony_ci return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; 1871cb0ef41Sopenharmony_ci } label BigIntTooBig { 1881cb0ef41Sopenharmony_ci // Smi sentinal is used to signal BigIntTooBig exception. 1891cb0ef41Sopenharmony_ci return Convert<Smi>(0); 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci} 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_cibuiltin BigIntSubtract(implicit context: Context)( 1941cb0ef41Sopenharmony_ci xNum: Numeric, yNum: Numeric): BigInt { 1951cb0ef41Sopenharmony_ci try { 1961cb0ef41Sopenharmony_ci const x = Cast<BigInt>(xNum) otherwise MixedTypes; 1971cb0ef41Sopenharmony_ci const y = Cast<BigInt>(yNum) otherwise MixedTypes; 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci return BigIntSubtractImpl(x, y) otherwise BigIntTooBig; 2001cb0ef41Sopenharmony_ci } label MixedTypes { 2011cb0ef41Sopenharmony_ci ThrowTypeError(MessageTemplate::kBigIntMixedTypes); 2021cb0ef41Sopenharmony_ci } label BigIntTooBig { 2031cb0ef41Sopenharmony_ci ThrowRangeError(MessageTemplate::kBigIntTooBig); 2041cb0ef41Sopenharmony_ci } 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_cibuiltin BigIntUnaryMinus(implicit context: Context)(bigint: BigInt): BigInt { 2081cb0ef41Sopenharmony_ci const length = ReadBigIntLength(bigint); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci // There is no -0n. 2111cb0ef41Sopenharmony_ci if (length == 0) { 2121cb0ef41Sopenharmony_ci return bigint; 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci const result = 2161cb0ef41Sopenharmony_ci AllocateEmptyBigInt(InvertSign(ReadBigIntSign(bigint)), length); 2171cb0ef41Sopenharmony_ci for (let i: intptr = 0; i < length; ++i) { 2181cb0ef41Sopenharmony_ci StoreBigIntDigit(result, i, LoadBigIntDigit(bigint, i)); 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci return Convert<BigInt>(result); 2211cb0ef41Sopenharmony_ci} 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci} // namespace bigint 224