瀏覽代碼

[jit] add OCatch g, check unwrapped ValueException in break_on_trap (#824)

Yuxiao Mao 3 天之前
父節點
當前提交
575ea8353d
共有 5 個文件被更改,包括 42 次插入4 次删除
  1. 1 0
      src/debugger.c
  2. 1 0
      src/hl.h
  3. 15 3
      src/jit.c
  4. 1 0
      src/opcodes.h
  5. 24 1
      src/std/error.c

+ 1 - 0
src/debugger.c

@@ -142,6 +142,7 @@ h_bool hl_module_debug( hl_module *m, int port, h_bool wait ) {
 	hl_socket_close(debug_socket);
 	debug_socket = NULL;
 #	endif
+	hl_set_debug_mode(true);
 	return true;
 }
 

+ 1 - 0
src/hl.h

@@ -639,6 +639,7 @@ HL_API bool hl_maybe_print_custom_stack( vdynamic *exc );
 HL_API void hl_print_uncaught_exception( vdynamic *exc );
 HL_API varray *hl_exception_stack( void );
 HL_API bool hl_detect_debugger( void );
+HL_API void hl_set_debug_mode( bool b );
 
 HL_API vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj );
 HL_API void hl_init_virtual( hl_type *vt, hl_module_context *ctx );

+ 15 - 3
src/jit.c

@@ -4249,6 +4249,13 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				op64(ctx,MOV,pmem(&p,treg->id,offset),trap);
 
 				/*
+					trap E,@catch
+					catch g
+					catch g2
+					...
+					@:catch
+
+					// Before haxe 5
 					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:
 
@@ -4260,13 +4267,15 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 
 					??? is expected to be hl.BaseType.check
 				*/
+				hl_opcode *cat = f->ops + opCount + 1;
 				hl_opcode *next = f->ops + opCount + 1 + o->p2;
 				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];
+				if( cat->op == OCatch || (next->op == OGetGlobal && next2->op == OCall2 && next2->p3 == next->p1 && dst->stack.id == (int)(int_val)next2->extra) ) {
+					int gindex = cat->op == OCatch ? cat->p1 : next->p2;
+					hl_type *gt = m->code->globals[gindex];
 					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 ) {
-						void *addr = m->globals_data + m->globals_indexes[next->p2];
+						void *addr = m->globals_data + m->globals_indexes[gindex];
 #						ifdef HL_64
 						op64(ctx,MOV,treg,pconst64(&p,(int_val)addr));
 						op64(ctx,MOV,treg,pmem(&p,treg->id,0));
@@ -4472,6 +4481,9 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				}
 			}
 			break;
+		case OCatch:
+			// Only used by OTrap typing
+			break;
 		default:
 			jit_error(hl_op_name(o->op));
 			break;

+ 1 - 0
src/opcodes.h

@@ -144,6 +144,7 @@ OP_BEGIN
 	OP(ONop,0)
 	OP(OPrefetch, 3)
 	OP(OAsm, 3)
+	OP(OCatch, 1)
 	// --
 	OP(OLast,0)
 OP_END

+ 24 - 1
src/std/error.c

@@ -79,12 +79,35 @@ HL_PRIM void hl_set_error_handler( vclosure *d ) {
 	t->exc_handler = d;
 }
 
+#ifdef HL_DEBUG
+static bool hl_is_debug_mode = true;
+#else
+static bool hl_is_debug_mode = false;
+#endif
+
+HL_PRIM void hl_set_debug_mode( bool b ) {
+	hl_is_debug_mode = b;
+}
+
 static bool break_on_trap( hl_thread_info *t, hl_trap_ctx *trap, vdynamic *v ) {
+	bool unwrapped = false;
+	vdynamic *vvalue = NULL;
+	if( !hl_is_debug_mode ) return false;
 	while( true ) {
 		if( trap == NULL || trap == t->trap_uncaught || t->trap_current == NULL || trap->prev == NULL ) return true;
 		if( !trap->tcheck || !v ) return false;
+		if( !unwrapped ) {
+			unwrapped = true;
+			hl_type *vt = v->t;
+			if( vt->kind == HOBJ && ucmp(vt->obj->name, USTR("haxe.ValueException")) == 0 ) {
+				hl_field_lookup *f = hl_lookup_find(vt->obj->rt->lookup, vt->obj->rt->nlookup, hl_hash_gen(USTR("value"), true));
+				if( f != NULL && f->field_index >= 0 )
+					vvalue = *(vdynamic**)((char*)(v) + f->field_index);
+			}
+		}
 		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;
+		if( vvalue != NULL && hl_safe_cast(vvalue->t,ot) ) return false;
 		trap = trap->prev;
 	}
 	return false;
@@ -102,11 +125,11 @@ HL_PRIM void hl_throw( vdynamic *v ) {
 	t->trap_current = trap->prev;
 	call_handler = trap == t->trap_uncaught || t->trap_current == NULL;
 	if( (t->flags&HL_EXC_CATCH_ALL) || break_on_trap(t,trap,v) ) {
-		if( trap == t->trap_uncaught ) t->trap_uncaught = NULL;
 		t->flags |= HL_EXC_IS_THROW;
 		hl_debug_break();
 		t->flags &= ~HL_EXC_IS_THROW;
 	}
+	if( trap == t->trap_uncaught ) t->trap_uncaught = NULL;
 	t->flags &= ~HL_EXC_RETHROW;
 	if( t->exc_handler && call_handler ) hl_dyn_call_safe(t->exc_handler,&v,1,&call_handler);
 	if( throw_jump == NULL ) throw_jump = longjmp;