소스 검색

bugfix with filtered exceptions

ncannasse 7 년 전
부모
커밋
a100237730
2개의 변경된 파일19개의 추가작업 그리고 4개의 파일을 삭제
  1. 14 1
      src/jit.c
  2. 5 3
      src/std/error.c

+ 14 - 1
src/jit.c

@@ -3843,8 +3843,21 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				op64(ctx,MOV,trap,PESP);
 				op64(ctx,MOV,pmem(&p,treg->id,offset),trap);
 
+				/*
+					This is a bit hackshish : we want to detect the type of exception filtered by the catch so we check the following
+					sequence of HL opcodes:
+
+					trap E,@catch
+					...
+					@catch:
+					global R, _
+					call _, ???(R,E)
+
+					??? is expected to be hl.BaseType.check
+				*/
 				hl_opcode *next = f->ops + opCount + 1 + o->p2;
-				if( next->op == OGetGlobal ) {
+				hl_opcode *next2 = f->ops + opCount + 2 + o->p2;
+				if( next->op == OGetGlobal && next2->op == OCall2 && next2->p3 == next->p1 && dst->stack.id == (int)(int_val)next2->extra ) {
 					hl_type *gt = m->code->globals[next->p2];
 					while( gt->kind == HOBJ && gt->obj->super ) gt = gt->obj->super;
 					if( gt->kind == HOBJ && gt->obj->nfields && gt->obj->fields[0].t->kind == HTYPE ) {

+ 5 - 3
src/std/error.c

@@ -87,9 +87,11 @@ static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) {
 HL_PRIM void hl_throw( vdynamic *v ) {
 	hl_thread_info *t = hl_get_thread();
 	hl_trap_ctx *trap = t->trap_current;
-	if( t->exc_flags & HL_EXC_RETHROW )
+	bool was_rethrow = false;
+	if( t->exc_flags & HL_EXC_RETHROW ) {
+		was_rethrow = true;
 		t->exc_flags &= ~HL_EXC_RETHROW;
-	else
+	} else
 		t->exc_stack_count = capture_stack_func(t->exc_stack_trace, HL_EXC_MAX_STACK);
 	t->exc_value = v;
 	t->trap_current = trap->prev;
@@ -98,7 +100,7 @@ HL_PRIM void hl_throw( vdynamic *v ) {
 		t->exc_flags |= HL_EXC_IS_THROW;
 		hl_debug_break();
 		t->exc_flags &= ~HL_EXC_IS_THROW;
-		if( t->exc_handler ) hl_dyn_call(t->exc_handler,&v,1);
+		if( t->exc_handler && !was_rethrow ) hl_dyn_call(t->exc_handler,&v,1);
 	}
 	if( throw_jump == NULL ) throw_jump = longjmp;
 	throw_jump(trap->buf,1);