[wasm] Move {export_wrappers} field to {WasmModuleObject}.
This makes the fact that export wrapper code is shared across instances explicit by hanging the {export_wrappers} array off the module object instead of the instance-specific {WasmCompiledModule} object. R=titzer@chromium.org Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: Ic5c73bcc17f759e520c105317361e5654628b99e Reviewed-on: https://chromium-review.googlesource.com/1051987 Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Ben Titzer <titzer@chromium.org> Cr-Commit-Position: refs/heads/master@{#53131}
This commit is contained in:
parent
a2430e247c
commit
f6fbbc0c51
@ -7461,17 +7461,16 @@ MaybeLocal<WasmCompiledModule> WasmCompiledModule::Deserialize(
|
||||
const WasmCompiledModule::CallerOwnedBuffer& serialized_module,
|
||||
const WasmCompiledModule::CallerOwnedBuffer& wire_bytes) {
|
||||
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
|
||||
i::MaybeHandle<i::WasmCompiledModule> maybe_compiled_module =
|
||||
i::MaybeHandle<i::WasmModuleObject> maybe_module_object =
|
||||
i::wasm::DeserializeNativeModule(
|
||||
i_isolate, {serialized_module.first, serialized_module.second},
|
||||
{wire_bytes.first, wire_bytes.second});
|
||||
i::Handle<i::WasmCompiledModule> compiled_module;
|
||||
if (!maybe_compiled_module.ToHandle(&compiled_module)) {
|
||||
i::Handle<i::WasmModuleObject> module_object;
|
||||
if (!maybe_module_object.ToHandle(&module_object)) {
|
||||
return MaybeLocal<WasmCompiledModule>();
|
||||
}
|
||||
return Local<WasmCompiledModule>::Cast(
|
||||
Utils::ToLocal(i::Handle<i::JSObject>::cast(
|
||||
i::WasmModuleObject::New(i_isolate, compiled_module))));
|
||||
Utils::ToLocal(i::Handle<i::JSObject>::cast(module_object)));
|
||||
}
|
||||
|
||||
MaybeLocal<WasmCompiledModule> WasmCompiledModule::DeserializeOrCompile(
|
||||
|
@ -1554,7 +1554,6 @@ void Tuple3::Tuple3Verify() {
|
||||
void WasmCompiledModule::WasmCompiledModuleVerify() {
|
||||
CHECK(IsWasmCompiledModule());
|
||||
VerifyObjectField(kSharedOffset);
|
||||
VerifyObjectField(kExportWrappersOffset);
|
||||
VerifyObjectField(kNextInstanceOffset);
|
||||
VerifyObjectField(kPrevInstanceOffset);
|
||||
VerifyObjectField(kOwningInstanceOffset);
|
||||
|
@ -927,7 +927,7 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
|
||||
wire_bytes->set_is_external(true);
|
||||
isolate->heap()->UnregisterArrayBuffer(*wire_bytes);
|
||||
}
|
||||
MaybeHandle<WasmCompiledModule> maybe_compiled_module =
|
||||
MaybeHandle<WasmModuleObject> maybe_module_object =
|
||||
wasm::DeserializeNativeModule(
|
||||
isolate, {mem_start, mem_size},
|
||||
Vector<const uint8_t>(
|
||||
@ -937,11 +937,11 @@ RUNTIME_FUNCTION(Runtime_DeserializeWasmModule) {
|
||||
wire_bytes->set_is_external(false);
|
||||
isolate->heap()->RegisterNewArrayBuffer(*wire_bytes);
|
||||
}
|
||||
Handle<WasmCompiledModule> compiled_module;
|
||||
if (!maybe_compiled_module.ToHandle(&compiled_module)) {
|
||||
Handle<WasmModuleObject> module_object;
|
||||
if (!maybe_module_object.ToHandle(&module_object)) {
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
return *WasmModuleObject::New(isolate, compiled_module);
|
||||
return *module_object;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_ValidateWasmInstancesChain) {
|
||||
|
@ -1792,12 +1792,8 @@ MaybeHandle<JSObject> ValueDeserializer::ReadWasmModule() {
|
||||
}
|
||||
|
||||
// Try to deserialize the compiled module first.
|
||||
Handle<WasmCompiledModule> compiled_module;
|
||||
MaybeHandle<JSObject> result;
|
||||
if (wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes)
|
||||
.ToHandle(&compiled_module)) {
|
||||
result = WasmModuleObject::New(isolate_, compiled_module);
|
||||
}
|
||||
MaybeHandle<WasmModuleObject> result =
|
||||
wasm::DeserializeNativeModule(isolate_, compiled_bytes, wire_bytes);
|
||||
if (result.is_null()) {
|
||||
wasm::ErrorThrower thrower(isolate_, "ValueDeserializer::ReadWasmModule");
|
||||
result = isolate_->wasm_engine()->SyncCompile(
|
||||
|
@ -341,8 +341,7 @@ class InstanceBuilder {
|
||||
|
||||
// Process the exports, creating wrappers for functions, tables, memories,
|
||||
// and globals.
|
||||
void ProcessExports(Handle<WasmInstanceObject> instance,
|
||||
Handle<WasmCompiledModule> compiled_module);
|
||||
void ProcessExports(Handle<WasmInstanceObject> instance);
|
||||
|
||||
void InitializeTables(Handle<WasmInstanceObject> instance);
|
||||
|
||||
@ -925,10 +924,9 @@ ModuleEnv CreateDefaultModuleEnv(WasmModule* module) {
|
||||
|
||||
Handle<WasmCompiledModule> NewCompiledModule(Isolate* isolate,
|
||||
WasmModule* module,
|
||||
Handle<FixedArray> export_wrappers,
|
||||
ModuleEnv& env) {
|
||||
Handle<WasmCompiledModule> compiled_module =
|
||||
WasmCompiledModule::New(isolate, module, export_wrappers, env);
|
||||
WasmCompiledModule::New(isolate, module, env);
|
||||
return compiled_module;
|
||||
}
|
||||
|
||||
@ -1085,49 +1083,27 @@ void FinishCompilationUnits(CompilationState* compilation_state,
|
||||
}
|
||||
}
|
||||
|
||||
void PatchNativeModule(NativeModule* cloning_module,
|
||||
Handle<WasmCompiledModule> compiled_module) {
|
||||
// Link.
|
||||
CodeSpecialization code_specialization;
|
||||
code_specialization.RelocateDirectCalls(cloning_module);
|
||||
code_specialization.ApplyToWholeModule(cloning_module, compiled_module);
|
||||
}
|
||||
|
||||
void UpdateAllCompiledModulesWithTopTierCode(
|
||||
Handle<WasmCompiledModule> compiled_module) {
|
||||
// We want to disallow heap allocation here, as this might interfere with
|
||||
// iterating over the chain of compiled modules for updating all native
|
||||
// modules.
|
||||
DisallowHeapAllocation no_gc;
|
||||
|
||||
WasmModule* module = compiled_module->shared()->module();
|
||||
Handle<WasmModuleObject> module_object) {
|
||||
WasmModule* module = module_object->compiled_module()->shared()->module();
|
||||
DCHECK_GT(module->functions.size() - module->num_imported_functions, 0);
|
||||
USE(module);
|
||||
|
||||
CodeSpaceMemoryModificationScope modification_scope(
|
||||
compiled_module->GetIsolate()->heap());
|
||||
module_object->GetIsolate()->heap());
|
||||
|
||||
Handle<WasmCompiledModule> current = compiled_module;
|
||||
PatchNativeModule(current->GetNativeModule(), current);
|
||||
NativeModule* native_module =
|
||||
module_object->compiled_module()->GetNativeModule();
|
||||
|
||||
// Go through the chain of compiled modules to update each (next in chain).
|
||||
while (current->has_next_instance()) {
|
||||
current = handle(current->next_instance());
|
||||
PatchNativeModule(current->GetNativeModule(), current);
|
||||
}
|
||||
|
||||
// Go through the chain of compiled modules to update each (previous in
|
||||
// chain).
|
||||
current = compiled_module;
|
||||
while (current->has_prev_instance()) {
|
||||
current = handle(current->prev_instance());
|
||||
PatchNativeModule(current->GetNativeModule(), current);
|
||||
}
|
||||
// Link.
|
||||
CodeSpecialization code_specialization;
|
||||
code_specialization.RelocateDirectCalls(native_module);
|
||||
code_specialization.ApplyToWholeModule(native_module, module_object);
|
||||
}
|
||||
|
||||
void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
||||
const ModuleWireBytes& wire_bytes, ModuleEnv* module_env,
|
||||
Handle<WasmCompiledModule> compiled_module,
|
||||
Handle<WasmModuleObject> module_object,
|
||||
Handle<Code> centry_stub, ErrorThrower* thrower) {
|
||||
const WasmModule* module = module_env->module;
|
||||
// Data structures for the parallel compilation.
|
||||
@ -1167,17 +1143,17 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
||||
|
||||
DeferredHandles* deferred_handles = nullptr;
|
||||
Handle<Code> centry_deferred = centry_stub;
|
||||
Handle<WasmCompiledModule> compiled_module_deferred;
|
||||
Handle<WasmModuleObject> module_object_deferred;
|
||||
if (compilation_state->compile_mode() == CompileMode::kTiering) {
|
||||
// Open a deferred handle scope for the centry_stub, in order to allow
|
||||
// for background tiering compilation.
|
||||
DeferredHandleScope deferred(isolate);
|
||||
centry_deferred = Handle<Code>(*centry_stub, isolate);
|
||||
compiled_module_deferred = handle(*compiled_module, isolate);
|
||||
module_object_deferred = handle(*module_object, isolate);
|
||||
deferred_handles = deferred.Detach();
|
||||
}
|
||||
compilation_state->AddCallback(
|
||||
[compiled_module_deferred, deferred_handles](
|
||||
[module_object_deferred, deferred_handles](
|
||||
// Callback is called from a foreground thread.
|
||||
CompilationEvent event, ErrorThrower* thrower) mutable {
|
||||
switch (event) {
|
||||
@ -1186,7 +1162,7 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
||||
// in this foreground thread.
|
||||
return;
|
||||
case CompilationEvent::kFinishedTopTierCompilation:
|
||||
UpdateAllCompiledModulesWithTopTierCode(compiled_module_deferred);
|
||||
UpdateAllCompiledModulesWithTopTierCode(module_object_deferred);
|
||||
// TODO(wasm): Currently compilation has to finish before the
|
||||
// {deferred_handles} can be removed. We need to make sure that
|
||||
// we can clean it up at a time when the native module
|
||||
@ -1200,7 +1176,8 @@ void CompileInParallel(Isolate* isolate, NativeModule* native_module,
|
||||
// a callback, in this thread through {thrower}.
|
||||
// Tier-up compilation should not fail if baseline compilation
|
||||
// did not fail.
|
||||
DCHECK(!compiled_module_deferred->GetNativeModule()
|
||||
DCHECK(!module_object_deferred->compiled_module()
|
||||
->GetNativeModule()
|
||||
->compilation_state()
|
||||
->baseline_compilation_finished());
|
||||
delete deferred_handles;
|
||||
@ -1377,10 +1354,12 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
|
||||
// serializable. Instantiation may occur off a deserialized version of this
|
||||
// object.
|
||||
Handle<WasmCompiledModule> compiled_module =
|
||||
NewCompiledModule(isolate, shared->module(), export_wrappers, env);
|
||||
NewCompiledModule(isolate, shared->module(), env);
|
||||
NativeModule* native_module = compiled_module->GetNativeModule();
|
||||
compiled_module->set_shared(*shared);
|
||||
compiled_module->GetNativeModule()->SetSharedModuleData(shared);
|
||||
Handle<WasmModuleObject> module_object =
|
||||
WasmModuleObject::New(isolate, compiled_module, export_wrappers);
|
||||
if (lazy_compile) {
|
||||
if (wasm_module->is_wasm()) {
|
||||
// Validate wasm modules for lazy compilation. Don't validate asm.js
|
||||
@ -1403,8 +1382,8 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
|
||||
V8::GetCurrentPlatform()->NumberOfWorkerThreads() > 0;
|
||||
|
||||
if (compile_parallel) {
|
||||
CompileInParallel(isolate, native_module, wire_bytes, &env,
|
||||
compiled_module, centry_stub, thrower);
|
||||
CompileInParallel(isolate, native_module, wire_bytes, &env, module_object,
|
||||
centry_stub, thrower);
|
||||
} else {
|
||||
CompileSequentially(isolate, native_module, wire_bytes, &env, thrower);
|
||||
}
|
||||
@ -1414,12 +1393,9 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
|
||||
}
|
||||
|
||||
// Compile JS->wasm wrappers for exported functions.
|
||||
CompileJsToWasmWrappers(isolate, compiled_module,
|
||||
CompileJsToWasmWrappers(isolate, module_object,
|
||||
isolate->async_counters().get());
|
||||
|
||||
Handle<WasmModuleObject> result =
|
||||
WasmModuleObject::New(isolate, compiled_module);
|
||||
|
||||
// If we created a wasm script, finish it now and make it public to the
|
||||
// debugger.
|
||||
if (asm_js_script.is_null()) {
|
||||
@ -1429,7 +1405,7 @@ MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
|
||||
isolate->debug()->OnAfterCompile(script);
|
||||
}
|
||||
|
||||
return result;
|
||||
return module_object;
|
||||
}
|
||||
|
||||
// The runnable task that finishes compilation in foreground (e.g. updating
|
||||
@ -1780,7 +1756,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
//--------------------------------------------------------------------------
|
||||
// Set up the exports object for the new instance.
|
||||
//--------------------------------------------------------------------------
|
||||
ProcessExports(instance, compiled_module_);
|
||||
ProcessExports(instance);
|
||||
if (thrower_->error()) return {};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@ -1802,10 +1778,10 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
|
||||
//--------------------------------------------------------------------------
|
||||
CodeSpecialization code_specialization;
|
||||
code_specialization.RelocateDirectCalls(native_module);
|
||||
code_specialization.ApplyToWholeModule(native_module, compiled_module_,
|
||||
code_specialization.ApplyToWholeModule(native_module, module_object_,
|
||||
SKIP_ICACHE_FLUSH);
|
||||
FlushICache(native_module);
|
||||
FlushICache(handle(compiled_module_->export_wrappers()));
|
||||
FlushICache(handle(module_object_->export_wrappers()));
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Unpack and notify signal handler of protected instructions.
|
||||
@ -2458,10 +2434,8 @@ bool InstanceBuilder::NeedsWrappers() const {
|
||||
|
||||
// Process the exports, creating wrappers for functions, tables, memories,
|
||||
// and globals.
|
||||
void InstanceBuilder::ProcessExports(
|
||||
Handle<WasmInstanceObject> instance,
|
||||
Handle<WasmCompiledModule> compiled_module) {
|
||||
Handle<FixedArray> export_wrappers(compiled_module->export_wrappers(),
|
||||
void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
|
||||
Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
|
||||
isolate_);
|
||||
if (NeedsWrappers()) {
|
||||
// Fill the table to cache the exported JSFunction wrappers.
|
||||
@ -2835,6 +2809,9 @@ void AsyncCompileJob::FinishCompile() {
|
||||
TENURED)
|
||||
.ToHandleChecked();
|
||||
DCHECK(module_bytes->IsSeqOneByteString());
|
||||
int export_wrapper_size = static_cast<int>(module_->num_exported_functions);
|
||||
Handle<FixedArray> export_wrappers =
|
||||
isolate_->factory()->NewFixedArray(export_wrapper_size, TENURED);
|
||||
|
||||
// The {managed_module} will take ownership of the {WasmModule} object,
|
||||
// and it will be destroyed when the GC reclaims the wrapper object.
|
||||
@ -2852,7 +2829,8 @@ void AsyncCompileJob::FinishCompile() {
|
||||
compiled_module_->GetNativeModule()->SetSharedModuleData(shared);
|
||||
|
||||
// Create the module object.
|
||||
module_object_ = WasmModuleObject::New(isolate_, compiled_module_);
|
||||
module_object_ =
|
||||
WasmModuleObject::New(isolate_, compiled_module_, export_wrappers);
|
||||
{
|
||||
DeferredHandleScope deferred(isolate_);
|
||||
module_object_ = handle(*module_object_, isolate_);
|
||||
@ -3047,13 +3025,8 @@ class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
|
||||
// and information needed at instantiation time. This object needs to be
|
||||
// serializable. Instantiation may occur off a deserialized version of
|
||||
// this object.
|
||||
int export_wrapper_size = static_cast<int>(module_->num_exported_functions);
|
||||
Handle<FixedArray> export_wrappers =
|
||||
job_->isolate_->factory()->NewFixedArray(export_wrapper_size, TENURED);
|
||||
|
||||
ModuleEnv env = CreateDefaultModuleEnv(module_);
|
||||
job_->compiled_module_ =
|
||||
NewCompiledModule(job_->isolate_, module_, export_wrappers, env);
|
||||
job_->compiled_module_ = NewCompiledModule(job_->isolate_, module_, env);
|
||||
|
||||
{
|
||||
DeferredHandleScope deferred(job_->isolate_);
|
||||
@ -3174,7 +3147,7 @@ class AsyncCompileJob::CompileWrappers : public CompileStep {
|
||||
// TODO(6792): No longer needed once WebAssembly code is off heap.
|
||||
CodeSpaceMemoryModificationScope modification_scope(job_->isolate_->heap());
|
||||
// Compile JS->wasm wrappers for exported functions.
|
||||
CompileJsToWasmWrappers(job_->isolate_, job_->compiled_module_,
|
||||
CompileJsToWasmWrappers(job_->isolate_, job_->module_object_,
|
||||
job_->counters());
|
||||
job_->DoSync<FinishModule>();
|
||||
}
|
||||
@ -3219,7 +3192,7 @@ class AsyncCompileJob::UpdateToTopTierCompiledCode : public CompileStep {
|
||||
void RunInForeground() override {
|
||||
TRACE_COMPILE("(7) Update native module to use optimized code...\n");
|
||||
|
||||
UpdateAllCompiledModulesWithTopTierCode(job_->compiled_module_);
|
||||
UpdateAllCompiledModulesWithTopTierCode(job_->module_object_);
|
||||
job_->isolate_->wasm_engine()->RemoveCompileJob(job_);
|
||||
}
|
||||
};
|
||||
@ -3656,23 +3629,23 @@ void CompilationState::NotifyOnEvent(CompilationEvent event,
|
||||
}
|
||||
|
||||
void CompileJsToWasmWrappers(Isolate* isolate,
|
||||
Handle<WasmCompiledModule> compiled_module,
|
||||
Handle<WasmModuleObject> module_object,
|
||||
Counters* counters) {
|
||||
JSToWasmWrapperCache js_to_wasm_cache;
|
||||
int wrapper_index = 0;
|
||||
Handle<FixedArray> export_wrappers(compiled_module->export_wrappers(),
|
||||
isolate);
|
||||
NativeModule* native_module = compiled_module->GetNativeModule();
|
||||
Handle<FixedArray> export_wrappers(module_object->export_wrappers(), isolate);
|
||||
NativeModule* native_module =
|
||||
module_object->compiled_module()->GetNativeModule();
|
||||
wasm::UseTrapHandler use_trap_handler =
|
||||
compiled_module->GetNativeModule()->use_trap_handler() ? kUseTrapHandler
|
||||
: kNoTrapHandler;
|
||||
for (auto exp : compiled_module->shared()->module()->export_table) {
|
||||
native_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
|
||||
for (auto exp :
|
||||
module_object->compiled_module()->shared()->module()->export_table) {
|
||||
if (exp.kind != kExternalFunction) continue;
|
||||
wasm::WasmCode* wasm_code =
|
||||
native_module->GetIndirectlyCallableCode(exp.index);
|
||||
Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(
|
||||
isolate, compiled_module->shared()->module(), wasm_code, exp.index,
|
||||
use_trap_handler);
|
||||
isolate, module_object->compiled_module()->shared()->module(),
|
||||
wasm_code, exp.index, use_trap_handler);
|
||||
export_wrappers->set(wrapper_index, *wrapper_code);
|
||||
RecordStats(*wrapper_code, counters);
|
||||
++wrapper_index;
|
||||
|
@ -57,7 +57,7 @@ MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
|
||||
|
||||
V8_EXPORT_PRIVATE
|
||||
void CompileJsToWasmWrappers(Isolate* isolate,
|
||||
Handle<WasmCompiledModule> compiled_module,
|
||||
Handle<WasmModuleObject> module_object,
|
||||
Counters* counters);
|
||||
|
||||
V8_EXPORT_PRIVATE Handle<Script> CreateWasmScript(
|
||||
|
@ -69,14 +69,14 @@ void CodeSpecialization::RelocateDirectCalls(NativeModule* native_module) {
|
||||
}
|
||||
|
||||
bool CodeSpecialization::ApplyToWholeModule(
|
||||
NativeModule* native_module, Handle<WasmCompiledModule> compiled_module,
|
||||
NativeModule* native_module, Handle<WasmModuleObject> module_object,
|
||||
ICacheFlushMode icache_flush_mode) {
|
||||
DisallowHeapAllocation no_gc;
|
||||
WasmSharedModuleData* shared = compiled_module->shared();
|
||||
WasmSharedModuleData* shared = module_object->compiled_module()->shared();
|
||||
WasmModule* module = shared->module();
|
||||
std::vector<WasmFunction>* wasm_functions = &shared->module()->functions;
|
||||
DCHECK_EQ(compiled_module->export_wrappers()->length(),
|
||||
shared->module()->num_exported_functions);
|
||||
FixedArray* export_wrappers = module_object->export_wrappers();
|
||||
DCHECK_EQ(export_wrappers->length(), module->num_exported_functions);
|
||||
|
||||
bool changed = false;
|
||||
int func_index = module->num_imported_functions;
|
||||
@ -106,8 +106,7 @@ bool CodeSpecialization::ApplyToWholeModule(
|
||||
int wrapper_index = 0;
|
||||
for (auto exp : module->export_table) {
|
||||
if (exp.kind != kExternalFunction) continue;
|
||||
Code* export_wrapper =
|
||||
Code::cast(compiled_module->export_wrappers()->get(wrapper_index++));
|
||||
Code* export_wrapper = Code::cast(export_wrappers->get(wrapper_index++));
|
||||
if (export_wrapper->kind() != Code::JS_TO_WASM_FUNCTION) continue;
|
||||
for (RelocIterator it(export_wrapper, reloc_mode); !it.done(); it.next()) {
|
||||
RelocInfo::Mode mode = it.rinfo()->rmode();
|
||||
@ -125,7 +124,7 @@ bool CodeSpecialization::ApplyToWholeModule(
|
||||
}
|
||||
}
|
||||
DCHECK_EQ(module->functions.size(), func_index);
|
||||
DCHECK_EQ(compiled_module->export_wrappers()->length(), wrapper_index);
|
||||
DCHECK_EQ(export_wrappers->length(), wrapper_index);
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,10 @@ namespace wasm {
|
||||
|
||||
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.
|
||||
// Helper class to specialize wasm code for a specific module.
|
||||
//
|
||||
// Note that code is shared among instances belonging to one module, hence all
|
||||
// specialization actions will implicitly apply to all instances of a module.
|
||||
//
|
||||
// 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.
|
||||
@ -25,11 +27,11 @@ class CodeSpecialization {
|
||||
CodeSpecialization();
|
||||
~CodeSpecialization();
|
||||
|
||||
// Update all direct call sites based on the code table in the given instance.
|
||||
// Update all direct call sites based on the code table in the given module.
|
||||
void RelocateDirectCalls(NativeModule* module);
|
||||
// Apply all relocations and patching to all code in the instance (wasm code
|
||||
// and exported functions).
|
||||
bool ApplyToWholeModule(NativeModule*, Handle<WasmCompiledModule>,
|
||||
// Apply all relocations and patching to all code in the module (i.e. wasm
|
||||
// code and exported function wrapper code).
|
||||
bool ApplyToWholeModule(NativeModule*, Handle<WasmModuleObject>,
|
||||
ICacheFlushMode = FLUSH_ICACHE_IF_NEEDED);
|
||||
// Apply all relocations and patching to one wasm code object.
|
||||
bool ApplyToWasmCode(wasm::WasmCode*,
|
||||
|
@ -613,7 +613,7 @@ void RedirectCallsitesInInstance(Isolate* isolate, WasmInstanceObject* instance,
|
||||
// TODO(6668): Find instances that imported our code and also patch those.
|
||||
|
||||
// Redirect all calls in exported functions.
|
||||
FixedArray* export_wrapper = instance->compiled_module()->export_wrappers();
|
||||
FixedArray* export_wrapper = instance->module_object()->export_wrappers();
|
||||
for (int i = 0, e = export_wrapper->length(); i != e; ++i) {
|
||||
Code* code = Code::cast(export_wrapper->get(i));
|
||||
RedirectCallsitesInJSWrapperCode(isolate, code, map);
|
||||
|
@ -50,6 +50,7 @@ CAST_ACCESSOR(WasmTableObject)
|
||||
// WasmModuleObject
|
||||
ACCESSORS(WasmModuleObject, compiled_module, WasmCompiledModule,
|
||||
kCompiledModuleOffset)
|
||||
ACCESSORS(WasmModuleObject, export_wrappers, FixedArray, kExportWrappersOffset)
|
||||
|
||||
WasmSharedModuleData* WasmModuleObject::shared() const {
|
||||
return compiled_module()->shared();
|
||||
@ -232,7 +233,6 @@ OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed<wasm::SignatureMap>,
|
||||
|
||||
// WasmCompiledModule
|
||||
WCM_OBJECT(WasmSharedModuleData, shared, kSharedOffset)
|
||||
WCM_OBJECT(FixedArray, export_wrappers, kExportWrappersOffset)
|
||||
WCM_OBJECT(WasmCompiledModule, next_instance, kNextInstanceOffset)
|
||||
WCM_OBJECT(WasmCompiledModule, prev_instance, kPrevInstanceOffset)
|
||||
WCM_WEAK_LINK(WasmInstanceObject, owning_instance, kOwningInstanceOffset)
|
||||
|
@ -262,12 +262,14 @@ enum DispatchTableElements : int {
|
||||
} // namespace
|
||||
|
||||
Handle<WasmModuleObject> WasmModuleObject::New(
|
||||
Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
|
||||
Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
|
||||
Handle<FixedArray> export_wrappers) {
|
||||
Handle<JSFunction> module_cons(
|
||||
isolate->native_context()->wasm_module_constructor());
|
||||
auto module_object = Handle<WasmModuleObject>::cast(
|
||||
isolate->factory()->NewJSObject(module_cons));
|
||||
module_object->set_compiled_module(*compiled_module);
|
||||
module_object->set_export_wrappers(*export_wrappers);
|
||||
if (compiled_module->shared()->script()->type() == Script::TYPE_WASM) {
|
||||
compiled_module->shared()->script()->set_wasm_module_object(*module_object);
|
||||
}
|
||||
@ -1347,14 +1349,11 @@ MaybeHandle<FixedArray> WasmSharedModuleData::CheckBreakPoints(
|
||||
return break_points_hit;
|
||||
}
|
||||
|
||||
Handle<WasmCompiledModule> WasmCompiledModule::New(
|
||||
Isolate* isolate, WasmModule* module, Handle<FixedArray> export_wrappers,
|
||||
wasm::ModuleEnv& env) {
|
||||
Handle<WasmCompiledModule> WasmCompiledModule::New(Isolate* isolate,
|
||||
WasmModule* module,
|
||||
wasm::ModuleEnv& env) {
|
||||
Handle<WasmCompiledModule> compiled_module = Handle<WasmCompiledModule>::cast(
|
||||
isolate->factory()->NewStruct(WASM_COMPILED_MODULE_TYPE, TENURED));
|
||||
if (!export_wrappers.is_null()) {
|
||||
compiled_module->set_export_wrappers(*export_wrappers);
|
||||
}
|
||||
compiled_module->set_weak_owning_instance(isolate->heap()->empty_weak_cell());
|
||||
{
|
||||
auto native_module =
|
||||
@ -1376,7 +1375,6 @@ Handle<WasmCompiledModule> WasmCompiledModule::Clone(
|
||||
Handle<WasmCompiledModule> ret = Handle<WasmCompiledModule>::cast(
|
||||
isolate->factory()->NewStruct(WASM_COMPILED_MODULE_TYPE, TENURED));
|
||||
ret->set_shared(module->shared());
|
||||
ret->set_export_wrappers(module->export_wrappers());
|
||||
ret->set_weak_owning_instance(isolate->heap()->empty_weak_cell());
|
||||
ret->set_native_module(module->native_module());
|
||||
|
||||
|
@ -107,6 +107,7 @@ class WasmModuleObject : public JSObject {
|
||||
|
||||
// Shared compiled code between multiple WebAssembly.Module objects.
|
||||
DECL_ACCESSORS(compiled_module, WasmCompiledModule)
|
||||
DECL_ACCESSORS(export_wrappers, FixedArray)
|
||||
|
||||
// TODO(mstarzinger): Currently this getter uses an indirection via the
|
||||
// {WasmCompiledModule}, but we will soon move the reference to the shared
|
||||
@ -116,6 +117,7 @@ class WasmModuleObject : public JSObject {
|
||||
// Layout description.
|
||||
#define WASM_MODULE_OBJECT_FIELDS(V) \
|
||||
V(kCompiledModuleOffset, kPointerSize) \
|
||||
V(kExportWrappersOffset, kPointerSize) \
|
||||
V(kSize, 0)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize,
|
||||
@ -123,7 +125,8 @@ class WasmModuleObject : public JSObject {
|
||||
#undef WASM_MODULE_OBJECT_FIELDS
|
||||
|
||||
static Handle<WasmModuleObject> New(
|
||||
Isolate* isolate, Handle<WasmCompiledModule> compiled_module);
|
||||
Isolate* isolate, Handle<WasmCompiledModule> compiled_module,
|
||||
Handle<FixedArray> export_wrappers);
|
||||
|
||||
// Set a breakpoint on the given byte position inside the given module.
|
||||
// This will affect all live and future instances of the module.
|
||||
@ -535,7 +538,6 @@ class WasmCompiledModule : public Struct {
|
||||
// Layout description.
|
||||
#define WASM_COMPILED_MODULE_FIELDS(V) \
|
||||
V(kSharedOffset, kPointerSize) \
|
||||
V(kExportWrappersOffset, kPointerSize) \
|
||||
V(kNextInstanceOffset, kPointerSize) \
|
||||
V(kPrevInstanceOffset, kPointerSize) \
|
||||
V(kOwningInstanceOffset, kPointerSize) \
|
||||
@ -571,7 +573,6 @@ class WasmCompiledModule : public Struct {
|
||||
// By default, instance values go to WasmInstanceObject, however, if
|
||||
// we embed the generated code with a value, then we track that value here.
|
||||
WCM_OBJECT(WasmSharedModuleData, shared)
|
||||
WCM_OBJECT(FixedArray, export_wrappers)
|
||||
WCM_CONST_OBJECT(WasmCompiledModule, next_instance)
|
||||
WCM_CONST_OBJECT(WasmCompiledModule, prev_instance)
|
||||
WCM_WEAK_LINK(WasmInstanceObject, owning_instance)
|
||||
@ -580,7 +581,6 @@ class WasmCompiledModule : public Struct {
|
||||
public:
|
||||
static Handle<WasmCompiledModule> New(Isolate* isolate,
|
||||
wasm::WasmModule* module,
|
||||
Handle<FixedArray> export_wrappers,
|
||||
wasm::ModuleEnv& env);
|
||||
|
||||
static Handle<WasmCompiledModule> Clone(Isolate* isolate,
|
||||
|
@ -614,7 +614,7 @@ Address NativeModuleDeserializer::GetTrampolineOrStubFromTag(uint32_t tag) {
|
||||
}
|
||||
}
|
||||
|
||||
MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
|
||||
MaybeHandle<WasmModuleObject> DeserializeNativeModule(
|
||||
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes) {
|
||||
if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
|
||||
return {};
|
||||
@ -654,7 +654,7 @@ MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
|
||||
wasm::ModuleEnv env(shared->module(), use_trap_handler,
|
||||
wasm::RuntimeExceptionSupport::kRuntimeExceptionSupport);
|
||||
Handle<WasmCompiledModule> compiled_module =
|
||||
WasmCompiledModule::New(isolate, shared->module(), export_wrappers, env);
|
||||
WasmCompiledModule::New(isolate, shared->module(), env);
|
||||
compiled_module->set_shared(*shared);
|
||||
compiled_module->GetNativeModule()->SetSharedModuleData(shared);
|
||||
NativeModuleDeserializer deserializer(isolate,
|
||||
@ -663,14 +663,17 @@ MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
|
||||
Reader reader(data + kVersionSize);
|
||||
if (!deserializer.Read(&reader)) return {};
|
||||
|
||||
Handle<WasmModuleObject> module_object =
|
||||
WasmModuleObject::New(isolate, compiled_module, export_wrappers);
|
||||
|
||||
// TODO(6792): Wrappers below might be cloned using {Factory::CopyCode}. This
|
||||
// requires unlocking the code space here. This should eventually be moved
|
||||
// into the allocator.
|
||||
CodeSpaceMemoryModificationScope modification_scope(isolate->heap());
|
||||
CompileJsToWasmWrappers(isolate, compiled_module, isolate->counters());
|
||||
CompileJsToWasmWrappers(isolate, module_object, isolate->counters());
|
||||
WasmCompiledModule::ReinitializeAfterDeserialization(isolate,
|
||||
compiled_module);
|
||||
return compiled_module;
|
||||
return module_object;
|
||||
}
|
||||
|
||||
} // namespace wasm
|
||||
|
@ -18,7 +18,7 @@ bool SerializeNativeModule(Isolate* isolate,
|
||||
Handle<WasmCompiledModule> compiled_module,
|
||||
Vector<byte> buffer);
|
||||
|
||||
MaybeHandle<WasmCompiledModule> DeserializeNativeModule(
|
||||
MaybeHandle<WasmModuleObject> DeserializeNativeModule(
|
||||
Isolate* isolate, Vector<const byte> data, Vector<const byte> wire_bytes);
|
||||
|
||||
} // namespace wasm
|
||||
|
@ -335,17 +335,18 @@ class WasmSerializationTest {
|
||||
HandleScope scope(serialization_isolate);
|
||||
testing::SetupIsolateForWasmModule(serialization_isolate);
|
||||
|
||||
MaybeHandle<WasmModuleObject> module_object =
|
||||
MaybeHandle<WasmModuleObject> maybe_module_object =
|
||||
serialization_isolate->wasm_engine()->SyncCompile(
|
||||
serialization_isolate, &thrower,
|
||||
ModuleWireBytes(buffer.begin(), buffer.end()));
|
||||
Handle<WasmModuleObject> module_object =
|
||||
maybe_module_object.ToHandleChecked();
|
||||
|
||||
MaybeHandle<WasmCompiledModule> compiled_module(
|
||||
module_object.ToHandleChecked()->compiled_module(),
|
||||
serialization_isolate);
|
||||
CHECK(!compiled_module.is_null());
|
||||
Handle<WasmCompiledModule> compiled_module(
|
||||
module_object->compiled_module());
|
||||
Handle<FixedArray> export_wrappers(module_object->export_wrappers());
|
||||
Handle<JSObject> module_obj = WasmModuleObject::New(
|
||||
serialization_isolate, compiled_module.ToHandleChecked());
|
||||
serialization_isolate, compiled_module, export_wrappers);
|
||||
v8::Local<v8::Object> v8_module_obj = v8::Utils::ToLocal(module_obj);
|
||||
CHECK(v8_module_obj->IsWebAssemblyCompiledModule());
|
||||
|
||||
|
@ -129,14 +129,14 @@ 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<WasmModuleObject> module_object(instance_object()->module_object(),
|
||||
isolate_);
|
||||
Handle<FixedArray> old_arr(module_object->export_wrappers(), isolate_);
|
||||
Handle<FixedArray> new_arr =
|
||||
isolate_->factory()->NewFixedArray(old_arr->length() + 1);
|
||||
old_arr->CopyTo(0, *new_arr, 0, old_arr->length());
|
||||
new_arr->set(old_arr->length(), *ret_code);
|
||||
compiled_module->set_export_wrappers(*new_arr);
|
||||
module_object->set_export_wrappers(*new_arr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -221,11 +221,11 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
|
||||
Handle<FixedArray> export_wrappers = isolate_->factory()->NewFixedArray(0);
|
||||
ModuleEnv env = CreateModuleEnv();
|
||||
Handle<WasmCompiledModule> compiled_module =
|
||||
WasmCompiledModule::New(isolate_, test_module_ptr_, export_wrappers, env);
|
||||
WasmCompiledModule::New(isolate_, test_module_ptr_, env);
|
||||
compiled_module->set_shared(*shared_module_data);
|
||||
compiled_module->GetNativeModule()->SetSharedModuleData(shared_module_data);
|
||||
Handle<WasmModuleObject> module_object =
|
||||
WasmModuleObject::New(isolate_, compiled_module);
|
||||
WasmModuleObject::New(isolate_, compiled_module, export_wrappers);
|
||||
// This method is called when we initialize TestEnvironment. We don't
|
||||
// have a memory yet, so we won't create it here. We'll update the
|
||||
// interpreter when we get a memory. We do have globals, though.
|
||||
|
@ -211,10 +211,10 @@ class TestingModuleBuilder {
|
||||
}
|
||||
void Link() {
|
||||
if (!linked_) {
|
||||
Handle<WasmCompiledModule> compiled(instance_object()->compiled_module());
|
||||
Handle<WasmModuleObject> module(instance_object()->module_object());
|
||||
CodeSpecialization code_specialization;
|
||||
code_specialization.RelocateDirectCalls(native_module_);
|
||||
code_specialization.ApplyToWholeModule(native_module_, compiled);
|
||||
code_specialization.ApplyToWholeModule(native_module_, module);
|
||||
linked_ = true;
|
||||
native_module_->SetExecutable(true);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user