[wasm] Deduplicate wasm scripts
R=clemensb@chromium.org Bug: v8:6847 Change-Id: I4509a7011a0d32f5bbd2eabf3d2ee6ef5304263d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2124320 Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#66981}
This commit is contained in:
parent
1bb1d634e1
commit
6ebccbd1f4
@ -1604,10 +1604,9 @@ void AsyncCompileJob::PrepareRuntimeObjects() {
|
||||
DCHECK(module_object_.is_null());
|
||||
const WasmModule* module = native_module_->module();
|
||||
auto source_url = stream_ ? stream_->url() : Vector<const char>();
|
||||
Handle<Script> script = CreateWasmScript(
|
||||
isolate_, native_module_->wire_bytes(), VectorOf(module->source_map_url),
|
||||
auto script = isolate_->wasm_engine()->GetOrCreateScript(
|
||||
isolate_, native_module_.get(), VectorOf(module->source_map_url),
|
||||
module->name, source_url);
|
||||
|
||||
Handle<WasmModuleObject> module_object =
|
||||
WasmModuleObject::New(isolate_, native_module_, script);
|
||||
|
||||
|
@ -131,6 +131,31 @@ class WasmGCForegroundTask : public CancelableTask {
|
||||
Isolate* isolate_;
|
||||
};
|
||||
|
||||
class WeakScriptHandle {
|
||||
public:
|
||||
explicit WeakScriptHandle(Handle<Script> handle) {
|
||||
auto global_handle =
|
||||
handle->GetIsolate()->global_handles()->Create(*handle);
|
||||
location_ = std::make_unique<Address*>(global_handle.location());
|
||||
GlobalHandles::MakeWeak(location_.get());
|
||||
}
|
||||
|
||||
WeakScriptHandle(WeakScriptHandle&&) V8_NOEXCEPT = default;
|
||||
|
||||
~WeakScriptHandle() {
|
||||
if (location_) {
|
||||
GlobalHandles::Destroy(*location_);
|
||||
}
|
||||
}
|
||||
|
||||
Handle<Script> handle() { return Handle<Script>(*location_); }
|
||||
|
||||
private:
|
||||
// Store the location in a unique_ptr so that its address stays the same even
|
||||
// when this object is moved/copied.
|
||||
std::unique_ptr<Address*> location_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<NativeModule> NativeModuleCache::MaybeGetNativeModule(
|
||||
@ -320,6 +345,9 @@ struct WasmEngine::IsolateInfo {
|
||||
// grows, never shrinks).
|
||||
std::set<NativeModule*> native_modules;
|
||||
|
||||
// Scripts created for each native module in this isolate.
|
||||
std::unordered_map<NativeModule*, WeakScriptHandle> scripts;
|
||||
|
||||
// Caches whether code needs to be logged on this isolate.
|
||||
bool log_codes;
|
||||
|
||||
@ -462,9 +490,9 @@ MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
|
||||
#endif
|
||||
|
||||
Handle<Script> script =
|
||||
CreateWasmScript(isolate, bytes.module_bytes(),
|
||||
VectorOf(native_module->module()->source_map_url),
|
||||
native_module->module()->name);
|
||||
GetOrCreateScript(isolate, native_module.get(),
|
||||
VectorOf(native_module->module()->source_map_url),
|
||||
native_module->module()->name);
|
||||
|
||||
// Create the compiled module object and populate with compiled functions
|
||||
// and information needed at instantiation time. This object needs to be
|
||||
@ -928,6 +956,7 @@ void WasmEngine::FreeNativeModule(NativeModule* native_module) {
|
||||
IsolateInfo* info = isolates_[isolate].get();
|
||||
DCHECK_EQ(1, info->native_modules.count(native_module));
|
||||
info->native_modules.erase(native_module);
|
||||
info->scripts.erase(native_module);
|
||||
// If there are {WasmCode} objects of the deleted {NativeModule}
|
||||
// outstanding to be logged in this isolate, remove them. Decrementing the
|
||||
// ref count is not needed, since the {NativeModule} dies anyway.
|
||||
@ -1089,6 +1118,29 @@ void WasmEngine::FreeDeadCodeLocked(const DeadCodeMap& dead_code) {
|
||||
}
|
||||
}
|
||||
|
||||
Handle<Script> WasmEngine::GetOrCreateScript(Isolate* isolate,
|
||||
NativeModule* native_module,
|
||||
Vector<const char> source_map_url,
|
||||
WireBytesRef name,
|
||||
Vector<const char> source_url) {
|
||||
base::MutexGuard guard(&mutex_);
|
||||
DCHECK_EQ(1, isolates_.count(isolate));
|
||||
auto& scripts = isolates_[isolate]->scripts;
|
||||
auto it = scripts.find(native_module);
|
||||
if (it != scripts.end()) {
|
||||
Handle<Script> weak_global_handle = it->second.handle();
|
||||
if (weak_global_handle.is_null()) {
|
||||
scripts.erase(it);
|
||||
} else {
|
||||
return Handle<Script>::New(*weak_global_handle, isolate);
|
||||
}
|
||||
}
|
||||
auto script = CreateWasmScript(isolate, native_module->wire_bytes(),
|
||||
source_map_url, name, source_url);
|
||||
scripts.emplace(native_module, WeakScriptHandle(script));
|
||||
return script;
|
||||
}
|
||||
|
||||
void WasmEngine::TriggerGC(int8_t gc_sequence_index) {
|
||||
DCHECK_NULL(current_gc_info_);
|
||||
DCHECK(FLAG_wasm_code_gc);
|
||||
|
@ -335,6 +335,11 @@ class V8_EXPORT_PRIVATE WasmEngine {
|
||||
void FreeDeadCode(const DeadCodeMap&);
|
||||
void FreeDeadCodeLocked(const DeadCodeMap&);
|
||||
|
||||
Handle<Script> GetOrCreateScript(Isolate*, NativeModule*,
|
||||
Vector<const char> source_map_url,
|
||||
WireBytesRef name,
|
||||
Vector<const char> source_url = {});
|
||||
|
||||
// Call on process start and exit.
|
||||
static void InitializeOncePerProcess();
|
||||
static void GlobalTearDown();
|
||||
|
@ -1,15 +1,25 @@
|
||||
Tests how wasm scripts are reported
|
||||
Check that each inspector gets a wasm script at module creation time.
|
||||
Session #1: Script #0 parsed. URL: wasm://wasm/7b04570e. Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #0 parsed. URL: wasm://wasm/7b04570e. Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #1 parsed. URL: wasm://wasm/ba7c35be. Source map URL: wasm://dwarf, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #1 parsed. URL: wasm://wasm/ba7c35be. Source map URL: wasm://dwarf, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #2 parsed. URL: wasm://wasm/1baa71fe. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #2 parsed. URL: wasm://wasm/1baa71fe. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #3 parsed. URL: wasm://wasm/95e97206. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #3 parsed. URL: wasm://wasm/95e97206. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #4 parsed. URL: wasm://wasm/7ab47392. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #4 parsed. URL: wasm://wasm/7ab47392. Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #0 parsed. URL: wasm://wasm/7b04570e. Script ID: 0, Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #0 parsed. URL: wasm://wasm/7b04570e. Script ID: 0, Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #1 parsed. URL: wasm://wasm/7b04570e. Script ID: 0, Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #1 parsed. URL: wasm://wasm/7b04570e. Script ID: 0, Source map URL: , module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #2 parsed. URL: wasm://wasm/ba7c35be. Script ID: 1, Source map URL: wasm://dwarf, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #2 parsed. URL: wasm://wasm/ba7c35be. Script ID: 1, Source map URL: wasm://dwarf, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #3 parsed. URL: wasm://wasm/1baa71fe. Script ID: 2, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #3 parsed. URL: wasm://wasm/1baa71fe. Script ID: 2, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #4 parsed. URL: wasm://wasm/95e97206. Script ID: 3, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #4 parsed. URL: wasm://wasm/95e97206. Script ID: 3, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Script #5 parsed. URL: wasm://wasm/7ab47392. Script ID: 4, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #2: Script #5 parsed. URL: wasm://wasm/7ab47392. Script ID: 4, Source map URL: abc, module begin: 0, module end: 0, code offset: 34
|
||||
Session #1: Source for wasm://wasm/7b04570e:
|
||||
Raw: 00 61 73 6d 01 00 00 00 01 07 02 60 00 00 60 00 00 03 03 02 00 01 07 08 01 04 6d 61 69 6e 00 01 0a 0e 02 03 00 01 0b 08 00 02 40 41 02 1a 0b 0b 00 1b 04 6e 61 6d 65 01 14 02 00 0b 6e 6f 70 46 75 6e 63 74 69 6f 6e 01 04 6d 61 69 6e
|
||||
Imports: []
|
||||
Exports: [main: function]
|
||||
Session #2: Source for wasm://wasm/7b04570e:
|
||||
Raw: 00 61 73 6d 01 00 00 00 01 07 02 60 00 00 60 00 00 03 03 02 00 01 07 08 01 04 6d 61 69 6e 00 01 0a 0e 02 03 00 01 0b 08 00 02 40 41 02 1a 0b 0b 00 1b 04 6e 61 6d 65 01 14 02 00 0b 6e 6f 70 46 75 6e 63 74 69 6f 6e 01 04 6d 61 69 6e
|
||||
Imports: []
|
||||
Exports: [main: function]
|
||||
Session #1: Source for wasm://wasm/7b04570e:
|
||||
Raw: 00 61 73 6d 01 00 00 00 01 07 02 60 00 00 60 00 00 03 03 02 00 01 07 08 01 04 6d 61 69 6e 00 01 0a 0e 02 03 00 01 0b 08 00 02 40 41 02 1a 0b 0b 00 1b 04 6e 61 6d 65 01 14 02 00 0b 6e 6f 70 46 75 6e 63 74 69 6f 6e 01 04 6d 61 69 6e
|
||||
Imports: []
|
||||
|
@ -35,6 +35,15 @@ function testFunction(bytes) {
|
||||
new WebAssembly.Module(new Uint8Array(bytes));
|
||||
}
|
||||
|
||||
// Generate stable IDs.
|
||||
let scriptIds = {};
|
||||
function nextStableId(id) {
|
||||
if (!(id in scriptIds)) {
|
||||
scriptIds[id] = Object.keys(scriptIds).length;
|
||||
}
|
||||
return scriptIds[id];
|
||||
}
|
||||
|
||||
contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction');
|
||||
|
||||
InspectorTest.log(
|
||||
@ -55,6 +64,9 @@ sessions[0].Protocol.Runtime
|
||||
// no debug info
|
||||
testFunction([${createModule()}]);
|
||||
|
||||
// shared script for identical modules
|
||||
testFunction([${createModule()}]);
|
||||
|
||||
// DWARF
|
||||
testFunction([${createModule(dwarfSection)}]);
|
||||
|
||||
@ -87,8 +99,9 @@ function trackScripts(debuggerParams) {
|
||||
|
||||
async function loadScript(
|
||||
{url, scriptId, sourceMapURL, startColumn, endColumn, codeOffset}) {
|
||||
let stableId = nextStableId(scriptId);
|
||||
InspectorTest.log(`Session #${sessionId}: Script #${
|
||||
scripts.length} parsed. URL: ${url}. Source map URL: ${
|
||||
scripts.length} parsed. URL: ${url}. Script ID: ${stableId}, Source map URL: ${
|
||||
sourceMapURL}, module begin: ${startColumn}, module end: ${endColumn}, code offset: ${codeOffset}`);
|
||||
let {result: {scriptSource, bytecode}} =
|
||||
await Protocol.Debugger.getScriptSource({scriptId});
|
||||
|
Loading…
Reference in New Issue
Block a user