Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

14
deps/v8/src/numbers/DIR_METADATA vendored Normal file
View File

@ -0,0 +1,14 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Blink>JavaScript>Runtime"
}
buganizer_public: {
component_id: 1456800
}

4
deps/v8/src/numbers/OWNERS vendored Normal file
View File

@ -0,0 +1,4 @@
clemensb@chromium.org
jgruber@chromium.org
jkummerow@chromium.org
verwaest@chromium.org

343
deps/v8/src/numbers/conversions-inl.h vendored Normal file
View File

@ -0,0 +1,343 @@
// Copyright 2011 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.
#ifndef V8_NUMBERS_CONVERSIONS_INL_H_
#define V8_NUMBERS_CONVERSIONS_INL_H_
#include "src/numbers/conversions.h"
// Include the non-inl header before the rest of the headers.
#include <float.h> // Required for DBL_MAX and on Win32 for finite()
#include <limits.h> // Required for INT_MAX etc.
#include <stdarg.h>
#include <cmath>
#include "src/common/globals.h" // Required for V8_INFINITY
// ----------------------------------------------------------------------------
// Extra POSIX/ANSI functions for Win32/MSVC.
#include "src/base/bits.h"
#include "src/base/numbers/double.h"
#include "src/base/platform/platform.h"
#include "src/objects/heap-number-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/smi-inl.h"
namespace v8 {
namespace internal {
// The fast double-to-unsigned-int conversion routine does not guarantee
// rounding towards zero, or any reasonable value if the argument is larger
// than what fits in an unsigned 32-bit integer.
inline unsigned int FastD2UI(double x) {
// There is no unsigned version of lrint, so there is no fast path
// in this function as there is in FastD2I. Using lrint doesn't work
// for values of 2^31 and above.
// Convert "small enough" doubles to uint32_t by fixing the 32
// least significant non-fractional bits in the low 32 bits of the
// double, and reading them from there.
const double k2Pow52 = 4503599627370496.0;
bool negative = x < 0;
if (negative) {
x = -x;
}
if (x < k2Pow52) {
x += k2Pow52;
uint32_t result;
#ifndef V8_TARGET_BIG_ENDIAN
void* mantissa_ptr = reinterpret_cast<void*>(&x);
#else
void* mantissa_ptr =
reinterpret_cast<void*>(reinterpret_cast<Address>(&x) + kInt32Size);
#endif
// Copy least significant 32 bits of mantissa.
memcpy(&result, mantissa_ptr, sizeof(result));
return negative ? ~result + 1 : result;
}
// Large number (outside uint32 range), Infinity or NaN.
return 0x80000000u; // Return integer indefinite.
}
// Adopted from https://gist.github.com/rygorous/2156668
inline uint16_t DoubleToFloat16(double value) {
uint64_t in = base::bit_cast<uint64_t>(value);
uint16_t out = 0;
// Take the absolute value of the input.
uint64_t sign = in & kFP64SignMask;
in ^= sign;
if (in >= kFP16InfinityAndNaNInfimum) {
// Result is infinity or NaN.
out = (in > kFP64Infinity) ? kFP16qNaN // NaN->qNaN
: kFP16Infinity; // Inf->Inf
} else {
// Result is a (de)normalized number or zero.
if (in < kFP16DenormalThreshold) {
// Result is a denormal or zero. Use the magic value and FP addition to
// align 10 mantissa bits at the bottom of the float. Depends on FP
// addition being round-to-nearest-even.
double temp = base::bit_cast<double>(in) +
base::bit_cast<double>(kFP64To16DenormalMagic);
out = base::bit_cast<uint64_t>(temp) - kFP64To16DenormalMagic;
} else {
// Result is not a denormal.
// Remember if the result mantissa will be odd before rounding.
uint64_t mant_odd = (in >> (kFP64MantissaBits - kFP16MantissaBits)) & 1;
// Update the exponent and round to nearest even.
//
// Rounding to nearest even is handled in two parts. First, adding
// kFP64To16RebiasExponentAndRound has the effect of rebiasing the
// exponent and that if any of the lower 41 bits of the mantissa are set,
// the 11th mantissa bit from the front becomes set. Second, adding
// mant_odd ensures ties are rounded to even.
in += kFP64To16RebiasExponentAndRound;
in += mant_odd;
out = in >> (kFP64MantissaBits - kFP16MantissaBits);
}
}
out |= sign >> 48;
return out;
}
inline float DoubleToFloat32(double x) {
using limits = std::numeric_limits<float>;
if (x > limits::max()) {
// kRoundingThreshold is the maximum double that rounds down to
// the maximum representable float. Its mantissa bits are:
// 1111111111111111111111101111111111111111111111111111
// [<--- float range --->]
// Note the zero-bit right after the float mantissa range, which
// determines the rounding-down.
static const double kRoundingThreshold = 3.4028235677973362e+38;
if (x <= kRoundingThreshold) return limits::max();
return limits::infinity();
}
if (x < limits::lowest()) {
// Same as above, mirrored to negative numbers.
static const double kRoundingThreshold = -3.4028235677973362e+38;
if (x >= kRoundingThreshold) return limits::lowest();
return -limits::infinity();
}
return static_cast<float>(x);
}
// #sec-tointegerorinfinity
inline double DoubleToInteger(double x) {
// ToIntegerOrInfinity normalizes -0 to +0. Special case 0 for performance.
if (std::isnan(x) || x == 0.0) return 0;
if (!std::isfinite(x)) return x;
// Add 0.0 in the truncation case to ensure this doesn't return -0.
return ((x > 0) ? std::floor(x) : std::ceil(x)) + 0.0;
}
// Implements most of https://tc39.github.io/ecma262/#sec-toint32.
int32_t DoubleToInt32(double x) {
if ((std::isfinite(x)) && (x <= INT_MAX) && (x >= INT_MIN)) {
// All doubles within these limits are trivially convertable to an int.
return static_cast<int32_t>(x);
}
base::Double d(x);
int exponent = d.Exponent();
uint64_t bits;
if (exponent < 0) {
if (exponent <= -base::Double::kSignificandSize) return 0;
bits = d.Significand() >> -exponent;
} else {
if (exponent > 31) return 0;
// Masking to a 32-bit value ensures that the result of the
// static_cast<int64_t> below is not the minimal int64_t value,
// which would overflow on multiplication with d.Sign().
bits = (d.Significand() << exponent) & 0xFFFFFFFFul;
}
return static_cast<int32_t>(d.Sign() * static_cast<int64_t>(bits));
}
// Implements https://heycam.github.io/webidl/#abstract-opdef-converttoint for
// the general case (step 1 and steps 8 to 12). Support for Clamp and
// EnforceRange will come in the future.
inline int64_t DoubleToWebIDLInt64(double x) {
if ((std::isfinite(x)) && (x <= kMaxSafeInteger) && (x >= kMinSafeInteger)) {
// All doubles within these limits are trivially convertable to an int.
return static_cast<int64_t>(x);
}
base::Double d(x);
int exponent = d.Exponent();
uint64_t bits;
if (exponent < 0) {
if (exponent <= -base::Double::kSignificandSize) return 0;
bits = d.Significand() >> -exponent;
} else {
if (exponent > 63) return 0;
bits = (d.Significand() << exponent);
int64_t bits_int64 = static_cast<int64_t>(bits);
if (bits_int64 == std::numeric_limits<int64_t>::min()) {
return bits_int64;
}
}
return static_cast<int64_t>(d.Sign() * static_cast<int64_t>(bits));
}
inline uint64_t DoubleToWebIDLUint64(double x) {
return static_cast<uint64_t>(DoubleToWebIDLInt64(x));
}
bool DoubleToSmiInteger(double value, int* smi_int_value) {
if (!IsSmiDouble(value)) return false;
*smi_int_value = FastD2I(value);
DCHECK(Smi::IsValid(*smi_int_value));
return true;
}
bool IsSmiDouble(double value) {
return value >= Smi::kMinValue && value <= Smi::kMaxValue &&
!IsMinusZero(value) && value == FastI2D(FastD2I(value));
}
bool IsInt32Double(double value) {
return value >= kMinInt && value <= kMaxInt && !IsMinusZero(value) &&
value == FastI2D(FastD2I(value));
}
bool IsUint32Double(double value) {
return !IsMinusZero(value) && value >= 0 && value <= kMaxUInt32 &&
value == FastUI2D(FastD2UI(value));
}
bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value) {
const double k2Pow52 = 4503599627370496.0;
const uint32_t kValidTopBits = 0x43300000;
const uint64_t kBottomBitMask = 0x0000'0000'FFFF'FFFF;
// Add 2^52 to the double, to place valid uint32 values in the low-significant
// bits of the exponent, by effectively setting the (implicit) top bit of the
// significand. Note that this addition also normalises 0.0 and -0.0.
double shifted_value = value + k2Pow52;
// At this point, a valid uint32 valued double will be represented as:
//
// sign = 0
// exponent = 52
// significand = 1. 00...00 <value>
// implicit^ ^^^^^^^ 32 bits
// ^^^^^^^^^^^^^^^ 52 bits
//
// Therefore, we can first check the top 32 bits to make sure that the sign,
// exponent and remaining significand bits are valid, and only then check the
// value in the bottom 32 bits.
uint64_t result = base::bit_cast<uint64_t>(shifted_value);
if ((result >> 32) == kValidTopBits) {
*uint32_value = result & kBottomBitMask;
return FastUI2D(result & kBottomBitMask) == value;
}
return false;
}
int32_t NumberToInt32(Tagged<Object> number) {
if (IsSmi(number)) return Smi::ToInt(number);
return DoubleToInt32(Cast<HeapNumber>(number)->value());
}
uint32_t NumberToUint32(Tagged<Object> number) {
if (IsSmi(number)) return Smi::ToInt(number);
return DoubleToUint32(Cast<HeapNumber>(number)->value());
}
uint32_t PositiveNumberToUint32(Tagged<Object> number) {
if (IsSmi(number)) {
int value = Smi::ToInt(number);
if (value <= 0) return 0;
return value;
}
double value = Cast<HeapNumber>(number)->value();
// Catch all values smaller than 1 and use the double-negation trick for NANs.
if (!(value >= 1)) return 0;
uint32_t max = std::numeric_limits<uint32_t>::max();
if (value < max) return static_cast<uint32_t>(value);
return max;
}
int64_t NumberToInt64(Tagged<Object> number) {
if (IsSmi(number)) return Smi::ToInt(number);
double d = Cast<HeapNumber>(number)->value();
if (std::isnan(d)) return 0;
if (d >= static_cast<double>(std::numeric_limits<int64_t>::max())) {
return std::numeric_limits<int64_t>::max();
}
if (d <= static_cast<double>(std::numeric_limits<int64_t>::min())) {
return std::numeric_limits<int64_t>::min();
}
return static_cast<int64_t>(d);
}
uint64_t PositiveNumberToUint64(Tagged<Object> number) {
if (IsSmi(number)) {
int value = Smi::ToInt(number);
if (value <= 0) return 0;
return value;
}
double value = Cast<HeapNumber>(number)->value();
// Catch all values smaller than 1 and use the double-negation trick for NANs.
if (!(value >= 1)) return 0;
uint64_t max = std::numeric_limits<uint64_t>::max();
if (value < max) return static_cast<uint64_t>(value);
return max;
}
bool TryNumberToSize(Tagged<Object> number, size_t* result) {
// Do not create handles in this function! Don't use SealHandleScope because
// the function can be used concurrently.
if (IsSmi(number)) {
int value = Smi::ToInt(number);
DCHECK(static_cast<unsigned>(Smi::kMaxValue) <=
std::numeric_limits<size_t>::max());
if (value >= 0) {
*result = static_cast<size_t>(value);
return true;
}
return false;
} else {
double value = Cast<HeapNumber>(number)->value();
// If value is compared directly to the limit, the limit will be
// casted to a double and could end up as limit + 1,
// because a double might not have enough mantissa bits for it.
// So we might as well cast the limit first, and use < instead of <=.
double maxSize = static_cast<double>(std::numeric_limits<size_t>::max());
if (value >= 0 && value < maxSize) {
size_t size = static_cast<size_t>(value);
#ifdef V8_ENABLE_SANDBOX
if (size > kMaxSafeBufferSizeForSandbox) {
return false;
}
#endif
*result = size;
return true;
} else {
return false;
}
}
}
size_t NumberToSize(Tagged<Object> number) {
size_t result = 0;
bool is_valid = TryNumberToSize(number, &result);
CHECK(is_valid);
return result;
}
uint32_t DoubleToUint32(double x) {
return static_cast<uint32_t>(DoubleToInt32(x));
}
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_CONVERSIONS_INL_H_

1458
deps/v8/src/numbers/conversions.cc vendored Normal file

File diff suppressed because it is too large Load Diff

288
deps/v8/src/numbers/conversions.h vendored Normal file
View File

@ -0,0 +1,288 @@
// Copyright 2011 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.
#ifndef V8_NUMBERS_CONVERSIONS_H_
#define V8_NUMBERS_CONVERSIONS_H_
#include <optional>
#include <string_view>
#include "src/base/export-template.h"
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/base/strings.h"
#include "src/base/vector.h"
#include "src/common/globals.h"
namespace v8 {
namespace internal {
class BigInt;
class SharedStringAccessGuardIfNeeded;
// uint64_t constants prefixed with kFP64 are bit patterns of doubles.
// uint64_t constants prefixed with kFP16 are bit patterns of doubles encoding
// limits of half-precision floating point values.
constexpr int kFP64ExponentBits = 11;
constexpr int kFP64MantissaBits = 52;
constexpr uint64_t kFP64ExponentBias = 1023;
constexpr uint64_t kFP64SignMask = uint64_t{1}
<< (kFP64ExponentBits + kFP64MantissaBits);
constexpr uint64_t kFP64Infinity = uint64_t{2047} << kFP64MantissaBits;
constexpr uint64_t kFP16InfinityAndNaNInfimum = (kFP64ExponentBias + 16)
<< kFP64MantissaBits;
constexpr uint64_t kFP16MinExponent = kFP64ExponentBias - 14;
constexpr uint64_t kFP16DenormalThreshold = kFP16MinExponent
<< kFP64MantissaBits;
constexpr int kFP16MantissaBits = 10;
constexpr uint16_t kFP16qNaN = 0x7e00;
constexpr uint16_t kFP16Infinity = 0x7c00;
// A value that, when added, has the effect that if any of the lower 41 bits of
// the mantissa are set, the 11th mantissa bit from the front becomes set. Used
// for rounding when converting from double to half-precision.
constexpr uint64_t kFP64To16RoundingAddend =
(uint64_t{1} << ((kFP64MantissaBits - kFP16MantissaBits) - 1)) - 1;
// A value that, when added, rebiases the exponent of a double to the range of
// the half precision and performs rounding as described above in
// kFP64To16RoundingAddend. Note that 15-kFP64ExponentBias overflows into the
// sign bit, but that bit is implicitly cut off when assigning the 64-bit double
// to a 16-bit output.
constexpr uint64_t kFP64To16RebiasExponentAndRound =
((uint64_t{15} - kFP64ExponentBias) << kFP64MantissaBits) +
kFP64To16RoundingAddend;
// A magic value that aligns 10 mantissa bits at the bottom of the double when
// added to a double using floating point addition. Depends on floating point
// addition being round-to-nearest-even.
constexpr uint64_t kFP64To16DenormalMagic =
(kFP16MinExponent + (kFP64MantissaBits - kFP16MantissaBits))
<< kFP64MantissaBits;
constexpr uint32_t kFP32WithoutSignMask = 0x7fffffff;
constexpr uint32_t kFP32MinFP16ZeroRepresentable = 0x33000000;
constexpr uint32_t kFP32MaxFP16Representable = 0x47800000;
constexpr uint32_t kFP32SubnormalThresholdOfFP16 = 0x38800000;
// The limit for the the fractionDigits/precision for toFixed, toPrecision
// and toExponential.
constexpr int kMaxFractionDigits = 100;
constexpr int kDoubleToFixedMaxDigitsBeforePoint = 21;
// Leave room in the result for appending a minus and a period.
constexpr int kDoubleToFixedMaxChars =
kDoubleToFixedMaxDigitsBeforePoint + kMaxFractionDigits + 2;
// Leave room in the result for appending a minus, for a period, up to 5 zeros
// padding after the period and a zero in front of the period.
constexpr int kDoubleToPrecisionMaxChars = kMaxFractionDigits + 8;
// Leave room in the result for one digit before the period, a minus, a period,
// the letter 'e', a minus or a plus depending on the exponent, and a three
// digit exponent.
constexpr int kDoubleToExponentialMaxChars = kMaxFractionDigits + 8;
// The algorithm starts with the decimal point in the middle and writes to the
// left for the integer part and to the right for the fractional part.
// 1024 characters for the exponent and 52 for the mantissa either way, with
// additional space for sign and decimal point.
constexpr int kDoubleToRadixMaxChars = 2200;
// The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero.
// If x is NaN, the result is INT_MIN. Otherwise the result is the argument x,
// clamped to [INT_MIN, INT_MAX] and then rounded to an integer.
inline int FastD2IChecked(double x) {
if (!(x >= INT_MIN)) return INT_MIN; // Negation to catch NaNs.
if (x > INT_MAX) return INT_MAX;
return static_cast<int>(x);
}
// The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero.
// The result is undefined if x is infinite or NaN, or if the rounded
// integer value is outside the range of type int.
inline int FastD2I(double x) {
DCHECK(x <= INT_MAX);
DCHECK(x >= INT_MIN);
return static_cast<int32_t>(x);
}
inline unsigned int FastD2UI(double x);
inline double FastI2D(int x) {
// There is no rounding involved in converting an integer to a
// double, so this code should compile to a few instructions without
// any FPU pipeline stalls.
return static_cast<double>(x);
}
inline double FastUI2D(unsigned x) {
// There is no rounding involved in converting an unsigned integer to a
// double, so this code should compile to a few instructions without
// any FPU pipeline stalls.
return static_cast<double>(x);
}
// This function should match the exact semantics of ECMA-262 20.2.2.17.
inline float DoubleToFloat32(double x);
V8_EXPORT_PRIVATE float DoubleToFloat32_NoInline(double x);
// This function should match the exact semantics of truncating x to
// IEEE 754-2019 binary16 format using roundTiesToEven mode.
inline uint16_t DoubleToFloat16(double x);
// This function should match the exact semantics of ECMA-262 9.4.
inline double DoubleToInteger(double x);
// This function should match the exact semantics of ECMA-262 9.5.
inline int32_t DoubleToInt32(double x);
V8_EXPORT_PRIVATE int32_t DoubleToInt32_NoInline(double x);
// This function should match the exact semantics of ECMA-262 9.6.
inline uint32_t DoubleToUint32(double x);
// These functions have similar semantics as the ones above, but are
// added for 64-bit integer types.
inline int64_t DoubleToInt64(double x);
inline uint64_t DoubleToUint64(double x);
// Enumeration for allowing radix prefixes or ignoring junk when converting
// strings to numbers. We never need to be able to allow both.
enum ConversionFlag {
NO_CONVERSION_FLAG,
ALLOW_NON_DECIMAL_PREFIX,
ALLOW_TRAILING_JUNK
};
// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(base::Vector<const uint8_t> str, ConversionFlag flag,
double empty_string_val = 0);
double StringToDouble(base::Vector<const base::uc16> str, ConversionFlag flag,
double empty_string_val = 0);
// This version expects a zero-terminated character array.
double V8_EXPORT_PRIVATE StringToDouble(const char* str, ConversionFlag flag,
double empty_string_val = 0);
// Converts a binary string (of the form `0b[0-1]*`) into a double value
// according to https://tc39.es/ecma262/#sec-numericvalue
double V8_EXPORT_PRIVATE BinaryStringToDouble(base::Vector<const uint8_t> str);
// Converts an octal string (of the form `0o[0-8]*`) into a double value
// according to https://tc39.es/ecma262/#sec-numericvalue
double V8_EXPORT_PRIVATE OctalStringToDouble(base::Vector<const uint8_t> str);
// Converts a hex string (of the form `0x[0-9a-f]*`) into a double value
// according to https://tc39.es/ecma262/#sec-numericvalue
double V8_EXPORT_PRIVATE HexStringToDouble(base::Vector<const uint8_t> str);
// Converts an implicit octal string (a.k.a. LegacyOctalIntegerLiteral, of the
// form `0[0-7]*`) into a double value according to
// https://tc39.es/ecma262/#sec-numericvalue
double V8_EXPORT_PRIVATE
ImplicitOctalStringToDouble(base::Vector<const uint8_t> str);
double StringToInt(Isolate* isolate, DirectHandle<String> string, int radix);
// This follows https://tc39.github.io/proposal-bigint/#sec-string-to-bigint
// semantics: "" => 0n.
MaybeHandle<BigInt> StringToBigInt(Isolate* isolate,
DirectHandle<String> string);
// This version expects a zero-terminated character array. Radix will
// be inferred from string prefix (case-insensitive):
// 0x -> hex
// 0o -> octal
// 0b -> binary
template <typename IsolateT>
EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE)
MaybeHandle<BigInt> BigIntLiteral(IsolateT* isolate, const char* string);
constexpr int kDoubleToStringMinBufferSize = 100;
// Converts a double to a string value according to ECMA-262 9.8.1.
// The buffer should be large enough for any floating point number.
// 100 characters is enough.
// Note: The returned string_view is not necessarily pointing inside the
// provided buffer.
V8_EXPORT_PRIVATE std::string_view DoubleToStringView(
double value, base::Vector<char> buffer);
V8_EXPORT_PRIVATE std::unique_ptr<char[]> BigIntLiteralToDecimal(
LocalIsolate* isolate, base::Vector<const uint8_t> literal);
// Convert an int to string value. The returned string is located inside the
// buffer, but not necessarily at the start.
V8_EXPORT_PRIVATE std::string_view IntToStringView(int n,
base::Vector<char> buffer);
// Additional number to string conversions for the number type.
std::string_view DoubleToFixedStringView(double value, int f,
base::Vector<char> buffer);
std::string_view DoubleToExponentialStringView(double value, int f,
base::Vector<char> buffer);
std::string_view DoubleToPrecisionStringView(double value, int f,
base::Vector<char> buffer);
std::string_view DoubleToRadixStringView(double value, int radix,
base::Vector<char> buffer);
static inline bool IsMinusZero(double value) {
return base::bit_cast<int64_t>(value) == base::bit_cast<int64_t>(-0.0);
}
// Returns true if value can be converted to a SMI, and returns the resulting
// integer value of the SMI in |smi_int_value|.
inline bool DoubleToSmiInteger(double value, int* smi_int_value);
inline bool IsSmiDouble(double value);
// Integer32 is an integer that can be represented as a signed 32-bit
// integer. It has to be in the range [-2^31, 2^31 - 1].
// We also have to check for negative 0 as it is not an Integer32.
inline bool IsInt32Double(double value);
// UInteger32 is an integer that can be represented as an unsigned 32-bit
// integer. It has to be in the range [0, 2^32 - 1].
// We also have to check for negative 0 as it is not a UInteger32.
inline bool IsUint32Double(double value);
// Tries to convert |value| to a uint32, setting the result in |uint32_value|.
// If the output does not compare equal to the input, returns false and the
// value in |uint32_value| is left unspecified.
// Used for conversions such as in ECMA-262 15.4.2.2, which check "ToUint32(len)
// is equal to len".
inline bool DoubleToUint32IfEqualToSelf(double value, uint32_t* uint32_value);
// Convert from Number object to C integer.
inline uint32_t PositiveNumberToUint32(Tagged<Object> number);
inline int32_t NumberToInt32(Tagged<Object> number);
inline uint32_t NumberToUint32(Tagged<Object> number);
inline int64_t NumberToInt64(Tagged<Object> number);
inline uint64_t PositiveNumberToUint64(Tagged<Object> number);
double StringToDouble(Isolate* isolate, DirectHandle<String> string,
ConversionFlag flags, double empty_string_val = 0.0);
double FlatStringToDouble(Tagged<String> string, ConversionFlag flags,
double empty_string_val);
// String to double helper without heap allocation.
// Returns std::nullopt if the string is longer than
// {max_length_for_conversion}. 23 was chosen because any representable double
// can be represented using a string of length 23.
V8_EXPORT_PRIVATE std::optional<double> TryStringToDouble(
LocalIsolate* isolate, DirectHandle<String> object,
uint32_t max_length_for_conversion = 23);
// Return std::nullopt if the string is longer than 20.
V8_EXPORT_PRIVATE std::optional<double> TryStringToInt(
LocalIsolate* isolate, DirectHandle<String> object, int radix);
inline bool TryNumberToSize(Tagged<Object> number, size_t* result);
// Converts a number into size_t.
inline size_t NumberToSize(Tagged<Object> number);
// returns DoubleToString(StringToDouble(string)) == string
V8_EXPORT_PRIVATE bool IsSpecialIndex(
Tagged<String> string, SharedStringAccessGuardIfNeeded& access_guard);
V8_EXPORT_PRIVATE bool IsSpecialIndex(Tagged<String> string);
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_CONVERSIONS_H_

54
deps/v8/src/numbers/hash-seed-inl.h vendored Normal file
View File

@ -0,0 +1,54 @@
// 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.
#ifndef V8_NUMBERS_HASH_SEED_INL_H_
#define V8_NUMBERS_HASH_SEED_INL_H_
#include <stdint.h>
// The #includes below currently lead to cyclic transitive includes, so
// HashSeed() ends up being required before it is defined, so we have to
// declare it here. This is a workaround; if we needed this permanently then
// we should put that line into a "hash-seed.h" header; but we won't need
// it for long.
// TODO(jkummerow): Get rid of this by breaking circular include dependencies.
namespace v8 {
namespace internal {
class Isolate;
class LocalIsolate;
class ReadOnlyRoots;
inline uint64_t HashSeed(Isolate* isolate);
inline uint64_t HashSeed(LocalIsolate* isolate);
inline uint64_t HashSeed(ReadOnlyRoots roots);
} // namespace internal
} // namespace v8
// See comment above for why this isn't at the top of the file.
#include "src/objects/fixed-array-inl.h"
#include "src/roots/roots-inl.h"
namespace v8 {
namespace internal {
inline uint64_t HashSeed(Isolate* isolate) {
return HashSeed(ReadOnlyRoots(isolate));
}
inline uint64_t HashSeed(LocalIsolate* isolate) {
return HashSeed(ReadOnlyRoots(isolate));
}
inline uint64_t HashSeed(ReadOnlyRoots roots) {
uint64_t seed;
MemCopy(&seed, roots.hash_seed()->begin(), sizeof(seed));
return seed;
}
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_HASH_SEED_INL_H_

53
deps/v8/src/numbers/ieee754.cc vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2011 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/numbers/ieee754.h"
#include <cmath>
#include "src/base/ieee754.h"
#include "src/flags/flags.h"
namespace v8::internal::math {
double pow(double x, double y) {
if (v8_flags.use_std_math_pow) {
if (std::isnan(y)) {
// 1. If exponent is NaN, return NaN.
return std::numeric_limits<double>::quiet_NaN();
}
if (std::isinf(y) && (x == 1 || x == -1)) {
// 9. If exponent is +∞𝔽, then
// b. If abs((base)) = 1, return NaN.
// and
// 10. If exponent is -∞𝔽, then
// b. If abs((base)) = 1, return NaN.
return std::numeric_limits<double>::quiet_NaN();
}
if (std::isnan(x)) {
// std::pow distinguishes between quiet and signaling NaN; JS doesn't.
x = std::numeric_limits<double>::quiet_NaN();
}
// The following special cases just exist to match the optimizing compilers'
// behavior, which avoid calls to `pow` in those cases.
if (y == 2) {
// x ** 2 ==> x * x
return x * x;
} else if (y == 0.5) {
// x ** 0.5 ==> sqrt(x), except if x is -Infinity
if (std::isinf(x)) {
return std::numeric_limits<double>::infinity();
} else {
// Note the +0 so that we get +0 for -0**0.5 rather than -0.
return std::sqrt(x + 0);
}
}
return std::pow(x, y);
}
return base::ieee754::legacy::pow(x, y);
}
} // namespace v8::internal::math

21
deps/v8/src/numbers/ieee754.h vendored Normal file
View File

@ -0,0 +1,21 @@
// Copyright 2011 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.
#ifndef V8_NUMBERS_IEEE754_H_
#define V8_NUMBERS_IEEE754_H_
#include "src/base/macros.h"
namespace v8::internal::math {
// Returns |x| to the power of |y|.
// The result of base ** exponent when base is 1 or -1 and exponent is
// +Infinity or -Infinity differs from IEEE 754-2008. The first edition
// of ECMAScript specified a result of NaN for this operation, whereas
// later versions of IEEE 754-2008 specified 1. The historical ECMAScript
// behaviour is preserved for compatibility reasons.
V8_EXPORT_PRIVATE double pow(double x, double y);
} // namespace v8::internal::math
#endif // V8_NUMBERS_IEEE754_H_

View File

@ -0,0 +1,44 @@
// Copyright 2022 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.
#ifndef V8_NUMBERS_INTEGER_LITERAL_INL_H_
#define V8_NUMBERS_INTEGER_LITERAL_INL_H_
#include "src/numbers/integer-literal.h"
// Include the non-inl header before the rest of the headers.
namespace v8 {
namespace internal {
inline std::string IntegerLiteral::ToString() const {
if (negative_) return std::string("-") + std::to_string(absolute_value_);
return std::to_string(absolute_value_);
}
inline IntegerLiteral operator<<(const IntegerLiteral& x,
const IntegerLiteral& y) {
DCHECK(!y.is_negative());
DCHECK_LT(y.absolute_value(), sizeof(uint64_t) * kBitsPerByte);
return IntegerLiteral(x.is_negative(), x.absolute_value()
<< y.absolute_value());
}
inline IntegerLiteral operator+(const IntegerLiteral& x,
const IntegerLiteral& y) {
if (x.is_negative() == y.is_negative()) {
DCHECK_GE(x.absolute_value() + y.absolute_value(), x.absolute_value());
return IntegerLiteral(x.is_negative(),
x.absolute_value() + y.absolute_value());
}
if (x.absolute_value() >= y.absolute_value()) {
return IntegerLiteral(x.is_negative(),
x.absolute_value() - y.absolute_value());
}
return IntegerLiteral(!x.is_negative(),
y.absolute_value() - x.absolute_value());
}
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_INTEGER_LITERAL_INL_H_

107
deps/v8/src/numbers/integer-literal.h vendored Normal file
View File

@ -0,0 +1,107 @@
// Copyright 2022 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.
#ifndef V8_NUMBERS_INTEGER_LITERAL_H_
#define V8_NUMBERS_INTEGER_LITERAL_H_
#include <optional>
#include "src/common/globals.h"
namespace v8 {
namespace internal {
class IntegerLiteral {
public:
IntegerLiteral(bool negative, uint64_t absolute_value)
: negative_(negative), absolute_value_(absolute_value) {
if (absolute_value == 0) negative_ = false;
}
template <typename T>
explicit IntegerLiteral(T value) : IntegerLiteral(value, true) {}
bool is_negative() const { return negative_; }
uint64_t absolute_value() const { return absolute_value_; }
template <typename T>
bool IsRepresentableAs() const {
static_assert(std::is_integral<T>::value, "Integral type required");
static_assert(sizeof(T) <= sizeof(uint64_t),
"Types with more than 64 bits are not supported");
return Compare(IntegerLiteral(std::numeric_limits<T>::min(), false)) >= 0 &&
Compare(IntegerLiteral(std::numeric_limits<T>::max(), false)) <= 0;
}
template <typename T>
T To() const {
static_assert(std::is_integral<T>::value, "Integral type required");
DCHECK(IsRepresentableAs<T>());
uint64_t v = absolute_value_;
if (negative_) v = ~v + 1;
return static_cast<T>(v);
}
template <typename T>
std::optional<T> TryTo() const {
static_assert(std::is_integral<T>::value, "Integral type required");
if (!IsRepresentableAs<T>()) return std::nullopt;
return To<T>();
}
int Compare(const IntegerLiteral& other) const {
if (absolute_value_ == other.absolute_value_) {
if (absolute_value_ == 0 || negative_ == other.negative_) return 0;
return negative_ ? -1 : 1;
} else if (absolute_value_ < other.absolute_value_) {
return other.negative_ ? 1 : -1;
} else {
return negative_ ? -1 : 1;
}
}
std::string ToString() const;
private:
template <typename T>
explicit IntegerLiteral(T value, bool perform_dcheck) : negative_(false) {
static_assert(std::is_integral<T>::value, "Integral type required");
absolute_value_ = static_cast<uint64_t>(value);
if (value < T(0)) {
negative_ = true;
absolute_value_ = ~absolute_value_ + 1;
}
if (perform_dcheck) DCHECK_EQ(To<T>(), value);
}
bool negative_;
uint64_t absolute_value_;
};
inline bool operator==(const IntegerLiteral& x, const IntegerLiteral& y) {
return x.Compare(y) == 0;
}
inline bool operator!=(const IntegerLiteral& x, const IntegerLiteral& y) {
return x.Compare(y) != 0;
}
inline std::ostream& operator<<(std::ostream& stream,
const IntegerLiteral& literal) {
return stream << literal.ToString();
}
inline IntegerLiteral operator|(const IntegerLiteral& x,
const IntegerLiteral& y) {
DCHECK(!x.is_negative());
DCHECK(!y.is_negative());
return IntegerLiteral(false, x.absolute_value() | y.absolute_value());
}
IntegerLiteral operator<<(const IntegerLiteral& x, const IntegerLiteral& y);
IntegerLiteral operator+(const IntegerLiteral& x, const IntegerLiteral& y);
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_INTEGER_LITERAL_H_

74
deps/v8/src/numbers/math-random.cc vendored Normal file
View File

@ -0,0 +1,74 @@
// Copyright 2018 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/numbers/math-random.h"
#include "src/base/utils/random-number-generator.h"
#include "src/common/assert-scope.h"
#include "src/execution/isolate.h"
#include "src/objects/contexts-inl.h"
#include "src/objects/fixed-array.h"
#include "src/objects/smi.h"
namespace v8 {
namespace internal {
void MathRandom::InitializeContext(Isolate* isolate,
DirectHandle<Context> native_context) {
auto cache = Cast<FixedDoubleArray>(
isolate->factory()->NewFixedDoubleArray(kCacheSize));
for (int i = 0; i < kCacheSize; i++) cache->set(i, 0);
native_context->set_math_random_cache(*cache);
DirectHandle<PodArray<State>> pod =
PodArray<State>::New(isolate, 1, AllocationType::kOld);
native_context->set_math_random_state(*pod);
ResetContext(*native_context);
}
void MathRandom::ResetContext(Tagged<Context> native_context) {
native_context->set_math_random_index(Smi::zero());
State state = {0, 0};
Cast<PodArray<State>>(native_context->math_random_state())->set(0, state);
}
Address MathRandom::RefillCache(Isolate* isolate, Address raw_native_context) {
Tagged<Context> native_context =
Cast<Context>(Tagged<Object>(raw_native_context));
DisallowGarbageCollection no_gc;
Tagged<PodArray<State>> pod =
Cast<PodArray<State>>(native_context->math_random_state());
State state = pod->get(0);
// Initialize state if not yet initialized. If a fixed random seed was
// requested, use it to reset our state the first time a script asks for
// random numbers in this context. This ensures the script sees a consistent
// sequence.
if (state.s0 == 0 && state.s1 == 0) {
uint64_t seed;
if (v8_flags.random_seed != 0) {
seed = v8_flags.random_seed;
} else {
isolate->random_number_generator()->NextBytes(&seed, sizeof(seed));
}
state.s0 = base::RandomNumberGenerator::MurmurHash3(seed);
state.s1 = base::RandomNumberGenerator::MurmurHash3(~seed);
CHECK(state.s0 != 0 || state.s1 != 0);
}
Tagged<FixedDoubleArray> cache =
Cast<FixedDoubleArray>(native_context->math_random_cache());
// Create random numbers.
for (int i = 0; i < kCacheSize; i++) {
// Generate random numbers using xorshift128+.
base::RandomNumberGenerator::XorShift128(&state.s0, &state.s1);
cache->set(i, base::RandomNumberGenerator::ToDouble(state.s0));
}
pod->set(0, state);
Tagged<Smi> new_index = Smi::FromInt(kCacheSize);
native_context->set_math_random_index(new_index);
return new_index.ptr();
}
} // namespace internal
} // namespace v8

35
deps/v8/src/numbers/math-random.h vendored Normal file
View File

@ -0,0 +1,35 @@
// Copyright 2018 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.
#ifndef V8_NUMBERS_MATH_RANDOM_H_
#define V8_NUMBERS_MATH_RANDOM_H_
#include "src/common/globals.h"
#include "src/objects/contexts.h"
namespace v8 {
namespace internal {
class MathRandom : public AllStatic {
public:
static void InitializeContext(Isolate* isolate,
DirectHandle<Context> native_context);
static void ResetContext(Tagged<Context> native_context);
// Takes native context as a raw Address for ExternalReference usage.
// Returns a tagged Smi as a raw Address.
static Address RefillCache(Isolate* isolate, Address raw_native_context);
static const int kCacheSize = 64;
static const int kStateSize = 2 * kInt64Size;
struct State {
uint64_t s0;
uint64_t s1;
};
};
} // namespace internal
} // namespace v8
#endif // V8_NUMBERS_MATH_RANDOM_H_