a4e162f761
Inspector will no longer report per-function wasm scripts or provide wasm disassembly. Locations in wasm are now consistently reported through the inspector API as lineNumber=0 columnNumber=byte offset in module. Bug: chromium:1013527, chromium:1003022 Change-Id: Ide85bbaa85ad75f29248ff82a3e7f3e40688d377 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1991481 Commit-Queue: Eric Leese <leese@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Reviewed-by: Simon Zünd <szuend@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#65660}
246 lines
7.6 KiB
JavaScript
246 lines
7.6 KiB
JavaScript
// 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));
|
|
}
|
|
}
|