Skip to content

Commit cbd2d5a

Browse files
authored
[cppia] Respect jit exceptions in interp mode (#1188)
* Add tests for local function exceptions in cppia * [cppia] Respect jit exceptions in interp mode When running in interp mode, native c++ exception handling is used, but when running jit mode, jumps are used along with ctx->exception. This means that an exception thrown from jit mode is not respected in interp mode. This can cause problems with local functions (which are interpreted even in jit mode). When a local function calls a compiled function that throws an exception, the exception is ignored until we return back into a compiled function. This patch fixes the problem by checking ctx->exception when running in interp mode, to make sure that no exception has been thrown from a jit compiled function. * [cppia] Catch jit exceptions from interp mode
1 parent 409c7d0 commit cbd2d5a

File tree

4 files changed

+125
-21
lines changed

4 files changed

+125
-21
lines changed

src/hx/cppia/Cppia.cpp

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ struct BlockExpr : public CppiaExpr
439439
return;
440440
CppiaExpr **e = &expressions[0];
441441
CppiaExpr **end = e+expressions.size();
442-
for(;e<end && !ctx->breakContReturn;e++)
442+
for(;e<end && !ctx->breakContReturn && !ctx->exception;e++)
443443
{
444444
CPPIA_STACK_LINE((*e));
445445
(*e)->runVoid(ctx);
@@ -800,8 +800,7 @@ struct CallFunExpr : public CppiaExpr
800800
{
801801
unsigned char *pointer = ctx->pointer;
802802
function->pushArgs(ctx,thisExpr?thisExpr->runObject(ctx):ctx->getThis(false),args);
803-
if (ctx->breakContReturn)
804-
return;
803+
BCR_VCHECK;
805804

806805
AutoStack save(ctx,pointer);
807806
ctx->runVoid(function);
@@ -5948,7 +5947,7 @@ struct TVars : public CppiaVoidExpr
59485947
{
59495948
CppiaExpr **v = &vars[0];
59505949
CppiaExpr **end = v + vars.size();
5951-
for(;v<end && !ctx->breakContReturn;v++)
5950+
for(;v<end && !ctx->breakContReturn && !ctx->exception;v++)
59525951
(*v)->runVoid(ctx);
59535952
}
59545953

@@ -5998,8 +5997,14 @@ struct ForExpr : public CppiaVoidExpr
59985997

59995998
while(hasNext())
60005999
{
6000+
if (ctx->exception)
6001+
return;
60016002
var.set(ctx,getNext());
6003+
if (ctx->exception)
6004+
return;
60026005
loop->runVoid(ctx);
6006+
if (ctx->exception)
6007+
return;
60036008

60046009
if (ctx->breakContReturn)
60056010
{
@@ -6045,6 +6050,9 @@ struct WhileExpr : public CppiaVoidExpr
60456050
{
60466051
loop->runVoid(ctx);
60476052

6053+
if (ctx->exception)
6054+
break;
6055+
60486056
if (ctx->breakContReturn)
60496057
{
60506058
if (ctx->breakContReturn & (bcrBreak|bcrReturn))
@@ -6053,7 +6061,7 @@ struct WhileExpr : public CppiaVoidExpr
60536061
ctx->breakContReturn = 0;
60546062
}
60556063

6056-
if (!condition->runInt(ctx) || ctx->breakContReturn)
6064+
if (!condition->runInt(ctx) || ctx->breakContReturn || ctx->exception)
60576065
break;
60586066
}
60596067
ctx->breakContReturn &= ~bcrLoop;
@@ -6338,30 +6346,38 @@ struct TryExpr : public CppiaVoidExpr
63386346
}
63396347
return this;
63406348
}
6349+
6350+
void handleException(CppiaCtx* ctx, Dynamic caught) {
6351+
//Class cls = caught.mPtr ? caught->__GetClass() : 0;
6352+
for(int i=0;i<catchCount;i++)
6353+
{
6354+
Catch &c = catches[i];
6355+
if ( c.type->isClassOf(caught) )
6356+
{
6357+
ctx->exception = nullptr;
6358+
HX_STACK_BEGIN_CATCH
6359+
c.var.set(ctx,caught);
6360+
c.body->runVoid(ctx);
6361+
return;
6362+
}
6363+
}
6364+
HX_STACK_DO_THROW(caught);
6365+
}
6366+
63416367
// TODO - return types...
63426368
void runVoid(CppiaCtx *ctx)
63436369
{
63446370
try
63456371
{
63466372
body->runVoid(ctx);
6347-
BCR_VCHECK;
63486373
}
63496374
catch(Dynamic caught)
63506375
{
6351-
//Class cls = caught.mPtr ? caught->__GetClass() : 0;
6352-
for(int i=0;i<catchCount;i++)
6353-
{
6354-
Catch &c = catches[i];
6355-
if ( c.type->isClassOf(caught) )
6356-
{
6357-
HX_STACK_BEGIN_CATCH
6358-
c.var.set(ctx,caught);
6359-
c.body->runVoid(ctx);
6360-
return;
6361-
}
6362-
}
6363-
HX_STACK_DO_THROW(caught);
6376+
handleException(ctx,caught);
6377+
return;
63646378
}
6379+
if (ctx->exception)
6380+
handleException(ctx,ctx->exception);
63656381
}
63666382

63676383
#ifdef CPPIA_JIT

src/hx/cppia/Cppia.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -834,9 +834,9 @@ struct BCRReturn
834834
};
835835

836836

837-
#define BCR_CHECK if (ctx->breakContReturn) return BCRReturn();
837+
#define BCR_CHECK if (ctx->breakContReturn || ctx->exception) return BCRReturn();
838838
#define BCR_CHECK_RET(x) if (ctx->breakContReturn) return x;
839-
#define BCR_VCHECK if (ctx->breakContReturn) return;
839+
#define BCR_VCHECK if (ctx->breakContReturn || ctx->exception) return;
840840

841841

842842

test/cppia/Client.hx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,26 @@ class Client
168168
return;
169169
}
170170

171+
switch LocalFunctionExceptions.testLocalCallingStatic() {
172+
case Error(message):
173+
Common.status = 'Failed test for throw in static called by local: ' + message;
174+
return;
175+
default:
176+
}
177+
178+
switch LocalFunctionExceptions.testCatchWithinLocal() {
179+
case Error(message):
180+
Common.status = 'Failed test for catch in local function: ' + message;
181+
return;
182+
default:
183+
}
184+
185+
switch LocalFunctionExceptions.testCatchFromLocal() {
186+
case Error(message):
187+
Common.status = 'Failed test for catching exception from local function: ' + message;
188+
return;
189+
default:
190+
}
171191

172192
final extending = new ClientExtendedExtendedRoot();
173193

test/cppia/LocalFunctionExceptions.hx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
enum Status {
2+
Ok;
3+
Error(message:String);
4+
}
5+
6+
class LocalFunctionExceptions {
7+
static function staticFunction() {
8+
throw 'Thrown from static';
9+
}
10+
11+
public static function testLocalCallingStatic():Status {
12+
function localFunction() {
13+
staticFunction();
14+
throw 'Thrown from local';
15+
}
16+
17+
try {
18+
localFunction();
19+
} catch (e:String) {
20+
if (e == 'Thrown from static') {
21+
return Ok;
22+
} else {
23+
return Error("Incorrect exception caught from local function call");
24+
}
25+
}
26+
27+
return Error("No exception caught");
28+
}
29+
30+
public static function testCatchWithinLocal():Status {
31+
function localFunction() {
32+
try {
33+
staticFunction();
34+
} catch (e:String) {
35+
if (e == 'Thrown from static') {
36+
return Ok;
37+
} else {
38+
return Error("Incorrect exception caught from local function call");
39+
}
40+
}
41+
return Error("Exception from static function not caught");
42+
}
43+
44+
return try {
45+
localFunction();
46+
} catch (e) {
47+
Error('Exception leaked from local function: $e');
48+
};
49+
}
50+
51+
public static function testCatchFromLocal():Status {
52+
function localFunction() {
53+
throw 'Thrown from local';
54+
}
55+
56+
try {
57+
localFunction();
58+
} catch (e:String) {
59+
if (e == 'Thrown from local') {
60+
return Ok;
61+
} else {
62+
return Error("Incorrect exception caught from local function call");
63+
}
64+
}
65+
66+
return Error("No exception caught");
67+
}
68+
}

0 commit comments

Comments
 (0)