Commit 518b3633 authored by Gus Caplan's avatar Gus Caplan Committed by Commit Bot

[fastcall] support float return types on x64

Bug: chromium:1052746
Change-Id: I79f58aa3f732f8569654f0d5751ae89a5b6f547d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2686667
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72733}
parent 83867ef6
......@@ -153,6 +153,8 @@
* - bool
* - int32_t
* - uint32_t
* - float32_t
* - float64_t
* Currently supported argument types:
* - pointer to an embedder type
* - bool
......@@ -383,11 +385,14 @@ class CFunctionInfoImpl : public CFunctionInfo {
static_assert(sizeof...(Args) >= kOptionsArgCount + kReceiverCount,
"The receiver or the fallback argument is missing.");
constexpr CTypeInfo::Type type = internal::GetCType<R>::Get().GetType();
static_assert(
type == CTypeInfo::Type::kVoid || type == CTypeInfo::Type::kBool ||
type == CTypeInfo::Type::kInt32 || type == CTypeInfo::Type::kUint32,
"floating point, 64-bit, and api object values are not currently "
"supported.");
static_assert(type == CTypeInfo::Type::kVoid ||
type == CTypeInfo::Type::kBool ||
type == CTypeInfo::Type::kInt32 ||
type == CTypeInfo::Type::kUint32 ||
type == CTypeInfo::Type::kFloat32 ||
type == CTypeInfo::Type::kFloat64,
"64-bit int and api object values are not currently "
"supported return types.");
}
const CTypeInfo& ReturnInfo() const override { return return_info_; }
......
......@@ -31,6 +31,7 @@ namespace {
#define STACK_SHADOW_WORDS 4
#define PARAM_REGISTERS rcx, rdx, r8, r9
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3
#define FP_RETURN_REGISTER xmm0
#define CALLEE_SAVE_REGISTERS \
rbx.bit() | rdi.bit() | rsi.bit() | r12.bit() | r13.bit() | r14.bit() | \
r15.bit()
......@@ -43,6 +44,7 @@ namespace {
// == x64 other ==============================================================
#define PARAM_REGISTERS rdi, rsi, rdx, rcx, r8, r9
#define FP_PARAM_REGISTERS xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
#define FP_RETURN_REGISTER xmm0
#define CALLEE_SAVE_REGISTERS \
rbx.bit() | r12.bit() | r13.bit() | r14.bit() | r15.bit()
#endif // V8_TARGET_OS_WIN
......@@ -248,27 +250,36 @@ CallDescriptor* Linkage::GetSimplifiedCDescriptor(Zone* zone,
#ifndef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
// Check the types of the signature.
for (size_t i = 0; i < msig->parameter_count(); i++) {
MachineRepresentation rep = msig->GetParam(i).representation();
CHECK_NE(MachineRepresentation::kFloat32, rep);
CHECK_NE(MachineRepresentation::kFloat64, rep);
MachineType type = msig->GetParam(i);
CHECK(!IsFloatingPoint(type.representation()));
}
#endif
// Add return location(s). We don't support FP returns for now.
// Check the return types.
for (size_t i = 0; i < locations.return_count_; i++) {
MachineType type = msig->GetReturn(i);
CHECK(!IsFloatingPoint(type.representation()));
}
#endif
CHECK_GE(2, locations.return_count_);
if (locations.return_count_ > 0) {
#ifdef FP_RETURN_REGISTER
const v8::internal::DoubleRegister kFPReturnRegister = FP_RETURN_REGISTER;
auto reg = IsFloatingPoint(msig->GetReturn(0).representation())
? kFPReturnRegister.code()
: kReturnRegister0.code();
#else
auto reg = kReturnRegister0.code();
#endif
// TODO(chromium:1052746): Use the correctly sized register here (e.g. "al"
// if the return type is kBit), so we don't have to use a hacky bitwise AND
// elsewhere.
locations.AddReturn(LinkageLocation::ForRegister(kReturnRegister0.code(),
msig->GetReturn(0)));
locations.AddReturn(LinkageLocation::ForRegister(reg, msig->GetReturn(0)));
}
if (locations.return_count_ > 1) {
DCHECK(!IsFloatingPoint(msig->GetReturn(0).representation()));
locations.AddReturn(LinkageLocation::ForRegister(kReturnRegister1.code(),
msig->GetReturn(1)));
}
......
......@@ -251,6 +251,7 @@ class EffectControlLinearizer {
Args...);
Node* ChangeBitToTagged(Node* value);
Node* ChangeFloat64ToTagged(Node* value, CheckForMinusZeroMode mode);
Node* ChangeInt32ToSmi(Node* value);
// In pointer compression, we smi-corrupt. This means the upper bits of a Smi
// are not important. ChangeTaggedInt32ToSmi has a known tagged int32 as input
......@@ -1381,7 +1382,11 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
Node* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
Node* value = node->InputAt(0);
return ChangeFloat64ToTagged(value, mode);
}
Node* EffectControlLinearizer::ChangeFloat64ToTagged(
Node* value, CheckForMinusZeroMode mode) {
auto done = __ MakeLabel(MachineRepresentation::kTagged);
auto if_heapnumber = __ MakeDeferredLabel();
auto if_int32 = __ MakeLabel();
......@@ -5104,8 +5109,16 @@ Node* EffectControlLinearizer::LowerFastApiCall(Node* node) {
break;
case CTypeInfo::Type::kInt64:
case CTypeInfo::Type::kUint64:
UNREACHABLE();
case CTypeInfo::Type::kFloat32:
fast_call_result =
ChangeFloat64ToTagged(__ ChangeFloat32ToFloat64(c_call_result),
CheckForMinusZeroMode::kCheckForMinusZero);
break;
case CTypeInfo::Type::kFloat64:
fast_call_result = ChangeFloat64ToTagged(
c_call_result, CheckForMinusZeroMode::kCheckForMinusZero);
break;
case CTypeInfo::Type::kV8Value:
UNREACHABLE();
}
......
......@@ -34,6 +34,7 @@ class BasicBlock;
V(BitcastInt32ToFloat32) \
V(BitcastWord32ToWord64) \
V(BitcastInt64ToFloat64) \
V(ChangeFloat32ToFloat64) \
V(ChangeFloat64ToInt32) \
V(ChangeFloat64ToInt64) \
V(ChangeFloat64ToUint32) \
......
......@@ -27811,8 +27811,9 @@ void CheckFastReturnValue(v8::Local<v8::Value> expected_value,
!checker.DidCallFast());
CHECK_EQ(expected_path == ApiCheckerResult::kFastCalled,
!checker.DidCallSlow());
CHECK(checker.DidCallFast() || checker.DidCallSlow());
CHECK(result->StrictEquals(expected_value));
CHECK(result->SameValue(expected_value));
}
void CallAndDeopt() {
......@@ -28419,6 +28420,30 @@ TEST(FastApiCalls) {
CheckFastReturnValue<uint32_t>(v8_num(std::numeric_limits<uint32_t>::max()),
ApiCheckerResult::kFastCalled);
#ifdef V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
CheckFastReturnValue<float>(v8_num(0), ApiCheckerResult::kFastCalled);
CheckFastReturnValue<float>(v8_num(-0.0), ApiCheckerResult::kFastCalled);
CheckFastReturnValue<float>(v8_num(std::numeric_limits<float>::quiet_NaN()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<float>(v8_num(std::numeric_limits<float>::infinity()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<float>(v8_num(std::numeric_limits<float>::min()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<float>(v8_num(std::numeric_limits<float>::max()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(0), ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(-0.0), ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(std::numeric_limits<double>::quiet_NaN()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(std::numeric_limits<double>::infinity()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(std::numeric_limits<double>::min()),
ApiCheckerResult::kFastCalled);
CheckFastReturnValue<double>(v8_num(std::numeric_limits<double>::max()),
ApiCheckerResult::kFastCalled);
#endif // V8_ENABLE_FP_PARAMS_IN_C_LINKAGE
// Check for the deopt loop protection
CallAndDeopt();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment