diff options
author | Sébastien Doeraene <sjrdoeraene@gmail.com> | 2024-08-21 00:43:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-20 15:43:25 -0700 |
commit | 340ad71810484c279b1a36a9a7e458c9b18855b9 (patch) | |
tree | 4167b08dea6f5ffcdb975d90eb6f3c7925f628e0 /src/wasm-interpreter.h | |
parent | 2c9c74d8b64e1776c6c374af8631995b0be606f1 (diff) | |
download | binaryen-340ad71810484c279b1a36a9a7e458c9b18855b9.tar.gz binaryen-340ad71810484c279b1a36a9a7e458c9b18855b9.tar.bz2 binaryen-340ad71810484c279b1a36a9a7e458c9b18855b9.zip |
[Exceptions] Finish interpreter + optimizer support for try_table. (#6814)
* Add interpreter support for exnref values.
* Fix optimization passes to support try_table.
* Enable the interpreter (but not in V8, see code) on exceptions.
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 70 |
1 files changed, 59 insertions, 11 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 644a141a2..1bf135c40 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -47,8 +47,7 @@ namespace wasm { struct WasmException { - Name tag; - Literals values; + Literal exn; }; std::ostream& operator<<(std::ostream& o, const WasmException& exn); @@ -204,6 +203,15 @@ protected: return Literal(allocation, type.getHeapType()); } + // Same as makeGCData but for ExnData. + Literal makeExnData(Name tag, const Literals& payload) { + auto allocation = std::make_shared<ExnData>(tag, payload); +#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer) + __lsan_ignore_object(allocation.get()); +#endif + return Literal(allocation); + } + public: // Indicates no limit of maxDepth or maxLoopIterations. static const Index NO_LIMIT = 0; @@ -1428,16 +1436,25 @@ public: return flow; } NOTE_EVAL1(curr->tag); - WasmException exn; - exn.tag = curr->tag; - for (auto item : arguments) { - exn.values.push_back(item); - } - throwException(exn); + throwException(WasmException{makeExnData(curr->tag, arguments)}); WASM_UNREACHABLE("throw"); } Flow visitRethrow(Rethrow* curr) { WASM_UNREACHABLE("unimp"); } - Flow visitThrowRef(ThrowRef* curr) { WASM_UNREACHABLE("unimp"); } + Flow visitThrowRef(ThrowRef* curr) { + NOTE_ENTER("ThrowRef"); + Flow flow = visit(curr->exnref); + if (flow.breaking()) { + return flow; + } + const auto& exnref = flow.getSingleValue(); + NOTE_EVAL1(exnref); + if (exnref.isNull()) { + trap("null ref"); + } + assert(exnref.isExn()); + throwException(WasmException{exnref}); + WASM_UNREACHABLE("throw"); + } Flow visitRefI31(RefI31* curr) { NOTE_ENTER("RefI31"); Flow flow = visit(curr->value); @@ -2455,6 +2472,10 @@ public: NOTE_ENTER("Try"); return Flow(NONCONSTANT_FLOW); } + Flow visitTryTable(TryTable* curr) { + NOTE_ENTER("TryTable"); + return Flow(NONCONSTANT_FLOW); + } Flow visitRethrow(Rethrow* curr) { NOTE_ENTER("Rethrow"); return Flow(NONCONSTANT_FLOW); @@ -4103,9 +4124,10 @@ public: return ret; }; + auto exnData = e.exn.getExnData(); for (size_t i = 0; i < curr->catchTags.size(); i++) { - if (curr->catchTags[i] == e.tag) { - multiValues.push_back(e.values); + if (curr->catchTags[i] == exnData->tag) { + multiValues.push_back(exnData->payload); return processCatchBody(curr->catchBodies[i]); } } @@ -4119,6 +4141,32 @@ public: throw; } } + Flow visitTryTable(TryTable* curr) { + NOTE_ENTER("TryTable"); + try { + return self()->visit(curr->body); + } catch (const WasmException& e) { + auto exnData = e.exn.getExnData(); + for (size_t i = 0; i < curr->catchTags.size(); i++) { + auto catchTag = curr->catchTags[i]; + if (!catchTag.is() || catchTag == exnData->tag) { + Flow ret; + ret.breakTo = curr->catchDests[i]; + if (catchTag.is()) { + for (auto item : exnData->payload) { + ret.values.push_back(item); + } + } + if (curr->catchRefs[i]) { + ret.values.push_back(e.exn); + } + return ret; + } + } + // This exception is not caught by this try_table. Rethrow it. + throw; + } + } Flow visitRethrow(Rethrow* curr) { for (int i = exceptionStack.size() - 1; i >= 0; i--) { if (exceptionStack[i].second == curr->target) { |