Commit eb04a25f authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Instantiate the interpreter on demand

If a breakpoint is set on a wasm function, compile an interpreter entry
stub for it, and replace all calls to the original function by calls to
this interpreter entry.
Also, instantiate a wasm interpreter object on demand and set the
breakpoint there.

R=titzer@chromium.org
BUG=v8:5822

Review-Url: https://codereview.chromium.org/2625093004
Cr-Commit-Position: refs/heads/master@{#42309}
parent 865b5e57
......@@ -2949,7 +2949,9 @@ void WasmGraphBuilder::BuildWasmInterpreterEntry(
}
// The return value is also passed via this buffer:
DCHECK_GE(1, sig->return_count());
DCHECK_GE(wasm::kV8MaxWasmFunctionReturns, sig->return_count());
// TODO(wasm): Handle multi-value returns.
DCHECK_EQ(1, wasm::kV8MaxWasmFunctionReturns);
int return_size_bytes =
sig->return_count() == 0 ? 0 : 1 << ElementSizeLog2Of(sig->GetReturn(0));
......
This diff is collapsed.
......@@ -1319,7 +1319,7 @@ class WasmInstanceBuilder {
//--------------------------------------------------------------------------
// Set up the exports object for the new instance.
//--------------------------------------------------------------------------
ProcessExports(code_table, instance);
ProcessExports(code_table, instance, compiled_module_);
//--------------------------------------------------------------------------
// Add instance to Memory object
......@@ -1781,24 +1781,23 @@ class WasmInstanceBuilder {
return mem_buffer;
}
// Process the exports, creating wrappers for functions, tables, memories,
// and globals.
void ProcessExports(Handle<FixedArray> code_table,
Handle<WasmInstanceObject> instance) {
bool needs_wrappers = module_->num_exported_functions > 0;
bool NeedsWrappers() {
if (module_->num_exported_functions > 0) return true;
for (auto table_instance : table_instances_) {
if (!table_instance.js_wrappers.is_null()) {
needs_wrappers = true;
break;
}
if (!table_instance.js_wrappers.is_null()) return true;
}
for (auto table : module_->function_tables) {
if (table.exported) {
needs_wrappers = true;
break;
if (table.exported) return true;
}
return false;
}
if (needs_wrappers) {
// Process the exports, creating wrappers for functions, tables, memories,
// and globals.
void ProcessExports(Handle<FixedArray> code_table,
Handle<WasmInstanceObject> instance,
Handle<WasmCompiledModule> compiled_module) {
if (NeedsWrappers()) {
// Fill the table to cache the exported JSFunction wrappers.
js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
Handle<JSFunction>::null());
......@@ -1826,6 +1825,18 @@ class WasmInstanceBuilder {
++export_index;
}
}
// Store weak references to all exported functions.
Handle<FixedArray> weak_exported_functions;
if (compiled_module->has_weak_exported_functions()) {
weak_exported_functions = compiled_module->weak_exported_functions();
} else {
weak_exported_functions =
isolate_->factory()->NewFixedArray(export_index);
compiled_module->set_weak_exported_functions(weak_exported_functions);
}
DCHECK_EQ(export_index, weak_exported_functions->length());
// Process each export in the export table (go in reverse so asm.js
// can skip duplicates).
for (auto exp : base::Reversed(module_->export_table)) {
......@@ -1858,6 +1869,10 @@ class WasmInstanceBuilder {
js_wrappers_[exp.index] = js_function;
}
desc.set_value(js_function);
Handle<WeakCell> weak_export =
isolate_->factory()->NewWeakCell(js_function);
DCHECK_GT(weak_exported_functions->length(), export_index);
weak_exported_functions->set(export_index, *weak_export);
break;
}
case kExternalTable: {
......
......@@ -239,6 +239,7 @@ class WasmCompiledModule : public FixedArray {
MACRO(WASM_OBJECT, WasmSharedModuleData, shared) \
MACRO(OBJECT, Context, native_context) \
MACRO(OBJECT, FixedArray, code_table) \
MACRO(OBJECT, FixedArray, weak_exported_functions) \
MACRO(OBJECT, FixedArray, function_tables) \
MACRO(OBJECT, FixedArray, signature_tables) \
MACRO(OBJECT, FixedArray, empty_function_tables) \
......@@ -280,6 +281,7 @@ class WasmCompiledModule : public FixedArray {
ret->reset_weak_owning_instance();
ret->reset_weak_next_instance();
ret->reset_weak_prev_instance();
ret->reset_weak_exported_functions();
return ret;
}
......@@ -373,17 +375,22 @@ class WasmCompiledModule : public FixedArray {
DISALLOW_IMPLICIT_CONSTRUCTORS(WasmCompiledModule);
};
// TODO(clemensh): Extend this object for breakpoint support, or remove it.
// TODO(clemensh): Exclude this object from serialization.
class WasmDebugInfo : public FixedArray {
enum Fields { kInstance, kFieldCount };
public:
enum Fields {
kInstance,
kInterpreterHandle,
kInterpretedFunctions,
kFieldCount
};
static Handle<WasmDebugInfo> New(Handle<WasmInstanceObject>);
static bool IsDebugInfo(Object*);
static WasmDebugInfo* cast(Object*);
static void SetBreakpoint(Handle<WasmDebugInfo>, int func_index, int offset);
static void RunInterpreter(Handle<WasmDebugInfo>, int func_index,
uint8_t* arg_buffer);
......
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