[turbofan] Add tests for int64 in fast API calls

Bug: chromium:1052746
Change-Id: I5c60625b25279866816a2f928e84d728b3f04d51
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2332157
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69240}
This commit is contained in:
Maya Lekova 2020-08-05 10:26:21 +02:00 committed by Commit Bot
parent 0c837e8342
commit ce4a5f4c41

View File

@ -27318,13 +27318,13 @@ static const int kV8WrapperTypeIndex = 0;
static const int kV8WrapperObjectIndex = 1;
template <typename T>
struct GetDeoptValue {
struct ConvertJSValue {
static Maybe<T> Get(v8::Local<v8::Value> value,
v8::Local<v8::Context> context);
};
template <>
struct GetDeoptValue<int32_t> {
struct ConvertJSValue<int32_t> {
static Maybe<int32_t> Get(v8::Local<v8::Value> value,
v8::Local<v8::Context> context) {
return value->Int32Value(context);
@ -27332,23 +27332,55 @@ struct GetDeoptValue<int32_t> {
};
template <>
struct GetDeoptValue<uint32_t> {
struct ConvertJSValue<uint32_t> {
static Maybe<uint32_t> Get(v8::Local<v8::Value> value,
v8::Local<v8::Context> context) {
return value->Uint32Value(context);
}
};
// NaNs and +/-Infinity should be 0, otherwise (modulo 2^64) - 2^63.
// Step 8 - 12 of https://heycam.github.io/webidl/#abstract-opdef-converttoint
template <>
struct GetDeoptValue<int64_t> {
struct ConvertJSValue<int64_t> {
static Maybe<int64_t> Get(v8::Local<v8::Value> value,
v8::Local<v8::Context> context) {
return value->IntegerValue(context);
Maybe<double> double_value = value->NumberValue(context);
if (!double_value.IsJust()) {
return v8::Nothing<int64_t>();
}
double result = double_value.ToChecked();
if (std::isinf(result) || std::isnan(result)) {
return v8::Just(int64_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) {
if (fmod_value < pow(2, 63)) {
// 0 <= fmod_value < 2^{63}.
// 0 <= value < 2^{63}. This cast causes no loss.
return v8::Just(static_cast<int64_t>(fmod_value));
} else {
// 2^{63} <= fmod_value < 2^{64}.
// 2^{63} <= value < 2^{64}. This cast causes no loss.
return v8::Just(static_cast<int64_t>(fmod_value - pow(2, 64)));
}
}
// -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<int64_t>(kMaxULL - fmod_value_uint64 + 1));
}
};
template <>
struct GetDeoptValue<bool> {
struct ConvertJSValue<bool> {
static Maybe<bool> Get(v8::Local<v8::Value> value,
v8::Local<v8::Context> context) {
return v8::Just<bool>(value->BooleanValue(CcTest::isolate()));
@ -27433,7 +27465,7 @@ struct ApiNumberChecker : BasicApiChecker<T, ApiNumberChecker<T>> {
checker->result_ |= ApiCheckerResult::kSlowCalled;
LocalContext env;
checker->slow_value_ = GetDeoptValue<T>::Get(info[0], env.local());
checker->slow_value_ = ConvertJSValue<T>::Get(info[0], env.local());
if (checker->raise_exception_) {
info.GetIsolate()->ThrowException(v8_str("Callback error"));
@ -27749,12 +27781,6 @@ TEST(FastApiCalls) {
CallAndCheck<uint32_t>(i::Smi::kMaxValue, Behavior::kNoException,
ApiCheckerResult::kFastCalled,
v8_num(i::Smi::kMaxValue));
#ifdef V8_TARGET_ARCH_X64
CallAndCheck<int64_t>(static_cast<int64_t>(i::Smi::kMaxValue) + 1,
Behavior::kNoException, ApiCheckerResult::kFastCalled,
v8_num(static_cast<int64_t>(i::Smi::kMaxValue) + 1));
#endif // V8_TARGET_ARCH_X64
CallAndCheck<bool>(false, Behavior::kNoException,
ApiCheckerResult::kFastCalled,
v8::Boolean::New(isolate, false));
@ -27819,6 +27845,77 @@ TEST(FastApiCalls) {
CallAndCheck<uint32_t>(3, Behavior::kNoException,
ApiCheckerResult::kFastCalled, v8_num(3.14));
// Corner cases - int64
#ifdef V8_TARGET_ARCH_X64
CallAndCheck<int64_t>(static_cast<int64_t>(i::Smi::kMaxValue) + 1,
Behavior::kNoException, ApiCheckerResult::kFastCalled,
v8_num(static_cast<int64_t>(i::Smi::kMaxValue) + 1));
CallAndCheck<int64_t>(std::numeric_limits<int64_t>::min(),
Behavior::kNoException, ApiCheckerResult::kFastCalled,
v8_num(std::numeric_limits<int64_t>::min()));
CallAndCheck<int64_t>(1ll << 62, Behavior::kNoException,
ApiCheckerResult::kFastCalled, v8_num(1ll << 62));
CallAndCheck<int64_t>(i::kMaxSafeInteger, Behavior::kNoException,
ApiCheckerResult::kFastCalled,
v8_num(i::kMaxSafeInteger));
CallAndCheck<int64_t>(-i::kMaxSafeInteger, Behavior::kNoException,
ApiCheckerResult::kFastCalled,
v8_num(-i::kMaxSafeInteger));
CallAndCheck<int64_t>((1ull << 63) - 1024, Behavior::kNoException,
ApiCheckerResult::kFastCalled,
v8_num((1ull << 63) - 1024));
// TODO(mslekova): We deopt for unsafe integers, but ultimately we want to
// 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()));
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,
ApiCheckerResult::kSlowCalled,
v8_num(std::pow(2, 65) + 8192));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
v8_num(std::pow(2, 1023)));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kFastCalled, v8_num(-0.0));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
v8_num(std::numeric_limits<double>::quiet_NaN()));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
v8_num(std::numeric_limits<double>::infinity()));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled, v8_str("some_string"));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
CompileRun("new Proxy({}, {});"));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
v8::Object::New(isolate));
CallAndCheck<int64_t>(0, Behavior::kNoException,
ApiCheckerResult::kSlowCalled, v8::Array::New(isolate));
CallAndCheck<int64_t>(0, Behavior::kException, ApiCheckerResult::kSlowCalled,
v8::BigInt::New(isolate, 42));
CallAndCheck<int64_t>(3, Behavior::kNoException,
ApiCheckerResult::kSlowCalled, v8_num(3.14));
CallAndCheck<int64_t>(
std::numeric_limits<int64_t>::min(), Behavior::kNoException,
ApiCheckerResult::kSlowCalled,
v8_num(static_cast<double>(std::numeric_limits<int64_t>::max()) + 3.14));
CallAndCheck<int64_t>(
0, Behavior::kNoException, ApiCheckerResult::kSlowCalled,
v8_num(static_cast<double>(std::numeric_limits<int64_t>::max()) * 2 +
3.14));
#endif // V8_TARGET_ARCH_X64
// Corner cases - bool
CallAndCheck<bool>(false, Behavior::kNoException,
ApiCheckerResult::kFastCalled, v8::Undefined(isolate));