Commit 8624662c authored by Qifan Pan's avatar Qifan Pan Committed by V8 LUCI CQ

[turbofan] Optimize wasm calls with i64 return

`JSWasmCallData` is replaced with a flag `do_conversion` to indicate if conversions of arguments and returns are needed, which is set as false for inlined js-to-wasm call wrappers.

Bug: v8:9407
Change-Id: I35244c8fc13d464d48031fb9d7d04ab277646ec5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3837858Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Qifan Pan <panq@google.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82579}
parent c3a5c5b1
...@@ -405,7 +405,6 @@ Reduction JSInliner::ReduceJSWasmCall(Node* node) { ...@@ -405,7 +405,6 @@ Reduction JSInliner::ReduceJSWasmCall(Node* node) {
CreateJSWasmCallBuiltinContinuationFrameState( CreateJSWasmCallBuiltinContinuationFrameState(
jsgraph(), n.context(), n.frame_state(), jsgraph(), n.context(), n.frame_state(),
wasm_call_params.signature()); wasm_call_params.signature());
JSWasmCallData js_wasm_call_data(wasm_call_params.signature());
// All the nodes inserted by the inlined subgraph will have // All the nodes inserted by the inlined subgraph will have
// id >= subgraph_min_node_id. We use this later to avoid wire nodes that // id >= subgraph_min_node_id. We use this later to avoid wire nodes that
...@@ -417,7 +416,7 @@ Reduction JSInliner::ReduceJSWasmCall(Node* node) { ...@@ -417,7 +416,7 @@ Reduction JSInliner::ReduceJSWasmCall(Node* node) {
graph()->zone(), jsgraph(), wasm_call_params.signature(), graph()->zone(), jsgraph(), wasm_call_params.signature(),
wasm_call_params.module(), isolate(), source_positions_, wasm_call_params.module(), isolate(), source_positions_,
StubCallMode::kCallBuiltinPointer, wasm::WasmFeatures::FromFlags(), StubCallMode::kCallBuiltinPointer, wasm::WasmFeatures::FromFlags(),
&js_wasm_call_data, continuation_frame_state); continuation_frame_state);
// Extract the inlinee start/end nodes. // Extract the inlinee start/end nodes.
start_node = graph()->start(); start_node = graph()->start();
......
...@@ -726,7 +726,7 @@ Type JSWasmCallNode::TypeForWasmReturnType(const wasm::ValueType& type) { ...@@ -726,7 +726,7 @@ Type JSWasmCallNode::TypeForWasmReturnType(const wasm::ValueType& type) {
case wasm::kI32: case wasm::kI32:
return Type::Signed32(); return Type::Signed32();
case wasm::kI64: case wasm::kI64:
return Type::BigInt(); return Type::SignedBigInt64();
case wasm::kF32: case wasm::kF32:
case wasm::kF64: case wasm::kF64:
return Type::Number(); return Type::Number();
......
...@@ -1980,12 +1980,12 @@ class RepresentationSelector { ...@@ -1980,12 +1980,12 @@ class RepresentationSelector {
switch (type.kind()) { switch (type.kind()) {
case wasm::kI32: case wasm::kI32:
return MachineType::Int32(); return MachineType::Int32();
case wasm::kI64:
return MachineType::Int64();
case wasm::kF32: case wasm::kF32:
return MachineType::Float32(); return MachineType::Float32();
case wasm::kF64: case wasm::kF64:
return MachineType::Float64(); return MachineType::Float64();
case wasm::kI64:
// Not used for i64, see VisitJSWasmCall().
default: default:
UNREACHABLE(); UNREACHABLE();
} }
...@@ -2055,17 +2055,11 @@ class RepresentationSelector { ...@@ -2055,17 +2055,11 @@ class RepresentationSelector {
ProcessRemainingInputs<T>(node, NodeProperties::FirstEffectIndex(node)); ProcessRemainingInputs<T>(node, NodeProperties::FirstEffectIndex(node));
if (wasm_signature->return_count() == 1) { if (wasm_signature->return_count() == 1) {
if (wasm_signature->GetReturn().kind() == wasm::kI64) { MachineType return_type =
// Conversion between negative int64 and BigInt not supported yet. MachineTypeForWasmReturnType(wasm_signature->GetReturn());
// Do not bypass the type conversion when the result type is i64. SetOutput<T>(
SetOutput<T>(node, MachineRepresentation::kTagged); node, return_type.representation(),
} else { JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn()));
MachineType return_type =
MachineTypeForWasmReturnType(wasm_signature->GetReturn());
SetOutput<T>(
node, return_type.representation(),
JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn()));
}
} else { } else {
DCHECK_EQ(wasm_signature->return_count(), 0); DCHECK_EQ(wasm_signature->return_count(), 0);
SetOutput<T>(node, MachineRepresentation::kTagged); SetOutput<T>(node, MachineRepresentation::kTagged);
......
...@@ -117,17 +117,6 @@ bool ContainsInt64(const wasm::FunctionSig* sig) { ...@@ -117,17 +117,6 @@ bool ContainsInt64(const wasm::FunctionSig* sig) {
} // namespace } // namespace
JSWasmCallData::JSWasmCallData(const wasm::FunctionSig* wasm_signature)
: result_needs_conversion_(wasm_signature->return_count() == 1 &&
wasm_signature->GetReturn().kind() ==
wasm::kI64) {
arg_needs_conversion_.resize(wasm_signature->parameter_count());
for (size_t i = 0; i < wasm_signature->parameter_count(); i++) {
// TODO(panq): Remove JSWasmCallData if conversion is not needed anymore
arg_needs_conversion_[i] = false;
}
}
WasmGraphBuilder::WasmGraphBuilder( WasmGraphBuilder::WasmGraphBuilder(
wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph, wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
const wasm::FunctionSig* sig, const wasm::FunctionSig* sig,
...@@ -6713,8 +6702,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6713,8 +6702,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* BuildCallAndReturn(bool is_import, Node* js_context, Node* BuildCallAndReturn(bool is_import, Node* js_context,
Node* function_data, Node* function_data,
base::SmallVector<Node*, 16> args, base::SmallVector<Node*, 16> args,
const JSWasmCallData* js_wasm_call_data, bool do_conversion, Node* frame_state) {
Node* frame_state) {
const int rets_count = static_cast<int>(sig_->return_count()); const int rets_count = static_cast<int>(sig_->return_count());
base::SmallVector<Node*, 1> rets(rets_count); base::SmallVector<Node*, 1> rets(rets_count);
...@@ -6751,9 +6739,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6751,9 +6739,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
if (sig_->return_count() == 0) { if (sig_->return_count() == 0) {
jsval = UndefinedValue(); jsval = UndefinedValue();
} else if (sig_->return_count() == 1) { } else if (sig_->return_count() == 1) {
jsval = js_wasm_call_data && !js_wasm_call_data->result_needs_conversion() jsval = !do_conversion ? rets[0]
? rets[0] : ToJS(rets[0], sig_->GetReturn(), js_context);
: ToJS(rets[0], sig_->GetReturn(), js_context);
} else { } else {
int32_t return_count = static_cast<int32_t>(sig_->return_count()); int32_t return_count = static_cast<int32_t>(sig_->return_count());
Node* size = gasm_->NumberConstant(return_count); Node* size = gasm_->NumberConstant(return_count);
...@@ -6838,8 +6825,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6838,8 +6825,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
} }
} }
void BuildJSToWasmWrapper(bool is_import, void BuildJSToWasmWrapper(bool is_import, bool do_conversion = true,
const JSWasmCallData* js_wasm_call_data = nullptr,
Node* frame_state = nullptr) { Node* frame_state = nullptr) {
const int wasm_param_count = static_cast<int>(sig_->parameter_count()); const int wasm_param_count = static_cast<int>(sig_->parameter_count());
...@@ -6867,7 +6853,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6867,7 +6853,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// Check whether the signature of the function allows for a fast // Check whether the signature of the function allows for a fast
// transformation (if any params exist that need transformation). // transformation (if any params exist that need transformation).
// Create a fast transformation path, only if it does. // Create a fast transformation path, only if it does.
bool include_fast_path = !js_wasm_call_data && wasm_param_count > 0 && bool include_fast_path = do_conversion && wasm_param_count > 0 &&
QualifiesForFastTransform(sig_); QualifiesForFastTransform(sig_);
// Prepare Param() nodes. Param() nodes can only be created once, // Prepare Param() nodes. Param() nodes can only be created once,
...@@ -6893,7 +6879,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6893,7 +6879,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
args[i + 1] = wasm_param; args[i + 1] = wasm_param;
} }
Node* jsval = BuildCallAndReturn(is_import, js_context, function_data, Node* jsval = BuildCallAndReturn(is_import, js_context, function_data,
args, js_wasm_call_data, frame_state); args, do_conversion, frame_state);
gasm_->Goto(&done, jsval); gasm_->Goto(&done, jsval);
gasm_->Bind(&slow_path); gasm_->Bind(&slow_path);
} }
...@@ -6901,8 +6887,6 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6901,8 +6887,6 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// and build the call. // and build the call.
base::SmallVector<Node*, 16> args(args_count); base::SmallVector<Node*, 16> args(args_count);
for (int i = 0; i < wasm_param_count; ++i) { for (int i = 0; i < wasm_param_count; ++i) {
bool do_conversion =
!js_wasm_call_data || js_wasm_call_data->arg_needs_conversion(i);
if (do_conversion) { if (do_conversion) {
args[i + 1] = args[i + 1] =
FromJS(params[i + 1], js_context, sig_->GetParam(i), frame_state); FromJS(params[i + 1], js_context, sig_->GetParam(i), frame_state);
...@@ -6921,7 +6905,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { ...@@ -6921,7 +6905,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
} }
} }
Node* jsval = BuildCallAndReturn(is_import, js_context, function_data, args, Node* jsval = BuildCallAndReturn(is_import, js_context, function_data, args,
js_wasm_call_data, frame_state); do_conversion, frame_state);
// If both the default and a fast transformation paths are present, // If both the default and a fast transformation paths are present,
// get the return value based on the path used. // get the return value based on the path used.
if (include_fast_path) { if (include_fast_path) {
...@@ -7622,12 +7606,11 @@ void BuildInlinedJSToWasmWrapper( ...@@ -7622,12 +7606,11 @@ void BuildInlinedJSToWasmWrapper(
Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature, Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature,
const wasm::WasmModule* module, Isolate* isolate, const wasm::WasmModule* module, Isolate* isolate,
compiler::SourcePositionTable* spt, StubCallMode stub_mode, compiler::SourcePositionTable* spt, StubCallMode stub_mode,
wasm::WasmFeatures features, const JSWasmCallData* js_wasm_call_data, wasm::WasmFeatures features, Node* frame_state) {
Node* frame_state) {
WasmWrapperGraphBuilder builder(zone, mcgraph, signature, module, WasmWrapperGraphBuilder builder(zone, mcgraph, signature, module,
WasmGraphBuilder::kNoSpecialParameterMode, WasmGraphBuilder::kNoSpecialParameterMode,
isolate, spt, stub_mode, features); isolate, spt, stub_mode, features);
builder.BuildJSToWasmWrapper(false, js_wasm_call_data, frame_state); builder.BuildJSToWasmWrapper(false, false, frame_state);
} }
std::unique_ptr<TurbofanCompilationJob> NewJSToWasmCompilationJob( std::unique_ptr<TurbofanCompilationJob> NewJSToWasmCompilationJob(
......
...@@ -168,21 +168,6 @@ enum CWasmEntryParameters { ...@@ -168,21 +168,6 @@ enum CWasmEntryParameters {
V8_EXPORT_PRIVATE Handle<CodeT> CompileCWasmEntry( V8_EXPORT_PRIVATE Handle<CodeT> CompileCWasmEntry(
Isolate*, const wasm::FunctionSig*, const wasm::WasmModule* module); Isolate*, const wasm::FunctionSig*, const wasm::WasmModule* module);
class JSWasmCallData {
public:
explicit JSWasmCallData(const wasm::FunctionSig* wasm_signature);
bool arg_needs_conversion(size_t index) const {
DCHECK_LT(index, arg_needs_conversion_.size());
return arg_needs_conversion_[index];
}
bool result_needs_conversion() const { return result_needs_conversion_; }
private:
bool result_needs_conversion_;
std::vector<bool> arg_needs_conversion_;
};
// Values from the instance object are cached between Wasm-level function calls. // Values from the instance object are cached between Wasm-level function calls.
// This struct allows the SSA environment handling this cache to be defined // This struct allows the SSA environment handling this cache to be defined
// and manipulated in wasm-compiler.{h,cc} instead of inside the Wasm decoder. // and manipulated in wasm-compiler.{h,cc} instead of inside the Wasm decoder.
...@@ -883,8 +868,7 @@ V8_EXPORT_PRIVATE void BuildInlinedJSToWasmWrapper( ...@@ -883,8 +868,7 @@ V8_EXPORT_PRIVATE void BuildInlinedJSToWasmWrapper(
Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature, Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature,
const wasm::WasmModule* module, Isolate* isolate, const wasm::WasmModule* module, Isolate* isolate,
compiler::SourcePositionTable* spt, StubCallMode stub_mode, compiler::SourcePositionTable* spt, StubCallMode stub_mode,
wasm::WasmFeatures features, const JSWasmCallData* js_wasm_call_data, wasm::WasmFeatures features, Node* frame_state);
Node* frame_state);
V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor( V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(
Zone* zone, const wasm::FunctionSig* signature, Zone* zone, const wasm::FunctionSig* signature,
......
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