| /* |
| * Copyright (C) 2017 Caio Lima <ticaiolima@gmail.com> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include "ExceptionHelpers.h" |
| #include "JSObject.h" |
| #include "ParseInt.h" |
| #include <wtf/CagedPtr.h> |
| #include <wtf/text/StringBuilder.h> |
| #include <wtf/text/StringView.h> |
| #include <wtf/text/WTFString.h> |
| |
| namespace JSC { |
| |
| class JSBigInt final : public JSCell { |
| using Base = JSCell; |
| static const unsigned StructureFlags = Base::StructureFlags | OverridesToThis; |
| |
| public: |
| |
| JSBigInt(VM&, Structure*, int length); |
| |
| enum class InitializationType { None, WithZero }; |
| void initialize(InitializationType); |
| |
| static void visitChildren(JSCell*, SlotVisitor&); |
| |
| static size_t estimatedSize(JSCell*); |
| static size_t allocationSize(int length); |
| |
| static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype); |
| |
| static JSBigInt* createZero(VM&); |
| static JSBigInt* createWithLength(VM&, int length); |
| |
| static JSBigInt* createFrom(VM&, int32_t value); |
| static JSBigInt* createFrom(VM&, uint32_t value); |
| static JSBigInt* createFrom(VM&, int64_t value); |
| static JSBigInt* createFrom(VM&, bool value); |
| |
| DECLARE_EXPORT_INFO; |
| |
| void finishCreation(VM&); |
| |
| JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; |
| |
| void setSign(bool sign) { m_sign = sign; } |
| bool sign() const { return m_sign; } |
| |
| void setLength(int length) { m_length = length; } |
| int length() const { return m_length; } |
| |
| static JSBigInt* parseInt(ExecState*, VM&, StringView, uint8_t radix); |
| static JSBigInt* parseInt(ExecState*, StringView); |
| |
| std::optional<uint8_t> singleDigitValueForString(); |
| String toString(ExecState&, int radix); |
| |
| JS_EXPORT_PRIVATE static bool equals(JSBigInt*, JSBigInt*); |
| |
| bool getPrimitiveNumber(ExecState*, double& number, JSValue& result) const; |
| double toNumber(ExecState*) const; |
| |
| JSObject* toObject(ExecState*, JSGlobalObject*) const; |
| |
| private: |
| using Digit = uintptr_t; |
| static constexpr const int bitsPerByte = 8; |
| static constexpr const int digitBits = sizeof(Digit) * bitsPerByte; |
| static constexpr const int halfDigitBits = digitBits / 2; |
| static constexpr const Digit halfDigitMask = (1ull << halfDigitBits) - 1; |
| static constexpr const int maxInt = 0x7FFFFFFF; |
| |
| // The maximum length that the current implementation supports would be |
| // maxInt / digitBits. However, we use a lower limit for now, because |
| // raising it later is easier than lowering it. |
| // Support up to 1 million bits. |
| static const int maxLength = 1024 * 1024 / (sizeof(void*) * bitsPerByte); |
| |
| static uint64_t calculateMaximumCharactersRequired(int length, int radix, Digit lastDigit, bool sign); |
| |
| static void absoluteDivSmall(ExecState&, JSBigInt* x, Digit divisor, JSBigInt** quotient, Digit& remainder); |
| static void internalMultiplyAdd(JSBigInt* source, Digit factor, Digit summand, int, JSBigInt* result); |
| |
| // Digit arithmetic helpers. |
| static Digit digitAdd(Digit a, Digit b, Digit& carry); |
| static Digit digitSub(Digit a, Digit b, Digit& borrow); |
| static Digit digitMul(Digit a, Digit b, Digit& high); |
| static Digit digitDiv(Digit high, Digit low, Digit divisor, Digit& remainder); |
| static Digit digitPow(Digit base, Digit exponent); |
| |
| static String toStringGeneric(ExecState&, JSBigInt*, int radix); |
| |
| bool isZero(); |
| |
| template <typename CharType> |
| static JSBigInt* parseInt(ExecState*, CharType* data, int length); |
| |
| template <typename CharType> |
| static JSBigInt* parseInt(ExecState*, VM&, CharType* data, int length, int startIndex, int radix, bool allowEmptyString = true); |
| |
| static JSBigInt* allocateFor(ExecState*, VM&, int radix, int charcount); |
| |
| JSBigInt* rightTrim(VM&); |
| |
| void inplaceMultiplyAdd(Digit multiplier, Digit part); |
| |
| static size_t offsetOfData(); |
| Digit* dataStorage(); |
| |
| Digit digit(int); |
| void setDigit(int, Digit); |
| |
| int m_length; |
| bool m_sign; |
| }; |
| |
| inline JSBigInt* asBigInt(JSValue value) |
| { |
| ASSERT(value.asCell()->isBigInt()); |
| return jsCast<JSBigInt*>(value.asCell()); |
| } |
| |
| } // namespace JSC |