[wasm] Load instances from {WasmExportedFunction} objects.
This changes JS-to-Wasm wrappers to no longer embed a WeakCell with the associated instance into the code, but load the instance object from the passed {WasmExportedFunction} object instead. R=titzer@chromium.org BUG=v8:7424 Change-Id: I5403f882912eb23e760fabe70207440648754a69 Reviewed-on: https://chromium-review.googlesource.com/1028053 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#53057}
This commit is contained in:
parent
f5fda7c83a
commit
55b70e8686
@ -3004,8 +3004,26 @@ Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
|
||||
return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
|
||||
}
|
||||
|
||||
void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<WeakCell> weak_instance,
|
||||
wasm::WasmCode* wasm_code) {
|
||||
Node* WasmGraphBuilder::BuildLoadInstanceFromExportedFunction(Node* closure) {
|
||||
Node* shared = *effect_ = graph()->NewNode(
|
||||
jsgraph()->machine()->Load(MachineType::AnyTagged()), closure,
|
||||
jsgraph()->Int32Constant(JSFunction::kSharedFunctionInfoOffset -
|
||||
kHeapObjectTag),
|
||||
*effect_, *control_);
|
||||
Node* function_data = *effect_ = graph()->NewNode(
|
||||
jsgraph()->machine()->Load(MachineType::AnyTagged()), shared,
|
||||
jsgraph()->Int32Constant(SharedFunctionInfo::kFunctionDataOffset -
|
||||
kHeapObjectTag),
|
||||
*effect_, *control_);
|
||||
Node* instance = *effect_ = graph()->NewNode(
|
||||
jsgraph()->machine()->Load(MachineType::AnyTagged()), function_data,
|
||||
jsgraph()->Int32Constant(WasmExportedFunctionData::kInstanceOffset -
|
||||
kHeapObjectTag),
|
||||
*effect_, *control_);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void WasmGraphBuilder::BuildJSToWasmWrapper(wasm::WasmCode* wasm_code) {
|
||||
const int wasm_count = static_cast<int>(sig_->parameter_count());
|
||||
const int count =
|
||||
wasm_count + 4; // wasm_code, instance_node, effect, and control.
|
||||
@ -3016,25 +3034,20 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<WeakCell> weak_instance,
|
||||
*control_ = start;
|
||||
*effect_ = start;
|
||||
|
||||
// Create the js_context parameter
|
||||
// Create the js_closure and js_context parameters.
|
||||
Node* js_closure =
|
||||
graph()->NewNode(jsgraph()->common()->Parameter(
|
||||
Linkage::kJSCallClosureParamIndex, "%closure"),
|
||||
graph()->start());
|
||||
Node* js_context = graph()->NewNode(
|
||||
jsgraph()->common()->Parameter(
|
||||
Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
|
||||
graph()->start());
|
||||
|
||||
// Create the instance_node node to pass as parameter. This is either
|
||||
// an actual reference to an instance or a placeholder reference,
|
||||
// since JSToWasm wrappers can be compiled at module compile time and
|
||||
// patched at instance build time.
|
||||
// Create the instance_node node to pass as parameter. It is loaded from the
|
||||
// called {WasmExportedFunction} via the {WasmExportedFunctionData} structure.
|
||||
DCHECK_NULL(instance_node_);
|
||||
// TODO(titzer): JSToWasmWrappers should load the instance from the
|
||||
// incoming JSFunction, but this is currently too slow/too complex because
|
||||
// we use a regular JS property with a private symbol.
|
||||
instance_node_ = graph()->NewNode(
|
||||
jsgraph()->machine()->Load(MachineType::TaggedPointer()),
|
||||
jsgraph()->HeapConstant(weak_instance),
|
||||
jsgraph()->Int32Constant(WeakCell::kValueOffset - kHeapObjectTag),
|
||||
*effect_, *control_);
|
||||
instance_node_ = BuildLoadInstanceFromExportedFunction(js_closure);
|
||||
|
||||
Address instr_start =
|
||||
wasm_code == nullptr ? kNullAddress : wasm_code->instruction_start();
|
||||
@ -4638,7 +4651,6 @@ void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
|
||||
} // namespace
|
||||
|
||||
Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
|
||||
Handle<WeakCell> weak_instance,
|
||||
wasm::WasmCode* wasm_code, uint32_t index,
|
||||
wasm::UseTrapHandler use_trap_handler) {
|
||||
const wasm::WasmFunction* func = &module->functions[index];
|
||||
@ -4665,7 +4677,7 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
|
||||
isolate->factory()->null_value(), func->sig);
|
||||
builder.set_control_ptr(&control);
|
||||
builder.set_effect_ptr(&effect);
|
||||
builder.BuildJSToWasmWrapper(weak_instance, wasm_code);
|
||||
builder.BuildJSToWasmWrapper(wasm_code);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Run the compilation pipeline.
|
||||
|
@ -108,9 +108,11 @@ Handle<Code> CompileWasmToJSWrapper(Isolate*, Handle<JSReceiver> target,
|
||||
wasm::ModuleOrigin, wasm::UseTrapHandler);
|
||||
|
||||
// Wraps a given wasm code object, producing a code object.
|
||||
V8_EXPORT_PRIVATE Handle<Code> CompileJSToWasmWrapper(
|
||||
Isolate*, wasm::WasmModule*, Handle<WeakCell> weak_instance,
|
||||
wasm::WasmCode*, uint32_t index, wasm::UseTrapHandler);
|
||||
V8_EXPORT_PRIVATE Handle<Code> CompileJSToWasmWrapper(Isolate*,
|
||||
wasm::WasmModule*,
|
||||
wasm::WasmCode*,
|
||||
uint32_t index,
|
||||
wasm::UseTrapHandler);
|
||||
|
||||
// Compiles a stub that redirects a call to a wasm function to the wasm
|
||||
// interpreter. It's ABI compatible with the compiled wasm function.
|
||||
@ -251,8 +253,7 @@ class WasmGraphBuilder {
|
||||
Node* CallIndirect(uint32_t index, Node** args, Node*** rets,
|
||||
wasm::WasmCodePosition position);
|
||||
|
||||
void BuildJSToWasmWrapper(Handle<WeakCell> weak_instance,
|
||||
wasm::WasmCode* wasm_code);
|
||||
void BuildJSToWasmWrapper(wasm::WasmCode* wasm_code);
|
||||
bool BuildWasmToJSWrapper(Handle<JSReceiver> target,
|
||||
int index);
|
||||
void BuildWasmInterpreterEntry(uint32_t func_index);
|
||||
@ -466,6 +467,8 @@ class WasmGraphBuilder {
|
||||
Node* BuildLoadHeapNumberValue(Node* value, Node* control);
|
||||
Node* BuildHeapNumberValueIndexConstant();
|
||||
|
||||
Node* BuildLoadInstanceFromExportedFunction(Node* closure);
|
||||
|
||||
// Asm.js specific functionality.
|
||||
Node* BuildI32AsmjsSConvertF32(Node* input);
|
||||
Node* BuildI32AsmjsSConvertF64(Node* input);
|
||||
|
@ -211,7 +211,7 @@ class JSToWasmWrapperCache {
|
||||
}
|
||||
|
||||
Handle<Code> code = compiler::CompileJSToWasmWrapper(
|
||||
isolate, module, weak_instance_, wasm_code, index, use_trap_handler);
|
||||
isolate, module, wasm_code, index, use_trap_handler);
|
||||
uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig);
|
||||
DCHECK_EQ(code_cache_.size(), new_cache_idx);
|
||||
USE(new_cache_idx);
|
||||
@ -219,15 +219,10 @@ class JSToWasmWrapperCache {
|
||||
return code;
|
||||
}
|
||||
|
||||
void SetWeakInstance(Handle<WeakCell> weak_instance) {
|
||||
weak_instance_ = weak_instance;
|
||||
}
|
||||
|
||||
private:
|
||||
// sig_map_ maps signatures to an index in code_cache_.
|
||||
wasm::SignatureMap sig_map_;
|
||||
std::vector<Handle<Code>> code_cache_;
|
||||
Handle<WeakCell> weak_instance_;
|
||||
};
|
||||
|
||||
// A helper class to simplify instantiating a module from a compiled module.
|
||||
@ -1617,9 +1612,9 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
MaybeHandle<WasmInstanceObject> old_instance;
|
||||
|
||||
TRACE("Starting new module instantiation\n");
|
||||
Handle<WasmCompiledModule> original =
|
||||
handle(module_object_->compiled_module());
|
||||
{
|
||||
Handle<WasmCompiledModule> original =
|
||||
handle(module_object_->compiled_module());
|
||||
if (original->has_instance()) {
|
||||
old_instance = handle(original->owning_instance());
|
||||
// Clone, but don't insert yet the clone in the instances chain.
|
||||
@ -1647,24 +1642,15 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
compiled_module_->GetNativeModule()->instance_id);
|
||||
}
|
||||
}
|
||||
base::Optional<wasm::NativeModuleModificationScope>
|
||||
native_module_modification_scope;
|
||||
if (native_module != nullptr) {
|
||||
native_module_modification_scope.emplace(native_module);
|
||||
}
|
||||
DCHECK_NOT_NULL(native_module);
|
||||
wasm::NativeModuleModificationScope native_modification_scope(native_module);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Create the WebAssembly.Instance object.
|
||||
//--------------------------------------------------------------------------
|
||||
CodeSpecialization code_specialization;
|
||||
Handle<WasmInstanceObject> instance =
|
||||
WasmInstanceObject::New(isolate_, module_object_, compiled_module_);
|
||||
Handle<WeakCell> weak_instance = factory->NewWeakCell(instance);
|
||||
Handle<WeakCell> old_weak_instance(original->weak_owning_instance(),
|
||||
isolate_);
|
||||
code_specialization.UpdateInstanceReferences(old_weak_instance,
|
||||
weak_instance);
|
||||
js_to_wasm_cache_.SetWeakInstance(weak_instance);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Set up the globals for the new instance.
|
||||
@ -1729,6 +1715,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
//--------------------------------------------------------------------------
|
||||
// Initialize the indirect tables.
|
||||
//--------------------------------------------------------------------------
|
||||
CodeSpecialization code_specialization;
|
||||
if (function_table_count > 0) {
|
||||
InitializeTables(instance, &code_specialization);
|
||||
}
|
||||
@ -3688,9 +3675,6 @@ void CompileJsToWasmWrappers(Isolate* isolate,
|
||||
Handle<WasmCompiledModule> compiled_module,
|
||||
Counters* counters) {
|
||||
JSToWasmWrapperCache js_to_wasm_cache;
|
||||
Handle<WeakCell> weak_instance(compiled_module->weak_owning_instance(),
|
||||
isolate);
|
||||
js_to_wasm_cache.SetWeakInstance(weak_instance);
|
||||
int wrapper_index = 0;
|
||||
Handle<FixedArray> export_wrappers(compiled_module->export_wrappers(),
|
||||
isolate);
|
||||
|
@ -62,14 +62,6 @@ CodeSpecialization::CodeSpecialization() {}
|
||||
|
||||
CodeSpecialization::~CodeSpecialization() {}
|
||||
|
||||
void CodeSpecialization::UpdateInstanceReferences(
|
||||
Handle<WeakCell> old_weak_instance, Handle<WeakCell> new_weak_instance) {
|
||||
DCHECK(!old_weak_instance.is_null());
|
||||
DCHECK(!new_weak_instance.is_null());
|
||||
old_weak_instance_ = old_weak_instance;
|
||||
new_weak_instance_ = new_weak_instance;
|
||||
}
|
||||
|
||||
void CodeSpecialization::RelocateDirectCalls(NativeModule* native_module) {
|
||||
DCHECK_NULL(relocate_direct_calls_module_);
|
||||
DCHECK_NOT_NULL(native_module);
|
||||
@ -101,9 +93,6 @@ bool CodeSpecialization::ApplyToWholeModule(
|
||||
changed |= ApplyToWasmCode(wasm_function, icache_flush_mode);
|
||||
}
|
||||
|
||||
bool patch_wasm_weak_instances =
|
||||
!old_weak_instance_.is_identical_to(new_weak_instance_);
|
||||
|
||||
// Patch all exported functions (JS_TO_WASM_FUNCTION).
|
||||
int reloc_mode = 0;
|
||||
// Patch CODE_TARGET if we shall relocate direct calls. If we patch direct
|
||||
@ -113,10 +102,6 @@ bool CodeSpecialization::ApplyToWholeModule(
|
||||
DCHECK_EQ(native_module, relocate_direct_calls_module_);
|
||||
reloc_mode |= RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL);
|
||||
}
|
||||
// Instance references are simply embedded objects.
|
||||
if (patch_wasm_weak_instances) {
|
||||
reloc_mode |= RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
}
|
||||
if (!reloc_mode) return changed;
|
||||
int wrapper_index = 0;
|
||||
for (auto exp : module->export_table) {
|
||||
@ -134,15 +119,6 @@ bool CodeSpecialization::ApplyToWholeModule(
|
||||
it.rinfo()->set_js_to_wasm_address(new_code->instruction_start(),
|
||||
icache_flush_mode);
|
||||
} break;
|
||||
case RelocInfo::EMBEDDED_OBJECT: {
|
||||
changed = true;
|
||||
const HeapObject* old = it.rinfo()->target_object();
|
||||
if (*old_weak_instance_ == old) {
|
||||
it.rinfo()->set_target_object(
|
||||
*new_weak_instance_, WriteBarrierMode::UPDATE_WRITE_BARRIER,
|
||||
icache_flush_mode);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ uint32_t ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc);
|
||||
|
||||
// Helper class to specialize wasm code for a specific instance, or to update
|
||||
// code when memory / globals / tables change.
|
||||
// This class in unhandlified, and contains a DisallowHeapAllocation field to
|
||||
// ensure that no allocations happen while it is alive.
|
||||
//
|
||||
// Set up all relocations / patching that should be performed by the Relocate* /
|
||||
// Patch* methods, then apply all changes in one step using the Apply* methods.
|
||||
@ -27,10 +25,6 @@ class CodeSpecialization {
|
||||
CodeSpecialization();
|
||||
~CodeSpecialization();
|
||||
|
||||
// Update instance references in code. Instance references should only
|
||||
// appear in export wrappers.
|
||||
void UpdateInstanceReferences(Handle<WeakCell> old_weak_instance,
|
||||
Handle<WeakCell> new_weak_instance);
|
||||
// Update all direct call sites based on the code table in the given instance.
|
||||
void RelocateDirectCalls(NativeModule* module);
|
||||
// Apply all relocations and patching to all code in the instance (wasm code
|
||||
@ -42,8 +36,6 @@ class CodeSpecialization {
|
||||
ICacheFlushMode = FLUSH_ICACHE_IF_NEEDED);
|
||||
|
||||
private:
|
||||
Handle<WeakCell> old_weak_instance_;
|
||||
Handle<WeakCell> new_weak_instance_;
|
||||
NativeModule* relocate_direct_calls_module_ = nullptr;
|
||||
};
|
||||
|
||||
|
@ -119,13 +119,8 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
|
||||
// Wrap the code so it can be called as a JS function.
|
||||
Link();
|
||||
wasm::WasmCode* code = native_module_->code(index);
|
||||
|
||||
Handle<WasmCompiledModule> compiled_module(
|
||||
instance_object()->compiled_module(), isolate_);
|
||||
Handle<WeakCell> weak_instance(compiled_module->weak_owning_instance(),
|
||||
isolate_);
|
||||
Handle<Code> ret_code = compiler::CompileJSToWasmWrapper(
|
||||
isolate_, test_module_ptr_, weak_instance, code, index,
|
||||
isolate_, test_module_ptr_, code, index,
|
||||
trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler);
|
||||
Handle<JSFunction> ret = WasmExportedFunction::New(
|
||||
isolate_, instance_object(), MaybeHandle<String>(),
|
||||
@ -134,6 +129,8 @@ Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
|
||||
ret_code);
|
||||
|
||||
// Add reference to the exported wrapper code.
|
||||
Handle<WasmCompiledModule> compiled_module(
|
||||
instance_object()->compiled_module(), isolate_);
|
||||
Handle<FixedArray> old_arr(compiled_module->export_wrappers(), isolate_);
|
||||
Handle<FixedArray> new_arr =
|
||||
isolate_->factory()->NewFixedArray(old_arr->length() + 1);
|
||||
|
Loading…
Reference in New Issue
Block a user