Skip to content

Commit db23896

Browse files
authored
[EH] Support try-delegate in interpreter (#4408)
1 parent 7598857 commit db23896

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

src/wasm-interpreter.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,6 +2697,9 @@ template<typename GlobalManager, typename SubType> class ModuleInstanceBase {
26972697
FunctionScope& scope;
26982698
// Stack of <caught exception, caught catch's try label>
26992699
SmallVector<std::pair<WasmException, Name>, 4> exceptionStack;
2700+
// The current delegate target, if delegation of an exception is in
2701+
// progress. If no delegation is in progress, this will be an empty Name.
2702+
Name currDelegateTarget;
27002703

27012704
protected:
27022705
// Returns the instance that defines the memory used by this one.
@@ -3443,6 +3446,16 @@ template<typename GlobalManager, typename SubType> class ModuleInstanceBase {
34433446
try {
34443447
return this->visit(curr->body);
34453448
} catch (const WasmException& e) {
3449+
// If delegation is in progress and the current try is not the target of
3450+
// the delegation, don't handle it and just rethrow.
3451+
if (currDelegateTarget.is()) {
3452+
if (currDelegateTarget == curr->name) {
3453+
currDelegateTarget.clear();
3454+
} else {
3455+
throw;
3456+
}
3457+
}
3458+
34463459
auto processCatchBody = [&](Expression* catchBody) {
34473460
// Push the current exception onto the exceptionStack in case
34483461
// 'rethrow's use it
@@ -3469,6 +3482,9 @@ template<typename GlobalManager, typename SubType> class ModuleInstanceBase {
34693482
if (curr->hasCatchAll()) {
34703483
return processCatchBody(curr->catchBodies.back());
34713484
}
3485+
if (curr->isDelegate()) {
3486+
currDelegateTarget = curr->delegateTarget;
3487+
}
34723488
// This exception is not caught by this try-catch. Rethrow it.
34733489
throw;
34743490
}

test/spec/exception-handling.wast

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,88 @@
201201
)
202202
)
203203
)
204+
205+
(func (export "try_delegate_caught") (result i32)
206+
(try $l0 (result i32)
207+
(do
208+
(try (result i32)
209+
(do
210+
(try (result i32)
211+
(do
212+
(throw $e-i32 (i32.const 3))
213+
)
214+
(delegate $l0)
215+
)
216+
)
217+
(catch_all
218+
(i32.const 0)
219+
)
220+
)
221+
)
222+
(catch $e-i32
223+
(pop i32)
224+
)
225+
)
226+
)
227+
228+
(func (export "try_delegate_to_catchless_try") (result i32)
229+
(try $l0 (result i32)
230+
(do
231+
(try (result i32)
232+
(do
233+
(try (result i32)
234+
(do
235+
(throw $e-i32 (i32.const 3))
236+
)
237+
(delegate $l0)
238+
)
239+
)
240+
(catch_all
241+
(i32.const 0)
242+
)
243+
)
244+
)
245+
)
246+
)
247+
248+
(func (export "try_delegate_to_delegate") (result i32)
249+
(try $l0 (result i32)
250+
(do
251+
(try $l1 (result i32)
252+
(do
253+
(try (result i32)
254+
(do
255+
(throw $e-i32 (i32.const 3))
256+
)
257+
(delegate $l1)
258+
)
259+
)
260+
(delegate $l0)
261+
)
262+
)
263+
(catch $e-i32
264+
(pop i32)
265+
)
266+
)
267+
)
268+
269+
(func (export "try_delegate_to_caller")
270+
(try $l0
271+
(do
272+
(try $l1
273+
(do
274+
(try
275+
(do
276+
(throw $e-i32 (i32.const 3))
277+
)
278+
(delegate 2) ;; to caller
279+
)
280+
)
281+
)
282+
)
283+
(catch_all)
284+
)
285+
)
204286
)
205287

206288
(assert_trap (invoke "throw_single_value"))
@@ -216,6 +298,10 @@
216298
(assert_return (invoke "rethrow_target_test1") (i32.const 2))
217299
(assert_return (invoke "rethrow_target_test2") (i32.const 1))
218300
(assert_return (invoke "rethrow_target_test3") (i32.const 1))
301+
(assert_return (invoke "try_delegate_caught") (i32.const 3))
302+
(assert_trap (invoke "try_delegate_to_catchless_try"))
303+
(assert_return (invoke "try_delegate_to_delegate") (i32.const 3))
304+
(assert_trap (invoke "try_delegate_to_caller"))
219305

220306
(assert_invalid
221307
(module

0 commit comments

Comments
 (0)