2016-05-12 09:06:47 +00:00
|
|
|
// 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
|
|
|
|
|
|
|
|
load("test/mjsunit/wasm/wasm-module-builder.js");
|
|
|
|
|
|
|
|
// Collect the Callsite objects instead of just a string:
|
|
|
|
Error.prepareStackTrace = function(error, frames) {
|
|
|
|
return frames;
|
|
|
|
};
|
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
function testTrapLocations(instance, expected_stack_length) {
|
|
|
|
function testWasmTrap(value, reason, position) {
|
2017-09-14 17:34:15 +00:00
|
|
|
let function_name = arguments.callee.name;
|
2017-08-25 09:54:26 +00:00
|
|
|
try {
|
|
|
|
instance.exports.main(value);
|
|
|
|
fail('expected wasm exception');
|
|
|
|
} catch (e) {
|
|
|
|
assertEquals(kTrapMsgs[reason], e.message, 'trap reason');
|
2017-09-14 17:34:15 +00:00
|
|
|
// Check that the trapping function is the one which was called from this
|
|
|
|
// function.
|
|
|
|
assertTrue(
|
|
|
|
e.stack[1].toString().startsWith(function_name), 'stack depth');
|
[stack-traces] Simplify and speedup stack trace collection.
Following up on https://crrev.com/c/2689185, this CL significantly
simplifies the whole implementation of the stack trace capturing.
Before this CL, capturing any stack trace (for the purpose of the API or
Error.stack) would roughly work like this:
1. The CaptureStackTrace() function uses the StackFrameIterator to
walk the system stack. For each native frame it uses the
FrameSummary abstraction to get all (including potentially inlined)
frames. For each of those it appends a record consisting of six
elements to a FrameArray (this holds pointers to the actual
closures and receivers).
2. Afterwards the FrameArray is shrinked to the required size, and a
new FixedArray is allocated, and initialized with new
StackTraceFrame objects where each holds a reference to the
FrameArray, the index of the frame, and an initially uninitialized
StackFrameInfo reference. This new FixedArray is then returned from
CaptureStackTrace() and either stored on a message object or
provided to the API as v8::StackTrace.
The new approach removes a lot of the machinery in between and directly
creates a FixedArray of StackFrameInfo objects in CaptureStackTrace().
These StackFrameInfo objects are directly exposed as v8::StackFrame on
the public API, and they hold the six fields that were previously stored
flat in the FrameArray. This not only avoids a lot of copying around of
data and creation of temporary objects and handles, but most importantly
unifies and simplifies the stack frame function inside StackFrameInfo,
so you no longer need to wonder which function / object might be
responsible for a certain API.
There's still a lot of room for improvement. In particular we currently
don't cache the source position for a given StackFrameInfo (or
globally), but rather recompute it every time. This is still very fast,
significantly faster than the previous approach.
There are some notable (potentially user visible) changes:
- The CallSite#GetPosition() method now consistently returns the
Wasm module relative bytecode offset for all Wasm frames (previously
it'd return the function relative bytecode offset for non-asm.js
Wasm frames).
- The column and line numbers returned from StackFrameInfo methods are
consistently 1-based now, instead of sometimes being 0-based (Wasm)
and sometimes being 1-based (JS and asm.js Wasm). The only
potentially noticable difference is that for
CallSite#GetLineNumber() no longer returns 0 for Wasm frames, but
that was wrong and useless anyways.
- CallSite#GetThis() would sometimes return the_hole, another bug
flushed out by this CL.
The CL also contains some other not noteworthy drive-by-cleanups.
Fixed: chromium:1057211
Bug: chromium:1077657, chromium:1069425, v8:8742
Bug: chromium:1127391, chromium:1098530, chromium:981541
Change-Id: Iff12f6838a4d99080db8dd96bccc14440affc5a5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2689183
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72694}
2021-02-12 12:02:19 +00:00
|
|
|
assertEquals(1, e.stack[0].getLineNumber(), 'wasmFunctionIndex');
|
2017-08-25 09:54:26 +00:00
|
|
|
assertEquals(position, e.stack[0].getPosition(), 'position');
|
|
|
|
}
|
|
|
|
}
|
2016-05-12 09:06:47 +00:00
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
// The actual tests:
|
[stack-traces] Simplify and speedup stack trace collection.
Following up on https://crrev.com/c/2689185, this CL significantly
simplifies the whole implementation of the stack trace capturing.
Before this CL, capturing any stack trace (for the purpose of the API or
Error.stack) would roughly work like this:
1. The CaptureStackTrace() function uses the StackFrameIterator to
walk the system stack. For each native frame it uses the
FrameSummary abstraction to get all (including potentially inlined)
frames. For each of those it appends a record consisting of six
elements to a FrameArray (this holds pointers to the actual
closures and receivers).
2. Afterwards the FrameArray is shrinked to the required size, and a
new FixedArray is allocated, and initialized with new
StackTraceFrame objects where each holds a reference to the
FrameArray, the index of the frame, and an initially uninitialized
StackFrameInfo reference. This new FixedArray is then returned from
CaptureStackTrace() and either stored on a message object or
provided to the API as v8::StackTrace.
The new approach removes a lot of the machinery in between and directly
creates a FixedArray of StackFrameInfo objects in CaptureStackTrace().
These StackFrameInfo objects are directly exposed as v8::StackFrame on
the public API, and they hold the six fields that were previously stored
flat in the FrameArray. This not only avoids a lot of copying around of
data and creation of temporary objects and handles, but most importantly
unifies and simplifies the stack frame function inside StackFrameInfo,
so you no longer need to wonder which function / object might be
responsible for a certain API.
There's still a lot of room for improvement. In particular we currently
don't cache the source position for a given StackFrameInfo (or
globally), but rather recompute it every time. This is still very fast,
significantly faster than the previous approach.
There are some notable (potentially user visible) changes:
- The CallSite#GetPosition() method now consistently returns the
Wasm module relative bytecode offset for all Wasm frames (previously
it'd return the function relative bytecode offset for non-asm.js
Wasm frames).
- The column and line numbers returned from StackFrameInfo methods are
consistently 1-based now, instead of sometimes being 0-based (Wasm)
and sometimes being 1-based (JS and asm.js Wasm). The only
potentially noticable difference is that for
CallSite#GetLineNumber() no longer returns 0 for Wasm frames, but
that was wrong and useless anyways.
- CallSite#GetThis() would sometimes return the_hole, another bug
flushed out by this CL.
The CL also contains some other not noteworthy drive-by-cleanups.
Fixed: chromium:1057211
Bug: chromium:1077657, chromium:1069425, v8:8742
Bug: chromium:1127391, chromium:1098530, chromium:981541
Change-Id: Iff12f6838a4d99080db8dd96bccc14440affc5a5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2689183
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72694}
2021-02-12 12:02:19 +00:00
|
|
|
testWasmTrap(0, kTrapDivByZero, 73);
|
|
|
|
testWasmTrap(1, kTrapMemOutOfBounds, 74);
|
|
|
|
testWasmTrap(2, kTrapUnreachable, 87);
|
|
|
|
testWasmTrap(3, kTrapTableOutOfBounds, 91);
|
2017-08-25 09:54:26 +00:00
|
|
|
}
|
2017-01-18 12:07:57 +00:00
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
builder.addMemory(0, 1, false);
|
2016-06-21 19:47:51 +00:00
|
|
|
var sig_index = builder.addType(kSig_i_v)
|
2016-05-12 09:06:47 +00:00
|
|
|
|
|
|
|
// Build a function to resemble this code:
|
|
|
|
// if (idx < 2) {
|
|
|
|
// return load(-2 / idx);
|
|
|
|
// } else if (idx == 2) {
|
|
|
|
// unreachable;
|
|
|
|
// } else {
|
|
|
|
// return call_indirect(idx);
|
|
|
|
// }
|
|
|
|
// There are four different traps which are triggered by different input values:
|
|
|
|
// (0) division by zero; (1) mem oob; (2) unreachable; (3) invalid call target
|
|
|
|
// Each of them also has a different location where it traps.
|
|
|
|
builder.addFunction("main", kSig_i_i)
|
|
|
|
.addBody([
|
|
|
|
// offset 1
|
2016-12-21 13:43:00 +00:00
|
|
|
kExprBlock, kWasmI32,
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprI32Const, 2,
|
|
|
|
kExprI32LtU,
|
2021-03-22 06:56:01 +00:00
|
|
|
kExprIf, kWasmVoid,
|
2016-09-27 20:46:10 +00:00
|
|
|
// offset 9
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprI32Const, 0x7e /* -2 */,
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprI32DivU,
|
2016-09-27 20:46:10 +00:00
|
|
|
// offset 15
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprI32LoadMem, 0, 0,
|
2016-09-27 20:46:10 +00:00
|
|
|
kExprBr, 1,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprEnd,
|
2016-09-27 20:46:10 +00:00
|
|
|
// offset 21
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprI32Const, 2,
|
|
|
|
kExprI32Eq,
|
2021-03-22 06:56:01 +00:00
|
|
|
kExprIf, kWasmVoid,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprUnreachable,
|
|
|
|
kExprEnd,
|
2016-09-27 20:46:10 +00:00
|
|
|
// offset 30
|
2019-10-08 12:38:48 +00:00
|
|
|
kExprLocalGet, 0,
|
2016-10-26 16:56:05 +00:00
|
|
|
kExprCallIndirect, sig_index, kTableZero,
|
2016-05-12 09:06:47 +00:00
|
|
|
kExprEnd,
|
|
|
|
])
|
|
|
|
.exportAs("main");
|
2016-11-09 08:37:05 +00:00
|
|
|
builder.appendToTable([0]);
|
2016-05-12 09:06:47 +00:00
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
let buffer = builder.toBuffer();
|
2016-05-12 09:06:47 +00:00
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
// Test async compilation and instantiation.
|
2017-10-25 14:12:49 +00:00
|
|
|
assertPromiseResult(WebAssembly.instantiate(buffer), pair => {
|
2017-11-30 15:27:59 +00:00
|
|
|
testTrapLocations(pair.instance, 5);
|
2017-10-25 14:12:49 +00:00
|
|
|
});
|
2016-05-12 09:06:47 +00:00
|
|
|
|
2017-08-25 09:54:26 +00:00
|
|
|
// Test sync compilation and instantiation.
|
|
|
|
testTrapLocations(builder.instantiate(), 4);
|