Parcourir la source

added field name to object null access

Nicolas Cannasse il y a 3 ans
Parent
commit
86da96dfe3
1 fichiers modifiés avec 48 ajouts et 6 suppressions
  1. 48 6
      src/jit.c

+ 48 - 6
src/jit.c

@@ -112,6 +112,7 @@ typedef enum {
 	MOV8,
 	CMP8,
 	TEST8,
+	PUSH8,
 	MOV16,
 	CMP16,
 	TEST16,
@@ -416,6 +417,7 @@ typedef struct {
 
 #define FLAG_LONGOP	0x80000000
 #define FLAG_16B	0x40000000
+#define FLAG_8B		0x20000000
 
 #define RM(op,id) ((op) | (((id)+1)<<8))
 #define GET_RM(op)	(((op) >> ((op) < 0 ? 24 : 8)) & 15)
@@ -481,6 +483,7 @@ static opform OP_FORMS[_CPU_LAST] = {
 	{ "MOV8", 0x8A, 0x88, 0, 0xB0, RM(0xC6,0) },
 	{ "CMP8", 0x3A, 0x38, 0, RM(0x80,7) },
 	{ "TEST8", 0x84, 0x84, RM(0xF6,0) },
+	{ "PUSH8", 0, 0, 0x6A | FLAG_8B },
 	{ "MOV16", OP16(0x8B), OP16(0x89), OP16(0xB8) },
 	{ "CMP16", OP16(0x3B), OP16(0x39) },
 	{ "TEST16", OP16(0x85) },
@@ -515,7 +518,7 @@ static bool is_reg8( preg *a ) {
 
 static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 	opform *f = &OP_FORMS[o];
-	int r64 = mode64 && (o != PUSH && o != POP && o != CALL) ? 8 : 0;
+	int r64 = mode64 && (o != PUSH && o != POP && o != CALL && o != PUSH8) ? 8 : 0;
 	switch( o ) {
 	case CMP8:
 	case TEST8:
@@ -628,7 +631,7 @@ static void op( jit_ctx *ctx, CpuOp o, preg *a, preg *b, bool mode64 ) {
 		{
 			int_val cval = a->holds ? (int_val)a->holds : a->id;
 			OP(f->r_const);
-			W((int)cval);
+			if( f->r_const & FLAG_8B ) B((int)cval); else W((int)cval);
 		}
 		break;
 	case ID2(RMEM,RUNUSED):
@@ -2584,6 +2587,26 @@ static void jit_null_access( jit_ctx *ctx ) {
 	call_native_consts(ctx, jit_fail, &arg, 1);
 }
 
+static void jit_null_fail( int fhash ) {
+	vbyte *field = hl_field_name(fhash);
+	hl_buffer *b = hl_alloc_buffer();
+	hl_buffer_str(b, USTR("Null access ."));
+	hl_buffer_str(b, (uchar*)field);
+	vdynamic *d = hl_alloc_dynamic(&hlt_bytes);
+	d->v.ptr = hl_buffer_content(b,NULL);
+	hl_throw(d);
+}
+
+static void jit_null_field_access( jit_ctx *ctx ) {
+	preg p;
+	op64(ctx,PUSH,PEBP,UNUSED);
+	op64(ctx,MOV,PEBP,PESP);
+	int size = begin_native_call(ctx, 1);
+	int args_pos = (IS_WINCALL64 ? 32 : 0) + HL_WSIZE*2;
+	set_native_arg(ctx, pmem(&p,Ebp,args_pos));
+	call_native(ctx,jit_null_fail,size);
+}
+
 static void jit_assert( jit_ctx *ctx ) {
 	op64(ctx,PUSH,PEBP,UNUSED);
 	op64(ctx,MOV,PEBP,PESP);
@@ -2621,6 +2644,7 @@ void hl_jit_init( jit_ctx *ctx, hl_module *m ) {
 #	endif
 	ctx->static_functions[0] = (void*)(int_val)jit_build(ctx,jit_null_access);
 	ctx->static_functions[1] = (void*)(int_val)jit_build(ctx,jit_assert);
+	ctx->static_functions[2] = (void*)(int_val)jit_build(ctx,jit_null_field_access);
 }
 
 void hl_jit_reset( jit_ctx *ctx, hl_module *m ) {
@@ -3773,11 +3797,29 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 				preg *r = alloc_cpu(ctx,dst,true);
 				op64(ctx,TEST,r,r);
 				XJump_small(JNotZero,jz);
-				pad_before_call(ctx, 0);
+
+				hl_opcode *next = f->ops + opCount + 1;
+				bool null_field_access = false;
+				if( next->op == OField && next->p2 == o->p1 ) {
+					hl_obj_field *f = NULL;
+					if( dst->t->kind == HOBJ || dst->t->kind == HSTRUCT )
+						f = hl_obj_field_fetch(dst->t, next->p3);
+					else if( dst->t->kind == HVIRTUAL )
+						f = dst->t->virt->fields + next->p3;
+					if( f == NULL ) ASSERT(dst->t->kind);
+ 					null_field_access = true;
+					pad_before_call(ctx, HL_WSIZE);
+					if( f->hashed_name < 256 )
+						op64(ctx,PUSH8,pconst(&p,f->hashed_name),UNUSED);
+					else
+						op32(ctx,PUSH,pconst(&p,f->hashed_name),UNUSED);
+				} else {
+					pad_before_call(ctx, 0);
+				}
 
 				jlist *j = (jlist*)hl_malloc(&ctx->galloc,sizeof(jlist));
 				j->pos = BUF_POS();
-				j->target = -1;
+				j->target = null_field_access ? -3 : -1;
 				j->next = ctx->calls;
 				ctx->calls = j;
 
@@ -4042,12 +4084,12 @@ int hl_jit_function( jit_ctx *ctx, hl_module *m, hl_function *f ) {
 			{
 				jlist *j = (jlist*)hl_malloc(&ctx->galloc,sizeof(jlist));
 				j->pos = BUF_POS();
-				j->target = -1;
+				j->target = -2;
 				j->next = ctx->calls;
 				ctx->calls = j;
 
 				op64(ctx,MOV,PEAX,pconst64(&p,RESERVE_ADDRESS));
-				op_call(ctx,PEAX,-2);
+				op_call(ctx,PEAX,-1);
 			}
 			break;
 		case ONop: