diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc index 64efb1ce9c..e28ddef03a 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -1404,11 +1404,13 @@ Object Isolate::StackOverflow() { MessageFormatter::TemplateString(MessageTemplate::kStackOverflow)); Handle options = factory()->undefined_value(); Handle no_caller; - Handle exception; + Handle exception; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( this, exception, ErrorUtils::Construct(this, fun, fun, msg, options, SKIP_NONE, no_caller, ErrorUtils::StackTraceCollection::kSimple)); + JSObject::AddProperty(this, exception, factory()->wasm_uncatchable_symbol(), + factory()->true_value(), NONE); Throw(*exception); diff --git a/test/cctest/wasm/test-run-wasm-exceptions.cc b/test/cctest/wasm/test-run-wasm-exceptions.cc index 38598f5b9a..284f27ec44 100644 --- a/test/cctest/wasm/test-run-wasm-exceptions.cc +++ b/test/cctest/wasm/test-run-wasm-exceptions.cc @@ -574,6 +574,64 @@ WASM_EXEC_TEST(TryCatchTrapRemByZero) { TestTrapNotCaught(code, arraysize(code), execution_tier); } +namespace { +// TODO(cleanup): Define in cctest.h and re-use where appropriate. +class IsolateScope { + public: + IsolateScope() { + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + isolate_ = v8::Isolate::New(create_params); + isolate_->Enter(); + } + + ~IsolateScope() { + isolate_->Exit(); + isolate_->Dispose(); + } + + v8::Isolate* isolate() { return isolate_; } + Isolate* i_isolate() { return reinterpret_cast(isolate_); } + + private: + v8::Isolate* isolate_; +}; +} // namespace + +UNINITIALIZED_WASM_EXEC_TEST(TestStackOverflowNotCaught) { + TestSignatures sigs; + EXPERIMENTAL_FLAG_SCOPE(eh); + // FLAG_stack_size must be set before isolate initialization. + FlagScope stack_size(&v8::internal::FLAG_stack_size, 8); + + IsolateScope isolate_scope; + LocalContext context(isolate_scope.isolate()); + + WasmRunner r(execution_tier, nullptr, "main", + kRuntimeExceptionSupport, isolate_scope.i_isolate()); + + // Build a function that calls itself until stack overflow. + WasmFunctionCompiler& stack_overflow = r.NewFunction(sigs.v_v()); + byte stack_overflow_code[] = {kExprCallFunction, + stack_overflow.function_index()}; + stack_overflow.Build(stack_overflow_code, + stack_overflow_code + arraysize(stack_overflow_code)); + + // Build the main test function. + BUILD(r, WASM_TRY_CATCH_ALL_T(kWasmI32, + WASM_STMTS(WASM_I32V(1), kExprCallFunction, + stack_overflow.function_index()), + WASM_STMTS(WASM_I32V(1)))); + + if (execution_tier != TestExecutionTier::kInterpreter) { + // Need to call through JS to allow for creation of stack traces. + r.CheckCallViaJSTraps(); + } else { + constexpr int stopped = 0; + CHECK_EQ(stopped, r.CallInterpreter()); + } +} + TEST(Regress1180457) { TestSignatures sigs; EXPERIMENTAL_FLAG_SCOPE(eh); diff --git a/test/common/wasm/wasm-interpreter.cc b/test/common/wasm/wasm-interpreter.cc index 38b4b04b66..cbf3e16ee4 100644 --- a/test/common/wasm/wasm-interpreter.cc +++ b/test/common/wasm/wasm-interpreter.cc @@ -3106,9 +3106,6 @@ class WasmInterpreterInternals { // it to 0 here such that we report the same position as in compiled code. frames_.back().pc = 0; isolate_->StackOverflow(); - if (FLAG_experimental_wasm_eh) { - possible_nondeterminism_ = true; - } if (HandleException(isolate_) == WasmInterpreter::HANDLED) { ReloadFromFrameOnException(decoder, target, pc, limit); return true; diff --git a/test/mjsunit/wasm/exceptions.js b/test/mjsunit/wasm/exceptions.js index 88e92fa3bb..bc64d83ee2 100644 --- a/test/mjsunit/wasm/exceptions.js +++ b/test/mjsunit/wasm/exceptions.js @@ -263,6 +263,27 @@ load("test/mjsunit/wasm/exceptions-utils.js"); assertInstanceof(caught.__proto__, WebAssembly.RuntimeError); })(); +(function TestStackOverflowNotCaught() { + print(arguments.callee.name); + function stack_overflow() { + %ThrowStackOverflow(); + } + let builder = new WasmModuleBuilder(); + let sig_v_v = builder.addType(kSig_v_v); + let kStackOverflow = builder.addImport('', 'stack_overflow', sig_v_v); + builder.addFunction('try_stack_overflow', kSig_v_v) + .addBody([ + kExprTry, kWasmVoid, + kExprCallFunction, 0, + kExprCatchAll, + kExprEnd + ]).exportFunc(); + let instance = builder.instantiate({'': {'stack_overflow': stack_overflow}}); + + assertThrows(() => instance.exports.try_stack_overflow(), + RangeError, 'Maximum call stack size exceeded'); +})(); + // Test that we can distinguish which exception was thrown by using a cascaded // sequence of nested try blocks with a single catch block each. (function TestCatchComplex1() {