Skip to content

Commit a803c8a

Browse files
committed
[js] Attach exceptions on contexts instead of putting them on a stack
On fibers we could have continuation local stacks on async/await continuations it's harder. This was causing problems when zipping sequences and resuming all the TAKE control exceptions got intertwined. # Please enter the commit message for your changes. Lines starting
1 parent 0df763e commit a803c8a

File tree

4 files changed

+33
-51
lines changed

4 files changed

+33
-51
lines changed

src/vm/js/Operations.nqp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ class QAST::OperationsJS {
881881
});
882882

883883

884-
add_simple_op('exception', $T_OBJ, []);
884+
add_simple_op('exception', $T_OBJ, [], sub () {"$*CTX.\$\$exception()"});
885885
add_simple_op('rethrow', $T_VOID, [$T_OBJ], sub ($exception) {"/*await*/ $*CTX.rethrow($exception)"}, :side_effects);
886886
add_simple_op('resume', $T_VOID, [$T_OBJ], sub ($exception) {"/*await*/ $*CTX.resume($exception)"}, :side_effects);
887887
add_simple_op('throw', $T_VOID, [$T_OBJ], :side_effects, sub ($exception) {"/*await*/ {$*CTX}.throw($exception)"});
@@ -1511,14 +1511,18 @@ class QAST::OperationsJS {
15111511
else {
15121512
my $unwind_marker := $*BLOCK.add_tmp;
15131513

1514-
my $handle_result := $comp.as_js(:want($T_OBJ), $node[2]);
1514+
my $handle_result;
1515+
{
1516+
my $*CTX := '$$ctx';
1517+
$handle_result := $comp.as_js(:want($T_OBJ), $node[2]);
1518+
}
15151519
my str $result := $*BLOCK.add_tmp;
15161520

15171521

15181522
Chunk.new($T_OBJ, $result, [
15191523
"$unwind_marker = \{\};\n",
15201524
"$*CTX.\$\$unwind = $unwind_marker;\n",
1521-
"$*CTX.\$\${$type} = /*async*/ function() \{\n",
1525+
"$*CTX.\$\${$type} = /*async*/ function(\$\$ctx) \{\n",
15221526
$handle_result,
15231527
"$result = {$handle_result.expr};\n",
15241528
"\};\n",
@@ -1564,7 +1568,7 @@ class QAST::OperationsJS {
15641568

15651569
add_simple_op('throwextype', $T_VOID, [$T_INT], :side_effects, :ctx, :await);
15661570

1567-
add_simple_op('lastexpayload', $T_OBJ, [], :!inlinable);
1571+
add_simple_op('lastexpayload', $T_OBJ, [], sub () {"$*CTX.\$\$lastexpayload()"}, :!inlinable);
15681572

15691573

15701574
add_op('control', sub ($comp, $node, :$want) {

src/vm/js/nqp-runtime/core.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ const null_s = require('./null_s.js');
3131

3232
const BOOT = require('./BOOT.js');
3333

34-
const exceptionsStack = require('./exceptions-stack.js');
35-
3634
const sixmodel = require('./sixmodel.js');
3735

3836
const Capture = require('./capture.js');
@@ -2006,16 +2004,6 @@ op.split = function(currentHLL, separator, string) {
20062004
: []).map(str => strToObj(currentHLL, str)));
20072005
};
20082006

2009-
op.exception = function() {
2010-
const stack = exceptionsStack();
2011-
return stack[stack.length - 1];
2012-
};
2013-
2014-
op.lastexpayload = function() {
2015-
const stack = exceptionsStack();
2016-
return stack[stack.length - 1].$$payload;
2017-
};
2018-
20192007
op.setextype = function(exception, category) {
20202008
exception.$$category = category;
20212009
return exception;

src/vm/js/nqp-runtime/ctx.js

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ const NQPExceptionWithCtx = require('./nqp-exception-with-ctx.js');
33
const NQPException = require('./nqp-exception.js');
44
const NQPObject = require('./nqp-object.js');
55
const Null = require('./null.js');
6-
const exceptionsStack = require('./exceptions-stack.js');
76

87
const BOOT = require('./BOOT.js');
98

@@ -117,9 +116,10 @@ class Ctx extends NQPObject {
117116
exception.caught = ctx;
118117
ctx.exception = exception;
119118

120-
exceptionsStack().push(exception);
121119
try {
122120
const wrapped = new Ctx(this, this, null);
121+
wrapped.$$currentException = exception;
122+
123123
if (ctx[handler]) {
124124
ctx.$$unwind.ret = /*await*/ ctx[handler](wrapped);
125125
} else {
@@ -131,8 +131,6 @@ class Ctx extends NQPObject {
131131
} else {
132132
throw e;
133133
}
134-
} finally {
135-
exceptionsStack().pop();
136134
}
137135

138136
throw ctx.$$unwind;
@@ -173,20 +171,18 @@ class Ctx extends NQPObject {
173171
exception.caught = ctx;
174172
ctx.exception = exception;
175173

176-
exceptionsStack().push(exception);
174+
177175
try {
178176
const wrapped = new Ctx(this, this, null);
177+
wrapped.$$currentException = exception;
179178
ctx.$$unwind.ret = /*await*/ ctx.$$CATCH(wrapped);
180179
} catch (e) {
181180
if (e instanceof ResumeException && e.exception === exception) {
182181
return;
183182
} else {
184183
throw e;
185184
}
186-
} finally {
187-
exceptionsStack().pop();
188185
}
189-
190186
throw ctx.$$unwind;
191187
}
192188
ctx = ctx.$$caller;
@@ -210,14 +206,10 @@ class Ctx extends NQPObject {
210206
}
211207

212208
/*async*/ catchException(exception) {
213-
this.exception = exception;
214-
exceptionsStack().push(exception);
215-
try {
216-
// we don't have access to the most correct ctx in case of this sort of exception
217-
return /*await*/ this.$$CATCH(this);
218-
} finally {
219-
exceptionsStack().pop();
220-
}
209+
// we don't have access to the most correct ctx in case of this sort of exception
210+
const wrapped = new Ctx(this, this, null);
211+
wrapped.$$currentException = exception;
212+
return /*await*/ this.$$CATCH(wrapped);
221213
}
222214

223215
rethrow(exception) {
@@ -277,9 +269,9 @@ class Ctx extends NQPObject {
277269
exception.caught = ctx;
278270
ctx.exception = exception;
279271

280-
exceptionsStack().push(exception);
281272
try {
282273
const wrapped = new Ctx(this, this, null);
274+
wrapped.$$currentException = exception;
283275
if (ctx[handler]) {
284276
ctx.$$unwind.ret = /*await*/ ctx[handler](wrapped);
285277
} else {
@@ -291,8 +283,6 @@ class Ctx extends NQPObject {
291283
} else {
292284
throw e;
293285
}
294-
} finally {
295-
exceptionsStack().pop();
296286
}
297287

298288
let check = lookFrom;
@@ -378,6 +368,22 @@ class Ctx extends NQPObject {
378368
return this.$$outer.lookup(name);
379369
}
380370

371+
$$exception() {
372+
let ctx = this;
373+
while (ctx) {
374+
if (ctx.$$currentException) {
375+
return ctx.$$currentException;
376+
}
377+
ctx = ctx.$$caller;
378+
}
379+
380+
console.log('exception not found');
381+
}
382+
383+
$$lastexpayload() {
384+
return this.$$exception().$$payload;
385+
}
386+
381387
$$getHLL() {
382388
let ctx = this;
383389
while (ctx) {

src/vm/js/nqp-runtime/exceptions-stack.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)