@@ -273,9 +273,14 @@ struct ContData {
273273 // suspend).
274274 Literals resumeArguments;
275275
276- // If set, this is the exception to be thrown at the resume point.
276+ // If set, this is the tag for an exception to be thrown at the resume point
277+ // (from resume_throw).
277278 Tag* exceptionTag = nullptr ;
278279
280+ // If set, this is the exception ref to be thrown at the resume point (from
281+ // resume_throw_ref).
282+ Literal exception;
283+
279284 // Whether we executed. Continuations are one-shot, so they may not be
280285 // executed a second time.
281286 bool executed = false ;
@@ -4480,7 +4485,6 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
44804485 }
44814486 }
44824487 Flow visitTryTable (TryTable* curr) {
4483- assert (!self ()->isResuming ()); // TODO
44844488 try {
44854489 return self ()->visit (curr->body );
44864490 } catch (const WasmException& e) {
@@ -4557,6 +4561,22 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
45574561 old->executed = true ;
45584562 return Literal (std::make_shared<ContData>(newData));
45594563 }
4564+
4565+ void maybeThrowAfterResuming (std::shared_ptr<ContData>& currContinuation) {
4566+ // We may throw by creating a tag, or an exnref.
4567+ auto * tag = currContinuation->exceptionTag ;
4568+ auto exnref = currContinuation->exception .type != Type::none;
4569+ assert (!(tag && exnref));
4570+ if (tag) {
4571+ // resume_throw
4572+ throwException (WasmException{
4573+ self ()->makeExnData (tag, currContinuation->resumeArguments )});
4574+ } else if (exnref) {
4575+ // resume_throw_ref
4576+ throwException (WasmException{currContinuation->exception });
4577+ }
4578+ }
4579+
45604580 Flow visitSuspend (Suspend* curr) {
45614581 // Process the arguments, whether or not we are resuming. If we are resuming
45624582 // then we don't need these values (we sent them as part of the suspension),
@@ -4579,11 +4599,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
45794599 // restoredValues map.
45804600 assert (currContinuation->resumeInfo .empty ());
45814601 assert (self ()->restoredValuesMap .empty ());
4582- // Throw, if we were resumed by resume_throw;
4583- if (auto * tag = currContinuation->exceptionTag ) {
4584- throwException (WasmException{
4585- self ()->makeExnData (tag, currContinuation->resumeArguments )});
4586- }
4602+ maybeThrowAfterResuming (currContinuation);
45874603 return currContinuation->resumeArguments ;
45884604 }
45894605
@@ -4616,7 +4632,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
46164632 new_->resumeExpr = curr;
46174633 return Flow (SUSPEND_FLOW, tag, std::move (arguments));
46184634 }
4619- template <typename T> Flow doResume (T* curr, Tag* exceptionTag = nullptr ) {
4635+ template <typename T> Flow doResume (T* curr) {
46204636 Literals arguments;
46214637 VISIT_ARGUMENTS (flow, curr->operands , arguments)
46224638 VISIT_REUSE (flow, curr->cont );
@@ -4636,13 +4652,26 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
46364652 trap (" continuation already executed" );
46374653 }
46384654 contData->executed = true ;
4655+
46394656 if (contData->resumeArguments .empty ()) {
46404657 // The continuation has no bound arguments. For now, we just handle the
46414658 // simple case of binding all of them, so that means we can just use all
46424659 // the immediate ones here. TODO
46434660 contData->resumeArguments = arguments;
46444661 }
4645- contData->exceptionTag = exceptionTag;
4662+ // Fill in the continuation data. How we do this depends on whether we
4663+ // are resume or resume_throw*.
4664+ if (auto * resumeThrow = curr->template dynCast <ResumeThrow>()) {
4665+ if (resumeThrow->tag ) {
4666+ // resume_throw
4667+ contData->exceptionTag =
4668+ self ()->getModule ()->getTag (resumeThrow->tag );
4669+ } else {
4670+ // resume_throw_ref
4671+ contData->exception = arguments[0 ];
4672+ }
4673+ }
4674+
46464675 self ()->pushCurrContinuation (contData);
46474676 self ()->continuationStore ->resuming = true ;
46484677#if WASM_INTERPRETER_DEBUG
@@ -4709,10 +4738,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
47094738 return ret;
47104739 }
47114740 Flow visitResume (Resume* curr) { return doResume (curr); }
4712- Flow visitResumeThrow (ResumeThrow* curr) {
4713- // TODO: should the Resume and ResumeThrow classes be merged?
4714- return doResume (curr, self ()->getModule ()->getTag (curr->tag ));
4715- }
4741+ Flow visitResumeThrow (ResumeThrow* curr) { return doResume (curr); }
47164742 Flow visitStackSwitch (StackSwitch* curr) { return Flow (NONCONSTANT_FLOW); }
47174743
47184744 void trap (const char * why) override {
@@ -4784,10 +4810,7 @@ class ModuleRunnerBase : public ExpressionRunner<SubType> {
47844810 // to do is just start calling this function (with the arguments we've
47854811 // set), so resuming is done. (And throw, if resume_throw.)
47864812 self ()->continuationStore ->resuming = false ;
4787- if (auto * tag = currContinuation->exceptionTag ) {
4788- throwException (WasmException{
4789- self ()->makeExnData (tag, currContinuation->resumeArguments )});
4790- }
4813+ maybeThrowAfterResuming (currContinuation);
47914814 }
47924815 }
47934816
0 commit comments