Commit 295dd222 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by Commit Bot

[wasm-gc] Add module argument to IsJSCompatibleSignature

This CL is non-functional by itself and it prepares extending
IsJSCompatibleSignature to wasm-gc types.

Bug: v8:7748
Change-Id: I0bf02d55e83ed020ef63b4eedf641d9405c3a689
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2413251Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69947}
parent 23a37871
......@@ -5858,9 +5858,11 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
public:
WasmWrapperGraphBuilder(Zone* zone, MachineGraph* mcgraph,
const wasm::FunctionSig* sig,
const wasm::WasmModule* module,
compiler::SourcePositionTable* spt,
StubCallMode stub_mode, wasm::WasmFeatures features)
: WasmGraphBuilder(nullptr, zone, mcgraph, sig, spt),
module_(module),
stub_mode_(stub_mode),
enabled_features_(features) {}
......@@ -6308,7 +6310,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
instance_node_.set(
BuildLoadInstanceFromExportedFunctionData(function_data));
if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_)) {
if (!wasm::IsJSCompatibleSignature(sig_, module_, enabled_features_)) {
// Throw a TypeError. Use the js_context of the calling javascript
// function (passed as a parameter), such that the generated code is
// js_context independent.
......@@ -6746,7 +6748,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
isolate->factory()->undefined_value()));
// Throw a TypeError if the signature is incompatible with JavaScript.
if (!wasm::IsJSCompatibleSignature(sig_, enabled_features_)) {
if (!wasm::IsJSCompatibleSignature(sig_, module_, enabled_features_)) {
BuildCallToRuntimeWithContext(Runtime::kWasmThrowTypeError, context,
nullptr, 0);
TerminateThrow(effect(), control());
......@@ -6901,6 +6903,7 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
}
private:
const wasm::WasmModule* module_;
StubCallMode stub_mode_;
SetOncePointer<Node> undefined_value_node_;
SetOncePointer<const Operator> int32_to_heapnumber_operator_;
......@@ -6917,8 +6920,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder {
std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
Isolate* isolate, wasm::WasmEngine* wasm_engine,
const wasm::FunctionSig* sig, bool is_import,
const wasm::WasmFeatures& enabled_features) {
const wasm::FunctionSig* sig, const wasm::WasmModule* module,
bool is_import, const wasm::WasmFeatures& enabled_features) {
//----------------------------------------------------------------------------
// Create the Graph.
//----------------------------------------------------------------------------
......@@ -6932,7 +6935,7 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
InstructionSelector::AlignmentRequirements());
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr,
StubCallMode::kCallBuiltinPointer,
enabled_features);
builder.BuildJSToWasmWrapper(is_import);
......@@ -6959,6 +6962,7 @@ std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall(
Handle<JSReceiver> callable, const wasm::FunctionSig* expected_sig,
const wasm::WasmModule* module,
const wasm::WasmFeatures& enabled_features) {
if (WasmExportedFunction::IsWasmExportedFunction(*callable)) {
auto imported_function = Handle<WasmExportedFunction>::cast(callable);
......@@ -6994,7 +6998,7 @@ std::pair<WasmImportCallKind, Handle<JSReceiver>> ResolveWasmImportCall(
return std::make_pair(WasmImportCallKind::kWasmToCapi, callable);
}
// Assuming we are calling to JS, check whether this would be a runtime error.
if (!wasm::IsJSCompatibleSignature(expected_sig, enabled_features)) {
if (!wasm::IsJSCompatibleSignature(expected_sig, module, enabled_features)) {
return std::make_pair(WasmImportCallKind::kRuntimeTypeError, callable);
}
// For JavaScript calls, determine whether the target has an arity match.
......@@ -7223,9 +7227,9 @@ wasm::WasmCompilationResult CompileWasmImportCallWrapper(
SourcePositionTable* source_position_table =
source_positions ? zone.New<SourcePositionTable>(graph) : nullptr;
WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, source_position_table,
StubCallMode::kCallWasmRuntimeStub,
env->enabled_features);
WasmWrapperGraphBuilder builder(
&zone, mcgraph, sig, env->module, source_position_table,
StubCallMode::kCallWasmRuntimeStub, env->enabled_features);
builder.BuildWasmImportCallWrapper(kind, expected_arity);
// Build a name in the form "wasm-to-js-<kind>-<signature>".
......@@ -7268,9 +7272,9 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine,
InstructionSelector::SupportedMachineOperatorFlags(),
InstructionSelector::AlignmentRequirements()));
WasmWrapperGraphBuilder builder(&zone, mcgraph, sig, source_positions,
StubCallMode::kCallWasmRuntimeStub,
native_module->enabled_features());
WasmWrapperGraphBuilder builder(
&zone, mcgraph, sig, native_module->module(), source_positions,
StubCallMode::kCallWasmRuntimeStub, native_module->enabled_features());
// Set up the graph start.
int param_count = static_cast<int>(sig->parameter_count()) +
......@@ -7304,7 +7308,8 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine* wasm_engine,
}
MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
const wasm::FunctionSig* sig) {
const wasm::FunctionSig* sig,
const wasm::WasmModule* module) {
std::unique_ptr<Zone> zone = std::make_unique<Zone>(
isolate->allocator(), ZONE_NAME, kCompressGraphZone);
Graph* graph = zone->New<Graph>(zone.get());
......@@ -7315,7 +7320,7 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
InstructionSelector::AlignmentRequirements());
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeatures::FromIsolate(isolate));
builder.BuildJSToJSWrapper(isolate);
......@@ -7349,7 +7354,8 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
return code;
}
Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig) {
Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig,
const wasm::WasmModule* module) {
std::unique_ptr<Zone> zone = std::make_unique<Zone>(
isolate->allocator(), ZONE_NAME, kCompressGraphZone);
Graph* graph = zone->New<Graph>(zone.get());
......@@ -7360,7 +7366,7 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, const wasm::FunctionSig* sig) {
InstructionSelector::AlignmentRequirements());
MachineGraph* mcgraph = zone->New<MachineGraph>(graph, common, machine);
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, nullptr,
WasmWrapperGraphBuilder builder(zone.get(), mcgraph, sig, module, nullptr,
StubCallMode::kCallBuiltinPointer,
wasm::WasmFeatures::FromIsolate(isolate));
builder.BuildCWasmEntry();
......
......@@ -106,6 +106,7 @@ constexpr WasmImportCallKind kDefaultImportCallKind =
// another target, which is why the ultimate target is returned as well.
V8_EXPORT_PRIVATE std::pair<WasmImportCallKind, Handle<JSReceiver>>
ResolveWasmImportCall(Handle<JSReceiver> callable, const wasm::FunctionSig* sig,
const wasm::WasmModule* module,
const wasm::WasmFeatures& enabled_features);
// Compiles an import call wrapper, which allows Wasm to call imports.
......@@ -122,13 +123,14 @@ wasm::WasmCode* CompileWasmCapiCallWrapper(wasm::WasmEngine*,
// Returns an OptimizedCompilationJob object for a JS to Wasm wrapper.
std::unique_ptr<OptimizedCompilationJob> NewJSToWasmCompilationJob(
Isolate* isolate, wasm::WasmEngine* wasm_engine,
const wasm::FunctionSig* sig, bool is_import,
const wasm::WasmFeatures& enabled_features);
const wasm::FunctionSig* sig, const wasm::WasmModule* module,
bool is_import, const wasm::WasmFeatures& enabled_features);
// Compiles a stub with JS linkage that serves as an adapter for function
// objects constructed via {WebAssembly.Function}. It performs a round-trip
// simulating a JS-to-Wasm-to-JS coercion of parameter and return values.
MaybeHandle<Code> CompileJSToJSWrapper(Isolate*, const wasm::FunctionSig*);
MaybeHandle<Code> CompileJSToJSWrapper(Isolate*, const wasm::FunctionSig*,
const wasm::WasmModule* module);
enum CWasmEntryParameters {
kCodeEntry,
......@@ -141,8 +143,8 @@ enum CWasmEntryParameters {
// Compiles a stub with C++ linkage, to be called from Execution::CallWasm,
// which knows how to feed it its parameters.
V8_EXPORT_PRIVATE Handle<Code> CompileCWasmEntry(Isolate*,
const wasm::FunctionSig*);
V8_EXPORT_PRIVATE Handle<Code> CompileCWasmEntry(
Isolate*, const wasm::FunctionSig*, const wasm::WasmModule* module);
// Values from the instance object are cached between Wasm-level function calls.
// This struct allows the SSA environment handling this cache to be defined
......
......@@ -1380,12 +1380,13 @@ i::Address CallTargetFromCache(i::Object cached_call_target) {
void PrepareFunctionData(i::Isolate* isolate,
i::Handle<i::WasmExportedFunctionData> function_data,
const i::wasm::FunctionSig* sig) {
const i::wasm::FunctionSig* sig,
const i::wasm::WasmModule* module) {
// If the data is already populated, return immediately.
if (!function_data->c_wrapper_code().IsSmi()) return;
// Compile wrapper code.
i::Handle<i::Code> wrapper_code =
i::compiler::CompileCWasmEntry(isolate, sig);
i::compiler::CompileCWasmEntry(isolate, sig, module);
function_data->set_c_wrapper_code(*wrapper_code);
// Compute packed args size.
function_data->set_packed_args_size(
......@@ -1526,7 +1527,7 @@ auto Func::call(const Val args[], Val results[]) const -> own<Trap> {
// Caching {sig} would give a ~10% reduction in overhead.
const i::wasm::FunctionSig* sig =
instance->module()->functions[function_index].sig;
PrepareFunctionData(isolate, function_data, sig);
PrepareFunctionData(isolate, function_data, sig, instance->module());
i::Handle<i::Code> wrapper_code = i::Handle<i::Code>(
i::Code::cast(function_data->c_wrapper_code()), isolate);
i::Address call_target =
......
......@@ -291,14 +291,15 @@ bool UseGenericWrapper(const FunctionSig* sig) {
JSToWasmWrapperCompilationUnit::JSToWasmWrapperCompilationUnit(
Isolate* isolate, WasmEngine* wasm_engine, const FunctionSig* sig,
bool is_import, const WasmFeatures& enabled_features)
const WasmModule* module, bool is_import,
const WasmFeatures& enabled_features)
: is_import_(is_import),
sig_(sig),
use_generic_wrapper_(UseGenericWrapper(sig) && !is_import),
job_(use_generic_wrapper_
? nullptr
: compiler::NewJSToWasmCompilationJob(
isolate, wasm_engine, sig, is_import, enabled_features)) {}
job_(use_generic_wrapper_ ? nullptr
: compiler::NewJSToWasmCompilationJob(
isolate, wasm_engine, sig, module,
is_import, enabled_features)) {}
JSToWasmWrapperCompilationUnit::~JSToWasmWrapperCompilationUnit() = default;
......@@ -330,11 +331,12 @@ Handle<Code> JSToWasmWrapperCompilationUnit::Finalize(Isolate* isolate) {
// static
Handle<Code> JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper(
Isolate* isolate, const FunctionSig* sig, bool is_import) {
Isolate* isolate, const FunctionSig* sig, const WasmModule* module,
bool is_import) {
// Run the compilation unit synchronously.
WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
JSToWasmWrapperCompilationUnit unit(isolate, isolate->wasm_engine(), sig,
is_import, enabled_features);
module, is_import, enabled_features);
unit.Execute();
return unit.Finalize(isolate);
}
......
......@@ -114,7 +114,8 @@ STATIC_ASSERT(sizeof(WasmCompilationUnit) <= 2 * kSystemPointerSize);
class V8_EXPORT_PRIVATE JSToWasmWrapperCompilationUnit final {
public:
JSToWasmWrapperCompilationUnit(Isolate* isolate, WasmEngine* wasm_engine,
const FunctionSig* sig, bool is_import,
const FunctionSig* sig,
const wasm::WasmModule* module, bool is_import,
const WasmFeatures& enabled_features);
~JSToWasmWrapperCompilationUnit();
......@@ -127,6 +128,7 @@ class V8_EXPORT_PRIVATE JSToWasmWrapperCompilationUnit final {
// Run a compilation unit synchronously.
static Handle<Code> CompileJSToWasmWrapper(Isolate* isolate,
const FunctionSig* sig,
const WasmModule* module,
bool is_import);
private:
......
......@@ -1400,8 +1400,8 @@ int AddExportWrapperUnits(Isolate* isolate, WasmEngine* wasm_engine,
JSToWasmWrapperKey key(function.imported, *function.sig);
if (keys.insert(key).second) {
auto unit = std::make_shared<JSToWasmWrapperCompilationUnit>(
isolate, wasm_engine, function.sig, function.imported,
enabled_features);
isolate, wasm_engine, function.sig, native_module->module(),
function.imported, enabled_features);
builder->AddJSToWasmWrapperUnit(std::move(unit));
}
}
......@@ -1418,7 +1418,8 @@ int AddImportWrapperUnits(NativeModule* native_module,
int num_imported_functions = native_module->num_imported_functions();
for (int func_index = 0; func_index < num_imported_functions; func_index++) {
const FunctionSig* sig = native_module->module()->functions[func_index].sig;
if (!IsJSCompatibleSignature(sig, native_module->enabled_features())) {
if (!IsJSCompatibleSignature(sig, native_module->module(),
native_module->enabled_features())) {
continue;
}
WasmImportWrapperCache::CacheKey key(
......@@ -3340,8 +3341,8 @@ void CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module,
JSToWasmWrapperKey key(function.imported, *function.sig);
if (queue.insert(key)) {
auto unit = std::make_unique<JSToWasmWrapperCompilationUnit>(
isolate, isolate->wasm_engine(), function.sig, function.imported,
enabled_features);
isolate, isolate->wasm_engine(), function.sig, module,
function.imported, enabled_features);
compilation_units.emplace(key, std::move(unit));
}
}
......
......@@ -716,7 +716,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
auto& function = module_->functions[start_index];
Handle<Code> wrapper_code =
JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper(
isolate_, function.sig, function.imported);
isolate_, function.sig, module_, function.imported);
// TODO(clemensb): Don't generate an exported function for the start
// function. Use CWasmEntry instead.
start_function_ = WasmExportedFunction::New(
......@@ -1007,8 +1007,8 @@ bool InstanceBuilder::ProcessImportedFunction(
}
auto js_receiver = Handle<JSReceiver>::cast(value);
const FunctionSig* expected_sig = module_->functions[func_index].sig;
auto resolved =
compiler::ResolveWasmImportCall(js_receiver, expected_sig, enabled_);
auto resolved = compiler::ResolveWasmImportCall(js_receiver, expected_sig,
module_, enabled_);
compiler::WasmImportCallKind kind = resolved.first;
js_receiver = resolved.second;
switch (kind) {
......@@ -1408,7 +1408,8 @@ void InstanceBuilder::CompileImportWrappers(
auto js_receiver = Handle<JSReceiver>::cast(value);
uint32_t func_index = module_->import_table[index].index;
const FunctionSig* sig = module_->functions[func_index].sig;
auto resolved = compiler::ResolveWasmImportCall(js_receiver, sig, enabled_);
auto resolved =
compiler::ResolveWasmImportCall(js_receiver, sig, module_, enabled_);
compiler::WasmImportCallKind kind = resolved.first;
if (kind == compiler::WasmImportCallKind::kWasmToWasm ||
kind == compiler::WasmImportCallKind::kLinkError ||
......
......@@ -405,8 +405,8 @@ Maybe<std::string> DebugEvaluateImpl(
Handle<WasmExportedFunction>::cast(entry_point_obj);
// TODO(wasm): Cache this code.
Handle<Code> wasm_entry =
compiler::CompileCWasmEntry(isolate, entry_point->sig());
Handle<Code> wasm_entry = compiler::CompileCWasmEntry(
isolate, entry_point->sig(), debuggee_instance->module());
CWasmArgumentsPacker packer(4 /* uint32_t return value, no parameters. */);
Execution::CallWasm(isolate, wasm_entry, entry_point->GetWasmCallTarget(),
......
......@@ -1397,7 +1397,7 @@ WasmInstanceObject::GetOrCreateWasmExternalFunction(
// this signature. We compile it and store the wrapper in the module for
// later use.
wrapper = wasm::JSToWasmWrapperCompilationUnit::CompileJSToWasmWrapper(
isolate, function.sig, function.imported);
isolate, function.sig, instance->module(), function.imported);
module_object->export_wrappers().set(wrapper_index, *wrapper);
}
result = Handle<WasmExternalFunction>::cast(WasmExportedFunction::New(
......@@ -1445,7 +1445,8 @@ void WasmInstanceObject::ImportWasmJSFunctionIntoTable(
instance->module_object().native_module();
// TODO(wasm): Cache and reuse wrapper code.
const wasm::WasmFeatures enabled = native_module->enabled_features();
auto resolved = compiler::ResolveWasmImportCall(callable, sig, enabled);
auto resolved = compiler::ResolveWasmImportCall(
callable, sig, instance->module(), enabled);
compiler::WasmImportCallKind kind = resolved.first;
callable = resolved.second; // Update to ultimate target.
DCHECK_NE(compiler::WasmImportCallKind::kLinkError, kind);
......@@ -1914,7 +1915,7 @@ Handle<WasmJSFunction> WasmJSFunction::New(Isolate* isolate,
// TODO(wasm): Think about caching and sharing the JS-to-JS wrappers per
// signature instead of compiling a new one for every instantiation.
Handle<Code> wrapper_code =
compiler::CompileJSToJSWrapper(isolate, sig).ToHandleChecked();
compiler::CompileJSToJSWrapper(isolate, sig, nullptr).ToHandleChecked();
Handle<WasmJSFunctionData> function_data =
Handle<WasmJSFunctionData>::cast(isolate->factory()->NewStruct(
WASM_JS_FUNCTION_DATA_TYPE, AllocationType::kOld));
......
......@@ -27,7 +27,12 @@ std::ostream& operator<<(std::ostream& os, const FunctionSig& sig) {
return os;
}
bool IsJSCompatibleSignature(const FunctionSig* sig,
// TODO(7748): Once we have a story for JS interaction of structs/arrays, this
// function should become independent of module. Remove 'module' parameter in
// this function as well as all transitive callees that no longer need it
// (In essence, revert
// https://chromium-review.googlesource.com/c/v8/v8/+/2413251).
bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmModule* module,
const WasmFeatures& enabled_features) {
if (!enabled_features.has_mv() && sig->return_count() > 1) {
return false;
......
......@@ -18,9 +18,11 @@ namespace internal {
namespace wasm {
class WasmFeatures;
struct WasmModule;
std::ostream& operator<<(std::ostream& os, const FunctionSig& function);
bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmFeatures&);
bool IsJSCompatibleSignature(const FunctionSig* sig, const WasmModule* module,
const WasmFeatures&);
// Control expressions and blocks.
#define FOREACH_CONTROL_OPCODE(V) \
......
......@@ -39,7 +39,8 @@ class CWasmEntryArgTester {
std::vector<uint8_t> code{wasm_function_bytes};
runner_.Build(code.data(), code.data() + code.size());
wasm_code_ = runner_.builder().GetFunctionCode(0);
c_wasm_entry_ = compiler::CompileCWasmEntry(isolate_, sig_);
c_wasm_entry_ = compiler::CompileCWasmEntry(
isolate_, sig_, wasm_code_->native_module()->module());
}
template <typename... Rest>
......
......@@ -101,11 +101,12 @@ class WasmGCTester {
void CallFunctionImpl(uint32_t function_index, const FunctionSig* sig,
CWasmArgumentsPacker* packer) {
WasmCodeRefScope scope;
NativeModule* module = instance_->module_object().native_module();
WasmCode* code = module->GetCode(function_index);
NativeModule* native_module = instance_->module_object().native_module();
WasmCode* code = native_module->GetCode(function_index);
Address wasm_call_target = code->instruction_start();
Handle<Object> object_ref = instance_;
Handle<Code> c_wasm_entry = compiler::CompileCWasmEntry(isolate_, sig);
Handle<Code> c_wasm_entry =
compiler::CompileCWasmEntry(isolate_, sig, native_module->module());
Execution::CallWasm(isolate_, c_wasm_entry, wasm_call_target, object_ref,
packer->argv());
}
......
......@@ -50,7 +50,8 @@ TestingModuleBuilder::TestingModuleBuilder(
// Manually compile an import wrapper and insert it into the instance.
CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
auto resolved = compiler::ResolveWasmImportCall(
maybe_import->js_function, maybe_import->sig, enabled_features_);
maybe_import->js_function, maybe_import->sig,
instance_object_->module(), enabled_features_);
compiler::WasmImportCallKind kind = resolved.first;
Handle<JSReceiver> callable = resolved.second;
WasmImportWrapperCache::ModificationScope cache_scope(
......
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