Commit f6fbbc0c authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[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: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53131}
parent a2430e24
......@@ -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(
......
This diff is collapsed.
......@@ -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);
}
......
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