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) {
CreateJSWasmCallBuiltinContinuationFrameState(
jsgraph(), n.context(), n.frame_state(),
wasm_call_params.signature());
JSWasmCallData js_wasm_call_data(wasm_call_params.signature());
// All the nodes inserted by the inlined subgraph will have
// id >= subgraph_min_node_id. We use this later to avoid wire nodes that
......@@ -417,7 +416,7 @@ Reduction JSInliner::ReduceJSWasmCall(Node* node) {
graph()->zone(), jsgraph(), wasm_call_params.signature(),
wasm_call_params.module(), isolate(), source_positions_,
StubCallMode::kCallBuiltinPointer, wasm::WasmFeatures::FromFlags(),
&js_wasm_call_data, continuation_frame_state);
continuation_frame_state);
// Extract the inlinee start/end nodes.
start_node = graph()->start();
......
......@@ -726,7 +726,7 @@ Type JSWasmCallNode::TypeForWasmReturnType(const wasm::ValueType& type) {
case wasm::kI32:
return Type::Signed32();
case wasm::kI64:
return Type::BigInt();
return Type::SignedBigInt64();
case wasm::kF32:
case wasm::kF64:
return Type::Number();
......
......@@ -1980,12 +1980,12 @@ class RepresentationSelector {
switch (type.kind()) {
case wasm::kI32:
return MachineType::Int32();
case wasm::kI64:
return MachineType::Int64();
case wasm::kF32:
return MachineType::Float32();
case wasm::kF64:
return MachineType::Float64();
case wasm::kI64:
// Not used for i64, see VisitJSWasmCall().
default:
UNREACHABLE();
}
......@@ -2055,17 +2055,11 @@ class RepresentationSelector {
ProcessRemainingInputs<T>(node, NodeProperties::FirstEffectIndex(node));
if (wasm_signature->return_count() == 1) {
if (wasm_signature->GetReturn().kind() == wasm::kI64) {
// Conversion between negative int64 and BigInt not supported yet.
// Do not bypass the type conversion when the result type is i64.
SetOutput<T>(node, MachineRepresentation::kTagged);
} else {
MachineType return_type =
MachineTypeForWasmReturnType(wasm_signature->GetReturn());
SetOutput<T>(
node, return_type.representation(),
JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn()));
}
MachineType return_type =
MachineTypeForWasmReturnType(wasm_signature->GetReturn());
SetOutput<T>(
node, return_type.representation(),
JSWasmCallNode::TypeForWasmReturnType(wasm_signature->GetReturn()));
} else {
DCHECK_EQ(wasm_signature->return_count(), 0);
SetOutput<T>(node, MachineRepresentation::kTagged);
......
......@@ -117,17 +117,6 @@ bool ContainsInt64(const wasm::FunctionSig* sig) {
} // 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(
wasm::CompilationEnv* env, Zone* zone, MachineGraph* mcgraph,
const wasm::FunctionSig* sig,
......@@ -6713,8 +6702,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
Node* BuildCallAndReturn(bool is_import, Node* js_context,
Node* function_data,
base::SmallVector<Node*, 16> args,
const JSWasmCallData* js_wasm_call_data,
Node* frame_state) {
bool do_conversion, Node* frame_state) {
const int rets_count = static_cast<int>(sig_->return_count());
base::SmallVector<Node*, 1> rets(rets_count);
......@@ -6751,9 +6739,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
if (sig_->return_count() == 0) {
jsval = UndefinedValue();
} else if (sig_->return_count() == 1) {
jsval = js_wasm_call_data && !js_wasm_call_data->result_needs_conversion()
? rets[0]
: ToJS(rets[0], sig_->GetReturn(), js_context);
jsval = !do_conversion ? rets[0]
: ToJS(rets[0], sig_->GetReturn(), js_context);
} else {
int32_t return_count = static_cast<int32_t>(sig_->return_count());
Node* size = gasm_->NumberConstant(return_count);
......@@ -6838,8 +6825,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
}
void BuildJSToWasmWrapper(bool is_import,
const JSWasmCallData* js_wasm_call_data = nullptr,
void BuildJSToWasmWrapper(bool is_import, bool do_conversion = true,
Node* frame_state = nullptr) {
const int wasm_param_count = static_cast<int>(sig_->parameter_count());
......@@ -6867,7 +6853,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// Check whether the signature of the function allows for a fast
// transformation (if any params exist that need transformation).
// 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_);
// Prepare Param() nodes. Param() nodes can only be created once,
......@@ -6893,7 +6879,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
args[i + 1] = wasm_param;
}
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_->Bind(&slow_path);
}
......@@ -6901,8 +6887,6 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
// and build the call.
base::SmallVector<Node*, 16> args(args_count);
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) {
args[i + 1] =
FromJS(params[i + 1], js_context, sig_->GetParam(i), frame_state);
......@@ -6921,7 +6905,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
}
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,
// get the return value based on the path used.
if (include_fast_path) {
......@@ -7622,12 +7606,11 @@ void BuildInlinedJSToWasmWrapper(
Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature,
const wasm::WasmModule* module, Isolate* isolate,
compiler::SourcePositionTable* spt, StubCallMode stub_mode,
wasm::WasmFeatures features, const JSWasmCallData* js_wasm_call_data,
Node* frame_state) {
wasm::WasmFeatures features, Node* frame_state) {
WasmWrapperGraphBuilder builder(zone, mcgraph, signature, module,
WasmGraphBuilder::kNoSpecialParameterMode,
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(
......
......@@ -168,21 +168,6 @@ enum CWasmEntryParameters {
V8_EXPORT_PRIVATE Handle<CodeT> CompileCWasmEntry(
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.
// 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.
......@@ -883,8 +868,7 @@ V8_EXPORT_PRIVATE void BuildInlinedJSToWasmWrapper(
Zone* zone, MachineGraph* mcgraph, const wasm::FunctionSig* signature,
const wasm::WasmModule* module, Isolate* isolate,
compiler::SourcePositionTable* spt, StubCallMode stub_mode,
wasm::WasmFeatures features, const JSWasmCallData* js_wasm_call_data,
Node* frame_state);
wasm::WasmFeatures features, Node* frame_state);
V8_EXPORT_PRIVATE CallDescriptor* GetWasmCallDescriptor(
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