diff options
author | Matheus Marchini <mmarchini@netflix.com> | 2020-03-05 10:49:19 -0800 |
---|---|---|
committer | Matheus Marchini <mmarchini@netflix.com> | 2020-03-18 16:23:22 -0700 |
commit | 2883c855e0105b51e5c8020d21458af109ffe3d4 (patch) | |
tree | 26777aad0a398e9f7755c8b65ac76827fe352a81 /deps/v8/test/inspector/debugger | |
parent | 5f0af2af2a67216e00fe07ccda11e889d14abfcd (diff) | |
download | node-new-2883c855e0105b51e5c8020d21458af109ffe3d4.tar.gz |
deps: update V8 to 8.1.307.20
PR-URL: https://github.com/nodejs/node/pull/32116
Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Diffstat (limited to 'deps/v8/test/inspector/debugger')
41 files changed, 2580 insertions, 1207 deletions
diff --git a/deps/v8/test/inspector/debugger/class-private-methods-expected.txt b/deps/v8/test/inspector/debugger/class-private-methods-expected.txt new file mode 100644 index 0000000000..d54076b6d5 --- /dev/null +++ b/deps/v8/test/inspector/debugger/class-private-methods-expected.txt @@ -0,0 +1,205 @@ +Test private class methods + +Running test: testScopesPaused +privateProperties on the base class instance +[ + [0] : { + name : #inc + value : { + className : Function + description : #inc() { this.#field++; return this.#field; } + objectId : <objectId> + type : function + } + } + [1] : { + name : #writeOnly + set : { + className : Function + description : set #writeOnly(val) { this.#field = val; } + objectId : <objectId> + type : function + } + } + [2] : { + get : { + className : Function + description : get #readOnly() { return this.#field; } + objectId : <objectId> + type : function + } + name : #readOnly + } + [3] : { + get : { + className : Function + description : get #accessor() { return this.#field; } + objectId : <objectId> + type : function + } + name : #accessor + set : { + className : Function + description : set #accessor(val) { this.#field = val; } + objectId : <objectId> + type : function + } + } + [4] : { + name : #field + value : { + description : 2 + type : number + value : 2 + } + } +] +Evaluating private methods +{ + result : { + description : 3 + type : number + value : 3 + } +} +Evaluating private methods +{ + result : { + description : 4 + type : number + value : 4 + } +} +Evaluating private accessors +{ + result : { + description : 5 + type : number + value : 5 + } +} +Evaluating read-only accessor +{ + result : { + description : 5 + type : number + value : 5 + } +} +Evaluating write-only accessor +{ + result : { + description : 0 + type : number + value : 0 + } +} +privateProperties on the subclass instance +[ + [0] : { + name : #inc + value : { + className : Function + description : #inc() { this.#field++; return this.#field; } + objectId : <objectId> + type : function + } + } + [1] : { + name : #writeOnly + set : { + className : Function + description : set #writeOnly(val) { this.#field = val; } + objectId : <objectId> + type : function + } + } + [2] : { + get : { + className : Function + description : get #readOnly() { return this.#field; } + objectId : <objectId> + type : function + } + name : #readOnly + } + [3] : { + get : { + className : Function + description : get #accessor() { return this.#field; } + objectId : <objectId> + type : function + } + name : #accessor + set : { + className : Function + description : set #accessor(val) { this.#field = val; } + objectId : <objectId> + type : function + } + } + [4] : { + name : #field + value : { + description : 2 + type : number + value : 2 + } + } + [5] : { + name : #subclassMethod + value : { + className : Function + description : #subclassMethod() { return 'subclassMethod'; } + objectId : <objectId> + type : function + } + } + [6] : { + name : #inc + value : { + className : Function + description : #inc() { return 'subclass #inc'; } + objectId : <objectId> + type : function + } + } +] +Evaluating private methods in the base class from the subclass +{ + exceptionDetails : { + columnNumber : 4 + exception : { + className : SyntaxError + description : SyntaxError: Private field '#subclassMethod' must be declared in an enclosing class at B.fn (<anonymous>:16:7) at run (<anonymous>:30:5) at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught + } + result : { + className : SyntaxError + description : SyntaxError: Private field '#subclassMethod' must be declared in an enclosing class at B.fn (<anonymous>:16:7) at run (<anonymous>:30:5) at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } +} +Evaluating private method in the subclass from the subclass +{ + result : { + type : string + value : subclassMethod + } +} +Evaluating private method shadowing the base class method +{ + result : { + type : string + value : subclass #inc + } +} diff --git a/deps/v8/test/inspector/debugger/class-private-methods-preview-expected.txt b/deps/v8/test/inspector/debugger/class-private-methods-preview-expected.txt new file mode 100644 index 0000000000..ddb1ec7329 --- /dev/null +++ b/deps/v8/test/inspector/debugger/class-private-methods-preview-expected.txt @@ -0,0 +1,30 @@ +Check private methods in object preview. + +Running test: testPrivateMethods +expression: new class extends class { constructor() { return new Proxy({}, {}); } } { #method() { return 1; } } +[ +] +expression: new class { #method() { return 1; } get #accessor() { } set #accessor(val) { } } +[ + [0] : { + name : #method + type : function + value : + } + [1] : { + name : #accessor + type : accessor + } +] +expression: new class extends class { #method() { return 1; } } { get #accessor() { } set #accessor(val) { } } +[ + [0] : { + name : #method + type : function + value : + } + [1] : { + name : #accessor + type : accessor + } +] diff --git a/deps/v8/test/inspector/debugger/class-private-methods-preview.js b/deps/v8/test/inspector/debugger/class-private-methods-preview.js new file mode 100644 index 0000000000..7a8dd87d7d --- /dev/null +++ b/deps/v8/test/inspector/debugger/class-private-methods-preview.js @@ -0,0 +1,38 @@ +// Copyright 2016 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. +// +// Flags: --harmony-private-methods + +let {session, contextGroup, Protocol} = InspectorTest.start("Check private methods in object preview."); + +Protocol.Debugger.enable(); +Protocol.Runtime.enable(); +Protocol.Runtime.onConsoleAPICalled(dumpInternalProperties); + +contextGroup.setupInjectedScriptEnvironment(); + +InspectorTest.runAsyncTestSuite([ + async function testPrivateMethods() { + const expressions = [ + "new class extends class { constructor() { return new Proxy({}, {}); } } { #method() { return 1; } }", + "new class { #method() { return 1; } get #accessor() { } set #accessor(val) { } }", + "new class extends class { #method() { return 1; } } { get #accessor() { } set #accessor(val) { } }", + ]; + for (const expression of expressions) { + InspectorTest.log(`expression: ${expression}`); + await Protocol.Runtime.evaluate({ + expression: `console.table(${expression})`, + generatePreview: true + }); + } + } +]); + +function dumpInternalProperties(message) { + try { + InspectorTest.logMessage(message.params.args[0].preview.properties); + } catch { + InspectorTest.logMessage(message); + } +} diff --git a/deps/v8/test/inspector/debugger/class-private-methods.js b/deps/v8/test/inspector/debugger/class-private-methods.js new file mode 100644 index 0000000000..7aa5f7a61f --- /dev/null +++ b/deps/v8/test/inspector/debugger/class-private-methods.js @@ -0,0 +1,139 @@ +// Copyright 2019 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. + +// Flags: --harmony-private-methods + +let { session, contextGroup, Protocol } = InspectorTest.start( + "Test private class methods" +); + +contextGroup.addScript(` +function run() { + class A { + #field = 2; + + #inc() { this.#field++; return this.#field; } + + set #writeOnly(val) { this.#field = val; } + + get #readOnly() { return this.#field; } + + get #accessor() { return this.#field; } + set #accessor(val) { this.#field = val; } + + fn() { + debugger; + } + }; + const a = new A(); + a.fn(); + + + class B extends A { + #subclassMethod() { return 'subclassMethod'; } + #inc() { return 'subclass #inc'; } + test() { debugger; } + } + + const b = new B(); + b.fn(); + b.test(); +}`); + +InspectorTest.runAsyncTestSuite([ + async function testScopesPaused() { + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({ expression: "run()" }); + + let { + params: { callFrames } + } = await Protocol.Debugger.oncePaused(); // inside a.fn() + let frame = callFrames[0]; + let { result } = await Protocol.Runtime.getProperties({ + objectId: frame.this.objectId + }); + + InspectorTest.log('privateProperties on the base class instance'); + InspectorTest.logMessage(result.privateProperties); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#inc();', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private methods'); + InspectorTest.logObject(result); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#inc();', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private methods'); + InspectorTest.logObject(result); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: '++this.#accessor;', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private accessors'); + InspectorTest.logObject(result); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#readOnly;', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating read-only accessor'); + InspectorTest.logObject(result); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#writeOnly = 0; this.#field;', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating write-only accessor'); + InspectorTest.logObject(result); + + Protocol.Debugger.resume(); + ({ params: { callFrames } } = await Protocol.Debugger.oncePaused()); // b.fn(); + frame = callFrames[0]; + + ({ result } = await Protocol.Runtime.getProperties({ + objectId: frame.this.objectId + })); + InspectorTest.log('privateProperties on the subclass instance'); + InspectorTest.logMessage(result.privateProperties); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#subclassMethod();', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private methods in the base class from the subclass'); + InspectorTest.logMessage(result); + + Protocol.Debugger.resume(); + ({ params: { callFrames } } = await Protocol.Debugger.oncePaused()); // b.test(); + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#subclassMethod();', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private method in the subclass from the subclass'); + InspectorTest.logObject(result); + + ({ result } = await Protocol.Debugger.evaluateOnCallFrame({ + expression: 'this.#inc();', + callFrameId: callFrames[0].callFrameId + })); + + InspectorTest.log('Evaluating private method shadowing the base class method'); + InspectorTest.logObject(result); + + Protocol.Debugger.resume(); + Protocol.Debugger.disable(); + } +]); diff --git a/deps/v8/test/inspector/debugger/pause-on-oom.js b/deps/v8/test/inspector/debugger/pause-on-oom.js index 062c53b0d7..81edfc8ade 100644 --- a/deps/v8/test/inspector/debugger/pause-on-oom.js +++ b/deps/v8/test/inspector/debugger/pause-on-oom.js @@ -11,7 +11,7 @@ var arr = []; var stop = false; function generateGarbage() { while(!stop) { - arr.push(42); + arr.push(new Array(1000)); } } //# sourceURL=test.js`, 10, 26); diff --git a/deps/v8/test/inspector/debugger/wasm-anyref-global.js b/deps/v8/test/inspector/debugger/wasm-anyref-global.js index d9f63d2d20..1c47cfc8d8 100644 --- a/deps/v8/test/inspector/debugger/wasm-anyref-global.js +++ b/deps/v8/test/inspector/debugger/wasm-anyref-global.js @@ -13,7 +13,7 @@ let {session, contextGroup, Protocol} = let builder = new WasmModuleBuilder(); builder.addImportedGlobal('m', 'global', kWasmAnyRef, false); - builder.addFunction('func', kSig_v_v) + let func = builder.addFunction('func', kSig_v_v) .addBody([ kExprGlobalGet, 0, // kExprDrop, // @@ -47,7 +47,7 @@ let {session, contextGroup, Protocol} = InspectorTest.log('Setting breakpoint in wasm.'); await Protocol.Debugger.setBreakpoint( - {location: {scriptId, lineNumber: 2}}); + {location: {scriptId, lineNumber: 0, columnNumber: func.body_offset}}); InspectorTest.log('Running main.'); Protocol.Runtime.evaluate({expression: 'instance.exports.main()'}); diff --git a/deps/v8/test/inspector/debugger/wasm-clone-module-expected.txt b/deps/v8/test/inspector/debugger/wasm-clone-module-expected.txt index d07f035f78..b437d1b253 100644 --- a/deps/v8/test/inspector/debugger/wasm-clone-module-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-clone-module-expected.txt @@ -1,5 +1,5 @@ Tests that cloning a module notifies the debugger -Got URL: wasm://wasm/wasm-95d1e44e/wasm-95d1e44e-0 -Got URL: wasm://wasm/wasm-95d1e44e/wasm-95d1e44e-0 -Got URL: wasm://wasm/wasm-95d1e44e/wasm-95d1e44e-0 +Got URL: wasm://wasm/95d1e44e +Got URL: wasm://wasm/95d1e44e +Got URL: wasm://wasm/95d1e44e Done! diff --git a/deps/v8/test/inspector/debugger/wasm-debug-command-expected.txt b/deps/v8/test/inspector/debugger/wasm-debug-command-expected.txt new file mode 100644 index 0000000000..eadcb7d671 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-debug-command-expected.txt @@ -0,0 +1,11 @@ +Tests debug command for wasm +Installing code and global variable. +Calling instantiate function. +Waiting for wasm scripts to be parsed. +Ignoring script with url v8://test/callInstantiate +Got wasm script: wasm://wasm/fa045c1e +paused No 1 +Script wasm://wasm/fa045c1e byte offset 35: Wasm opcode 0x20 +Debugger.resume +exports.main returned! +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-debug-command.js b/deps/v8/test/inspector/debugger/wasm-debug-command.js new file mode 100644 index 0000000000..672631bca2 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-debug-command.js @@ -0,0 +1,97 @@ +// Copyright 2020 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests debug command for wasm'); +session.setupScriptMap(); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +let builder = new WasmModuleBuilder(); + +// wasm_A +builder.addFunction('wasm_A', kSig_i_i) + .addBody([ + // clang-format off + kExprLocalGet, 0, // Line 1: get input + kExprI32Const, 1, // Line 2: get constant 1 + kExprI32Sub // Line 3: decrease + // clang-format on + ]) + .exportAs('main'); + +let module_bytes = builder.toArray(); + +function instantiate(bytes) { + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + let module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +let evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +let breakCount; + +Protocol.Debugger.onPaused(async message => { + breakCount++; + InspectorTest.log("paused No " + breakCount); + var frames = message.params.callFrames; + await session.logSourceLocation(frames[0].location); + let action= 'resume'; + InspectorTest.log('Debugger.' + action) + await Protocol.Debugger[action](); +}) + +let breakpointId; + +contextGroup.addScript(` +function test() { + debug(instance.exports.main); + instance.exports.main(3, 2); +} +//# sourceURL=test.js`); + +(async function Test() { + breakCount = 0; + breakpointId = 0; + await Protocol.Debugger.enable(); + InspectorTest.log('Installing code and global variable.'); + await evalWithUrl('var instance;\n' + instantiate.toString(), 'setup'); + InspectorTest.log('Calling instantiate function.'); + evalWithUrl( + 'instantiate(' + JSON.stringify(module_bytes) + ')', 'callInstantiate'); + const scriptId = await waitForWasmScript(); + await Protocol.Runtime.evaluate({ expression: 'test()', includeCommandLineAPI: true}); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +})(); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScript() { + InspectorTest.log('Waiting for wasm scripts to be parsed.'); + while (true) { + let msg = await Protocol.Debugger.onceScriptParsed(); + let url = msg.params.url; + if (!url.startsWith('wasm://')) { + InspectorTest.log('Ignoring script with url ' + url); + continue; + } + let scriptId = msg.params.scriptId; + InspectorTest.log('Got wasm script: ' + url); + return scriptId; + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets-expected.txt b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets-expected.txt new file mode 100644 index 0000000000..a0ff4a04a9 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets-expected.txt @@ -0,0 +1,83 @@ +Tests breakable locations in wasm +Running testFunction... +Script nr 0 parsed. URL: v8://test/setup +Script nr 1 parsed. URL: v8://test/runTestFunction +Script nr 2 parsed. URL: wasm://wasm/6a95b41e +This is a wasm script (nr 0). +Querying breakable locations for all wasm scripts now... +Requesting all breakable locations in wasm script 0 +Bytecode matches! +11 breakable location(s): +[0] 0:40 || byte=1 +[1] 0:41 || byte=65 +[2] 0:43 || byte=33 +[3] 0:45 || byte=11 +[4] 0:48 || byte=32 +[5] 0:50 || byte=4 +[6] 0:52 || byte=2 +[7] 0:54 || byte=16 +[8] 0:56 || byte=11 +[9] 0:57 || byte=11 +[10] 0:58 || byte=11 +Requesting breakable locations in offsets [0,45) +3 breakable location(s): +[0] 0:40 || byte=1 +[1] 0:41 || byte=65 +[2] 0:43 || byte=33 +Requesting breakable locations in offsets [50,60) +6 breakable location(s): +[0] 0:50 || byte=4 +[1] 0:52 || byte=2 +[2] 0:54 || byte=16 +[3] 0:56 || byte=11 +[4] 0:57 || byte=11 +[5] 0:58 || byte=11 +Setting a breakpoint on each breakable location... +Setting at wasm://wasm/6a95b41e:0:40 +Success! +Setting at wasm://wasm/6a95b41e:0:41 +Success! +Setting at wasm://wasm/6a95b41e:0:43 +Success! +Setting at wasm://wasm/6a95b41e:0:45 +Success! +Setting at wasm://wasm/6a95b41e:0:48 +Success! +Setting at wasm://wasm/6a95b41e:0:50 +Success! +Setting at wasm://wasm/6a95b41e:0:52 +Success! +Setting at wasm://wasm/6a95b41e:0:54 +Success! +Setting at wasm://wasm/6a95b41e:0:56 +Success! +Setting at wasm://wasm/6a95b41e:0:57 +Success! +Setting at wasm://wasm/6a95b41e:0:58 +Success! +Running wasm code... +Missing breakpoints: 11 +Script nr 3 parsed. URL: v8://test/runWasm +Stopped at wasm://wasm/6a95b41e:0:48 +Missing breakpoints: 10 +Stopped at wasm://wasm/6a95b41e:0:50 +Missing breakpoints: 9 +Stopped at wasm://wasm/6a95b41e:0:52 +Missing breakpoints: 8 +Stopped at wasm://wasm/6a95b41e:0:54 +Missing breakpoints: 7 +Stopped at wasm://wasm/6a95b41e:0:40 +Missing breakpoints: 6 +Stopped at wasm://wasm/6a95b41e:0:41 +Missing breakpoints: 5 +Stopped at wasm://wasm/6a95b41e:0:43 +Missing breakpoints: 4 +Stopped at wasm://wasm/6a95b41e:0:45 +Missing breakpoints: 3 +Stopped at wasm://wasm/6a95b41e:0:56 +Missing breakpoints: 2 +Stopped at wasm://wasm/6a95b41e:0:57 +Missing breakpoints: 1 +Stopped at wasm://wasm/6a95b41e:0:58 +Missing breakpoints: 0 +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets.js b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets.js new file mode 100644 index 0000000000..86b2dc5aaa --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-byte-offsets.js @@ -0,0 +1,245 @@ +// Copyright 2016 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. + +// Flags: --expose-wasm + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm'); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +// clang-format off +var func_idx = builder.addFunction('helper', kSig_v_v) + .addLocals({ i32_count: 1 }) + .addBody([ + kExprNop, + kExprI32Const, 12, + kExprLocalSet, 0, + ]).index; + +builder.addFunction('main', kSig_v_i) + .addBody([ + kExprLocalGet, 0, + kExprIf, kWasmStmt, + kExprBlock, kWasmStmt, + kExprCallFunction, func_idx, + kExprEnd, + kExprEnd + ]).exportAs('main'); +// clang-format on + +var module_bytes = builder.toArray(); + +function testFunction(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; i++) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +var evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +var setupCode = testFunction.toString() + ';\nvar module_bytes = ' + + JSON.stringify(module_bytes) + ';\nvar instance;'; + +Protocol.Debugger.enable(); +Protocol.Debugger.onScriptParsed(handleScriptParsed); + +async function runTest() { + InspectorTest.log('Running testFunction...'); + await evalWithUrl(setupCode, 'setup'); + await evalWithUrl('testFunction(module_bytes)', 'runTestFunction'); + await getBreakableLocationsForAllWasmScripts(); + await setAllBreakableLocations(); + InspectorTest.log('Running wasm code...'); + // Begin executing code: + var promise = evalWithUrl('instance.exports.main(1)', 'runWasm'); + await waitForAllPauses(); + // Code should now complete + await promise; + InspectorTest.log('Finished!'); +} + +runTest() + .catch(reason => InspectorTest.log(`Failed: ${reason}`)) + .then(InspectorTest.completeTest); + +var allBreakableLocations = []; + +var urls = {}; +var numScripts = 0; +var wasmScripts = []; +function handleScriptParsed(messageObject) { + var scriptId = messageObject.params.scriptId; + var url = messageObject.params.url; + urls[scriptId] = url; + InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url); + ++numScripts; + + if (url.startsWith('wasm://')) { + // Only want the full module script, not the function specific ones. + if (url.split('/').length == 4) { + InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').'); + wasmScripts.push(scriptId); + } + } +} + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } +} + +function printBreakableLocations(message, expectedScriptId, bytecode) { + var locations = message.result.locations; + InspectorTest.log(locations.length + ' breakable location(s):'); + for (var i = 0; i < locations.length; ++i) { + if (locations[i].scriptId != expectedScriptId) { + InspectorTest.log( + 'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' + + expectedScriptId); + } + if (locations[i].lineNumber != 0) { + InspectorTest.log(`Unexpected line number: ${bytecode[locations[i].lineNumber]}`); + } + var line = `byte=${bytecode[locations[i].columnNumber]}`; + InspectorTest.log( + '[' + i + '] ' + locations[i].lineNumber + ':' + + locations[i].columnNumber + ' || ' + line); + } +} + +function checkModuleBytes(encoded, bytecode) { + // Encode bytecode as base64. + var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + var PAD = '='; + var ret = ''; + var leftchar = 0; + var leftbits = 0; + for (var i = 0; i < bytecode.length; i++) { + leftchar = (leftchar << 8) | bytecode[i]; + leftbits += 8; + while (leftbits >= 6) { + var curr = (leftchar >> (leftbits-6)) & 0x3f; + leftbits -= 6; + ret += BASE[curr]; + } + } + if (leftbits == 2) { + ret += BASE[(leftchar&3) << 4]; + ret += PAD + PAD; + } else if (leftbits == 4) { + ret += BASE[(leftchar&0xf) << 2]; + ret += PAD; + } + + // Check the base64 strings match. + if(ret == encoded) { + InspectorTest.log('Bytecode matches!'); + } else { + InspectorTest.log('Original: ' + ret); + InspectorTest.log('Returned by API: ' + encoded); + } +} + +async function checkGetBreakableLocations(wasmScriptNr) { + InspectorTest.log( + 'Requesting all breakable locations in wasm script ' + wasmScriptNr); + var scriptId = wasmScripts[wasmScriptNr]; + + var msg = await Protocol.Debugger.getScriptSource({scriptId: scriptId}); + checkModuleBytes(msg.result.bytecode, module_bytes); + + msg = await Protocol.Debugger.getPossibleBreakpoints( + {start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}}); + printFailure(msg); + allBreakableLocations.push(...msg.result.locations); + printBreakableLocations(msg, scriptId, module_bytes); + + InspectorTest.log('Requesting breakable locations in offsets [0,45)'); + msg = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}, + end: {lineNumber: 0, columnNumber: 45, scriptId: scriptId}}); + printFailure(msg); + printBreakableLocations(msg, scriptId, module_bytes); + + InspectorTest.log('Requesting breakable locations in offsets [50,60)'); + msg = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber: 50, scriptId: scriptId}, + end: {lineNumber: 0, columnNumber: 60, scriptId: scriptId}}); + printFailure(msg); + printBreakableLocations(msg, scriptId, module_bytes); +} + +async function getBreakableLocationsForAllWasmScripts() { + InspectorTest.log('Querying breakable locations for all wasm scripts now...'); + for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length; + ++wasmScriptNr) { + await checkGetBreakableLocations(wasmScriptNr); + } +} + +function locationMatches(loc1, loc2) { + return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber && + loc1.columnNumber == loc2.columnNumber; +} + +function locationStr(loc) { + return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber; +} + +async function setBreakpoint(loc) { + InspectorTest.log('Setting at ' + locationStr(loc)); + + var msg = await Protocol.Debugger.setBreakpoint({ 'location': loc }); + printFailure(msg); + + if (locationMatches(loc, msg.result.actualLocation)) { + InspectorTest.log("Success!"); + } else { + InspectorTest.log("Mismatch!"); + InspectorTest.logMessage(msg); + } +} + +async function setAllBreakableLocations() { + InspectorTest.log('Setting a breakpoint on each breakable location...'); + for (var loc of allBreakableLocations) { + await setBreakpoint(loc); + } +} + +function recordPausedLocation(msg) { + var topLocation = msg.params.callFrames[0].location; + InspectorTest.log('Stopped at ' + locationStr(topLocation)); + for (var i = 0; i < allBreakableLocations.length; ++i) { + if (locationMatches(topLocation, allBreakableLocations[i])) { + allBreakableLocations.splice(i, 1); + break; + } + } +} + +async function waitForAllPauses() { + var remaining = allBreakableLocations.length; + InspectorTest.log('Missing breakpoints: ' + remaining); + while (remaining > 0) { + recordPausedLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + remaining--; + InspectorTest.log('Missing breakpoints: ' + remaining); + } + if (allBreakableLocations.length != 0) { + InspectorTest.log('Did not hit all breakable locations: ' + + JSON.stringify(allBreakableLocations)); + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt deleted file mode 100644 index 519d77911b..0000000000 --- a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt +++ /dev/null @@ -1,88 +0,0 @@ -Tests breakable locations in wasm -Running testFunction... -Script nr 0 parsed. URL: v8://test/setup -Script nr 1 parsed. URL: v8://test/runTestFunction -Script nr 2 parsed. URL: wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0 -This is a wasm script (nr 0). -Script nr 3 parsed. URL: wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1 -This is a wasm script (nr 1). -Querying breakable locations for all wasm scripts now... -Requesting all breakable locations in wasm script 0 -4 breakable location(s): -[0] 2:2 || >nop -[1] 3:2 || >i32.const 12 -[2] 4:2 || >local.set 0 -[3] 5:0 || >end -Requesting breakable locations in lines [0,3) -1 breakable location(s): -[0] 2:2 || >nop -Requesting breakable locations in lines [4,6) -2 breakable location(s): -[0] 4:2 || >local.set 0 -[1] 5:0 || >end -Requesting all breakable locations in wasm script 1 -7 breakable location(s): -[0] 1:2 || >local.get 0 -[1] 2:2 || >if -[2] 3:4 || >block -[3] 4:6 || >call 0 -[4] 5:4 || >end -[5] 6:2 || >end -[6] 7:0 || >end -Requesting breakable locations in lines [0,3) -2 breakable location(s): -[0] 1:2 || >local.get 0 -[1] 2:2 || >if -Requesting breakable locations in lines [4,6) -2 breakable location(s): -[0] 4:6 || >call 0 -[1] 5:4 || >end -Setting a breakpoint on each breakable location... -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:2:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:3:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:4:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:5:0 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:1:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:2:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:3:4 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:4:6 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:5:4 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:6:2 -Success! -Setting at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:7:0 -Success! -Running wasm code... -Missing breakpoints: 11 -Script nr 4 parsed. URL: v8://test/runWasm -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:1:2 -Missing breakpoints: 10 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:2:2 -Missing breakpoints: 9 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:3:4 -Missing breakpoints: 8 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:4:6 -Missing breakpoints: 7 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:2:2 -Missing breakpoints: 6 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:3:2 -Missing breakpoints: 5 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:4:2 -Missing breakpoints: 4 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-0:5:0 -Missing breakpoints: 3 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:5:4 -Missing breakpoints: 2 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:6:2 -Missing breakpoints: 1 -Stopped at wasm://wasm/wasm-6a95b41e/wasm-6a95b41e-1:7:0 -Missing breakpoints: 0 -Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations.js b/deps/v8/test/inspector/debugger/wasm-get-breakable-locations.js deleted file mode 100644 index 62f50749f3..0000000000 --- a/deps/v8/test/inspector/debugger/wasm-get-breakable-locations.js +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2016 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. - -// Flags: --expose-wasm - -let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm'); - -utils.load('test/mjsunit/wasm/wasm-module-builder.js'); - -var builder = new WasmModuleBuilder(); - -// clang-format off -var func_idx = builder.addFunction('helper', kSig_v_v) - .addLocals({i32_count: 1}) - .addBody([ - kExprNop, - kExprI32Const, 12, - kExprLocalSet, 0, - ]).index; - -builder.addFunction('main', kSig_v_i) - .addBody([ - kExprLocalGet, 0, - kExprIf, kWasmStmt, - kExprBlock, kWasmStmt, - kExprCallFunction, func_idx, - kExprEnd, - kExprEnd - ]).exportAs('main'); -// clang-format on - -var module_bytes = builder.toArray(); - -function testFunction(bytes) { - var buffer = new ArrayBuffer(bytes.length); - var view = new Uint8Array(buffer); - for (var i = 0; i < bytes.length; i++) { - view[i] = bytes[i] | 0; - } - - var module = new WebAssembly.Module(buffer); - // Set global variable. - instance = new WebAssembly.Instance(module); -} - -var evalWithUrl = (code, url) => Protocol.Runtime.evaluate( - {'expression': code + '\n//# sourceURL=v8://test/' + url}); - -var setupCode = testFunction.toString() + ';\nvar module_bytes = ' + - JSON.stringify(module_bytes) + ';\nvar instance;'; - -Protocol.Debugger.enable(); -Protocol.Debugger.onScriptParsed(handleScriptParsed); -InspectorTest.log('Running testFunction...'); -evalWithUrl(setupCode, 'setup') - .then(() => evalWithUrl('testFunction(module_bytes)', 'runTestFunction')) - .then(getBreakableLocationsForAllWasmScripts) - .then(setAllBreakableLocations) - .then(() => InspectorTest.log('Running wasm code...')) - .then(() => (evalWithUrl('instance.exports.main(1)', 'runWasm'), 0)) - .then(waitForAllPauses) - .then(() => InspectorTest.log('Finished!')) - .then(InspectorTest.completeTest); - -var allBreakableLocations = []; - -var urls = {}; -var numScripts = 0; -var wasmScripts = []; -function handleScriptParsed(messageObject) { - var scriptId = messageObject.params.scriptId; - var url = messageObject.params.url; - urls[scriptId] = url; - InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url); - ++numScripts; - - if (url.startsWith('wasm://')) { - InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').'); - wasmScripts.push(scriptId); - } -} - -function printFailure(message) { - if (!message.result) { - InspectorTest.logMessage(message); - } - return message; -} - -function printBreakableLocations(message, expectedScriptId, source) { - var lines = source.split('\n'); - var locations = message.result.locations; - InspectorTest.log(locations.length + ' breakable location(s):'); - for (var i = 0; i < locations.length; ++i) { - if (locations[i].scriptId != expectedScriptId) { - InspectorTest.log( - 'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' + - expectedScriptId); - } - var line = '<illegal line number>'; - if (locations[i].lineNumber < lines.length) { - line = lines[locations[i].lineNumber]; - if (locations[i].columnNumber < line.length) { - line = line.substr(0, locations[i].columnNumber) + '>' + - line.substr(locations[i].columnNumber); - } - } - InspectorTest.log( - '[' + i + '] ' + locations[i].lineNumber + ':' + - locations[i].columnNumber + ' || ' + line); - } -} - -function checkGetBreakableLocations(wasmScriptNr) { - InspectorTest.log( - 'Requesting all breakable locations in wasm script ' + wasmScriptNr); - var scriptId = wasmScripts[wasmScriptNr]; - var source; - return Protocol.Debugger.getScriptSource({scriptId: scriptId}) - .then(msg => source = msg.result.scriptSource) - .then( - () => Protocol.Debugger.getPossibleBreakpoints( - {start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}})) - .then(printFailure) - .then(msg => (allBreakableLocations.push(...msg.result.locations), msg)) - .then(msg => printBreakableLocations(msg, scriptId, source)) - .then( - () => InspectorTest.log( - 'Requesting breakable locations in lines [0,3)')) - .then(() => Protocol.Debugger.getPossibleBreakpoints({ - start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}, - end: {lineNumber: 3, columnNumber: 0, scriptId: scriptId} - })) - .then(printFailure) - .then(msg => printBreakableLocations(msg, scriptId, source)) - .then( - () => InspectorTest.log( - 'Requesting breakable locations in lines [4,6)')) - .then(() => Protocol.Debugger.getPossibleBreakpoints({ - start: {lineNumber: 4, columnNumber: 0, scriptId: scriptId}, - end: {lineNumber: 6, columnNumber: 0, scriptId: scriptId} - })) - .then(printFailure) - .then(msg => printBreakableLocations(msg, scriptId, source)); -} - -function getBreakableLocationsForAllWasmScripts() { - InspectorTest.log('Querying breakable locations for all wasm scripts now...'); - var promise = Promise.resolve(); - for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length; - ++wasmScriptNr) { - promise = promise.then(checkGetBreakableLocations.bind(null, wasmScriptNr)); - } - return promise; -} - -function locationMatches(loc1, loc2) { - return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber && - loc1.columnNumber == loc2.columnNumber; -} - -function locationStr(loc) { - return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber; -} - -function setBreakpoint(loc) { - InspectorTest.log('Setting at ' + locationStr(loc)); - function check(msg) { - if (locationMatches(loc, msg.result.actualLocation)) { - InspectorTest.log("Success!"); - } else { - InspectorTest.log("Mismatch!"); - InspectorTest.logMessage(msg); - } - } - return Protocol.Debugger.setBreakpoint({'location': loc}) - .then(printFailure) - .then(check); -} - -function setAllBreakableLocations() { - InspectorTest.log('Setting a breakpoint on each breakable location...'); - var promise = Promise.resolve(); - for (var loc of allBreakableLocations) { - promise = promise.then(setBreakpoint.bind(null, loc)); - } - return promise; -} - -function removePausedLocation(msg) { - var topLocation = msg.params.callFrames[0].location; - InspectorTest.log('Stopped at ' + locationStr(topLocation)); - for (var i = 0; i < allBreakableLocations.length; ++i) { - if (locationMatches(topLocation, allBreakableLocations[i])) { - allBreakableLocations.splice(i, 1); - --i; - } - } -} - -function waitForAllPauses() { - InspectorTest.log('Missing breakpoints: ' + allBreakableLocations.length); - if (allBreakableLocations.length == 0) return; - return Protocol.Debugger.oncePaused() - .then(removePausedLocation) - .then(Protocol.Debugger.resume()) - .then(waitForAllPauses); -} diff --git a/deps/v8/test/inspector/debugger/wasm-imports-expected.txt b/deps/v8/test/inspector/debugger/wasm-imports-expected.txt index d67d49742c..eb6b119dc3 100644 --- a/deps/v8/test/inspector/debugger/wasm-imports-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-imports-expected.txt @@ -4,17 +4,11 @@ Calling instantiate function for module A. Waiting for wasm script to be parsed. Got wasm script! Setting breakpoint in line 1: -func $func - #nop -end - +Script wasm://wasm/1871020e byte offset 33: Wasm opcode 0x1 Calling instantiate function for module B. Calling main function on module B. -Paused at 1:2. -func $func - #nop -end - +Paused at 0:33. +Script wasm://wasm/1871020e byte offset 33: Wasm opcode 0x1 Getting current stack trace via "new Error().stack". Error at v8://test/getStack:1:1 diff --git a/deps/v8/test/inspector/debugger/wasm-imports.js b/deps/v8/test/inspector/debugger/wasm-imports.js index 0d83917fa9..2efa7fdcbb 100644 --- a/deps/v8/test/inspector/debugger/wasm-imports.js +++ b/deps/v8/test/inspector/debugger/wasm-imports.js @@ -12,10 +12,9 @@ utils.load('test/mjsunit/wasm/wasm-module-builder.js'); // This failed before (http://crbug.com/v8/5971). var builder_a = new WasmModuleBuilder(); -var func_idx = builder_a.addFunction('func', kSig_v_v) +var func = builder_a.addFunction('func', kSig_v_v) .addBody([kExprNop]) - .exportFunc() - .index; + .exportFunc(); var module_a_bytes = builder_a.toArray(); var builder_b = new WasmModuleBuilder(); @@ -60,7 +59,8 @@ Protocol.Debugger.enable() .then(url => (InspectorTest.log('Setting breakpoint in line 1:'), url)) .then( url => - Protocol.Debugger.setBreakpointByUrl({lineNumber: 1, url: url})) + Protocol.Debugger.setBreakpointByUrl( + {lineNumber: 0, columnNumber: func.body_offset, url: url})) .then(printFailure) .then(msg => session.logSourceLocations(msg.result.locations)) .then(() => InspectorTest.log('Calling instantiate function for module B.')) diff --git a/deps/v8/test/inspector/debugger/wasm-remove-breakpoint-expected.txt b/deps/v8/test/inspector/debugger/wasm-remove-breakpoint-expected.txt new file mode 100644 index 0000000000..1554054e46 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-remove-breakpoint-expected.txt @@ -0,0 +1,19 @@ +Tests remove breakpoint from wasm scripts. +Installing code and global variable. +Calling instantiate function. +Waiting for wasm scripts to be parsed. +Ignoring script with url v8://test/callInstantiate +Got wasm script: wasm://wasm/fa045c1e +Setting breakpoint on line 3 of wasm function +{ + columnNumber : 39 + lineNumber : 0 + scriptId : <scriptId> +} +BreakpointId: 4:0:39:6 +paused No 1 +Script wasm://wasm/fa045c1e byte offset 39: Wasm opcode 0x6b +Remove breakpoint with breakpointId: 4:0:39:6 +Debugger.resume +exports.main returned! +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-remove-breakpoint.js b/deps/v8/test/inspector/debugger/wasm-remove-breakpoint.js new file mode 100644 index 0000000000..bfbf79af3a --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-remove-breakpoint.js @@ -0,0 +1,107 @@ +// Copyright 2019 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests remove breakpoint from wasm scripts.'); +session.setupScriptMap(); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +let builder = new WasmModuleBuilder(); + +// wasm_A +let func = builder.addFunction('wasm_A', kSig_i_i) + .addBody([ + // clang-format off + kExprLocalGet, 0, // Line 1: get input + kExprI32Const, 1, // Line 2: get constant 1 + kExprI32Sub // Line 3: decrease + // clang-format on + ]) + .exportAs('main'); + +let module_bytes = builder.toArray(); + +function instantiate(bytes) { + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + let module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +let evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +let breakCount = 0; +let breakpointId = 0; + +Protocol.Debugger.onPaused(async message => { + breakCount++; + InspectorTest.log("paused No " + breakCount); + var frames = message.params.callFrames; + await session.logSourceLocation(frames[0].location); + if (breakCount == 1) { + InspectorTest.log('Remove breakpoint with breakpointId: ' + breakpointId); + await Protocol.Debugger.removeBreakpoint({breakpointId}); + } + let action= 'resume'; + InspectorTest.log('Debugger.' + action) + await Protocol.Debugger[action](); +}) + +contextGroup.addScript(` +function test() { + instance.exports.main(1); + instance.exports.main(1); +} +//# sourceURL=test.js`); + +(async function Test() { + await Protocol.Debugger.enable(); + InspectorTest.log('Installing code and global variable.'); + await evalWithUrl('var instance;\n' + instantiate.toString(), 'setup'); + InspectorTest.log('Calling instantiate function.'); + evalWithUrl( + 'instantiate(' + JSON.stringify(module_bytes) + ')', 'callInstantiate'); + const scriptId = await waitForWasmScript(); + InspectorTest.log( + 'Setting breakpoint on line 3 of wasm function'); + let msg = await Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': scriptId, 'lineNumber': 0, 'columnNumber': func.body_offset + 4}}); + printFailure(msg); + InspectorTest.logMessage(msg.result.actualLocation); + InspectorTest.logMessage('BreakpointId: '+ msg.result.breakpointId); + breakpointId = msg.result.breakpointId; + await Protocol.Runtime.evaluate({ expression: 'test()' }); + await Protocol.Runtime.evaluate({ expression: 'test()' }); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +})(); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScript() { + InspectorTest.log('Waiting for wasm scripts to be parsed.'); + while (true) { + let msg = await Protocol.Debugger.onceScriptParsed(); + let url = msg.params.url; + if (!url.startsWith('wasm://')) { + InspectorTest.log('Ignoring script with url ' + url); + continue; + } + let scriptId = msg.params.scriptId; + InspectorTest.log('Got wasm script: ' + url); + return scriptId; + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-scope-info-expected.txt b/deps/v8/test/inspector/debugger/wasm-scope-info-expected.txt index cc2df0326c..1ab0977e1f 100644 --- a/deps/v8/test/inspector/debugger/wasm-scope-info-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-scope-info-expected.txt @@ -1,284 +1,308 @@ Test retrieving scope information when pausing in wasm functions -Installing code and global variable. Calling instantiate function. Waiting for wasm script to be parsed. Got wasm script! -Setting breakpoint on line 2 (first instruction) +Setting breakpoint on first instruction of second function { - columnNumber : 2 - lineNumber : 2 + columnNumber : 69 + lineNumber : 0 scriptId : <scriptId> } Paused: -(local i32 i64 f64) - #i32.const 11 - local.set 0 - +Script wasm://wasm/a6e9de16 byte offset 69: Wasm opcode 0x41 Scope: -at func (2:2): +at func (0:69): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 4 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 4 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i32.const 11 - #local.set 0 - i32.const 47 - +Script wasm://wasm/a6e9de16 byte offset 71: Wasm opcode 0x21 Scope: -at func (3:2): +at func (0:71): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 4 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 4 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: "0": 11 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - local.set 0 - #i32.const 47 - local.set 1 - +Script wasm://wasm/a6e9de16 byte offset 73: Wasm opcode 0x41 Scope: -at func (4:2): +at func (0:73): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i32.const 47 - #local.set 1 - i64.const 9223372036854775807 - +Script wasm://wasm/a6e9de16 byte offset 75: Wasm opcode 0x21 Scope: -at func (5:2): +at func (0:75): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 0 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: "0": 47 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - local.set 1 - #i64.const 9223372036854775807 - local.set 2 - +Script wasm://wasm/a6e9de16 byte offset 77: Wasm opcode 0x42 Scope: -at func (6:2): +at func (0:77): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i64.const 9223372036854775807 - #local.set 2 - i64.const -9223372036854775808 - +Script wasm://wasm/a6e9de16 byte offset 88: Wasm opcode 0x21 Scope: -at func (7:2): +at func (0:88): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 0 (number), "unicodeā¼f64": 0 (number) stack: "0": 9223372036854775807 (string) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - local.set 2 - #i64.const -9223372036854775808 - local.set 2 - +Script wasm://wasm/a6e9de16 byte offset 90: Wasm opcode 0x42 Scope: -at func (8:2): +at func (0:90): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 9223372036854775807 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 9223372036854775807 (string), "unicodeā¼f64": 0 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i64.const -9223372036854775808 - #local.set 2 - i32.const 1 - +Script wasm://wasm/a6e9de16 byte offset 101: Wasm opcode 0x21 Scope: -at func (9:2): +at func (0:101): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 9223372036854775807 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": 9223372036854775807 (string), "unicodeā¼f64": 0 (number) stack: "0": -9223372036854775808 (string) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - local.set 2 - #i32.const 1 - f64.convert_i32_u - +Script wasm://wasm/a6e9de16 byte offset 103: Wasm opcode 0x41 Scope: -at func (10:2): +at func (0:103): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i32.const 1 - #f64.convert_i32_u - i32.const 7 - +Script wasm://wasm/a6e9de16 byte offset 105: Wasm opcode 0xb8 Scope: -at func (11:2): +at func (0:105): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: "0": 1 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - f64.convert_i32_u - #i32.const 7 - f64.convert_i32_u - +Script wasm://wasm/a6e9de16 byte offset 106: Wasm opcode 0x41 Scope: -at func (12:2): +at func (0:106): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: "0": 1 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i32.const 7 - #f64.convert_i32_u - f64.div - +Script wasm://wasm/a6e9de16 byte offset 108: Wasm opcode 0xb8 Scope: -at func (13:2): +at func (0:108): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: "0": 1 (number), "1": 7 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - f64.convert_i32_u - #f64.div - local.set 3 - +Script wasm://wasm/a6e9de16 byte offset 109: Wasm opcode 0xa3 Scope: -at func (14:2): +at func (0:109): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: "0": 1 (number), "1": 7 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - f64.div - #local.set 3 - i32.const 15 - +Script wasm://wasm/a6e9de16 byte offset 110: Wasm opcode 0x21 Scope: -at func (15:2): +at func (0:110): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0 (number) stack: "0": 0.14285714285714285 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - local.set 3 - #i32.const 15 - global.set 0 - +Script wasm://wasm/a6e9de16 byte offset 112: Wasm opcode 0x41 Scope: -at func (16:2): +at func (0:112): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - i32.const 15 - #global.set 0 -end - +Script wasm://wasm/a6e9de16 byte offset 114: Wasm opcode 0x24 Scope: -at func (17:2): +at func (0:114): - scope (global): globals: "global#0": 0 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) stack: "0": 15 (number) +at call_func (0:58): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals Paused: - global.set 0 -#end - - +Script wasm://wasm/a6e9de16 byte offset 116: Wasm opcode 0xb Scope: -at func (18:0): +at func (0:116): - scope (global): globals: "global#0": 15 (number) - scope (local): - locals: "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) + locals: "0": 0 (number), "i32Arg": 11 (number), "local#1": 47 (number), "i64_local": -9223372036854775808 (string), "unicodeā¼f64": 0.14285714285714285 (number) stack: +at call_func (0:58): + - scope (global): + globals: "global#0": 15 (number) + - scope (local): at (anonymous) (0:17): - scope (global): -- skipped globals +Paused: +instance.exports.main(4)# + +Scope: +at (anonymous) (0:24): + - scope (global): + -- skipped globals + exports.main returned. Test finished. diff --git a/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff-expected.txt b/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff-expected.txt new file mode 100644 index 0000000000..74d3016a54 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff-expected.txt @@ -0,0 +1,145 @@ +Test retrieving scope information from compiled Liftoff frames +Installing instantiate code. +Waiting for wasm script to be parsed. +Calling instantiate function. +Got wasm script! +Setting breakpoint on line 2 (first instruction) of third function +{ + columnNumber : 85 + lineNumber : 0 + scriptId : <scriptId> +} +Paused: +Script wasm://wasm/89d60696 byte offset 85: Wasm opcode 0x20 +Scope: +at C (interpreted) (0:85): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "i32_arg": 42 (number), "i32_local": 0 (number) + stack: +at B (liftoff) (0:76): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "0": 0 (number), "i32_arg": 42 (number), "i32_local": 0 (number), "f32_local": 7.199999809265137 (number), "local#5": 0 (number) + stack: "0": 42 (number), "1": 3 (number) +at A (liftoff) (0:54): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "arg#0": 42 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped globals + +Paused: +Script wasm://wasm/89d60696 byte offset 87: Wasm opcode 0x24 +Scope: +at C (interpreted) (0:87): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "i32_arg": 42 (number), "i32_local": 0 (number) + stack: "0": 42 (number) +at B (liftoff) (0:76): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "0": 0 (number), "i32_arg": 42 (number), "i32_local": 0 (number), "f32_local": 7.199999809265137 (number), "local#5": 0 (number) + stack: "0": 42 (number), "1": 3 (number) +at A (liftoff) (0:54): + - scope (global): + globals: "global#0": 0 (number) + - scope (local): + locals: "arg#0": 42 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped globals + +Paused: +Script wasm://wasm/89d60696 byte offset 89: Wasm opcode 0x41 +Scope: +at C (interpreted) (0:89): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "i32_arg": 42 (number), "i32_local": 0 (number) + stack: +at B (liftoff) (0:76): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "0": 0 (number), "i32_arg": 42 (number), "i32_local": 0 (number), "f32_local": 7.199999809265137 (number), "local#5": 0 (number) + stack: "0": 42 (number), "1": 3 (number) +at A (liftoff) (0:54): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "arg#0": 42 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped globals + +Paused: +Script wasm://wasm/89d60696 byte offset 91: Wasm opcode 0x21 +Scope: +at C (interpreted) (0:91): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "i32_arg": 42 (number), "i32_local": 0 (number) + stack: "0": 47 (number) +at B (liftoff) (0:76): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "0": 0 (number), "i32_arg": 42 (number), "i32_local": 0 (number), "f32_local": 7.199999809265137 (number), "local#5": 0 (number) + stack: "0": 42 (number), "1": 3 (number) +at A (liftoff) (0:54): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "arg#0": 42 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped globals + +Paused: +Script wasm://wasm/89d60696 byte offset 93: Wasm opcode 0xb +Scope: +at C (interpreted) (0:93): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "i32_arg": 42 (number), "i32_local": 47 (number) + stack: +at B (liftoff) (0:76): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "0": 0 (number), "i32_arg": 42 (number), "i32_local": 0 (number), "f32_local": 7.199999809265137 (number), "local#5": 0 (number) + stack: "0": 42 (number), "1": 3 (number) +at A (liftoff) (0:54): + - scope (global): + globals: "global#0": 42 (number) + - scope (local): + locals: "arg#0": 42 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped globals + +Paused: +instance.exports.main(42)# + +Scope: +at (anonymous) (0:25): + - scope (global): + -- skipped globals + +exports.main returned. Test finished. diff --git a/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff.js b/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff.js new file mode 100644 index 0000000000..a945d77626 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-scope-info-liftoff.js @@ -0,0 +1,171 @@ +// Copyright 2019 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. + +// TODO(clemensb): In the long term this test should also work without any +// flags, once we tier down to Liftoff when the debugger is enabled. +// Flags: --liftoff --no-wasm-tier-up + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'Test retrieving scope information from compiled Liftoff frames'); +session.setupScriptMap(); +Protocol.Debugger.enable(); +Protocol.Debugger.onPaused(printPauseLocationsAndContinue); + +let evaluate = code => Protocol.Runtime.evaluate({expression: code}); + +let breakpointLocation = -1; + +(async function test() { + // Instantiate wasm and wait for three wasm scripts for the three functions. + instantiateWasm(); + let scriptIds = await waitForWasmScripts(); + + // Set a breakpoint. + InspectorTest.log( + 'Setting breakpoint on line 2 (first instruction) of third function'); + let breakpoint = await Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': scriptIds[0], 'lineNumber': 0, 'columnNumber': breakpointLocation}}); + printIfFailure(breakpoint); + InspectorTest.logMessage(breakpoint.result.actualLocation); + + // Now run the wasm code. + await evaluate('instance.exports.main(42)'); + InspectorTest.log('exports.main returned. Test finished.'); + InspectorTest.completeTest(); +})(); + +async function printPauseLocationsAndContinue(msg) { + let loc = msg.params.callFrames[0].location; + InspectorTest.log('Paused:'); + await session.logSourceLocation(loc); + InspectorTest.log('Scope:'); + for (var frame of msg.params.callFrames) { + var isWasmFrame = /^wasm/.test(frame.url); + var functionName = frame.functionName || '(anonymous)'; + var lineNumber = frame.location.lineNumber; + var columnNumber = frame.location.columnNumber; + InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); + for (var scope of frame.scopeChain) { + InspectorTest.logObject(' - scope (' + scope.type + '):'); + if (!isWasmFrame && scope.type == 'global') { + // Skip global scope for non wasm-functions. + InspectorTest.logObject(' -- skipped globals'); + continue; + } + var properties = await Protocol.Runtime.getProperties( + {'objectId': scope.object.objectId}); + await dumpScopeProperties(properties); + } + } + InspectorTest.log(); + Protocol.Debugger.stepOver(); +} + +async function instantiateWasm() { + utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + + var builder = new WasmModuleBuilder(); + // Also add a global, so we have some global scope. + builder.addGlobal(kWasmI32, true); + + // Add two functions without breakpoint, to check that locals and operand + // stack values are shown correctly in Liftoff code. + // Function A will have its parameter spilled to the stack, because it calls + // function B. + // Function B has a local with a constant value (not using a register), the + // parameter will be held in a register. + builder.addFunction('A (liftoff)', kSig_v_i) + .addBody([ + // Call function 'B', forwarding param 0. + kExprLocalGet, 0, kExprCallFunction, 1 + ]) + .exportAs('main'); + + builder.addFunction('B (liftoff)', kSig_v_i) + .addLocals( + {i32_count: 1, f32_count: 4}, + ['i32_arg', 'i32_local', 'f32_local', '0', '0']) + .addBody([ + // Load a parameter and a constant onto the operand stack. + kExprLocalGet, 0, kExprI32Const, 3, + // Set local 2 to 7.2. + ...wasmF32Const(7.2), kExprLocalSet, 2, + // Call function 'C', forwarding param 0. + kExprLocalGet, 0, kExprCallFunction, 2, + // Drop the two operand stack values. + kExprDrop, kExprDrop + ]); + + // A third function which will be stepped through. + let func = builder.addFunction('C (interpreted)', kSig_v_i) + .addLocals({i32_count: 1}, ['i32_arg', 'i32_local']) + .addBody([ + // Set global 0 to param 0. + kExprLocalGet, 0, kExprGlobalSet, 0, + // Set local 1 to 47. + kExprI32Const, 47, kExprLocalSet, 1, + ]); + + var module_bytes = builder.toArray(); + breakpointLocation = func.body_offset; + + function instantiate(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + return new WebAssembly.Instance(module); + } + + InspectorTest.log('Installing instantiate code.'); + await evaluate(instantiate.toString()); + InspectorTest.log('Calling instantiate function.'); + evaluate('var instance = instantiate(' + JSON.stringify(module_bytes) + ');'); +} + +function printIfFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScripts() { + InspectorTest.log('Waiting for wasm script to be parsed.'); + let wasm_script_ids = []; + while (wasm_script_ids.length < 1) { + let script_msg = await Protocol.Debugger.onceScriptParsed(); + let url = script_msg.params.url; + if (url.startsWith('wasm://')) { + InspectorTest.log('Got wasm script!'); + wasm_script_ids.push(script_msg.params.scriptId); + } + } + return wasm_script_ids; +} + +async function getScopeValues(value) { + if (value.type != 'object') { + InspectorTest.log('Expected object. Found:'); + InspectorTest.logObject(value); + return; + } + + let msg = await Protocol.Runtime.getProperties({objectId: value.objectId}); + printIfFailure(msg); + let printProperty = elem => '"' + elem.name + '"' + + ': ' + elem.value.value + ' (' + elem.value.type + ')'; + return msg.result.result.map(printProperty).join(', '); +} + +async function dumpScopeProperties(message) { + printIfFailure(message); + for (var value of message.result.result) { + var value_str = await getScopeValues(value.value); + InspectorTest.log(' ' + value.name + ': ' + value_str); + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-scope-info.js b/deps/v8/test/inspector/debugger/wasm-scope-info.js index 2a5e2961ac..693fb00277 100644 --- a/deps/v8/test/inspector/debugger/wasm-scope-info.js +++ b/deps/v8/test/inspector/debugger/wasm-scope-info.js @@ -2,43 +2,92 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Disable Liftoff to get deterministic (non-existing) scope information for +// compiled frames. +// Flags: --no-liftoff + let {session, contextGroup, Protocol} = InspectorTest.start( 'Test retrieving scope information when pausing in wasm functions'); session.setupScriptMap(); Protocol.Debugger.enable(); +Protocol.Debugger.onPaused(printPauseLocationsAndContinue); let evaluate = code => Protocol.Runtime.evaluate({expression: code}); +let breakpointLocation = undefined; // Will be set by {instantiateWasm}. + (async function test() { - let scriptId = await instantiateWasm(); - await setBreakpoint(scriptId); - printPauseLocationsAndContinue(); + // Instantiate wasm and wait for three wasm scripts for the three functions. + instantiateWasm(); + let scriptIds = await waitForWasmScripts(); + + // Set a breakpoint. + InspectorTest.log( + 'Setting breakpoint on first instruction of second function'); + let breakpoint = await Protocol.Debugger.setBreakpoint({ + 'location' : { + 'scriptId' : scriptIds[0], + 'lineNumber' : 0, + 'columnNumber' : breakpointLocation + } + }); + printIfFailure(breakpoint); + InspectorTest.logMessage(breakpoint.result.actualLocation); + + // Now run the wasm code. await evaluate('instance.exports.main(4)'); InspectorTest.log('exports.main returned. Test finished.'); InspectorTest.completeTest(); })(); -async function printPauseLocationsAndContinue() { - while (true) { - let msg = await Protocol.Debugger.oncePaused(); - let loc = msg.params.callFrames[0].location; - InspectorTest.log('Paused:'); - await session.logSourceLocation(loc); - await dumpScopeChainsOnPause(msg); - Protocol.Debugger.stepOver(); +async function printPauseLocationsAndContinue(msg) { + let loc = msg.params.callFrames[0].location; + InspectorTest.log('Paused:'); + await session.logSourceLocation(loc); + InspectorTest.log('Scope:'); + for (var frame of msg.params.callFrames) { + var isWasmFrame = /^wasm/.test(frame.url); + var functionName = frame.functionName || '(anonymous)'; + var lineNumber = frame.location.lineNumber; + var columnNumber = frame.location.columnNumber; + InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); + for (var scope of frame.scopeChain) { + InspectorTest.logObject(' - scope (' + scope.type + '):'); + if (!isWasmFrame && scope.type == 'global') { + // Skip global scope for non wasm-functions. + InspectorTest.logObject(' -- skipped globals'); + continue; + } + var properties = await Protocol.Runtime.getProperties( + {'objectId': scope.object.objectId}); + await dumpScopeProperties(properties); + } } + InspectorTest.log(); + Protocol.Debugger.stepOver(); } async function instantiateWasm() { utils.load('test/mjsunit/wasm/wasm-module-builder.js'); var builder = new WasmModuleBuilder(); + // Also add a global, so we have some global scope. builder.addGlobal(kWasmI32, true); - builder.addFunction('func', kSig_v_i) + // Add a function without breakpoint, to check that locals are shown + // correctly in compiled code. + builder.addFunction('call_func', kSig_v_i).addLocals({f32_count: 1}).addBody([ + // Set local 1 to 7.2. + ...wasmF32Const(7.2), kExprLocalSet, 1, + // Call function 'func', forwarding param 0. + kExprLocalGet, 0, kExprCallFunction, 1 + ]).exportAs('main'); + + // A second function which will be stepped through. + let func = builder.addFunction('func', kSig_v_i) .addLocals( - {i32_count: 1, i64_count: 1, f64_count: 1}, - ['i32Arg', undefined, 'i64_local', 'unicodeā¼f64']) + {i32_count: 1, i64_count: 1, f64_count: 3}, + ['i32Arg', undefined, 'i64_local', 'unicodeā¼f64', '0', '0']) .addBody([ // Set param 0 to 11. kExprI32Const, 11, kExprLocalSet, 0, @@ -56,10 +105,10 @@ async function instantiateWasm() { // Set global 0 to 15 kExprI32Const, 15, kExprGlobalSet, 0, - ]) - .exportAs('main'); + ]); - var module_bytes = builder.toArray(); + let moduleBytes = builder.toArray(); + breakpointLocation = func.body_offset; function instantiate(bytes) { var buffer = new ArrayBuffer(bytes.length); @@ -69,43 +118,32 @@ async function instantiateWasm() { } var module = new WebAssembly.Module(buffer); - // Set global variable. - instance = new WebAssembly.Instance(module); + return new WebAssembly.Instance(module); } - InspectorTest.log('Installing code and global variable.'); - await evaluate('var instance;\n' + instantiate.toString()); InspectorTest.log('Calling instantiate function.'); - evaluate('instantiate(' + JSON.stringify(module_bytes) + ')'); - return waitForWasmScript(); + evaluate(`var instance = (${instantiate})(${JSON.stringify(moduleBytes)})`); } -async function setBreakpoint(scriptId) { - InspectorTest.log('Setting breakpoint on line 2 (first instruction)'); - let breakpoint = await Protocol.Debugger.setBreakpoint( - {'location': {'scriptId': scriptId, 'lineNumber': 2}}); - printFailure(breakpoint); - InspectorTest.logMessage(breakpoint.result.actualLocation); -} - -function printFailure(message) { +function printIfFailure(message) { if (!message.result) { InspectorTest.logMessage(message); } return message; } -async function waitForWasmScript() { +async function waitForWasmScripts() { InspectorTest.log('Waiting for wasm script to be parsed.'); - while (true) { + let wasm_script_ids = []; + while (wasm_script_ids.length < 1) { let script_msg = await Protocol.Debugger.onceScriptParsed(); let url = script_msg.params.url; - if (!url.startsWith('wasm://')) { - continue; + if (url.startsWith('wasm://')) { + InspectorTest.log('Got wasm script!'); + wasm_script_ids.push(script_msg.params.scriptId); } - InspectorTest.log('Got wasm script!'); - return script_msg.params.scriptId; } + return wasm_script_ids; } async function getScopeValues(value) { @@ -116,39 +154,16 @@ async function getScopeValues(value) { } let msg = await Protocol.Runtime.getProperties({objectId: value.objectId}); - printFailure(msg); + printIfFailure(msg); let printProperty = elem => '"' + elem.name + '"' + ': ' + elem.value.value + ' (' + elem.value.type + ')'; return msg.result.result.map(printProperty).join(', '); } async function dumpScopeProperties(message) { - printFailure(message); + printIfFailure(message); for (var value of message.result.result) { var value_str = await getScopeValues(value.value); InspectorTest.log(' ' + value.name + ': ' + value_str); } } - -async function dumpScopeChainsOnPause(message) { - InspectorTest.log(`Scope:`); - for (var frame of message.params.callFrames) { - var isWasmFrame = /^wasm/.test(frame.url); - var functionName = frame.functionName || '(anonymous)'; - var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber; - var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber; - InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); - for (var scope of frame.scopeChain) { - InspectorTest.logObject(' - scope (' + scope.type + '):'); - if (!isWasmFrame && scope.type == 'global') { - // Skip global scope for non wasm-functions. - InspectorTest.logObject(' -- skipped globals'); - continue; - } - var properties = await Protocol.Runtime.getProperties( - {'objectId': scope.object.objectId}); - await dumpScopeProperties(properties); - } - } - InspectorTest.log(); -} diff --git a/deps/v8/test/inspector/debugger/wasm-scripts-expected.txt b/deps/v8/test/inspector/debugger/wasm-scripts-expected.txt index 210292c858..3918e210a3 100644 --- a/deps/v8/test/inspector/debugger/wasm-scripts-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-scripts-expected.txt @@ -1,72 +1,52 @@ Tests how wasm scripts are reported -Check that each inspector gets two wasm scripts at module creation time. -Session #1: Script #0 parsed. URL: wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-0. Source map URL: -Session #1: Script #1 parsed. URL: wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-1. Source map URL: -Session #2: Script #0 parsed. URL: wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-0. Source map URL: -Session #2: Script #1 parsed. URL: wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-1. Source map URL: -Session #1: Script #2 parsed. URL: wasm://wasm/wasm-74f86b7e. Source map URL: wasm://dwarf -Session #2: Script #2 parsed. URL: wasm://wasm/wasm-74f86b7e. Source map URL: wasm://dwarf -Session #1: Script #3 parsed. URL: wasm://wasm/wasm-3754e3fe. Source map URL: abc -Session #2: Script #3 parsed. URL: wasm://wasm/wasm-3754e3fe. Source map URL: abc -Session #1: Script #4 parsed. URL: wasm://wasm/wasm-2bd2e40e. Source map URL: abc -Session #2: Script #4 parsed. URL: wasm://wasm/wasm-2bd2e40e. Source map URL: abc -Session #1: Script #5 parsed. URL: wasm://wasm/wasm-f568e726. Source map URL: abc -Session #2: Script #5 parsed. URL: wasm://wasm/wasm-f568e726. Source map URL: abc -Session #1: Source for wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-0: -func $nopFunction - nop -end - -Session #1: Source for wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-1: -func $main - block - i32.const 2 - drop - end -end - -Session #2: Source for wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-0: -func $nopFunction - nop -end - -Session #2: Source for wasm://wasm/wasm-f608ae1e/wasm-f608ae1e-1: -func $main - block - i32.const 2 - drop - end -end - -Session #1: Source for wasm://wasm/wasm-74f86b7e: +Check that each inspector gets a wasm script at module creation time. +Session #1: Script #0 parsed. URL: wasm://wasm/f608ae1e. Source map URL: +Session #2: Script #0 parsed. URL: wasm://wasm/f608ae1e. Source map URL: +Session #1: Script #1 parsed. URL: wasm://wasm/74f86b7e. Source map URL: wasm://dwarf +Session #2: Script #1 parsed. URL: wasm://wasm/74f86b7e. Source map URL: wasm://dwarf +Session #1: Script #2 parsed. URL: wasm://wasm/3754e3fe. Source map URL: abc +Session #2: Script #2 parsed. URL: wasm://wasm/3754e3fe. Source map URL: abc +Session #1: Script #3 parsed. URL: wasm://wasm/2bd2e40e. Source map URL: abc +Session #2: Script #3 parsed. URL: wasm://wasm/2bd2e40e. Source map URL: abc +Session #1: Script #4 parsed. URL: wasm://wasm/f568e726. Source map URL: abc +Session #2: Script #4 parsed. URL: wasm://wasm/f568e726. Source map URL: abc +Session #1: Source for wasm://wasm/f608ae1e: +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/f608ae1e: +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/74f86b7e: 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 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 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/wasm-74f86b7e: +Session #2: Source for wasm://wasm/74f86b7e: 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 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 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/wasm-3754e3fe: +Session #1: Source for wasm://wasm/3754e3fe: 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 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 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/wasm-3754e3fe: +Session #2: Source for wasm://wasm/3754e3fe: 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 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 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/wasm-2bd2e40e: +Session #1: Source for wasm://wasm/2bd2e40e: 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 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 00 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 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/wasm-2bd2e40e: +Session #2: Source for wasm://wasm/2bd2e40e: 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 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 00 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 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/wasm-f568e726: +Session #1: Source for wasm://wasm/f568e726: 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 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 00 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 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/wasm-f568e726: +Session #2: Source for wasm://wasm/f568e726: 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 15 10 73 6f 75 72 63 65 4d 61 70 70 69 6e 67 55 52 4c 03 61 62 63 00 11 0b 2e 64 65 62 75 67 5f 69 6e 66 6f 01 02 03 04 05 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] diff --git a/deps/v8/test/inspector/debugger/wasm-scripts-with-name-expected.txt b/deps/v8/test/inspector/debugger/wasm-scripts-with-name-expected.txt new file mode 100644 index 0000000000..f655ff17e7 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-scripts-with-name-expected.txt @@ -0,0 +1,7 @@ +Tests how wasm scripts are reported with name +Check that the inspector gets four wasm scripts at module creation time. +Session #1: Script #0 parsed. URL: wasm://wasm/49a8663e. +Session #1: Script #1 parsed. URL: wasm://wasm/moduleName-aea4a206. +Session #1: Source for wasm://wasm/49a8663e: + +Session #1: Source for wasm://wasm/moduleName-aea4a206: diff --git a/deps/v8/test/inspector/debugger/wasm-scripts-with-name.js b/deps/v8/test/inspector/debugger/wasm-scripts-with-name.js new file mode 100644 index 0000000000..7cf17190c0 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-scripts-with-name.js @@ -0,0 +1,75 @@ +// Copyright 2019 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. + +// Flags: --expose-wasm + +InspectorTest.log("Tests how wasm scripts are reported with name"); + +let contextGroup = new InspectorTest.ContextGroup(); +let sessions = [ + // Main session. + trackScripts(), +]; + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); +builder.addFunction('nopFunction', kSig_v_v).addBody([kExprNop]); +var module_bytes = builder.toArray(); +builder.setName('moduleName'); +var module_bytes_with_name = builder.toArray(); + +function testFunction(bytes) { + // Compilation triggers registration of wasm scripts. + new WebAssembly.Module(new Uint8Array(bytes)); +} + +contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction'); +contextGroup.addScript('var module_bytes = ' + JSON.stringify(module_bytes)); +contextGroup.addScript('var module_bytes_with_name = ' + JSON.stringify(module_bytes_with_name)); + +InspectorTest.log( + 'Check that the inspector gets four wasm scripts at module creation time.'); + +sessions[0].Protocol.Runtime + .evaluate({ + 'expression': '//# sourceURL=v8://test/runTestRunction\n' + + 'testFunction(module_bytes); testFunction(module_bytes_with_name);' + }) + .then(() => ( + // At this point all scripts were parsed. + // Stop tracking and wait for script sources in each session. + Promise.all(sessions.map(session => session.getScripts())) + )) + .catch(err => { + InspectorTest.log(err.stack); + }) + .then(() => InspectorTest.completeTest()); + +function trackScripts(debuggerParams) { + let {id: sessionId, Protocol} = contextGroup.connect(); + let scripts = []; + + Protocol.Debugger.enable(debuggerParams); + Protocol.Debugger.onScriptParsed(handleScriptParsed); + + async function loadScript({url, scriptId}) { + InspectorTest.log(`Session #${sessionId}: Script #${scripts.length} parsed. URL: ${url}.`); + let scriptSource; + ({result: {scriptSource}} = await Protocol.Debugger.getScriptSource({scriptId})); + InspectorTest.log(`Session #${sessionId}: Source for ${url}:`); + InspectorTest.log(scriptSource); + } + + function handleScriptParsed({params}) { + if (params.url.startsWith("wasm://")) { + scripts.push(loadScript(params)); + } + } + + return { + Protocol, + getScripts: () => Promise.all(scripts), + }; +} diff --git a/deps/v8/test/inspector/debugger/wasm-scripts.js b/deps/v8/test/inspector/debugger/wasm-scripts.js index 72d886b0e5..6a342922a8 100644 --- a/deps/v8/test/inspector/debugger/wasm-scripts.js +++ b/deps/v8/test/inspector/debugger/wasm-scripts.js @@ -38,7 +38,7 @@ function testFunction(bytes) { contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction'); InspectorTest.log( - 'Check that each inspector gets two wasm scripts at module creation time.'); + 'Check that each inspector gets a wasm script at module creation time.'); // Sample .debug_info section. // Content doesn't matter, as we don't try to parse it in V8, @@ -78,30 +78,6 @@ sessions[0].Protocol.Runtime }) .then(() => InspectorTest.completeTest()); -function decodeBase64(base64) { - const LOOKUP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - - const paddingLength = base64.match(/=*$/)[0].length; - const bytesLength = base64.length * 0.75 - paddingLength; - - let bytes = new Uint8Array(bytesLength); - - for (let i = 0, p = 0; i < base64.length; i += 4, p += 3) { - let bits = 0; - for (let j = 0; j < 4; j++) { - bits <<= 6; - const c = base64[i + j]; - if (c !== '=') bits |= LOOKUP.indexOf(c); - } - for (let j = p + 2; j >= p; j--) { - if (j < bytesLength) bytes[j] = bits; - bits >>= 8; - } - } - - return bytes; -} - function trackScripts(debuggerParams) { let {id: sessionId, Protocol} = contextGroup.connect(); let scripts = []; @@ -111,11 +87,14 @@ function trackScripts(debuggerParams) { async function loadScript({url, scriptId, sourceMapURL}) { InspectorTest.log(`Session #${sessionId}: Script #${scripts.length} parsed. URL: ${url}. Source map URL: ${sourceMapURL}`); - let scriptSource; - if (sourceMapURL) { - let {result: {bytecode}} = await Protocol.Debugger.getWasmBytecode({scriptId}); + let {result: {scriptSource, bytecode}} = await Protocol.Debugger.getScriptSource({scriptId}); + if (bytecode) { + if (scriptSource) { + InspectorTest.log('Unexpected scriptSource with bytecode: '); + InspectorTest.log(scriptSource); + } // Binary value is represented as base64 in JSON, decode it. - bytecode = decodeBase64(bytecode); + bytecode = InspectorTest.decodeBase64(bytecode); // Check that it can be parsed back to a WebAssembly module. let module = new WebAssembly.Module(bytecode); scriptSource = ` @@ -123,15 +102,13 @@ Raw: ${Array.from(bytecode, b => ('0' + b.toString(16)).slice(-2)).join(' ')} Imports: [${WebAssembly.Module.imports(module).map(i => `${i.name}: ${i.kind} from "${i.module}"`).join(', ')}] Exports: [${WebAssembly.Module.exports(module).map(e => `${e.name}: ${e.kind}`).join(', ')}] `.trim(); - } else { - ({result: {scriptSource}} = await Protocol.Debugger.getScriptSource({scriptId})); } InspectorTest.log(`Session #${sessionId}: Source for ${url}:`); InspectorTest.log(scriptSource); } function handleScriptParsed({params}) { - if (params.url.startsWith("wasm://")) { + if (params.url.startsWith('wasm://')) { scripts.push(loadScript(params)); } } diff --git a/deps/v8/test/inspector/debugger/wasm-set-breakpoint-expected.txt b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-expected.txt index 29ee78c65a..b53a17610b 100644 --- a/deps/v8/test/inspector/debugger/wasm-set-breakpoint-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-expected.txt @@ -1,58 +1,38 @@ Tests stepping through wasm scripts. Instantiating. -Waiting for two wasm scripts (ignoring first non-wasm script). -Source of script wasm://wasm/wasm-18214bfe/wasm-18214bfe-0: -1: func $wasm_A -2: nop -3: nop -4: end - -Source of script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1: -1: func $wasm_B (param i32) -2: loop -3: local.get 0 -4: if -5: local.get 0 -6: i32.const 1 -7: i32.sub -8: local.set 0 -9: call 0 -10: br 1 -11: end -12: end -13: end - -Setting breakpoint on line 8 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Setting breakpoint on line 7 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Setting breakpoint on line 6 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Setting breakpoint on line 5 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Setting breakpoint on line 3 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Setting breakpoint on line 4 on script wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 +Waiting for wasm script (ignoring first non-wasm script). +Setting breakpoint at offset 54 on script wasm://wasm/18214bfe +Setting breakpoint at offset 53 on script wasm://wasm/18214bfe +Setting breakpoint at offset 51 on script wasm://wasm/18214bfe +Setting breakpoint at offset 49 on script wasm://wasm/18214bfe +Setting breakpoint at offset 45 on script wasm://wasm/18214bfe +Setting breakpoint at offset 47 on script wasm://wasm/18214bfe Calling main(4) -Breaking on line 3 -Breaking on line 4 -Breaking on line 5 -Breaking on line 6 -Breaking on line 7 -Breaking on line 8 -Breaking on line 3 -Breaking on line 4 -Breaking on line 5 -Breaking on line 6 -Breaking on line 7 -Breaking on line 8 -Breaking on line 3 -Breaking on line 4 -Breaking on line 5 -Breaking on line 6 -Breaking on line 7 -Breaking on line 8 -Breaking on line 3 -Breaking on line 4 -Breaking on line 5 -Breaking on line 6 -Breaking on line 7 -Breaking on line 8 -Breaking on line 3 +Breaking on byte offset 45 +Breaking on byte offset 47 +Breaking on byte offset 49 +Breaking on byte offset 51 +Breaking on byte offset 53 +Breaking on byte offset 54 +Breaking on byte offset 45 +Breaking on byte offset 47 +Breaking on byte offset 49 +Breaking on byte offset 51 +Breaking on byte offset 53 +Breaking on byte offset 54 +Breaking on byte offset 45 +Breaking on byte offset 47 +Breaking on byte offset 49 +Breaking on byte offset 51 +Breaking on byte offset 53 +Breaking on byte offset 54 +Breaking on byte offset 45 +Breaking on byte offset 47 +Breaking on byte offset 49 +Breaking on byte offset 51 +Breaking on byte offset 53 +Breaking on byte offset 54 +Breaking on byte offset 45 +Breaking on byte offset 47 exports.main returned! Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff-expected.txt b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff-expected.txt new file mode 100644 index 0000000000..735fc49f44 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff-expected.txt @@ -0,0 +1,12 @@ +Tests stepping through wasm scripts. +Instantiating. +Waiting for wasm script (ignoring first non-wasm script). +Setting breakpoint at offset 54 on script wasm://wasm/18214bfe +Setting breakpoint at offset 53 on script wasm://wasm/18214bfe +Setting breakpoint at offset 51 on script wasm://wasm/18214bfe +Setting breakpoint at offset 49 on script wasm://wasm/18214bfe +Setting breakpoint at offset 45 on script wasm://wasm/18214bfe +Setting breakpoint at offset 47 on script wasm://wasm/18214bfe +Calling main(4) +exports.main returned! +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff.js b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff.js new file mode 100644 index 0000000000..ce70f91921 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-set-breakpoint-liftoff.js @@ -0,0 +1,93 @@ +// Copyright 2020 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. + +// Flags: --debug-in-liftoff + +const {session, contextGroup, Protocol} = + InspectorTest.start('Tests stepping through wasm scripts.'); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +const builder = new WasmModuleBuilder(); + +const func_a_idx = + builder.addFunction('wasm_A', kSig_v_v).addBody([kExprNop, kExprNop]).index; + +// wasm_B calls wasm_A <param0> times. +const func_b = builder.addFunction('wasm_B', kSig_v_i) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprLocalGet, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + kExprLocalGet, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprLocalSet, 0, // decrease <param0> + kExprCallFunction, func_a_idx, // - + kExprBr, 1, // continue + kExprEnd, // - + kExprEnd, // break + // clang-format on + ]) + .exportAs('main'); + +const module_bytes = builder.toArray(); + +function instantiate(bytes) { + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + let module = new WebAssembly.Module(buffer); + return new WebAssembly.Instance(module); +} + +const getResult = msg => msg.result || InspectorTest.logMessage(msg); + +const evalWithUrl = (code, url) => + Protocol.Runtime + .evaluate({'expression': code + '\n//# sourceURL=v8://test/' + url}) + .then(getResult); + +function setBreakpoint(offset, script) { + InspectorTest.log( + 'Setting breakpoint at offset ' + offset + ' on script ' + script.url); + return Protocol.Debugger + .setBreakpoint( + {'location': {'scriptId': script.scriptId, 'lineNumber': 0, 'columnNumber': offset}}) + .then(getResult); +} + +Protocol.Debugger.onPaused(pause_msg => { + let loc = pause_msg.params.callFrames[0].location; + if (loc.lineNumber != 0) { + InspectorTest.log('Unexpected line number: ' + loc.lineNumber); + } + InspectorTest.log('Breaking on byte offset ' + loc.columnNumber); + Protocol.Debugger.resume(); +}); + +(async function test() { + await Protocol.Debugger.enable(); + InspectorTest.log('Instantiating.'); + // Spawn asynchronously: + let instantiate_code = 'const instance = (' + instantiate + ')(' + + JSON.stringify(module_bytes) + ');'; + evalWithUrl(instantiate_code, 'instantiate'); + InspectorTest.log( + 'Waiting for wasm script (ignoring first non-wasm script).'); + // Ignore javascript and full module wasm script, get scripts for functions. + const [, {params: wasm_script}] = await Protocol.Debugger.onceScriptParsed(2); + for (offset of [11, 10, 8, 6, 2, 4]) { + await setBreakpoint(func_b.body_offset + offset, wasm_script); + } + InspectorTest.log('Calling main(4)'); + await evalWithUrl('instance.exports.main(4)', 'runWasm'); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +})(); diff --git a/deps/v8/test/inspector/debugger/wasm-set-breakpoint.js b/deps/v8/test/inspector/debugger/wasm-set-breakpoint.js index 1696a0f59c..0c73cf5dba 100644 --- a/deps/v8/test/inspector/debugger/wasm-set-breakpoint.js +++ b/deps/v8/test/inspector/debugger/wasm-set-breakpoint.js @@ -13,7 +13,7 @@ const func_a_idx = builder.addFunction('wasm_A', kSig_v_v).addBody([kExprNop, kExprNop]).index; // wasm_B calls wasm_A <param0> times. -builder.addFunction('wasm_B', kSig_v_i) +const func_b = builder.addFunction('wasm_B', kSig_v_i) .addBody([ // clang-format off kExprLoop, kWasmStmt, // while @@ -51,18 +51,21 @@ const evalWithUrl = (code, url) => .evaluate({'expression': code + '\n//# sourceURL=v8://test/' + url}) .then(getResult); -function setBreakpoint(line, script) { +function setBreakpoint(offset, script) { InspectorTest.log( - 'Setting breakpoint on line ' + line + ' on script ' + script.url); + 'Setting breakpoint at offset ' + offset + ' on script ' + script.url); return Protocol.Debugger .setBreakpoint( - {'location': {'scriptId': script.scriptId, 'lineNumber': line}}) + {'location': {'scriptId': script.scriptId, 'lineNumber': 0, 'columnNumber': offset}}) .then(getResult); } Protocol.Debugger.onPaused(pause_msg => { let loc = pause_msg.params.callFrames[0].location; - InspectorTest.log('Breaking on line ' + loc.lineNumber); + if (loc.lineNumber != 0) { + InspectorTest.log('Unexpected line number: ' + loc.lineNumber); + } + InspectorTest.log('Breaking on byte offset ' + loc.columnNumber); Protocol.Debugger.resume(); }); @@ -74,19 +77,11 @@ Protocol.Debugger.onPaused(pause_msg => { JSON.stringify(module_bytes) + ');'; evalWithUrl(instantiate_code, 'instantiate'); InspectorTest.log( - 'Waiting for two wasm scripts (ignoring first non-wasm script).'); - const [, {params: wasm_script_a}, {params: wasm_script_b}] = - await Protocol.Debugger.onceScriptParsed(3); - for (script of [wasm_script_a, wasm_script_b]) { - InspectorTest.log('Source of script ' + script.url + ':'); - let src_msg = - await Protocol.Debugger.getScriptSource({scriptId: script.scriptId}); - let lines = getResult(src_msg).scriptSource.replace(/\s+$/, '').split('\n'); - InspectorTest.log( - lines.map((line, nr) => (nr + 1) + ': ' + line).join('\n') + '\n'); - } - for (line of [8, 7, 6, 5, 3, 4]) { - await setBreakpoint(line, wasm_script_b); + 'Waiting for wasm script (ignoring first non-wasm script).'); + // Ignore javascript and full module wasm script, get scripts for functions. + const [, {params: wasm_script}] = await Protocol.Debugger.onceScriptParsed(2); + for (offset of [11, 10, 8, 6, 2, 4]) { + await setBreakpoint(func_b.body_offset + offset, wasm_script); } InspectorTest.log('Calling main(4)'); await evalWithUrl('instance.exports.main(4)', 'runWasm'); diff --git a/deps/v8/test/inspector/debugger/wasm-source-expected.txt b/deps/v8/test/inspector/debugger/wasm-source-expected.txt index b140be0876..e81fa564dc 100644 --- a/deps/v8/test/inspector/debugger/wasm-source-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-source-expected.txt @@ -1,10 +1,10 @@ Tests how wasm scrips report the source -Check that inspector gets disassembled wasm code +Check that inspector gets wasm bytecode Paused on debugger! Number of frames: 5 [0] debugger; -[1] call 0 -[2] call_indirect 2 +[1] Wasm offset 72: 0x10 +[2] Wasm offset 81: 0x11 [3] instance.exports.main(); [4] testFunction(module_bytes) Finished. diff --git a/deps/v8/test/inspector/debugger/wasm-source.js b/deps/v8/test/inspector/debugger/wasm-source.js index 6c5b14c4be..55da49f446 100644 --- a/deps/v8/test/inspector/debugger/wasm-source.js +++ b/deps/v8/test/inspector/debugger/wasm-source.js @@ -51,30 +51,37 @@ contextGroup.addScript('var module_bytes = ' + JSON.stringify(module_bytes)); Protocol.Debugger.enable(); Protocol.Debugger.onPaused(handleDebuggerPaused); -InspectorTest.log('Check that inspector gets disassembled wasm code'); +InspectorTest.log('Check that inspector gets wasm bytecode'); Protocol.Runtime.evaluate({'expression': 'testFunction(module_bytes)'}); -function handleDebuggerPaused(message) { +async function handleDebuggerPaused(message) { InspectorTest.log('Paused on debugger!'); var frames = message.params.callFrames; InspectorTest.log('Number of frames: ' + frames.length); - function dumpSourceLine(frameId, sourceMessage) { + async function dumpSourceLine(frameId, sourceMessage) { if (sourceMessage.error) InspectorTest.logObject(sourceMessage); var text = sourceMessage.result.scriptSource; var lineNr = frames[frameId].location.lineNumber; - var line = text.split('\n')[lineNr]; - InspectorTest.log('[' + frameId + '] ' + line); + if (text) { + var line = text.split('\n')[lineNr]; + InspectorTest.log('[' + frameId + '] ' + line); + } else { + if (lineNr != 0) { + InspectorTest.log('Unexpected line number in wasm: ' + lineNr); + } + let byteOffset = frames[frameId].location.columnNumber; + let data = InspectorTest.decodeBase64(sourceMessage.result.bytecode); + // Print a byte, which can be compared to the expected wasm opcode. + InspectorTest.log('[' + frameId + '] Wasm offset ' + byteOffset + + ': 0x' + data[byteOffset].toString(16)); + } } - function next(frameId) { - if (frameId == frames.length) return Promise.resolve(); - return Protocol.Debugger - .getScriptSource({scriptId: frames[frameId].location.scriptId}) - .then(dumpSourceLine.bind(null, frameId)) - .then(() => next(frameId + 1)); - } - function finished() { - InspectorTest.log('Finished.'); - InspectorTest.completeTest(); + + for (let frameId = 0; frameId < frames.length; frameId++) { + result = await Protocol.Debugger + .getScriptSource({scriptId: frames[frameId].location.scriptId}); + await dumpSourceLine(frameId, result); } - next(0).then(finished); + InspectorTest.log('Finished.'); + InspectorTest.completeTest(); } diff --git a/deps/v8/test/inspector/debugger/wasm-stack-expected.txt b/deps/v8/test/inspector/debugger/wasm-stack-expected.txt index 1d6f51b997..364a319b93 100644 --- a/deps/v8/test/inspector/debugger/wasm-stack-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-stack-expected.txt @@ -3,8 +3,8 @@ Running testFunction with generated wasm bytes... Paused on 'debugger;' Number of frames: 5 - [0] {"functionName":"call_debugger","function_lineNumber":1,"function_columnNumber":24,"lineNumber":2,"columnNumber":4} - - [1] {"functionName":"call_func","lineNumber":1,"columnNumber":2} - - [2] {"functionName":"main","lineNumber":2,"columnNumber":4} + - [1] {"functionName":"call_func","lineNumber":0,"columnNumber":55} + - [2] {"functionName":"main","lineNumber":0,"columnNumber":62} - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":14,"columnNumber":19} - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} Getting v8-generated stack trace... diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets-expected.txt b/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets-expected.txt new file mode 100644 index 0000000000..409e7cc002 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets-expected.txt @@ -0,0 +1,300 @@ +Tests stepping through wasm scripts by byte offsets +Setting up global instance variable. +Got wasm script: wasm://wasm/7dfc8356 +Setting breakpoint on offset 59 (should be propagated to 60, the offset of the call), url wasm://wasm/7dfc8356 +{ + columnNumber : 60 + lineNumber : 0 + scriptId : <scriptId> +} +Paused at wasm://wasm/7dfc8356:0:60 +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} + stack: {"0":1024} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:39 +at wasm_A (0:39): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOver called +Paused at wasm://wasm/7dfc8356:0:40 +at wasm_A (0:40): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/7dfc8356:0:62 +at wasm_B (0:62): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/7dfc8356:0:60 +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} + stack: {"0":1024} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOver called +Paused at wasm://wasm/7dfc8356:0:62 +at wasm_B (0:62): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:44 +at wasm_B (0:44): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.resume called +Paused at wasm://wasm/7dfc8356:0:60 +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {"0":1024} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:39 +at wasm_A (0:39): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/7dfc8356:0:62 +at wasm_B (0:62): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:44 +at wasm_B (0:44): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:46 +at wasm_B (0:46): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:48 +at wasm_B (0:48): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {"0":1} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:50 +at wasm_B (0:50): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:52 +at wasm_B (0:52): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {"0":1} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:54 +at wasm_B (0:54): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {"0":1,"1":1} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:55 +at wasm_B (0:55): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} + stack: {"0":0} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:57 +at wasm_B (0:57): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:60 +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {"0":1024} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:39 +at wasm_A (0:39): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:40 +at wasm_A (0:40): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:41 +at wasm_A (0:41): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1024} + stack: {} +at wasm_B (0:60): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/7dfc8356:0:62 +at wasm_B (0:62): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} + stack: {} +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.resume called +exports.main returned! +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets.js b/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets.js new file mode 100644 index 0000000000..738544d418 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-byte-offsets.js @@ -0,0 +1,124 @@ +// Copyright 2019 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests stepping through wasm scripts by byte offsets'); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +var func_a_idx = + builder.addFunction('wasm_A', kSig_v_i).addBody([kExprNop, kExprNop]).index; + +// wasm_B calls wasm_A <param0> times. +builder.addFunction('wasm_B', kSig_v_i) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprLocalGet, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + kExprLocalGet, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprLocalSet, 0, // decrease <param0> + ...wasmI32Const(1024), // some longer i32 const (2 byte imm) + kExprCallFunction, func_a_idx, // - + kExprBr, 1, // continue + kExprEnd, // - + kExprEnd, // break + // clang-format on + ]) + .exportAs('main'); + + +var module_bytes = builder.toArray(); + +function instantiate(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +(async function test() { + for (const action of ['stepInto', 'stepOver', 'stepOut', 'resume']) + InspectorTest.logProtocolCommandCalls('Debugger.' + action); + + await Protocol.Debugger.enable(); + InspectorTest.log('Setting up global instance variable.'); + Protocol.Runtime.evaluate({ + expression: `var instance;` + + `(${instantiate.toString()})(${JSON.stringify(module_bytes)})` + }); + const [, {params: wasmScript}] = await Protocol.Debugger.onceScriptParsed(2); + + InspectorTest.log('Got wasm script: ' + wasmScript.url); + + // Set the breakpoint on a non-breakable position. This should resolve to the + // next instruction. + InspectorTest.log( + `Setting breakpoint on offset 59 (should be propagated to 60, the ` + + `offset of the call), url ${wasmScript.url}`); + const bpmsg = await Protocol.Debugger.setBreakpoint({ + location: {scriptId: wasmScript.scriptId, lineNumber: 0, columnNumber: 59} + }); + + const actualLocation = bpmsg.result.actualLocation; + InspectorTest.logMessage(actualLocation); + Protocol.Runtime.evaluate({ expression: 'instance.exports.main(4)' }); + await waitForPauseAndStep('stepInto'); // into call to wasm_A + await waitForPauseAndStep('stepOver'); // over first nop + await waitForPauseAndStep('stepOut'); // out of wasm_A + await waitForPauseAndStep('stepOut'); // out of wasm_B, stop on breakpoint + await waitForPauseAndStep('stepOver'); // over call + await waitForPauseAndStep('stepInto'); // == stepOver br + await waitForPauseAndStep('resume'); // to next breakpoint (3rd iteration) + await waitForPauseAndStep('stepInto'); // into wasm_A + await waitForPauseAndStep('stepOut'); // out to wasm_B + // Now step 10 times, until we are in wasm_A again. + for (let i = 0; i < 10; ++i) await waitForPauseAndStep('stepInto'); + // 3 more times, back to wasm_B. + for (let i = 0; i < 3; ++i) await waitForPauseAndStep('stepInto'); + // Then just resume. + await waitForPauseAndStep('resume'); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished!'); +})().catch(reason => InspectorTest.log(`Failed: ${reason}`)) + .finally(InspectorTest.completeTest); + +async function waitForPauseAndStep(stepAction) { + const {params: {callFrames}} = await Protocol.Debugger.oncePaused(); + const topFrame = callFrames[0]; + InspectorTest.log( + `Paused at ${topFrame.url}:${topFrame.location.lineNumber}:${topFrame.location.columnNumber}`); + for (var frame of callFrames) { + const functionName = frame.functionName || '(anonymous)'; + const lineNumber = frame.location.lineNumber; + const columnNumber = frame.location.columnNumber; + InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); + for (var scope of frame.scopeChain) { + InspectorTest.logObject(' - scope (' + scope.type + '):'); + if (scope.type === 'global') { + InspectorTest.logObject(' -- skipped'); + } else { + const {result: {result: {value}}} = + await Protocol.Runtime.callFunctionOn({ + objectId: scope.object.objectId, + functionDeclaration: 'function() { return this; }', + returnByValue: true + }); + if (value.locals) + InspectorTest.log(` locals: ${JSON.stringify(value.locals)}`); + InspectorTest.log(` stack: ${JSON.stringify(value.stack)}`); + } + } + } + Protocol.Debugger[stepAction](); +} diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-expected.txt b/deps/v8/test/inspector/debugger/wasm-stepping-expected.txt deleted file mode 100644 index 4a1fd58f2b..0000000000 --- a/deps/v8/test/inspector/debugger/wasm-stepping-expected.txt +++ /dev/null @@ -1,330 +0,0 @@ -Tests stepping through wasm scripts -Installing code an global variable. -Calling instantiate function. -Waiting for two wasm scripts to be parsed. -Ignoring script with url v8://test/callInstantiate -Got wasm script: wasm://wasm/wasm-18214bfe/wasm-18214bfe-0 -Requesting source for wasm://wasm/wasm-18214bfe/wasm-18214bfe-0... -Got wasm script: wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -Requesting source for wasm://wasm/wasm-18214bfe/wasm-18214bfe-1... -func $wasm_A - nop - nop -end - -func $wasm_B (param i32) - loop - local.get 0 - if - local.get 0 - i32.const 1 - i32.sub - local.set 0 - call 0 - br 1 - end - end -end - -Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/wasm-18214bfe/wasm-18214bfe-1 -{ - columnNumber : 6 - lineNumber : 7 - scriptId : <scriptId> -} -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:7:6: >local.set 0 -at wasm_B (7:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":4} (Object) - stack: {"0":3} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:8:6: >call 0 -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":3} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:1:2: >nop -at wasm_A (1:2): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":3} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOver called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:2:2: >nop -at wasm_A (2:2): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":3} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOut called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:9:6: >br 1 -at wasm_B (9:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":3} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOut called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:7:6: >local.set 0 -at wasm_B (7:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":3} (Object) - stack: {"0":2} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOver called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:8:6: >call 0 -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":2} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOver called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:9:6: >br 1 -at wasm_B (9:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":2} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.resume called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:7:6: >local.set 0 -at wasm_B (7:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":2} (Object) - stack: {"0":1} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:8:6: >call 0 -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:1:2: >nop -at wasm_A (1:2): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepOut called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:9:6: >br 1 -at wasm_B (9:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:1:2: >loop -at wasm_B (1:2): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:2:4: >local.get 0 -at wasm_B (2:4): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:3:4: >if -at wasm_B (3:4): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {"0":1} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:4:6: >local.get 0 -at wasm_B (4:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:5:6: >i32.const 1 -at wasm_B (5:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {"0":1} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:6:6: >i32.sub -at wasm_B (6:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {"0":1,"1":1} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:7:6: >local.set 0 -at wasm_B (7:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":1} (Object) - stack: {"0":0} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:8:6: >call 0 -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":0} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:1:2: >nop -at wasm_A (1:2): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":0} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:2:2: >nop -at wasm_A (2:2): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":0} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-0:3:0: >end -at wasm_A (3:0): - - scope (global): - -- skipped - - scope (local): - stack: {} (Object) -at wasm_B (8:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":0} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.stepInto called -Paused at wasm://wasm/wasm-18214bfe/wasm-18214bfe-1:9:6: >br 1 -at wasm_B (9:6): - - scope (global): - -- skipped - - scope (local): - locals: {"arg#0":0} (Object) - stack: {} (Object) -at (anonymous) (0:17): - - scope (global): - -- skipped -Debugger.resume called -exports.main returned! -Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js-expected.txt b/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js-expected.txt new file mode 100644 index 0000000000..422aa8b9f3 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js-expected.txt @@ -0,0 +1,32 @@ +Tests stepping from javascript into wasm +Installing code and global variable. +Calling instantiate function. +Waiting for wasm scripts to be parsed. +Ignoring script with url v8://test/callInstantiate +Got wasm script: wasm://wasm/fa045c1e +Setting breakpoint on line 3 of wasm function +{ + columnNumber : 37 + lineNumber : 0 + scriptId : <scriptId> +} +paused +function test() { + #debugger; + instance.exports.main(1); + +Debugger.stepInto +paused + debugger; + #instance.exports.main(1); +} + +Debugger.stepInto +paused +Script wasm://wasm/fa045c1e byte offset 35: Wasm opcode 0x20 +Debugger.resume +paused +Script wasm://wasm/fa045c1e byte offset 37: Wasm opcode 0x41 +Debugger.resume +exports.main returned! +Finished! diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js.js b/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js.js new file mode 100644 index 0000000000..f8c0b9dbbb --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-in-from-js.js @@ -0,0 +1,104 @@ +// Copyright 2019 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests stepping from javascript into wasm'); +session.setupScriptMap(); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +let builder = new WasmModuleBuilder(); + +// wasm_A +let func = builder.addFunction('wasm_A', kSig_i_i) + .addBody([ + // clang-format off + kExprLocalGet, 0, // Line 1: get input + kExprI32Const, 1, // Line 2: get constant 1 + kExprI32Sub // Line 3: decrease + // clang-format on + ]) + .exportAs('main'); + +let module_bytes = builder.toArray(); + +function instantiate(bytes) { + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + let module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +let evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +Protocol.Debugger.onPaused(async message => { + InspectorTest.log("paused"); + var frames = message.params.callFrames; + await session.logSourceLocation(frames[0].location); + let action = step_actions.shift() || 'resume'; + InspectorTest.log('Debugger.' + action) + await Protocol.Debugger[action](); +}) + +let step_actions = [ + 'stepInto', // # debugger + 'stepInto', // step into instance.exports.main(1) + 'resume', // move to breakpoint + // then just resume. + 'resume', +]; + +contextGroup.addScript(` +function test() { + debugger; + instance.exports.main(1); +} +//# sourceURL=test.js`); + +(async function Test() { + await Protocol.Debugger.enable(); + InspectorTest.log('Installing code and global variable.'); + await evalWithUrl('var instance;\n' + instantiate.toString(), 'setup'); + InspectorTest.log('Calling instantiate function.'); + evalWithUrl( + 'instantiate(' + JSON.stringify(module_bytes) + ')', 'callInstantiate'); + const scriptId = await waitForWasmScript(); + InspectorTest.log( + 'Setting breakpoint on line 3 of wasm function'); + let msg = await Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': scriptId, 'lineNumber': 0, 'columnNumber': 2 + func.body_offset}}); + printFailure(msg); + InspectorTest.logMessage(msg.result.actualLocation); + await Protocol.Runtime.evaluate({ expression: 'test()' }); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +})(); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScript() { + InspectorTest.log('Waiting for wasm scripts to be parsed.'); + while (true) { + let msg = await Protocol.Debugger.onceScriptParsed(); + let url = msg.params.url; + if (!url.startsWith('wasm://')) { + InspectorTest.log('Ignoring script with url ' + url); + continue; + } + let scriptId = msg.params.scriptId; + InspectorTest.log('Got wasm script: ' + url); + return scriptId; + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-to-js-expected.txt b/deps/v8/test/inspector/debugger/wasm-stepping-to-js-expected.txt new file mode 100644 index 0000000000..962456cabf --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-to-js-expected.txt @@ -0,0 +1,62 @@ +Tests stepping to javascript from wasm +Installing code and global variable. +Calling instantiate function. +Waiting for wasm scripts to be parsed. +Ignoring script with url v8://test/callInstantiate +Got wasm script: wasm://wasm/485e942e +Setting breakpoint at start of wasm function +{ + columnNumber : 33 + lineNumber : 0 + scriptId : <scriptId> +} +Start run 1 +paused +function test() { + #debugger; + instance.exports.main(); + +Debugger.resume +paused +Script wasm://wasm/485e942e byte offset 33: Wasm opcode 0x1 +Debugger.stepOut +paused + instance.exports.main(); + var x = #1; + x++; + +Debugger.resume +exports.main returned! +Finished run 1! + +Start run 2 +paused +function test() { + #debugger; + instance.exports.main(); + +Debugger.resume +paused +Script wasm://wasm/485e942e byte offset 33: Wasm opcode 0x1 +Debugger.stepOver +paused +Script wasm://wasm/485e942e byte offset 34: Wasm opcode 0xb +Debugger.resume +exports.main returned! +Finished run 2! + +Start run 3 +paused +function test() { + #debugger; + instance.exports.main(); + +Debugger.resume +paused +Script wasm://wasm/485e942e byte offset 33: Wasm opcode 0x1 +Debugger.stepInto +paused +Script wasm://wasm/485e942e byte offset 34: Wasm opcode 0xb +Debugger.resume +exports.main returned! +Finished run 3! diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-to-js.js b/deps/v8/test/inspector/debugger/wasm-stepping-to-js.js new file mode 100644 index 0000000000..f480e4e567 --- /dev/null +++ b/deps/v8/test/inspector/debugger/wasm-stepping-to-js.js @@ -0,0 +1,123 @@ +// Copyright 2019 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests stepping to javascript from wasm'); +session.setupScriptMap(); + +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +let builder = new WasmModuleBuilder(); + +// wasm_A +let func = builder.addFunction('wasm_A', kSig_v_v) + .addBody([ + // clang-format off + kExprNop, // Line 1 + // clang-format on + ]) + .exportAs('main'); + +let module_bytes = builder.toArray(); + +function instantiate(bytes) { + let buffer = new ArrayBuffer(bytes.length); + let view = new Uint8Array(buffer); + for (let i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + let module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +let evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +Protocol.Debugger.onPaused(async message => { + InspectorTest.log("paused"); + var frames = message.params.callFrames; + await session.logSourceLocation(frames[0].location); + let action = step_actions.shift() || 'resume'; + InspectorTest.log('Debugger.' + action) + await Protocol.Debugger[action](); +}) + +let step_actions = [ + // start of run 1 + 'resume', // move to breakpoint + // then get back to Javascript. + 'stepOut', + 'resume', + // end of run 1 + + // start of run 2 + 'resume', // move to breakpoint + // then get back to Javascript. + 'stepOver', + 'resume', + // end of run 2 + + // start of run 3 + 'resume', // move to breakpoint + // then get back to Javascript. + 'stepInto', + 'resume', + // end of run 3 +]; + +contextGroup.addScript(` +function test() { + debugger; + instance.exports.main(); + var x = 1; + x++; +} +//# sourceURL=test.js`); + +(async function Test() { + await Protocol.Debugger.enable(); + InspectorTest.log('Installing code and global variable.'); + await evalWithUrl('var instance;\n' + instantiate.toString(), 'setup'); + InspectorTest.log('Calling instantiate function.'); + evalWithUrl( + 'instantiate(' + JSON.stringify(module_bytes) + ')', 'callInstantiate'); + const scriptId = await waitForWasmScript(); + InspectorTest.log( + 'Setting breakpoint at start of wasm function'); + let msg = await Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': scriptId, 'lineNumber': 0, 'columnNumber': func.body_offset}}); + printFailure(msg); + InspectorTest.logMessage(msg.result.actualLocation); + + for (var i=1; i<=3; i++) { + InspectorTest.log('Start run '+ i); + await Protocol.Runtime.evaluate({ expression: 'test()' }); + InspectorTest.log('exports.main returned!'); + InspectorTest.log('Finished run '+ i +'!\n'); + } + InspectorTest.completeTest(); +})(); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScript() { + InspectorTest.log('Waiting for wasm scripts to be parsed.'); + while (true) { + let msg = await Protocol.Debugger.onceScriptParsed(); + let url = msg.params.url; + if (!url.startsWith('wasm://')) { + InspectorTest.log('Ignoring script with url ' + url); + continue; + } + let scriptId = msg.params.scriptId; + InspectorTest.log('Got wasm script: ' + url); + return scriptId; + } +} diff --git a/deps/v8/test/inspector/debugger/wasm-stepping-with-source-map-expected.txt b/deps/v8/test/inspector/debugger/wasm-stepping-with-source-map-expected.txt index 325049fffb..7d4f3a71ed 100644 --- a/deps/v8/test/inspector/debugger/wasm-stepping-with-source-map-expected.txt +++ b/deps/v8/test/inspector/debugger/wasm-stepping-with-source-map-expected.txt @@ -1,16 +1,16 @@ Tests stepping through wasm scripts with source maps Installing code an global variable and instantiate. -Got wasm script: wasm://wasm/wasm-3697f0fe +Got wasm script: wasm://wasm/3697f0fe Script sourceMapURL: abc -Requesting source for wasm://wasm/wasm-3697f0fe... +Requesting source for wasm://wasm/3697f0fe... Source retrieved without error: true -Setting breakpoint on offset 54 (on the setlocal before the call), url wasm://wasm/wasm-3697f0fe +Setting breakpoint on offset 54 (on the setlocal before the call), url wasm://wasm/3697f0fe { columnNumber : 54 lineNumber : 0 scriptId : <scriptId> } -Paused at wasm://wasm/wasm-3697f0fe:0:54 +Paused at wasm://wasm/3697f0fe:0:54 at wasm_B (0:54): - scope (global): -- skipped @@ -21,7 +21,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:56 +Paused at wasm://wasm/3697f0fe:0:56 at wasm_B (0:56): - scope (global): -- skipped @@ -32,7 +32,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:38 +Paused at wasm://wasm/3697f0fe:0:38 at wasm_A (0:38): - scope (global): -- skipped @@ -48,7 +48,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOver called -Paused at wasm://wasm/wasm-3697f0fe:0:39 +Paused at wasm://wasm/3697f0fe:0:39 at wasm_A (0:39): - scope (global): -- skipped @@ -64,7 +64,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOut called -Paused at wasm://wasm/wasm-3697f0fe:0:58 +Paused at wasm://wasm/3697f0fe:0:58 at wasm_B (0:58): - scope (global): -- skipped @@ -75,7 +75,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOut called -Paused at wasm://wasm/wasm-3697f0fe:0:54 +Paused at wasm://wasm/3697f0fe:0:54 at wasm_B (0:54): - scope (global): -- skipped @@ -86,7 +86,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOver called -Paused at wasm://wasm/wasm-3697f0fe:0:56 +Paused at wasm://wasm/3697f0fe:0:56 at wasm_B (0:56): - scope (global): -- skipped @@ -97,7 +97,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOver called -Paused at wasm://wasm/wasm-3697f0fe:0:58 +Paused at wasm://wasm/3697f0fe:0:58 at wasm_B (0:58): - scope (global): -- skipped @@ -108,7 +108,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.resume called -Paused at wasm://wasm/wasm-3697f0fe:0:54 +Paused at wasm://wasm/3697f0fe:0:54 at wasm_B (0:54): - scope (global): -- skipped @@ -119,7 +119,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:56 +Paused at wasm://wasm/3697f0fe:0:56 at wasm_B (0:56): - scope (global): -- skipped @@ -130,7 +130,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:38 +Paused at wasm://wasm/3697f0fe:0:38 at wasm_A (0:38): - scope (global): -- skipped @@ -146,7 +146,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepOut called -Paused at wasm://wasm/wasm-3697f0fe:0:58 +Paused at wasm://wasm/3697f0fe:0:58 at wasm_B (0:58): - scope (global): -- skipped @@ -157,7 +157,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:43 +Paused at wasm://wasm/3697f0fe:0:43 at wasm_B (0:43): - scope (global): -- skipped @@ -168,7 +168,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:45 +Paused at wasm://wasm/3697f0fe:0:45 at wasm_B (0:45): - scope (global): -- skipped @@ -179,7 +179,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:47 +Paused at wasm://wasm/3697f0fe:0:47 at wasm_B (0:47): - scope (global): -- skipped @@ -190,7 +190,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:49 +Paused at wasm://wasm/3697f0fe:0:49 at wasm_B (0:49): - scope (global): -- skipped @@ -201,7 +201,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:51 +Paused at wasm://wasm/3697f0fe:0:51 at wasm_B (0:51): - scope (global): -- skipped @@ -212,7 +212,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:53 +Paused at wasm://wasm/3697f0fe:0:53 at wasm_B (0:53): - scope (global): -- skipped @@ -223,7 +223,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:54 +Paused at wasm://wasm/3697f0fe:0:54 at wasm_B (0:54): - scope (global): -- skipped @@ -234,7 +234,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:56 +Paused at wasm://wasm/3697f0fe:0:56 at wasm_B (0:56): - scope (global): -- skipped @@ -245,7 +245,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:38 +Paused at wasm://wasm/3697f0fe:0:38 at wasm_A (0:38): - scope (global): -- skipped @@ -261,7 +261,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:39 +Paused at wasm://wasm/3697f0fe:0:39 at wasm_A (0:39): - scope (global): -- skipped @@ -277,7 +277,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:40 +Paused at wasm://wasm/3697f0fe:0:40 at wasm_A (0:40): - scope (global): -- skipped @@ -293,7 +293,7 @@ at (anonymous) (0:17): - scope (global): -- skipped Debugger.stepInto called -Paused at wasm://wasm/wasm-3697f0fe:0:58 +Paused at wasm://wasm/3697f0fe:0:58 at wasm_B (0:58): - scope (global): -- skipped diff --git a/deps/v8/test/inspector/debugger/wasm-stepping.js b/deps/v8/test/inspector/debugger/wasm-stepping.js deleted file mode 100644 index 01d83b6696..0000000000 --- a/deps/v8/test/inspector/debugger/wasm-stepping.js +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2017 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. - -let {session, contextGroup, Protocol} = InspectorTest.start('Tests stepping through wasm scripts'); - -utils.load('test/mjsunit/wasm/wasm-module-builder.js'); - -let builder = new WasmModuleBuilder(); - -let func_a_idx = - builder.addFunction('wasm_A', kSig_v_v).addBody([kExprNop, kExprNop]).index; - -// wasm_B calls wasm_A <param0> times. -builder.addFunction('wasm_B', kSig_v_i) - .addBody([ - // clang-format off - kExprLoop, kWasmStmt, // while - kExprLocalGet, 0, // - - kExprIf, kWasmStmt, // if <param0> != 0 - kExprLocalGet, 0, // - - kExprI32Const, 1, // - - kExprI32Sub, // - - kExprLocalSet, 0, // decrease <param0> - kExprCallFunction, func_a_idx, // - - kExprBr, 1, // continue - kExprEnd, // - - kExprEnd, // break - // clang-format on - ]) - .exportAs('main'); - -let module_bytes = builder.toArray(); - -function instantiate(bytes) { - let buffer = new ArrayBuffer(bytes.length); - let view = new Uint8Array(buffer); - for (let i = 0; i < bytes.length; ++i) { - view[i] = bytes[i] | 0; - } - - let module = new WebAssembly.Module(buffer); - // Set global variable. - instance = new WebAssembly.Instance(module); -} - -let evalWithUrl = (code, url) => Protocol.Runtime.evaluate( - {'expression': code + '\n//# sourceURL=v8://test/' + url}); - -Protocol.Debugger.onPaused(handlePaused); -let wasm_B_scriptId; -let step_actions = [ - 'stepInto', // == stepOver, to call instruction - 'stepInto', // into call to wasm_A - 'stepOver', // over first nop - 'stepOut', // out of wasm_A - 'stepOut', // out of wasm_B, stop on breakpoint again - 'stepOver', // to call - 'stepOver', // over call - 'resume', // to next breakpoint (third iteration) - 'stepInto', // to call - 'stepInto', // into wasm_A - 'stepOut', // out to wasm_B - // now step 9 times, until we are in wasm_A again. - 'stepInto', 'stepInto', 'stepInto', 'stepInto', 'stepInto', 'stepInto', - 'stepInto', 'stepInto', 'stepInto', - // 3 more times, back to wasm_B. - 'stepInto', 'stepInto', 'stepInto', - // then just resume. - 'resume' -]; -for (let action of step_actions) { - InspectorTest.logProtocolCommandCalls('Debugger.' + action) -} -let sources = {}; -let urls = {}; -let afterTwoSourcesCallback; - -(async function Test() { - await Protocol.Debugger.enable(); - InspectorTest.log('Installing code an global variable.'); - await evalWithUrl('var instance;\n' + instantiate.toString(), 'setup'); - InspectorTest.log('Calling instantiate function.'); - evalWithUrl( - 'instantiate(' + JSON.stringify(module_bytes) + ')', 'callInstantiate'); - await waitForTwoWasmScripts(); - InspectorTest.log( - 'Setting breakpoint on line 7 (on the setlocal before the call), url ' + - urls[wasm_B_scriptId]); - let msg = await Protocol.Debugger.setBreakpoint( - {'location': {'scriptId': wasm_B_scriptId, 'lineNumber': 7}}); - printFailure(msg); - InspectorTest.logMessage(msg.result.actualLocation); - await evalWithUrl('instance.exports.main(4)', 'runWasm'); - InspectorTest.log('exports.main returned!'); - InspectorTest.log('Finished!'); - InspectorTest.completeTest(); -})(); - -function printFailure(message) { - if (!message.result) { - InspectorTest.logMessage(message); - } - return message; -} - -async function waitForTwoWasmScripts() { - let num = 0; - InspectorTest.log('Waiting for two wasm scripts to be parsed.'); - let source_promises = []; - async function getWasmSource(scriptId) { - let msg = await Protocol.Debugger.getScriptSource({scriptId: scriptId}); - printFailure(msg); - InspectorTest.log(msg.result.scriptSource); - sources[scriptId] = msg.result.scriptSource; - } - while (num < 2) { - let msg = await Protocol.Debugger.onceScriptParsed(); - let url = msg.params.url; - if (!url.startsWith('wasm://')) { - InspectorTest.log('Ignoring script with url ' + url); - continue; - } - num += 1; - let scriptId = msg.params.scriptId; - urls[scriptId] = url; - InspectorTest.log('Got wasm script: ' + url); - if (url.substr(-2) == '-1') wasm_B_scriptId = scriptId; - InspectorTest.log('Requesting source for ' + url + '...'); - source_promises.push(getWasmSource(scriptId)); - } - await Promise.all(source_promises); -} - -function printPauseLocation(scriptId, lineNr, columnNr) { - let lines = sources[scriptId].split('\n'); - let line = '<illegal line number>'; - if (lineNr < lines.length) { - line = lines[lineNr]; - if (columnNr < line.length) { - line = line.substr(0, columnNr) + '>' + line.substr(columnNr); - } - } - InspectorTest.log( - 'Paused at ' + urls[scriptId] + ':' + lineNr + ':' + columnNr + ': ' + - line); -} - -async function getValueString(value) { - if (value.type == 'object') { - let msg = await Protocol.Runtime.callFunctionOn({ - objectId: value.objectId, - functionDeclaration: 'function () { return JSON.stringify(this); }' - }); - printFailure(msg); - return msg.result.result.value + ' (' + value.description + ')'; - } - return value.value + ' (' + value.type + ')'; -} - -async function dumpProperties(message) { - printFailure(message); - for (let value of message.result.result) { - let value_str = await getValueString(value.value); - InspectorTest.log(' ' + value.name + ': ' + value_str); - } -} - -async function dumpScopeChainsOnPause(message) { - for (let frame of message.params.callFrames) { - let functionName = frame.functionName || '(anonymous)'; - let lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber; - let columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber; - InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); - for (let scope of frame.scopeChain) { - InspectorTest.logObject(' - scope (' + scope.type + '):'); - if (scope.type == 'global') { - InspectorTest.logObject(' -- skipped'); - } else { - let properties = await Protocol.Runtime.getProperties( - {'objectId': scope.object.objectId}); - await dumpProperties(properties); - } - } - } -} - -async function handlePaused(msg) { - let loc = msg.params.callFrames[0].location; - printPauseLocation(loc.scriptId, loc.lineNumber, loc.columnNumber); - await dumpScopeChainsOnPause(msg); - let action = step_actions.shift() || 'resume'; - await Protocol.Debugger[action](); -} |