[turbofan] Add tests for uint64 for fast API calls
TBR=cbruni@chromium.org Bug: chromium:1052746 Change-Id: Ib61b06bcc4cd7cf9cfa741899322739e807605b0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2339619 Commit-Queue: Maya Lekova <mslekova@chromium.org> Auto-Submit: Maya Lekova <mslekova@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#69274}
This commit is contained in:
parent
c813817d55
commit
4eb1505997
@ -122,9 +122,13 @@
|
||||
* - bool
|
||||
* - int32_t
|
||||
* - uint32_t
|
||||
* To be supported types:
|
||||
* - int64_t
|
||||
* - uint64_t
|
||||
* The 64-bit integer types currently have the IDL (unsigned) long long
|
||||
* semantics: https://heycam.github.io/webidl/#abstract-opdef-converttoint
|
||||
* In the future we'll extend the API to also provide conversions from/to
|
||||
* BigInt to preserve full precision.
|
||||
* To be supported types:
|
||||
* - float32_t
|
||||
* - float64_t
|
||||
* - arrays of C types
|
||||
|
@ -1740,17 +1740,13 @@ class RepresentationSelector {
|
||||
case CTypeInfo::Type::kUint32:
|
||||
case CTypeInfo::Type::kFloat32:
|
||||
return UseInfo::CheckedNumberAsWord32(feedback);
|
||||
// TODO(mslekova): We deopt for unsafe integers, but ultimately we want
|
||||
// to make this less restrictive in order to stay on the fast path.
|
||||
case CTypeInfo::Type::kInt64:
|
||||
case CTypeInfo::Type::kUint64:
|
||||
return UseInfo::CheckedSigned64AsWord64(kIdentifyZeros, feedback);
|
||||
case CTypeInfo::Type::kFloat64:
|
||||
return UseInfo::CheckedNumberAsFloat64(kIdentifyZeros, feedback);
|
||||
// UseInfo::Word64 does not propagate any TypeCheckKind, so it relies
|
||||
// on the implicit assumption that Word64 representation only holds
|
||||
// Numbers, which is already no longer true with BigInts. By now,
|
||||
// BigInts are handled in a very conservative way to make sure they don't
|
||||
// fall into that pit, but future changes may break this here.
|
||||
case CTypeInfo::Type::kUint64:
|
||||
return UseInfo::Word64();
|
||||
case CTypeInfo::Type::kV8Value:
|
||||
return UseInfo::AnyTagged();
|
||||
}
|
||||
|
@ -27383,6 +27383,8 @@ struct ConvertJSValue<uint32_t> {
|
||||
|
||||
// NaNs and +/-Infinity should be 0, otherwise (modulo 2^64) - 2^63.
|
||||
// Step 8 - 12 of https://heycam.github.io/webidl/#abstract-opdef-converttoint
|
||||
// The int64_t and uint64_t implementations below are copied from Blink:
|
||||
// https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h;l=249?q=doubletointeger&sq=&ss=chromium%2Fchromium%2Fsrc
|
||||
template <>
|
||||
struct ConvertJSValue<int64_t> {
|
||||
static Maybe<int64_t> Get(v8::Local<v8::Value> value,
|
||||
@ -27421,6 +27423,36 @@ struct ConvertJSValue<int64_t> {
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ConvertJSValue<uint64_t> {
|
||||
static Maybe<uint64_t> Get(v8::Local<v8::Value> value,
|
||||
v8::Local<v8::Context> context) {
|
||||
Maybe<double> double_value = value->NumberValue(context);
|
||||
if (!double_value.IsJust()) {
|
||||
return v8::Nothing<uint64_t>();
|
||||
}
|
||||
double result = double_value.ToChecked();
|
||||
if (std::isinf(result) || std::isnan(result)) {
|
||||
return v8::Just(uint64_t(0));
|
||||
}
|
||||
result = trunc(result);
|
||||
|
||||
constexpr uint64_t kMaxULL = std::numeric_limits<uint64_t>::max();
|
||||
|
||||
// -2^{64} < fmod_value < 2^{64}.
|
||||
double fmod_value = fmod(result, kMaxULL + 1.0);
|
||||
if (fmod_value >= 0) {
|
||||
return v8::Just(static_cast<uint64_t>(fmod_value));
|
||||
}
|
||||
// -2^{64} < fmod_value < 0.
|
||||
// 0 < fmod_value_uint64 < 2^{64}. This cast causes no loss.
|
||||
uint64_t fmod_value_uint64 = static_cast<uint64_t>(-fmod_value);
|
||||
// -1 < (kMaxULL - fmod_value_uint64) < 2^{64} - 1.
|
||||
// 0 < value < 2^{64}.
|
||||
return v8::Just(static_cast<uint64_t>(kMaxULL - fmod_value_uint64 + 1));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ConvertJSValue<bool> {
|
||||
static Maybe<bool> Get(v8::Local<v8::Value> value,
|
||||
@ -27910,13 +27942,10 @@ TEST(FastApiCalls) {
|
||||
// stay on the fast path.
|
||||
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min(),
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(std::numeric_limits<int64_t>::max()));
|
||||
v8_num(static_cast<double>(1ull << 63)));
|
||||
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min(),
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(1ull << 63));
|
||||
CallAndCheck<int64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2));
|
||||
CallAndCheck<int64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled, v8_num(std::pow(2, 65)));
|
||||
CallAndCheck<int64_t>(8192, Behavior::kNoException,
|
||||
@ -27955,7 +27984,82 @@ TEST(FastApiCalls) {
|
||||
0, Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(std::numeric_limits<int64_t>::max()) * 2 +
|
||||
3.14));
|
||||
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min(),
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63)));
|
||||
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min(),
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(-static_cast<double>(1ll << 63)));
|
||||
CallAndCheck<int64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2));
|
||||
CallAndCheck<int64_t>(4096, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2 + 4096));
|
||||
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min() + 4096,
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 3 + 4096));
|
||||
|
||||
// Corner cases - uint64_t
|
||||
CallAndCheck<uint64_t>(static_cast<uint64_t>(i::Smi::kMaxValue) + 1,
|
||||
Behavior::kNoException, ApiCheckerResult::kFastCalled,
|
||||
v8_num(static_cast<uint64_t>(i::Smi::kMaxValue) + 1));
|
||||
CallAndCheck<uint64_t>(std::numeric_limits<uint64_t>::min(),
|
||||
Behavior::kNoException, ApiCheckerResult::kFastCalled,
|
||||
v8_num(std::numeric_limits<uint64_t>::min()));
|
||||
CallAndCheck<uint64_t>(1ll << 62, Behavior::kNoException,
|
||||
ApiCheckerResult::kFastCalled, v8_num(1ll << 62));
|
||||
CallAndCheck<uint64_t>(
|
||||
std::numeric_limits<uint64_t>::max() - ((1ll << 62) - 1),
|
||||
Behavior::kNoException, ApiCheckerResult::kFastCalled,
|
||||
v8_num(-(1ll << 62)));
|
||||
CallAndCheck<uint64_t>(i::kMaxSafeIntegerUint64, Behavior::kNoException,
|
||||
ApiCheckerResult::kFastCalled,
|
||||
v8_num(i::kMaxSafeInteger));
|
||||
CallAndCheck<uint64_t>(
|
||||
std::numeric_limits<uint64_t>::max() - (i::kMaxSafeIntegerUint64 - 1),
|
||||
Behavior::kNoException, ApiCheckerResult::kFastCalled,
|
||||
v8_num(-i::kMaxSafeInteger));
|
||||
CallAndCheck<uint64_t>(1ull << 63, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63)));
|
||||
CallAndCheck<uint64_t>(static_cast<double>(1ull << 63) * 2 - 2048,
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2 - 2048));
|
||||
// TODO(mslekova): We deopt for unsafe integers, but ultimately we want to
|
||||
// stay on the fast path.
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kFastCalled, v8_num(-0.0));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(std::numeric_limits<double>::quiet_NaN()));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(std::numeric_limits<double>::infinity()));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled, v8_str("some_string"));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
CompileRun("new Proxy({}, {});"));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8::Object::New(isolate));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8::Array::New(isolate));
|
||||
CallAndCheck<uint64_t>(0, Behavior::kException, ApiCheckerResult::kSlowCalled,
|
||||
v8::BigInt::New(isolate, 42));
|
||||
CallAndCheck<uint64_t>(3, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled, v8_num(3.14));
|
||||
CallAndCheck<uint64_t>(4096, Behavior::kNoException,
|
||||
ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 2 + 4096));
|
||||
CallAndCheck<uint64_t>(static_cast<double>(1ull << 63) + 4096,
|
||||
Behavior::kNoException, ApiCheckerResult::kSlowCalled,
|
||||
v8_num(static_cast<double>(1ull << 63) * 3 + 4096));
|
||||
#endif // V8_TARGET_ARCH_X64
|
||||
|
||||
// Corner cases - bool
|
||||
|
Loading…
Reference in New Issue
Block a user