1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_JS_BIGINT_H 17 #define ECMASCRIPT_JS_BIGINT_H 18 19 #include "ecmascript/ecma_macros.h" 20 #include "ecmascript/js_handle.h" 21 #include "ecmascript/js_thread.h" 22 #include "js_object.h" 23 24 namespace panda::ecmascript { 25 enum class Operate : uint32_t { AND = 0, OR, XOR }; 26 enum class Comparestr : uint32_t { EQUAL = 0, GREATER, LESS }; 27 28 class BigInt : public TaggedObject { 29 public: 30 Comparestr static ComString(std::string &a, std::string &b); 31 static constexpr uint32_t DATEBITS = sizeof(uint32_t) * 8; // 8 : one-bit number of bytes 32 static constexpr uint32_t MAXBITS = 1024 * 1024; // 1024 * 1024 : Maximum space that can be opened up 33 static constexpr uint32_t MAXSIZE = MAXBITS / DATEBITS; // the maximum value of size 34 static constexpr uint32_t MAXOCTALVALUE = 7; // 7 : max octal value 35 static constexpr uint32_t BINARY = 2; // 2 : binary 36 37 static constexpr uint32_t OCTAL = 8; // 8 : octal 38 static constexpr uint32_t DECIMAL = 10; // 10 : decimal 39 static constexpr uint32_t HEXADECIMAL = 16; // 16 : hexadecimal 40 CAST_CHECK(BigInt, IsBigInt); 41 static JSHandle<BigInt> CreateBigint(JSThread *thread, uint32_t size); 42 43 static bool Equal(const JSTaggedValue &x, const JSTaggedValue &y); 44 static bool Equal(const BigInt *x, const BigInt *y); 45 static bool SameValue(const JSTaggedValue &x, const JSTaggedValue &y); 46 static bool SameValueZero(const JSTaggedValue &x, const JSTaggedValue &y); 47 48 static void InitializationZero(JSThread *thread, JSHandle<BigInt> bigint); 49 static JSHandle<BigInt> BitwiseOp(JSThread *thread, Operate op, JSHandle<BigInt> x, JSHandle<BigInt> y); 50 static JSHandle<BigInt> BitwiseAND(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 51 static JSHandle<BigInt> BitwiseXOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 52 static JSHandle<BigInt> BitwiseOR(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 53 static JSHandle<BigInt> BitwiseSubOne(JSThread *thread, JSHandle<BigInt> bigint, uint32_t maxLen); 54 static JSHandle<BigInt> BitwiseAddOne(JSThread *thread, JSHandle<BigInt> bigint); 55 static JSHandle<EcmaString> ToString(JSThread *thread, JSHandle<BigInt> bigint, 56 uint32_t conversionToRadix = BigInt::DECIMAL); 57 static std::string ToStdString(JSThread *thread, JSHandle<BigInt> bigint, 58 uint32_t conversionToRadix = BigInt::DECIMAL); 59 60 static JSHandle<BigInt> UnaryMinus(JSThread *thread, JSHandle<BigInt> x); 61 static JSHandle<BigInt> BitwiseNOT(JSThread *thread, JSHandle<BigInt> x); 62 static JSHandle<BigInt> Exponentiate(JSThread *thread, JSHandle<BigInt> base, JSHandle<BigInt> exponent); 63 static JSHandle<BigInt> Multiply(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 64 static JSHandle<BigInt> Divide(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 65 static JSHandle<BigInt> Remainder(JSThread *thread, JSHandle<BigInt> n, JSHandle<BigInt> d); 66 static JSHandle<BigInt> BigintAddOne(JSThread *thread, JSHandle<BigInt> x); 67 static JSHandle<BigInt> BigintSubOne(JSThread *thread, JSHandle<BigInt> x); 68 static JSHandle<BigInt> copy(JSThread *thread, JSHandle<BigInt> x); 69 70 static JSHandle<BigInt> Add(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 71 static JSHandle<BigInt> Subtract(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 72 static bool LessThan(const JSTaggedValue &x, const JSTaggedValue &y); 73 static bool LessThan(const BigInt *x, const BigInt *y); 74 static ComparisonResult Compare(JSThread *thread, const JSTaggedValue &x, const JSTaggedValue &y); 75 static JSHandle<BigInt> SignedRightShift(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 76 static JSHandle<BigInt> RightShiftHelper(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 77 static JSTaggedValue UnsignedRightShift(JSThread *thread); 78 static JSHandle<BigInt> LeftShift(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 79 static JSHandle<BigInt> LeftShiftHelper(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 80 static JSHandle<BigInt> BigintAdd(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y, bool resultSign); 81 static JSHandle<BigInt> BigintSub(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y, bool resultSign); 82 83 static JSTaggedValue NumberToBigInt(JSThread *thread, JSHandle<JSTaggedValue> number); 84 static JSHandle<BigInt> Int32ToBigInt(JSThread *thread, const int &number); 85 static JSHandle<BigInt> Int64ToBigInt(JSThread *thread, const int64_t &number); 86 static JSHandle<BigInt> Uint64ToBigInt(JSThread *thread, const uint64_t &number); 87 static void BigIntToInt64(JSThread *thread, JSHandle<JSTaggedValue> bigint, int64_t *cValue, bool *lossless); 88 static void BigIntToUint64(JSThread *thread, JSHandle<JSTaggedValue> bigint, uint64_t *cValue, bool *lossless); 89 static JSHandle<BigInt> CreateBigWords(JSThread *thread, bool sign, uint32_t size, const uint64_t* words); 90 static JSHandle<BigInt> FloorMod(JSThread *thread, JSHandle<BigInt> leftVal, JSHandle<BigInt> rightVal); 91 static JSTaggedValue AsUintN(JSThread *thread, JSTaggedNumber &bits, JSHandle<BigInt> bigint); 92 static JSTaggedValue AsintN(JSThread *thread, JSTaggedNumber &bits, JSHandle<BigInt> bigint); 93 static JSTaggedNumber BigIntToNumber(JSThread *thread, JSHandle<BigInt> bigint); 94 static ComparisonResult CompareWithNumber(JSThread *thread, JSHandle<BigInt> bigint, 95 JSHandle<JSTaggedValue> number); IsZero()96 inline bool IsZero() 97 { 98 return GetLength() == 1 && !GetDigit(0); 99 } 100 101 uint32_t GetDigit(uint32_t index) const; 102 static void SetDigit(JSThread* thread, JSHandle<BigInt> bigint, uint32_t index, uint32_t digit); 103 104 uint32_t GetLength() const; 105 106 static constexpr size_t DATA_OFFSET = TaggedObjectSize(); 107 ACCESSORS(Data, DATA_OFFSET, BIT_FIELD_OFFSET); 108 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 109 DEFINE_ALIGN_SIZE(LAST_OFFSET); 110 111 // define BitField 112 static constexpr size_t SIGN_BITS = 1; 113 FIRST_BIT_FIELD(BitField, Sign, bool, SIGN_BITS) 114 115 DECL_VISIT_OBJECT(DATA_OFFSET, BIT_FIELD_OFFSET) 116 DECL_DUMP() 117 }; 118 119 class BigIntHelper { 120 public: 121 static std::string Conversion(const std::string &num, uint32_t conversionToRadix, uint32_t currentRadix); 122 static JSHandle<BigInt> SetBigInt(JSThread *thread, const std::string &numStr, 123 uint32_t currentRadix = BigInt::DECIMAL); 124 static std::string GetBinary(JSHandle<BigInt> bigint); 125 static JSHandle<BigInt> RightTruncate(JSThread *thread, JSHandle<BigInt> x); 126 127 static JSHandle<BigInt> DivideImpl(JSThread *thread, JSHandle<BigInt> x, JSHandle<BigInt> y); 128 static std::string MultiplyImpl(std::string &a, std::string &b); 129 static std::string DeZero(std::string &a); 130 static std::string Minus(std::string &a, std::string &b); 131 static std::string DevStr(std::string &strValue); 132 static std::string Divide(std::string &a, std::string &b); 133 134 static uint32_t AddHelper(uint32_t x, uint32_t y, uint32_t &bigintCarry); 135 static uint32_t SubHelper(uint32_t x, uint32_t y, uint32_t &bigintCarry); 136 }; 137 } // namespace panda::ecmascript 138 #endif // ECMASCRIPT_TAGGED_BIGINT_H