421fd3929d
This brings our constants back in line with the changed spec text. We already use kExprTableGet and kExprTableSet, but for locals and globals we still use the old wording. This renaming is mostly mechanical. PS1 was created using: ag -l 'kExpr(Get|Set|Tee)Local' src test | \ xargs -L1 sed -E 's/kExpr(Get|Set|Tee)Local\b/kExprLocal\1/g' -i PS2 contains manual fixes. R=mstarzinger@chromium.org Bug: v8:9810 Change-Id: I1617f1b2a100685a3bf56218e76845a9481959c5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1847354 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#64161}
195 lines
6.5 KiB
JavaScript
195 lines
6.5 KiB
JavaScript
// 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]();
|
|
}
|