Commit d6aed443 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Use pending exceptions consistently

In our internal code, we should only use pending exceptions. They will
be converted to scheduled exceptions on the API boundary.
Hence, the ErrorThrower just sets a pending exception; it should never
have to think about scheduled exceptions. The new
ScheduledErrorThrower inherits from ErrorThrower and reschedules any
pending exceptions in its destructor (turning them into scheduled
exceptions).
In some situations, there might already be a scheduled exception, e.g.
when calling other API methods (v8::Value::Get). In this case, the
ErrorThrower should also not set another pending exception. For the
reasons mentioned above, this can only be handled in the
ScheduledErrorThrower, which is used the API methods.

This fixes one DCHECK failure and one TODO about scheduled exceptions
if no instance can be created, because the start function throws.

R=mtrofin@chromium.org, mstarzinger@chromium.org
BUG=v8:6232,chromium:736256

Change-Id: I4905be04c565df9495de18fb26adbb5c05d193d2
Reviewed-on: https://chromium-review.googlesource.com/548641
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarMircea Trofin <mtrofin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46314}
parent 365fd661
......@@ -1121,7 +1121,6 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
if (retval.is_null()) {
DCHECK(isolate_->has_pending_exception());
isolate_->OptionalRescheduleException(false);
// It's unfortunate that the new instance is already linked in the
// chain. However, we need to set up everything before executing the
// start function, such that stack trace information can be generated
......
This diff is collapsed.
......@@ -808,11 +808,9 @@ MaybeHandle<WasmInstanceObject> wasm::SyncCompileAndInstantiate(
DCHECK_EQ(thrower->error(), module.is_null());
if (module.is_null()) return {};
MaybeHandle<WasmInstanceObject> instance = wasm::SyncInstantiate(
isolate, thrower, module.ToHandleChecked(), Handle<JSReceiver>::null(),
return wasm::SyncInstantiate(isolate, thrower, module.ToHandleChecked(),
Handle<JSReceiver>::null(),
Handle<JSArrayBuffer>::null());
DCHECK_EQ(thrower->error(), instance.is_null());
return instance;
}
namespace {
......
......@@ -136,10 +136,8 @@ Handle<Object> ErrorThrower::Reify() {
Vector<const char> msg_vec(error_msg_.data(), error_msg_.size());
Handle<String> message =
isolate_->factory()->NewStringFromUtf8(msg_vec).ToHandleChecked();
error_type_ = kNone; // Reset.
Handle<Object> exception =
isolate_->factory()->NewError(constructor, message);
return exception;
Reset();
return isolate_->factory()->NewError(constructor, message);
}
void ErrorThrower::Reset() {
......@@ -157,7 +155,10 @@ ErrorThrower::ErrorThrower(ErrorThrower&& other)
ErrorThrower::~ErrorThrower() {
if (error() && !isolate_->has_pending_exception()) {
isolate_->ScheduleThrow(*Reify());
// We don't want to mix pending exceptions and scheduled exceptions, hence
// an existing exception should be pending, never scheduled.
DCHECK(!isolate_->has_scheduled_exception());
isolate_->Throw(*Reify());
}
}
......
......@@ -123,6 +123,8 @@ class V8_EXPORT_PRIVATE ErrorThrower {
bool error() const { return error_type_ != kNone; }
bool wasm_error() { return error_type_ >= kFirstWasmError; }
Isolate* isolate() const { return isolate_; }
private:
enum ErrorType {
kNone,
......@@ -146,6 +148,9 @@ class V8_EXPORT_PRIVATE ErrorThrower {
std::string error_msg_;
DISALLOW_COPY_AND_ASSIGN(ErrorThrower);
// ErrorThrower should always be stack-allocated, since it constitutes a scope
// (things happen in the destructor).
DISALLOW_NEW_AND_DELETE();
};
} // namespace wasm
......
......@@ -134,6 +134,8 @@ int32_t CallWasmFunctionForTesting(Isolate* isolate, Handle<JSObject> instance,
// The result should be a number.
if (retval.is_null()) {
DCHECK(isolate->has_pending_exception());
isolate->clear_pending_exception();
thrower->RuntimeError("Calling exported wasm function failed.");
return -1;
}
......
......@@ -27,6 +27,9 @@ std::unique_ptr<WasmModule> DecodeWasmModuleForTesting(
Isolate* isolate, ErrorThrower* thrower, const byte* module_start,
const byte* module_end, ModuleOrigin origin, bool verify_functions = false);
// Call an exported wasm function by name. Returns -1 if the export does not
// exist or throws an error. Errors are cleared from the isolate before
// returning.
int32_t CallWasmFunctionForTesting(Isolate* isolate, Handle<JSObject> instance,
ErrorThrower* thrower, const char* name,
int argc, Handle<Object> argv[]);
......
......@@ -29,7 +29,7 @@ function assertVerifies(sig, body) {
assertVerifies(kSig_v_v, [kExprNop]);
// Arguments aren't allow to start functions.
// Arguments aren't allowed to start functions.
assertThrows(() => {instantiate(kSig_i_i, [kExprGetLocal, 0]);});
assertThrows(() => {instantiate(kSig_i_ii, [kExprGetLocal, 0]);});
assertThrows(() => {instantiate(kSig_i_dd, [kExprGetLocal, 0]);});
......@@ -122,3 +122,27 @@ assertThrows(() => {instantiate(kSig_i_v, [kExprI32Const, 0]);});
var module = builder.instantiate(ffi);
assertTrue(ranned);
})();
(function testStartFunctionThrowsExplicitly() {
print('testStartFunctionThrowsExplicitly');
let error = new Error('my explicit error');
function throw_fn() {
throw error;
}
let builder = new WasmModuleBuilder();
builder.addImport('foo', 'bar', kSig_v_v);
let func = builder.addFunction('', kSig_v_v).addBody([kExprCallFunction, 0]);
builder.addStart(func.index);
assertThrowsEquals(() => builder.instantiate(ffi), error);
})();
(function testStartFunctionThrowsImplicitly() {
print("testStartFunctionThrowsImplicitly");
let builder = new WasmModuleBuilder();
let func = builder.addFunction('', kSig_v_v).addBody([kExprUnreachable]);
builder.addStart(func.index);
assertThrows(
() => builder.instantiate(), WebAssembly.RuntimeError, /unreachable/);
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment