Bug 1319203: Add tests; r=luke

MozReview-Commit-ID: 5Xf6NZRpQ4M

--HG--
extra : rebase_source : 971bc1c9c6e9c87fdc3e9f75eaaab868a85800ad
This commit is contained in:
Benjamin Bouvier 2018-01-22 16:38:28 +01:00
Родитель f229366eba
Коммит 65b5cadd76
11 изменённых файлов: 775 добавлений и 81 удалений

Просмотреть файл

@ -172,3 +172,141 @@ function wasmGetScriptBreakpoints(wasmScript) {
});
return result;
}
const WasmHelpers = {};
(function() {
let enabled = false;
try {
enableSingleStepProfiling();
disableSingleStepProfiling();
enabled = true;
} catch (e) {
print(e.message);
}
WasmHelpers.isSingleStepProfilingEnabled = enabled;
})();
WasmHelpers._normalizeStack = (stack, preciseStacks) => {
var wasmFrameTypes = [
{re:/^jit call to int64 wasm function$/, sub:"i64>"},
{re:/^out-of-line coercion for jit entry arguments \(in wasm\)$/, sub:"ool>"},
{re:/^wasm-function\[(\d+)\] \(.*\)$/, sub:"$1"},
{re:/^(fast|slow) exit trampoline (to native )?\(in wasm\)$/, sub:"<"},
{re:/^call to[ asm.js]? native (.*) \(in wasm\)$/, sub:"$1"},
{re:/ \(in wasm\)$/, sub:""}
];
let entryRegexps;
if (preciseStacks) {
entryRegexps = [
{re:/^slow entry trampoline \(in wasm\)$/, sub:"!>"},
{re:/^fast entry trampoline \(in wasm\)$/, sub:">"},
];
} else {
entryRegexps = [
{re:/^(fast|slow) entry trampoline \(in wasm\)$/, sub:">"}
];
}
wasmFrameTypes = entryRegexps.concat(wasmFrameTypes);
var framesIn = stack.split(',');
var framesOut = [];
for (let frame of framesIn) {
for (let {re, sub} of wasmFrameTypes) {
if (re.test(frame)) {
framesOut.push(frame.replace(re, sub));
break;
}
}
}
return framesOut.join(',');
};
WasmHelpers._removeAdjacentDuplicates = array => {
if (array.length < 2)
return;
let i = 0;
for (let j = 1; j < array.length; j++) {
if (array[i] !== array[j])
array[++i] = array[j];
}
array.length = i + 1;
}
WasmHelpers.normalizeStacks = (stacks, preciseStacks = false) => {
let observed = [];
for (let i = 0; i < stacks.length; i++)
observed[i] = WasmHelpers._normalizeStack(stacks[i], preciseStacks);
WasmHelpers._removeAdjacentDuplicates(observed);
return observed;
};
WasmHelpers._compareStacks = (got, expect) => {
if (got.length != expect.length) {
return false;
}
for (let i = 0; i < got.length; i++) {
if (got[i] !== expect[i])
return false;
}
return true;
}
WasmHelpers.assertEqImpreciseStacks = (got, expect) => {
let observed = WasmHelpers.normalizeStacks(got, /* precise */ false);
let same = WasmHelpers._compareStacks(observed, expect);
if (!same) {
if (observed.length != expect.length) {
print(`Got:\n${observed.toSource()}\nExpect:\n${expect.toSource()}`);
assertEq(observed.length, expect.length);
}
for (let i = 0; i < observed.length; i++) {
if (observed[i] !== expect[i]) {
print(`On stack ${i}, Got:\n${observed[i]}\nExpect:\n${expect[i]}`);
assertEq(observed[i], expect[i]);
}
}
}
}
WasmHelpers.assertStackTrace = (exception, expected) => {
let callsites = exception.stack.trim().split('\n').map(line => line.split('@')[0]);
assertEq(callsites.length, expected.length);
for (let i = 0; i < callsites.length; i++) {
assertEq(callsites[i], expected[i]);
}
};
WasmHelpers.nextLineNumber = (n=1) => {
return +(new Error().stack).split('\n')[1].split(':')[1] + n;
}
WasmHelpers.startProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return;
enableSingleStepProfiling();
}
WasmHelpers.endProfiling = () => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return;
return disableSingleStepProfiling();
}
WasmHelpers.assertEqPreciseStacks = (observed, expectedStacks) => {
if (!WasmHelpers.isSingleStepProfilingEnabled)
return null;
observed = WasmHelpers.normalizeStacks(observed, /* precise */ true);
for (let i = 0; i < expectedStacks.length; i++) {
if (WasmHelpers._compareStacks(observed, expectedStacks[i]))
return i;
}
throw new Error(`no plausible stacks found, observed: ${observed.join('/')}
Expected one of:
${expectedStacks.map(stacks => stacks.join("/")).join('\n')}`);
}

Просмотреть файл

@ -37,10 +37,10 @@ function assertStackContainsSeq(got, expect)
for (var j = 0; j < parts.length; j++) {
var frame = parts[j];
frame = frame.replace(/ \([^\)]*\)/g, "");
frame = frame.replace(/fast FFI trampoline to native/g, "N");
frame = frame.replace(/fast exit trampoline to native/g, "N");
frame = frame.replace(/^call to( asm.js)? native .*\(in wasm\)$/g, "N");
frame = frame.replace(/(fast|slow) FFI trampoline/g, "<");
frame = frame.replace(/slow entry trampoline/g, ">");
frame = frame.replace(/(fast|slow) exit trampoline/g, "<");
frame = frame.replace(/(fast|slow) entry trampoline/g, ">");
frame = frame.replace(/(\/[^\/,<]+)*\/testProfiling.js/g, "");
frame = frame.replace(/testBuiltinD2D/g, "");
frame = frame.replace(/testBuiltinF2F/g, "");

Просмотреть файл

@ -0,0 +1,60 @@
let { exports } = wasmEvalText(`(module
(func (export "i32") (result i32) (param i32)
get_local 0
)
(func (export "f32") (result f32) (param f32)
get_local 0
)
(func (export "f64") (result f64) (param f64)
get_local 0
)
)`);
const options = getJitCompilerOptions();
const jitThreshold = options['ion.warmup.trigger'] * 2;
let coercions = {
i32(x) { return x|0; },
f32(x) { return Math.fround(x); },
f64(x) { return +x; }
}
function call(func, coercion, arg) {
let expected;
try {
expected = coercion(arg);
} catch(e) {
expected = e.message;
}
for (var i = jitThreshold; i --> 0;) {
try {
assertEq(func(arg), expected);
} catch(e) {
assertEq(e.message, expected);
}
}
}
const inputs = [
42,
3.5,
-0,
-Infinity,
2**32,
true,
Symbol(),
undefined,
null,
{},
{ valueOf() { return 13.37; } },
"bonjour"
];
for (let arg of inputs) {
for (let func of ['i32', 'f32', 'f64']) {
call(exports[func], coercions[func], arg);
}
}

Просмотреть файл

@ -0,0 +1,15 @@
if (typeof evaluate === 'undefined')
quit();
evaluate(`
var f = (function module() {
"use asm";
function f(i) {
i=i|0;
if (!i)
return;
}
return f;
})();
evaluate(\`new f({}, {});\`);
`);

Просмотреть файл

@ -0,0 +1,18 @@
var g = newGlobal();
g.parent = this;
g.eval("Debugger(parent).onExceptionUnwind = function () {};");
lfModule = new WebAssembly.Module(wasmTextToBinary(`
(module
(export "f" $func0)
(func $func0 (result i32)
i32.const -1
)
)
`));
processModule(lfModule);
function processModule(module, jscode) {
for (let i = 0; i < 2; ++i) {
imports = {}
instance = new WebAssembly.Instance(module, imports);
}
}

Просмотреть файл

@ -0,0 +1,85 @@
const options = getJitCompilerOptions();
// These tests need at least baseline to make sense.
if (!options['baseline.enable'])
quit();
const { nextLineNumber, startProfiling, endProfiling, assertEqPreciseStacks } = WasmHelpers;
const TRIGGER = options['ion.warmup.trigger'] + 10;
const ITER = 2 * TRIGGER;
const EXCEPTION_ITER = ITER - 2;
enableGeckoProfiling();
var instance = wasmEvalText(`(module
(func $add (export "add") (result i32) (param i32) (param i32)
get_local 0
get_local 1
i32.add
)
(func $addi64 (export "add64") (result i64) (param i32) (param i32)
get_local 0
get_local 1
call $add
i64.extend_s/i32
)
)`).exports;
var callToMain;
function main() {
var arr = [instance.add, (x,y)=>x+y];
var arrayCallLine = nextLineNumber(6);
for (var i = 0; i < ITER; i++) {
var caught = null;
startProfiling();
try {
arr[i%2](i, i);
} catch(e) {
caught = e;
}
let profilingStack = endProfiling();
if (i === EXCEPTION_ITER - 1) {
arr[0] = instance.add64;
} else if (i === EXCEPTION_ITER) {
arr[0] = instance.add;
}
assertEq(!!caught, i === EXCEPTION_ITER);
if (caught) {
assertEqPreciseStacks(profilingStack, [
// Error stack: control flow is redirected to a builtin thunk
// then calling into C++ from the wasm entry before jumping to
// the wasm jit entry exception handler.
['', '>', '<,>', 'i64>,>', '<,>', '>', ''],
[''] // the jit path wasn't taken (interpreter/baseline only).
]);
assertEq(caught.message, 'cannot pass i64 to or from JS');
let stack = caught.stack.split('\n');
// Which callsites appear on the error stack.
let callsites = stack.map(s => s.split('@')[0]);
assertEq(callsites[0], 'main');
assertEq(callsites[1], ''); // global scope
// Which line numbers appear in the error stack.
let lines = stack.map(s => s.split(':')[1]);
assertEq(+lines[0], arrayCallLine);
assertEq(+lines[1], callToMain);
} else if ((i % 2) == 0) {
assertEqPreciseStacks(profilingStack, [
['', '>', '0,>', '>', ''], // fast path
['', '!>', '0,!>', '!>', ''], // slow path
]);
}
}
}
callToMain = nextLineNumber();
main();

Просмотреть файл

@ -0,0 +1,78 @@
const options = getJitCompilerOptions();
// These tests need at least baseline to make sense.
if (!options['baseline.enable'])
quit();
const { assertStackTrace, startProfiling, endProfiling, assertEqPreciseStacks } = WasmHelpers;
const TRIGGER = options['baseline.warmup.trigger'] + 10;
const ITER = 2 * TRIGGER;
const EXCEPTION_ITER = TRIGGER + 5;
const SLOW_ENTRY_STACK = ['', '!>', '0,!>', '!>', ''];
const FAST_ENTRY_STACK = ['', '>', '0,>', '>', ''];
const FAST_OOL_ENTRY_STACK = ['', '>', '<,>', 'ool>,>', '<,>', '>', '0,>', '>', ''];
const EXCEPTION_ENTRY_STACK = ['', '>', '<,>', 'ool>,>', '<,>', '>', ''];
enableGeckoProfiling();
for (let type of ['i32', 'f32', 'f64']) {
var instance = wasmEvalText(`(module
(func $add (export "add") (result ${type}) (param ${type}) (param ${type})
get_local 0
get_local 1
${type}.add
)
)`).exports;
function loopBody(a, b) {
var caught = null;
try {
instance.add(a, b);
} catch(e) {
assertEq(e.message, "ph34r");
assertStackTrace(e, ['innerValueOf', 'outerValueOf', 'loopBody', 'main', '']);
caught = e;
}
assertEq(!!caught, b === EXCEPTION_ITER);
}
var x = 0;
function main() {
let observedStacks = [0, 0, 0];
for (var i = 0; i < ITER; i++) {
startProfiling();
loopBody(i + 1, i + EXCEPTION_ITER + 1);
assertEqPreciseStacks(endProfiling(), [FAST_ENTRY_STACK, SLOW_ENTRY_STACK]);
if (i === EXCEPTION_ITER) {
x = { valueOf: function innerValueOf() { throw new Error("ph34r"); }};
} else {
x = i;
}
startProfiling();
loopBody({valueOf: function outerValueOf() { return x|0; }}, i);
let stack = endProfiling();
let which = assertEqPreciseStacks(stack, [FAST_OOL_ENTRY_STACK, SLOW_ENTRY_STACK, EXCEPTION_ENTRY_STACK]);
if (which !== null) {
if (i === EXCEPTION_ITER) {
assertEq(which, 2);
}
observedStacks[which]++;
}
}
let sum = observedStacks.reduce((acc, x) => acc + x);
assertEq(sum === 0 || sum === ITER, true);
if (sum === ITER) {
assertEq(observedStacks[0] > 0, true, "the fast entry should have been taken at least once");
assertEq(observedStacks[2], 1, "the error path should have been taken exactly once");
}
}
main();
}
disableGeckoProfiling();

Просмотреть файл

@ -0,0 +1,126 @@
///////////////////////////////////////////////////////////////////////////////
// FIRST TEST /////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
(function() {
function debug() {
throw new Error('gotcha');
}
var imports = {
numCalls:0,
main: {
f() {
debug();
}
}
};
var instance = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module
(import $main "main" "f" (func))
(func $lol (export "add") (result i32) (param i32) (param i32)
get_local 0
get_local 1
call $add
)
(func $add (result i32) (param i32) (param i32)
get_local 0
i32.const 5000
i32.eq
if
call $main
end
get_local 0
get_local 1
i32.add
)
)`)), imports).exports;
function loopBody(i) {
var caught = null;
try {
assertEq(instance.add(i, i), 2 * i);
} catch(e) {
// TODO check stack trace
print(e.stack);
caught = e;
}
assertEq(!!caught, i === 5000);
}
function main() {
for (var i = 0; i < 100000; i++) {
loopBody(i);
}
assertEq(i, 100000);
}
main();
})();
///////////////////////////////////////////////////////////////////////////////
// SECOND TEST ////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
(function() {
function debug() {
gc();
}
var imports = {
numCalls:0,
main: {
f() {
debug();
}
}
};
var instance = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(`(module
(import $main "main" "f" (func))
(func $lol (export "add") (result i32) (param i32) (param i32)
get_local 0
get_local 1
call $add
)
(func $add (result i32) (param i32) (param i32)
get_local 0
i32.const 5000
i32.eq
if
call $main
unreachable
end
get_local 0
get_local 1
i32.add
)
)`)), imports).exports;
function loopBody(i) {
var caught = null;
try {
assertEq(instance.add(i, i), 2 * i);
} catch(e) {
// TODO check stack trace
print(e.stack);
caught = e;
}
assertEq(!!caught, i === 5000);
}
function main() {
for (var i = 0; i < 100000; i++) {
loopBody(i);
}
assertEq(i, 100000);
}
main();
})();

Просмотреть файл

@ -0,0 +1,55 @@
const options = getJitCompilerOptions();
// These tests need at least baseline to make sense.
if (!options['baseline.enable'])
quit();
const TRIGGER = options['baseline.warmup.trigger'] + 10;
const ITER = 2 * TRIGGER;
const EXCEPTION_ITER = TRIGGER + 5;
for (let type of ['i32', 'f32', 'f64']) {
var instance = wasmEvalText(`(module
(func $add (export "add") (result ${type}) (param ${type}) (param ${type})
get_local 0
get_local 1
${type}.add
)
)`).exports;
function loopBody(a, b) {
var caught = null;
try {
instance.add(a, b);
} catch(e) {
caught = e;
}
assertEq(!!caught, b === EXCEPTION_ITER);
}
var x = 0;
function main() {
for (var i = 0; i <= EXCEPTION_ITER; i++) {
loopBody(i + 1, i + EXCEPTION_ITER + 1);
let otherArg = { valueOf() { return i|0; } };
if (i === EXCEPTION_ITER) {
x = { valueOf: function innerValueOf() {
// Supress callee.
instance = null;
// Suppress other arguments.
otherArg = null;
gc();
return 42;
}};
} else {
x = i;
}
loopBody({valueOf: function outerValueOf() { return x|0; }}, otherArg);
}
}
main();
}

Просмотреть файл

@ -0,0 +1,174 @@
var ITERATIONS = 10;
var INNER_ITERATIONS = 100;
let instance = wasmEvalText(`(module
(func (export "add") (result i32) (param i32) (param i32)
get_local 0
get_local 1
i32.add
)
(func (export "no_arg") (result i32)
i32.const 42
i32.const 58
i32.add
)
(global $g (mut i32) (i32.const 0))
(func (export "set_global_one") (param i32)
get_local 0
set_global $g
)
(func (export "set_global_two") (param i32) (param i32)
get_local 0
get_local 1
i32.add
set_global $g
)
(func (export "glob") (result i32)
get_global $g
)
)`).exports;
function run(name, func) {
for (let i = ITERATIONS; i --> 0;) {
func();
}
}
function testCallKnown() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add(i, i + 1), 2*i + 1);
}
}
function testCallKnownRectifying() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add(i + 1), i+1);
}
}
function jsAdd(x, y) {
return (x|0) + (y|0) | 0;
}
function testCallGeneric() {
var arr = [instance.add, jsAdd];
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(arr[i%2](i, i+1), 2*i + 1);
}
}
function testCallGenericRectifying() {
var arr = [instance.add, jsAdd];
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(arr[i%2](i+1), i + 1);
}
}
function testCallScriptedGetter() {
var obj = {};
Object.defineProperty(obj, 'x', {
get: instance.no_arg
});
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(obj.x, 100);
}
}
function testCallScriptedGetterRectifying() {
var obj = {};
Object.defineProperty(obj, 'x', {
// Missing two arguments.
get: instance.add
});
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(obj.x, 0);
}
}
function testCallScriptedSetter() {
var obj = {};
Object.defineProperty(obj, 'x', {
set: instance.set_global_one
});
for (let i = 0; i < INNER_ITERATIONS; i++) {
obj.x = i;
}
assertEq(instance.glob(), INNER_ITERATIONS-1);
}
function testCallScriptedSetterRectifying() {
var obj = {};
Object.defineProperty(obj, 'x', {
set: instance.set_global_two
});
for (let i = 0; i < INNER_ITERATIONS; i++) {
obj.x = i;
}
assertEq(instance.glob(), INNER_ITERATIONS-1);
}
function testFunctionApplyArray() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add.apply(null, [i, i + 1]), 2*i+1);
}
}
function testFunctionApplyArrayRectifying() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add.apply(null, [i + 1]), i+1);
}
}
function testFunctionApplyArgs() {
function wrapper() {
assertEq(instance.add.apply(null, arguments), 2*arguments[0]+1);
}
for (let i = 0; i < INNER_ITERATIONS; i++) {
wrapper(i, i + 1);
}
}
function testFunctionApplyArgsRectifying() {
function wrapper() {
assertEq(instance.add.apply(null, arguments), arguments[0]);
}
for (let i = 0; i < INNER_ITERATIONS; i++) {
wrapper(i + 1);
}
}
function testFunctionCall() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add.call(null, i, i + 1), 2*i+1);
}
}
function testFunctionCallRectifying() {
for (let i = 0; i < INNER_ITERATIONS; i++) {
assertEq(instance.add.call(null, i + 1), i+1);
}
}
run('call known', testCallKnown);
run('call known rectifying', testCallKnownRectifying);
run('call generic', testCallGeneric);
run('call generic rectifying', testCallGenericRectifying);
run('scripted getter', testCallScriptedGetter);
run('scripted getter rectifiying', testCallScriptedGetterRectifying);
run('scripted setter', testCallScriptedSetter);
run('scripted setter rectifiying', testCallScriptedSetterRectifying);
run('function.apply array', testFunctionApplyArray);
run('function.apply array rectifying', testFunctionApplyArrayRectifying);
run('function.apply args', testFunctionApplyArgs);
run('function.apply args rectifying', testFunctionApplyArgsRectifying);
run('function.call', testFunctionCall);
run('function.call rectifying', testFunctionCallRectifying);

Просмотреть файл

@ -1,78 +1,20 @@
try {
enableSingleStepProfiling();
disableSingleStepProfiling();
} catch(e) {
// Single step profiling not supported here.
if (!WasmHelpers.isSingleStepProfilingEnabled)
quit();
}
const Module = WebAssembly.Module;
const Instance = WebAssembly.Instance;
const Table = WebAssembly.Table;
function normalize(stack)
{
var wasmFrameTypes = [
{re:/^slow entry trampoline \(in wasm\)$/, sub:">"},
{re:/^wasm-function\[(\d+)\] \(.*\)$/, sub:"$1"},
{re:/^(fast|slow) FFI trampoline (to native )?\(in wasm\)$/, sub:"<"},
{re:/^call to[ asm.js]? native (.*) \(in wasm\)$/, sub:"$1"},
{re:/ \(in wasm\)$/, sub:""}
];
const { assertEqImpreciseStacks, startProfiling, endProfiling } = WasmHelpers;
var framesIn = stack.split(',');
var framesOut = [];
for (let frame of framesIn) {
for (let {re, sub} of wasmFrameTypes) {
if (re.test(frame)) {
framesOut.push(frame.replace(re, sub));
break;
}
}
}
return framesOut.join(',');
}
function removeAdjacentDuplicates(array) {
if (array.length < 2)
return;
let i = 0;
for (let j = 1; j < array.length; j++) {
if (array[i] !== array[j])
array[++i] = array[j];
}
array.length = i + 1;
}
function assertEqStacks(got, expect)
{
for (let i = 0; i < got.length; i++)
got[i] = normalize(got[i]);
removeAdjacentDuplicates(got);
if (got.length != expect.length) {
print(`Got:\n${got.toSource()}\nExpect:\n${expect.toSource()}`);
assertEq(got.length, expect.length);
}
for (let i = 0; i < got.length; i++) {
if (got[i] !== expect[i]) {
print(`On stack ${i}, Got:\n${got[i]}\nExpect:\n${expect[i]}`);
assertEq(got[i], expect[i]);
}
}
}
function test(code, importObj, expect)
function test(code, importObj, expectedStacks)
{
enableGeckoProfiling();
var f = wasmEvalText(code, importObj).exports[""];
enableSingleStepProfiling();
startProfiling();
f();
assertEqStacks(disableSingleStepProfiling(), expect);
assertEqImpreciseStacks(endProfiling(), expectedStacks);
disableGeckoProfiling();
}
@ -137,7 +79,8 @@ if (getBuildConfiguration()["arm-simulator"]) {
)
)`,
this,
["", ">", "0,>", "<,0,>", `i64.${op},0,>`, "<,0,>", "0,>", ">", ""]);
["", ">", "0,>", "<,0,>", `i64.${op},0,>`, "<,0,>", "0,>", ">", ""],
);
}
}
@ -149,7 +92,8 @@ test(`(module
)
)`,
this,
["", ">", "0,>", "<,0,>", "current_memory,0,>", "<,0,>", "0,>", ">", ""]);
["", ">", "0,>", "<,0,>", "current_memory,0,>", "<,0,>", "0,>", ">", ""],
);
// grow_memory is a callout.
test(`(module
@ -160,7 +104,8 @@ test(`(module
)
)`,
this,
["", ">", "0,>", "<,0,>", "grow_memory,0,>", "<,0,>", "0,>", ">", ""]);
["", ">", "0,>", "<,0,>", "grow_memory,0,>", "<,0,>", "0,>", ">", ""],
);
// A few math builtins.
for (let type of ['f32', 'f64']) {
@ -184,7 +129,7 @@ for (let type of ['f32', 'f64']) {
var f = wasmEvalText(code).exports[""];
enableSingleStepProfiling();
assertThrowsInstanceOf(f, error);
assertEqStacks(disableSingleStepProfiling(), expect);
assertEqImpreciseStacks(disableSingleStepProfiling(), expect);
disableGeckoProfiling();
}
@ -230,7 +175,7 @@ for (let type of ['f32', 'f64']) {
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e.tbl.get(0)(), 42);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", ""]);
disableGeckoProfiling();
assertEq(e.foo(), 42);
@ -240,7 +185,7 @@ for (let type of ['f32', 'f64']) {
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e.tbl.get(1)(), 13);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", ">", ""]);
disableGeckoProfiling();
assertEq(e.tbl.get(0)(), 42);
@ -251,7 +196,7 @@ for (let type of ['f32', 'f64']) {
enableSingleStepProfiling();
assertEq(e.foo(), 42);
assertEq(e.tbl.get(1)(), 13);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", "", ">", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", "", ">", "1,>", ">", ""]);
disableGeckoProfiling();
var e2 = wasmEvalText(`
@ -267,19 +212,19 @@ for (let type of ['f32', 'f64']) {
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e2.baz(0), 42);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
disableGeckoProfiling();
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e2.baz(1), 13);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "1,1,>", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", "1,1,>", "1,>", ">", ""]);
disableGeckoProfiling();
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e2.baz(2), 99);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
disableGeckoProfiling();
})();
@ -301,7 +246,7 @@ for (let type of ['f32', 'f64']) {
enableGeckoProfiling();
enableSingleStepProfiling();
assertEq(e2.bar(), 42);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
disableGeckoProfiling();
assertEq(e2.bar(), 42);
@ -311,7 +256,7 @@ for (let type of ['f32', 'f64']) {
var e4 = new Instance(m2, {a:e3}).exports;
enableSingleStepProfiling();
assertEq(e4.bar(), 42);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
disableGeckoProfiling();
assertEq(e4.bar(), 42);
})();
@ -377,7 +322,7 @@ for (let type of ['f32', 'f64']) {
// Test normal conditions.
enableSingleStepProfiling();
assertEq(i.foo(0), 42);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>",
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>",
// Losing stack information while the JIT func prologue sets profiler
// virtual FP.
"",
@ -394,7 +339,7 @@ for (let type of ['f32', 'f64']) {
// Test rectifier frame.
enableSingleStepProfiling();
assertEq(i.id(100), 100);
assertEqStacks(disableSingleStepProfiling(), ["", ">", "3,>", "<,3,>",
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "3,>", "<,3,>",
// Rectifier frame time is spent here (lastProfilingFrame has not been
// set).
"",
@ -409,7 +354,7 @@ for (let type of ['f32', 'f64']) {
enableSingleStepProfiling();
assertEq(i.foo(1337), -(2**31));
assertEqStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>", "", "<,2,>", "",
assertEqImpreciseStacks(disableSingleStepProfiling(), ["", ">", "2,>", "<,2,>", "", "<,2,>", "",
// Back into the jit exit (frame info has been recovered).
// Inline conversion fails, we skip to the OOL path, call from there
// and get back to the jit exit.