|
Lines 1866-1890
JSValue JSBigInt::parseInt(JSGlobalObjec
Source/JavaScriptCore/runtime/JSBigInt.cpp_sec1
|
| 1866 |
#endif |
1866 |
#endif |
| 1867 |
} |
1867 |
} |
| 1868 |
|
1868 |
|
| 1869 |
// The idea is to pick the largest number such that radix ** lengthLimitForBigInt32 <= INT32_MAX |
|
|
| 1870 |
unsigned lengthLimitForBigInt32; |
1869 |
unsigned lengthLimitForBigInt32; |
|
|
1870 |
#if USE(BIGINT32) |
| 1871 |
static_assert(sizeof(Digit) >= sizeof(uint64_t)); |
| 1872 |
// The idea is to pick the limit such that: |
| 1873 |
// radix ** lengthLimitForBigInt32 >= INT32_MAX |
| 1874 |
// radix ** (lengthLimitForBigInt32 - 1) <= INT32_MAX |
| 1875 |
#if ASSERT_ENABLED |
| 1876 |
auto limitWorks = [&] { |
| 1877 |
double lengthLimit = lengthLimitForBigInt32; |
| 1878 |
double lowerLimit = pow(static_cast<double>(radix), lengthLimit - 1); |
| 1879 |
double upperLimit = pow(static_cast<double>(radix), lengthLimit); |
| 1880 |
double target = std::numeric_limits<int32_t>::max(); |
| 1881 |
return lowerLimit <= target && target <= upperLimit && upperLimit <= std::numeric_limits<int64_t>::max(); |
| 1882 |
}; |
| 1883 |
#endif |
| 1884 |
switch (radix) { |
| 1885 |
case 2: |
| 1886 |
lengthLimitForBigInt32 = 31; |
| 1887 |
ASSERT(limitWorks()); |
| 1888 |
break; |
| 1889 |
case 8: |
| 1890 |
lengthLimitForBigInt32 = 11; |
| 1891 |
ASSERT(limitWorks()); |
| 1892 |
break; |
| 1893 |
case 10: |
| 1894 |
lengthLimitForBigInt32 = 10; |
| 1895 |
ASSERT(limitWorks()); |
| 1896 |
break; |
| 1897 |
case 16: |
| 1898 |
lengthLimitForBigInt32 = 8; |
| 1899 |
ASSERT(limitWorks()); |
| 1900 |
break; |
| 1901 |
default: |
| 1902 |
lengthLimitForBigInt32 = 1; |
| 1903 |
break; |
| 1904 |
} |
| 1905 |
#else |
| 1906 |
// The idea is to pick the largest limit such that: |
| 1907 |
// radix ** lengthLimitForBigInt32 <= INT32_MAX |
| 1908 |
#if ASSERT_ENABLED |
| 1909 |
auto limitWorks = [&] { |
| 1910 |
double lengthLimit = lengthLimitForBigInt32; |
| 1911 |
double valueLimit = pow(static_cast<double>(radix), lengthLimit); |
| 1912 |
double overValueLimit = pow(static_cast<double>(radix), lengthLimit + 1); |
| 1913 |
double target = std::numeric_limits<int32_t>::max(); |
| 1914 |
return valueLimit <= target && target < overValueLimit; |
| 1915 |
}; |
| 1916 |
#endif |
| 1871 |
switch (radix) { |
1917 |
switch (radix) { |
| 1872 |
case 2: |
1918 |
case 2: |
| 1873 |
lengthLimitForBigInt32 = 30; |
1919 |
lengthLimitForBigInt32 = 30; |
|
|
1920 |
ASSERT(limitWorks()); |
| 1874 |
break; |
1921 |
break; |
| 1875 |
case 8: |
1922 |
case 8: |
| 1876 |
lengthLimitForBigInt32 = 10; |
1923 |
lengthLimitForBigInt32 = 10; |
|
|
1924 |
ASSERT(limitWorks()); |
| 1877 |
break; |
1925 |
break; |
| 1878 |
case 10: |
1926 |
case 10: |
| 1879 |
lengthLimitForBigInt32 = 9; |
1927 |
lengthLimitForBigInt32 = 9; |
|
|
1928 |
ASSERT(limitWorks()); |
| 1880 |
break; |
1929 |
break; |
| 1881 |
case 16: |
1930 |
case 16: |
| 1882 |
lengthLimitForBigInt32 = 7; |
1931 |
lengthLimitForBigInt32 = 7; |
|
|
1932 |
ASSERT(limitWorks()); |
| 1883 |
break; |
1933 |
break; |
| 1884 |
default: |
1934 |
default: |
| 1885 |
lengthLimitForBigInt32 = 1; |
1935 |
lengthLimitForBigInt32 = 1; |
| 1886 |
break; |
1936 |
break; |
| 1887 |
} |
1937 |
} |
|
|
1938 |
#endif // USE(BIGINT32) |
| 1888 |
|
1939 |
|
| 1889 |
JSBigInt* heapResult = nullptr; |
1940 |
JSBigInt* heapResult = nullptr; |
| 1890 |
|
1941 |
|
|
Lines 1893-1909
JSValue JSBigInt::parseInt(JSGlobalObjec
Source/JavaScriptCore/runtime/JSBigInt.cpp_sec2
|
| 1893 |
unsigned limitA = 'A' + (static_cast<int32_t>(radix) - 10); |
1944 |
unsigned limitA = 'A' + (static_cast<int32_t>(radix) - 10); |
| 1894 |
unsigned initialLength = length - p; |
1945 |
unsigned initialLength = length - p; |
| 1895 |
while (p < length) { |
1946 |
while (p < length) { |
| 1896 |
int32_t digit = 0; |
1947 |
Checked<uint64_t, CrashOnOverflow> digit = 0; |
| 1897 |
Checked<int32_t, CrashOnOverflow> multiplier = 1; |
1948 |
Checked<uint64_t, CrashOnOverflow> multiplier = 1; |
| 1898 |
for (unsigned i = 0; i < lengthLimitForBigInt32 && p < length ; ++i, ++p) { |
1949 |
for (unsigned i = 0; i < lengthLimitForBigInt32 && p < length; ++i, ++p) { |
| 1899 |
digit *= radix; |
1950 |
digit *= radix; |
| 1900 |
multiplier *= radix; |
1951 |
multiplier *= radix; |
| 1901 |
if (data[p] >= '0' && data[p] < limit0) |
1952 |
if (data[p] >= '0' && data[p] < limit0) |
| 1902 |
digit += data[p] - '0'; |
1953 |
digit += static_cast<uint64_t>(data[p] - '0'); |
| 1903 |
else if (data[p] >= 'a' && data[p] < limita) |
1954 |
else if (data[p] >= 'a' && data[p] < limita) |
| 1904 |
digit += data[p] - 'a' + 10; |
1955 |
digit += static_cast<uint64_t>(data[p] - 'a' + 10); |
| 1905 |
else if (data[p] >= 'A' && data[p] < limitA) |
1956 |
else if (data[p] >= 'A' && data[p] < limitA) |
| 1906 |
digit += data[p] - 'A' + 10; |
1957 |
digit += static_cast<uint64_t>(data[p] - 'A' + 10); |
| 1907 |
else { |
1958 |
else { |
| 1908 |
if (errorParseMode == ErrorParseMode::ThrowExceptions) { |
1959 |
if (errorParseMode == ErrorParseMode::ThrowExceptions) { |
| 1909 |
ASSERT(globalObject); |
1960 |
ASSERT(globalObject); |
|
Lines 1912-1928
JSValue JSBigInt::parseInt(JSGlobalObjec
Source/JavaScriptCore/runtime/JSBigInt.cpp_sec3
|
| 1912 |
return JSValue(); |
1963 |
return JSValue(); |
| 1913 |
} |
1964 |
} |
| 1914 |
} |
1965 |
} |
| 1915 |
ASSERT(digit < multiplier.unsafeGet()); |
|
|
| 1916 |
|
1966 |
|
| 1917 |
if (!heapResult) { |
1967 |
if (!heapResult) { |
| 1918 |
if (p == length) { |
1968 |
if (p == length) { |
|
|
1969 |
ASSERT(digit.unsafeGet() <= std::numeric_limits<int64_t>::max()); |
| 1970 |
int64_t maybeResult = digit.unsafeGet(); |
| 1971 |
ASSERT(maybeResult >= 0); |
| 1919 |
if (sign == ParseIntSign::Signed) |
1972 |
if (sign == ParseIntSign::Signed) |
| 1920 |
digit *= -1; |
1973 |
maybeResult *= -1; |
|
|
1974 |
|
| 1975 |
if (static_cast<int64_t>(static_cast<int32_t>(maybeResult)) == maybeResult) { |
| 1921 |
#if USE(BIGINT32) |
1976 |
#if USE(BIGINT32) |
| 1922 |
return JSValue(JSValue::JSBigInt32, digit); |
1977 |
return JSValue(JSValue::JSBigInt32, static_cast<int32_t>(maybeResult)); |
| 1923 |
#else |
1978 |
#else |
| 1924 |
return createFrom(vm, static_cast<int64_t>(digit)); |
1979 |
return JSBigInt::createFrom(vm, static_cast<int32_t>(maybeResult)); |
| 1925 |
#endif |
1980 |
#endif |
|
|
1981 |
} |
| 1926 |
} |
1982 |
} |
| 1927 |
heapResult = allocateFor(globalObject, vm, radix, initialLength); |
1983 |
heapResult = allocateFor(globalObject, vm, radix, initialLength); |
| 1928 |
RETURN_IF_EXCEPTION(scope, JSValue()); |
1984 |
RETURN_IF_EXCEPTION(scope, JSValue()); |
|
Lines 1931-1937
JSValue JSBigInt::parseInt(JSGlobalObjec
Source/JavaScriptCore/runtime/JSBigInt.cpp_sec4
|
| 1931 |
return JSValue(); |
1987 |
return JSValue(); |
| 1932 |
heapResult->initialize(InitializationType::WithZero); |
1988 |
heapResult->initialize(InitializationType::WithZero); |
| 1933 |
} |
1989 |
} |
| 1934 |
heapResult->inplaceMultiplyAdd(static_cast<Digit>(multiplier.unsafeGet()), static_cast<Digit>(digit)); |
1990 |
|
|
|
1991 |
ASSERT(static_cast<uint64_t>(static_cast<Digit>(multiplier.unsafeGet())) == multiplier.unsafeGet()); |
| 1992 |
ASSERT(static_cast<uint64_t>(static_cast<Digit>(digit.unsafeGet())) == digit.unsafeGet()); |
| 1993 |
heapResult->inplaceMultiplyAdd(static_cast<Digit>(multiplier.unsafeGet()), static_cast<Digit>(digit.unsafeGet())); |
| 1935 |
} |
1994 |
} |
| 1936 |
|
1995 |
|
| 1937 |
heapResult->setSign(sign == ParseIntSign::Signed); |
1996 |
heapResult->setSign(sign == ParseIntSign::Signed); |