Commit 81f42220 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] cloning compiled module before instantiation

To correctly support instantiating a compiled module multiple times, we clone the
compiled module each time we create an instance, since some of the data is specific
to the instance - e.g. export code, wasm functions, indirect table.

BUG=v8:5072

Review-Url: https://codereview.chromium.org/2134593002
Cr-Commit-Position: refs/heads/master@{#37692}
parent 117fda14
......@@ -3113,25 +3113,10 @@ static void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
*script_str, 0, 0));
}
Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
wasm::ModuleEnv* module,
Handle<String> name,
Handle<Code> wasm_code,
uint32_t index) {
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<Code> wasm_code, uint32_t index) {
const wasm::WasmFunction* func = &module->module->functions[index];
//----------------------------------------------------------------------------
// Create the JSFunction object.
//----------------------------------------------------------------------------
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfo(name, wasm_code, false);
int params = static_cast<int>(func->sig->parameter_count());
shared->set_length(params);
shared->set_internal_formal_parameter_count(params);
Handle<JSFunction> function = isolate->factory()->NewFunction(
isolate->wasm_function_map(), name, MaybeHandle<Code>());
function->set_shared(*shared);
//----------------------------------------------------------------------------
// Create the Graph
//----------------------------------------------------------------------------
......@@ -3153,59 +3138,53 @@ Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
//----------------------------------------------------------------------------
// Run the compilation pipeline.
//----------------------------------------------------------------------------
{
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Graph after change lowering -- " << std::endl;
os << AsRPO(graph);
}
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Graph after change lowering -- " << std::endl;
os << AsRPO(graph);
}
// Schedule and compile to machine code.
int params = static_cast<int>(
module->GetFunctionSignature(index)->parameter_count());
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags);
Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION);
bool debugging =
// Schedule and compile to machine code.
int params =
static_cast<int>(module->GetFunctionSignature(index)->parameter_count());
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags);
Code::Flags flags = Code::ComputeFlags(Code::JS_TO_WASM_FUNCTION);
bool debugging =
#if DEBUG
true;
true;
#else
FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph;
#endif
Vector<const char> func_name = ArrayVector("js-to-wasm");
Vector<const char> func_name = ArrayVector("js-to-wasm");
static unsigned id = 0;
Vector<char> buffer;
if (debugging) {
buffer = Vector<char>::New(128);
int chars = SNPrintF(buffer, "js-to-wasm#%d", id);
func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
}
static unsigned id = 0;
Vector<char> buffer;
if (debugging) {
buffer = Vector<char>::New(128);
int chars = SNPrintF(buffer, "js-to-wasm#%d", id);
func_name = Vector<const char>::cast(buffer.SubVector(0, chars));
}
CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph);
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_opt_code && !code.is_null()) {
OFStream os(stdout);
code->Disassemble(buffer.start(), os);
}
if (FLAG_print_opt_code && !code.is_null()) {
OFStream os(stdout);
code->Disassemble(buffer.start(), os);
}
#endif
if (debugging) {
buffer.Dispose();
}
if (debugging) {
buffer.Dispose();
}
if (isolate->logger()->is_logging_code_events() ||
isolate->is_profiling()) {
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index,
wasm::WasmName("export"),
module->module->GetName(func->name_offset, func->name_length));
}
// Set the JSFunction's machine code.
function->set_code(*code);
if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
RecordFunctionCompilation(
CodeEventListener::FUNCTION_TAG, isolate, code, "js-to-wasm", index,
wasm::WasmName("export"),
module->module->GetName(func->name_offset, func->name_length));
}
return function;
return code;
}
Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
......
......@@ -83,13 +83,9 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate,
Handle<String> import_module,
MaybeHandle<String> import_function);
// Wraps a given wasm code object, producing a JSFunction that can be called
// from JavaScript.
Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
wasm::ModuleEnv* module,
Handle<String> name,
Handle<Code> wasm_code,
uint32_t index);
// Wraps a given wasm code object, producing a code object.
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Handle<Code> wasm_code, uint32_t index);
// Abstracts details of building TurboFan graph nodes for WASM to separate
// the WASM decoder from the internal details of TurboFan.
......
......@@ -552,8 +552,6 @@ class Factory final {
Handle<Code> CopyCode(Handle<Code> code);
Handle<Code> CopyCode(Handle<Code> code, Vector<byte> reloc_info);
Handle<BytecodeArray> CopyBytecodeArray(Handle<BytecodeArray>);
// Interface for creating error objects.
......
This diff is collapsed.
......@@ -165,6 +165,9 @@ struct WasmModule {
uint32_t max_mem_pages; // maximum size of the memory in 64k pages.
bool mem_export; // true if the memory is exported.
bool mem_external; // true if the memory is external.
// TODO(wasm): reconcile start function index being an int with
// the fact that we index on uint32_t, so we may technically not be
// able to represent some start_function_index -es.
int start_function_index; // start function, if any.
ModuleOrigin origin; // origin of the module
......@@ -359,6 +362,12 @@ Handle<WasmDebugInfo> GetDebugInfo(Handle<JSObject> wasm);
// Return the number of functions in the given wasm object.
int GetNumberOfFunctions(JSObject* wasm);
// Create and export JSFunction
Handle<JSFunction> WrapExportCodeAsJSFunction(Isolate* isolate,
Handle<Code> export_code,
Handle<String> name, int arity,
Handle<JSObject> module_instance);
// Check whether the given object is a wasm object.
// This checks the number and type of internal fields, so it's not 100 percent
// secure. If it turns out that we need more complete checks, we could add a
......
......@@ -207,9 +207,12 @@ class TestingModule : public ModuleEnv {
Handle<JSObject> module_object = Handle<JSObject>(0, isolate_);
Handle<Code> code = instance->function_code[index];
WasmJs::InstallWasmFunctionMap(isolate_, isolate_->native_context());
Handle<JSFunction> ret =
compiler::CompileJSToWasmWrapper(isolate_, this, name, code, index);
ret->SetInternalField(0, *module_object);
Handle<Code> ret_code =
compiler::CompileJSToWasmWrapper(isolate_, this, code, index);
Handle<JSFunction> ret = WrapExportCodeAsJSFunction(
isolate_, ret_code, name,
static_cast<int>(this->module->functions[index].sig->parameter_count()),
module_object);
return ret;
}
......@@ -238,6 +241,7 @@ class TestingModule : public ModuleEnv {
*instance->function_code[function_index]);
}
}
WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
WasmInterpreter* interpreter() { return interpreter_; }
......
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