[wasm][debug] Properly mark WebAssembly APIs as side-effect free.
Various WebAssembly APIs that don't have observable side-effects aren't marked as such, leading to the inability of DevTools front-end to generate eager evaluation previews in the Console, and also making them unusable in conditional breakpoints and logpoints. Bug: chromium:1164241 Change-Id: I8f0675d2ed5b362b34a6f6c756d372a61e9e8564 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2891571 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Auto-Submit: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Andreas Haas <ahaas@chromium.org> Cr-Commit-Position: refs/heads/master@{#74563}
This commit is contained in:
parent
5cee1bc1b4
commit
679ccde045
@ -2032,7 +2032,8 @@ Handle<JSFunction> InstallConstructorFunc(Isolate* isolate,
|
||||
Handle<JSObject> object,
|
||||
const char* str,
|
||||
FunctionCallback func) {
|
||||
return InstallFunc(isolate, object, str, func, 1, true, DONT_ENUM);
|
||||
return InstallFunc(isolate, object, str, func, 1, true, DONT_ENUM,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
}
|
||||
|
||||
Handle<String> GetterName(Isolate* isolate, Handle<String> name) {
|
||||
@ -2062,7 +2063,8 @@ void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
|
||||
FunctionCallback setter) {
|
||||
Handle<String> name = v8_str(isolate, str);
|
||||
Handle<JSFunction> getter_func =
|
||||
CreateFunc(isolate, GetterName(isolate, name), getter, false);
|
||||
CreateFunc(isolate, GetterName(isolate, name), getter, false,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
Handle<JSFunction> setter_func =
|
||||
CreateFunc(isolate, SetterName(isolate, name), setter, false);
|
||||
setter_func->shared().set_length(1);
|
||||
@ -2146,11 +2148,12 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
|
||||
JSFunction::SetInitialMap(isolate, module_constructor, module_map,
|
||||
module_proto);
|
||||
InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
|
||||
1);
|
||||
1, false, NONE, SideEffectType::kHasNoSideEffect);
|
||||
InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
|
||||
1);
|
||||
1, false, NONE, SideEffectType::kHasNoSideEffect);
|
||||
InstallFunc(isolate, module_constructor, "customSections",
|
||||
WebAssemblyModuleCustomSections, 2);
|
||||
WebAssemblyModuleCustomSections, 2, false, NONE,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
JSObject::AddProperty(isolate, module_proto, factory->to_string_tag_symbol(),
|
||||
v8_str(isolate, "WebAssembly.Module"), ro_attributes);
|
||||
|
||||
@ -2190,7 +2193,8 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
|
||||
JSFunction::SetInitialMap(isolate, table_constructor, table_map, table_proto);
|
||||
InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
|
||||
InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow, 1);
|
||||
InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1);
|
||||
InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet, 1, false, NONE,
|
||||
SideEffectType::kHasNoSideEffect);
|
||||
InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet, 2);
|
||||
if (enabled_features.has_type_reflection()) {
|
||||
InstallFunc(isolate, table_constructor, "type", WebAssemblyTableType, 1);
|
||||
@ -2230,7 +2234,8 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
|
||||
i::WASM_GLOBAL_OBJECT_TYPE, WasmGlobalObject::kHeaderSize);
|
||||
JSFunction::SetInitialMap(isolate, global_constructor, global_map,
|
||||
global_proto);
|
||||
InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
|
||||
InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0,
|
||||
false, NONE, SideEffectType::kHasNoSideEffect);
|
||||
InstallGetterSetter(isolate, global_proto, "value", WebAssemblyGlobalGetValue,
|
||||
WebAssemblyGlobalSetValue);
|
||||
if (enabled_features.has_type_reflection()) {
|
||||
|
@ -0,0 +1,33 @@
|
||||
Test side-effect-free evaluation of WebAssembly APIs
|
||||
|
||||
Running test: testWebAssemblyGlobal
|
||||
someGlobalGlobal.value: ok
|
||||
someGlobalGlobal.valueOf(): ok
|
||||
new WebAssembly.Global({value: "f32", mutable: true}, 3.14): ok
|
||||
new WebAssembly.Global({value: "f32", mutable: false}, 3.14): ok
|
||||
new WebAssembly.Global({value: "f32", mutable: true}, 3.14).value: ok
|
||||
new WebAssembly.Global({value: "f32", mutable: true}, 3.14).valueOf(): ok
|
||||
|
||||
Running test: testWebAssemblyInstance
|
||||
someGlobalInstance.exports: ok
|
||||
new WebAssembly.Instance(someGlobalModule): ok
|
||||
new WebAssembly.Instance(someGlobalModule).exports: ok
|
||||
|
||||
Running test: testWebAssemblyMemory
|
||||
someGlobalMemory.buffer: ok
|
||||
new WebAssembly.Memory({initial: 1}): ok
|
||||
new WebAssembly.Memory({initial: 1}).buffer: ok
|
||||
|
||||
Running test: testWebAssemblyModule
|
||||
WebAssembly.Module.customSections(someGlobalModule, ".debug_info"): ok
|
||||
WebAssembly.Module.exports(someGlobalModule): ok
|
||||
WebAssembly.Module.imports(someGlobalModule): ok
|
||||
new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES): ok
|
||||
WebAssembly.Module.customSections(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES), ".debug_info"): ok
|
||||
WebAssembly.Module.exports(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES)): ok
|
||||
WebAssembly.Module.imports(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES)): ok
|
||||
|
||||
Running test: testWebAssemblyTable
|
||||
someGlobalTable.get(0): ok
|
||||
new WebAssembly.Table({element: "anyfunc", initial: 1}): ok
|
||||
new WebAssembly.Table({element: "anyfunc", initial: 1}).get(0): ok
|
@ -0,0 +1,72 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
utils.load('test/inspector/wasm-inspector-test.js');
|
||||
|
||||
let {session, contextGroup, Protocol} =
|
||||
InspectorTest.start('Test side-effect-free evaluation of WebAssembly APIs');
|
||||
|
||||
contextGroup.addScript(`
|
||||
var EMPTY_WASM_MODULE_BYTES = new Uint8Array([0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]);
|
||||
var someGlobalGlobal = new WebAssembly.Global({value: "i64"}, 42n);
|
||||
var someGlobalMemory = new WebAssembly.Memory({initial: 1});
|
||||
var someGlobalModule = new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES);
|
||||
var someGlobalInstance = new WebAssembly.Instance(someGlobalModule);
|
||||
var someGlobalTable = new WebAssembly.Table({element: 'anyfunc', initial: 1});
|
||||
someGlobalTable.set(0, x => x);
|
||||
`, 0, 0, 'foo.js');
|
||||
|
||||
async function check(expression) {
|
||||
const {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({expression, throwOnSideEffect: true});
|
||||
InspectorTest.log(`${expression}: ${exceptionDetails ? 'throws' : 'ok'}`);
|
||||
}
|
||||
|
||||
InspectorTest.runAsyncTestSuite([
|
||||
async function testWebAssemblyGlobal() {
|
||||
await Protocol.Runtime.enable();
|
||||
await check('someGlobalGlobal.value');
|
||||
await check('someGlobalGlobal.valueOf()');
|
||||
await check('new WebAssembly.Global({value: "f32", mutable: true}, 3.14)');
|
||||
await check('new WebAssembly.Global({value: "f32", mutable: false}, 3.14)');
|
||||
await check('new WebAssembly.Global({value: "f32", mutable: true}, 3.14).value');
|
||||
await check('new WebAssembly.Global({value: "f32", mutable: true}, 3.14).valueOf()');
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
|
||||
async function testWebAssemblyInstance() {
|
||||
await Protocol.Runtime.enable();
|
||||
await check('someGlobalInstance.exports');
|
||||
await check('new WebAssembly.Instance(someGlobalModule)');
|
||||
await check('new WebAssembly.Instance(someGlobalModule).exports');
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
|
||||
async function testWebAssemblyMemory() {
|
||||
await Protocol.Runtime.enable();
|
||||
await check('someGlobalMemory.buffer');
|
||||
await check('new WebAssembly.Memory({initial: 1})');
|
||||
await check('new WebAssembly.Memory({initial: 1}).buffer');
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
|
||||
async function testWebAssemblyModule() {
|
||||
await Protocol.Runtime.enable();
|
||||
await check('WebAssembly.Module.customSections(someGlobalModule, ".debug_info")');
|
||||
await check('WebAssembly.Module.exports(someGlobalModule)');
|
||||
await check('WebAssembly.Module.imports(someGlobalModule)');
|
||||
await check('new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES)');
|
||||
await check('WebAssembly.Module.customSections(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES), ".debug_info")');
|
||||
await check('WebAssembly.Module.exports(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES))');
|
||||
await check('WebAssembly.Module.imports(new WebAssembly.Module(EMPTY_WASM_MODULE_BYTES))');
|
||||
await Protocol.Runtime.disable();
|
||||
},
|
||||
|
||||
async function testWebAssemblyTable() {
|
||||
await Protocol.Runtime.enable();
|
||||
await check('someGlobalTable.get(0)');
|
||||
await check('new WebAssembly.Table({element: "anyfunc", initial: 1})');
|
||||
await check('new WebAssembly.Table({element: "anyfunc", initial: 1}).get(0)');
|
||||
await Protocol.Runtime.disable();
|
||||
}
|
||||
]);
|
Loading…
Reference in New Issue
Block a user