浏览代码

register exception filter type check to correctly break in debugger

ncannasse 7 年之前
父节点
当前提交
18e1d15d32
共有 3 个文件被更改,包括 27 次插入2 次删除
  1. 2 1
      src/hl.h
  2. 13 0
      src/jit.c
  3. 12 1
      src/std/error.c

+ 2 - 1
src/hl.h

@@ -799,8 +799,9 @@ typedef struct _hl_trap_ctx hl_trap_ctx;
 struct _hl_trap_ctx {
 	jmp_buf buf;
 	hl_trap_ctx *prev;
+	vdynamic *tcheck;
 };
-#define hl_trap(ctx,r,label) { hl_thread_info *__tinf = hl_get_thread(); ctx.prev = __tinf->trap_current; __tinf->trap_current = &ctx; if( setjmp(ctx.buf) ) { r = __tinf->exc_value; goto label; } }
+#define hl_trap(ctx,r,label) { hl_thread_info *__tinf = hl_get_thread(); ctx.tcheck = NULL; ctx.prev = __tinf->trap_current; __tinf->trap_current = &ctx; if( setjmp(ctx.buf) ) { r = __tinf->exc_value; goto label; } }
 #define hl_endtrap(ctx)	hl_get_thread()->trap_current = ctx.prev
 
 #define HL_EXC_MAX_STACK	0x100

+ 13 - 0
src/jit.c

@@ -3843,6 +3843,19 @@ 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);
 
+				hl_opcode *next = f->ops + opCount + 1 + o->p2;
+				if( next->op == OGetGlobal ) {
+					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 ) {
+						op64(ctx,MOV,treg,paddr(&p,m->globals_data + m->globals_indexes[next->p2]));
+					} else
+						op64(ctx,MOV,treg,pconst(&p,0));
+				} else {
+					op64(ctx,MOV,treg,pconst(&p,0));
+				}
+				op64(ctx,MOV,pmem(&p,Esp,(int)(int_val)&t->tcheck),treg);
+
 				size = begin_native_call(ctx, 1);
 				set_native_arg(ctx,trap);
 				call_native(ctx,setjmp,size);

+ 12 - 1
src/std/error.c

@@ -73,6 +73,17 @@ HL_PRIM void hl_set_error_handler( vclosure *d ) {
 	t->exc_handler = d;
 }
 
+static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) {
+	while( true ) {
+		if( trap == NULL || trap == t->trap_uncaught || t->trap_current == NULL ) return true;
+		if( !trap->tcheck || !v ) return false;
+		hl_type *ot = ((hl_type**)trap->tcheck)[1]; // it's an obj with first field is a hl_type
+		if( !ot || hl_safe_cast(v->t,ot) ) return false;
+		trap = trap->prev;
+	}
+	return false;
+}
+
 HL_PRIM void hl_throw( vdynamic *v ) {
 	hl_thread_info *t = hl_get_thread();
 	hl_trap_ctx *trap = t->trap_current;
@@ -82,7 +93,7 @@ HL_PRIM void hl_throw( vdynamic *v ) {
 		t->exc_stack_count = capture_stack_func(t->exc_stack_trace, HL_EXC_MAX_STACK);
 	t->exc_value = v;
 	t->trap_current = trap->prev;
-	if( trap == t->trap_uncaught || t->trap_current == NULL || (t->exc_flags&HL_EXC_CATCH_ALL) ) {
+	if( (t->exc_flags&HL_EXC_CATCH_ALL) || break_on_trap(t,trap,v) ) {
 		if( trap == t->trap_uncaught ) t->trap_uncaught = NULL;
 		t->exc_flags |= HL_EXC_IS_THROW;
 		hl_debug_break();