Преглед на файлове

keep ordering of dynobj fields in the order they were set

Nicolas Cannasse преди 2 години
родител
ревизия
ba0e666c85
променени са 2 файла, в които са добавени 34 реда и са изтрити 10 реда
  1. 7 1
      src/std/buffer.c
  2. 27 9
      src/std/obj.c

+ 7 - 1
src/std/buffer.c

@@ -327,12 +327,18 @@ static void hl_buffer_rec( hl_buffer *b, vdynamic *v, vlist *stack ) {
 				}
 			}
 			hl_buffer_char(b, '{');
+			int tmp[128];
+			int *indexes = o->nfields <= 128 ? tmp : (int*)hl_gc_alloc_noptr(sizeof(int) * o->nfields);
 			for(i=0;i<o->nfields;i++) {
 				hl_field_lookup *f = o->lookup + i;
+				indexes[((unsigned)f->field_index)>>17] = i;
+			}
+			for(i=0;i<o->nfields;i++) {
+				hl_field_lookup *f = o->lookup + indexes[i];
 				if( i ) hl_buffer_str_sub(b,USTR(", "),2);
 				hl_buffer_str(b,(uchar*)hl_field_name(f->hashed_name));
 				hl_buffer_str_sub(b,USTR(" : "),3);
-				hl_buffer_addr(b, hl_is_ptr(f->t) ? (void*)(o->values + f->field_index) : (void*)(o->raw_data + f->field_index), f->t, &l);
+				hl_buffer_addr(b, hl_is_ptr(f->t) ? (void*)(o->values + (f->field_index&0x1FFFF)) : (void*)(o->raw_data + (f->field_index&0x1FFFF)), f->t, &l);
 			}
 			hl_buffer_char(b, '}');
 		}

+ 27 - 9
src/std/obj.c

@@ -495,7 +495,10 @@ HL_API void hl_init_virtual( hl_type *vt, hl_module_context *ctx ) {
 	}
 }
 
-#define hl_dynobj_field(o,f) (hl_is_ptr((f)->t) ? (void*)((o)->values + (f)->field_index) : (void*) ((o)->raw_data + (f)->field_index))
+#define DYNOBJ_INDEX_SHIFT 17
+#define DYNOBJ_INDEX_MASK ((1 << DYNOBJ_INDEX_SHIFT) - 1)
+#define hl_dynobj_field(o,f) (hl_is_ptr((f)->t) ? (void*)((o)->values + ((f)->field_index&DYNOBJ_INDEX_MASK)) : (void*) ((o)->raw_data + ((f)->field_index&DYNOBJ_INDEX_MASK)))
+#define hl_dynobj_order(f) (((unsigned)(f)->field_index) >> DYNOBJ_INDEX_SHIFT)
 
 vdynamic *hl_virtual_make_value( vvirtual *v ) {
 	vdynobj *o;
@@ -518,6 +521,8 @@ vdynamic *hl_virtual_make_value( vvirtual *v ) {
 			f->field_index = raw_size;
 			raw_size += hl_type_size(f->t);
 		}
+		if( f->field_index > DYNOBJ_INDEX_MASK ) hl_error("Too many dynobj fields");
+		f->field_index |= (i << DYNOBJ_INDEX_SHIFT);
 	}
 	// copy the data & rebind virtual addresses
 	o->raw_data = hl_gc_alloc_noptr(raw_size);
@@ -681,7 +686,8 @@ static void hl_dynobj_remap_virtuals( vdynobj *o, hl_field_lookup *f, int_val ad
 
 static void hl_dynobj_delete_field( vdynobj *o, hl_field_lookup *f ) {
 	int i;
-	int index = f->field_index;
+	unsigned int order = hl_dynobj_order(f);
+	int index = f->field_index & DYNOBJ_INDEX_MASK;
 	bool is_ptr = hl_is_ptr(f->t); 
 	// erase data
 	if( is_ptr ) {
@@ -690,7 +696,7 @@ static void hl_dynobj_delete_field( vdynobj *o, hl_field_lookup *f ) {
 		o->values[o->nvalues] = NULL;
 		for(i=0;i<o->nfields;i++) {
 			hl_field_lookup *f = o->lookup + i;
-			if( hl_is_ptr(f->t) && f->field_index > index )
+			if( hl_is_ptr(f->t) && (f->field_index&DYNOBJ_INDEX_MASK) > index )
 				f->field_index--;
 		}
 	} else {
@@ -720,6 +726,12 @@ static void hl_dynobj_delete_field( vdynobj *o, hl_field_lookup *f ) {
 	int field = (int)(f - o->lookup);
 	memmove(o->lookup + field, o->lookup + field + 1, (o->nfields - (field + 1)) * sizeof(hl_field_lookup));
 	o->nfields--;
+	// remap order indexes
+	for(i=0;i<o->nfields;i++) {
+		hl_field_lookup *f = o->lookup + i;
+		if( hl_dynobj_order(f) > order )
+			f->field_index -= 1 << DYNOBJ_INDEX_SHIFT;
+	}
 }
 
 static hl_field_lookup *hl_dynobj_add_field( vdynobj *o, int hfield, hl_type *t ) {
@@ -728,9 +740,10 @@ static hl_field_lookup *hl_dynobj_add_field( vdynobj *o, int hfield, hl_type *t
 
 	// expand data
 	if( hl_is_ptr(t) ) {
+		index = o->nvalues;
+		if( index > DYNOBJ_INDEX_MASK ) hl_error("Too many dynobj values");
 		void **nvalues = hl_gc_alloc_raw( (o->nvalues + 1) * sizeof(void*) );
 		memcpy(nvalues,o->values,o->nvalues * sizeof(void*));
-		index = o->nvalues;
 		nvalues[index] = NULL;
 		address_offset = (char*)nvalues - (char*)o->values;
 		o->values = nvalues;
@@ -748,6 +761,9 @@ static hl_field_lookup *hl_dynobj_add_field( vdynobj *o, int hfield, hl_type *t
 			raw_size = o->raw_size;
 		int pad = hl_pad_size(raw_size, t);
 		int size = hl_type_size(t);
+
+		if( raw_size + pad > DYNOBJ_INDEX_MASK ) hl_error("Too many dynobj values");
+
 		char *newData = (char*)hl_gc_alloc_noptr(raw_size + pad + size);
 		if( raw_size == o->raw_size )
 			memcpy(newData,o->raw_data,o->raw_size);
@@ -755,11 +771,11 @@ static hl_field_lookup *hl_dynobj_add_field( vdynobj *o, int hfield, hl_type *t
 			raw_size = 0;
 			for(i=0;i<o->nfields;i++) {
 				hl_field_lookup *f = o->lookup + i;
-				int index = f->field_index;
+				int index = f->field_index & DYNOBJ_INDEX_MASK;
 				if( hl_is_ptr(f->t) ) continue;
 				raw_size += hl_pad_size(raw_size, f->t);
 				memcpy(newData + raw_size, o->raw_data + index, hl_type_size(f->t));
-				f->field_index = raw_size;
+				f->field_index = raw_size | (hl_dynobj_order(f) << DYNOBJ_INDEX_SHIFT);
 				if( index != raw_size )
 					hl_dynobj_remap_virtuals(o, f, 0);
 				raw_size += hl_type_size(f->t);
@@ -780,7 +796,7 @@ static hl_field_lookup *hl_dynobj_add_field( vdynobj *o, int hfield, hl_type *t
 	hl_field_lookup *f = new_lookup + field_pos;
 	f->t = t;
 	f->hashed_name = hfield;
-	f->field_index = index;
+	f->field_index = index | (o->nfields << DYNOBJ_INDEX_SHIFT);
 	memcpy(new_lookup + (field_pos + 1),o->lookup + field_pos, (o->nfields - field_pos) * sizeof(hl_field_lookup));
 	o->nfields++;
 	o->lookup = new_lookup;
@@ -1221,8 +1237,10 @@ HL_PRIM varray *hl_obj_fields( vdynamic *obj ) {
 			vdynobj *o = (vdynobj*)obj;
 			int i;
 			a = hl_alloc_array(&hlt_bytes,o->nfields);
-			for(i=0;i<o->nfields;i++)
-				hl_aptr(a,vbyte*)[i] = (vbyte*)hl_field_name((o->lookup + i)->hashed_name);
+			for(i=0;i<o->nfields;i++) {
+				hl_field_lookup *f = o->lookup + i;
+				hl_aptr(a,vbyte*)[hl_dynobj_order(f)] = (vbyte*)hl_field_name(f->hashed_name);
+			}
 		}
 		break;
 	case HOBJ: