Browse code

WiP fixing globals in interpreter.

Török Edvin authored on 2010/03/22 02:47:25
Showing 4 changed files
... ...
@@ -1441,6 +1441,7 @@ void cli_bytecode_destroy(struct cli_bc *bc)
1441 1441
     if (bc->uses_apis)
1442 1442
 	cli_bitset_free(bc->uses_apis);
1443 1443
     free(bc->lsig);
1444
+    free(bc->globalBytes);
1444 1445
 }
1445 1446
 
1446 1447
 #define MAP(val) do { operand_t o = val; \
... ...
@@ -1476,6 +1477,9 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
1476 1476
 	gmap[j] = bc->numGlobalBytes;
1477 1477
 	bc->numGlobalBytes += typesize(bc, ty);
1478 1478
     }
1479
+    bc->globalBytes = cli_calloc(1, bc->numGlobalBytes);
1480
+    if (!bc->globalBytes)
1481
+	return CL_EMEM;
1479 1482
 
1480 1483
     for (i=0;i<bc->num_func;i++) {
1481 1484
 	struct cli_bc_func *bcfunc = &bc->funcs[i];
... ...
@@ -166,8 +166,6 @@ struct cli_bc_ctx {
166 166
     unsigned line;
167 167
     unsigned col;
168 168
     mpool_t *mpool;
169
-    uint32_t numGlobals;
170
-    uint8_t* globals;
171 169
     struct bc_inflate* inflates;
172 170
     unsigned ninflates;
173 171
     struct bc_buffer *buffers;
... ...
@@ -36,7 +36,7 @@
36 36
 /* These checks will also be done by the bytecode verifier, but for
37 37
  * debugging purposes we have explicit checks, these should never fail! */
38 38
 #ifdef CL_BYTECODE_DEBUG
39
-static int bcfail(const char *msg, long a, long b,
39
+static int never_inline bcfail(const char *msg, long a, long b,
40 40
 		  const char *file, unsigned line)
41 41
 {
42 42
     cli_errmsg("bytecode: check failed %s (%lx and %lx) at %s:%u\n", msg, a, b, file, line);
... ...
@@ -56,6 +56,8 @@ static int bcfail(const char *msg, long a, long b,
56 56
 #define TRACE_W(x, w, p) cli_dbgmsg("bytecode trace: %u, write%d @%u %llx\n", pc, p, w, (long long)x);
57 57
 #define TRACE_EXEC(id, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %d, -> %u (%u); %u\n", id, dest, ty, stack)
58 58
 #else
59
+static inline int bcfail(const char *msg, long a, long b,
60
+			 const char *file, unsigned line) {}
59 61
 #define TRACE_R(x)
60 62
 #define TRACE_W(x, w, p)
61 63
 #define TRACE_EXEC(id, dest, ty, stack)
... ...
@@ -262,6 +264,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
262 262
 #define uint_type(n) uint##n##_t
263 263
 #define READNfrom(maxBytes, from, x, n, p)\
264 264
     CHECK_GT((maxBytes), (p)+(n/8)-1);\
265
+    CHECK_EQ((p)&(n-1), 0);\
265 266
     x = *(uint_type(n)*)&(from)[(p)];\
266 267
     TRACE_R(x)
267 268
 
... ...
@@ -269,7 +272,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
269 269
  do {\
270 270
      if (p&0x80000000) {\
271 271
 	 uint32_t pg = p&0x7fffffff;\
272
-	 READNfrom(ctx->numGlobals, ctx->globals, x, n, p);\
272
+	 READNfrom(bc->numGlobalBytes, bc->globals, x, n, pg);\
273 273
      } else {\
274 274
 	 READNfrom(func->numBytes, values, x, n, p);\
275 275
      }\
... ...
@@ -282,11 +285,16 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
282 282
 #define READ32(x, p) READN(x, 32, p)
283 283
 #define READ64(x, p) READN(x, 64, p)
284 284
 
285
-#define PSIZE sizeof(void*)
286
-#define READP(x, p) CHECK_GT(func->numBytes, p+PSIZE-1);\
287
-    CHECK_EQ((p)&(PSIZE-1), 0);\
288
-    x = *(void**)&values[p];\
289
-    TRACE_R(x)
285
+#define PSIZE sizeof(int64_t)
286
+#define READP(x, p, asize) { int64_t iptr__;\
287
+    READN(iptr__, 8, p);\
288
+    x = ptr_torealptr(&ptrinfos, iptr__, (asize));\
289
+    if (!x) {\
290
+	stop = CL_EBYTECODE;\
291
+	break;\
292
+    }\
293
+    TRACE_R(x)\
294
+}
290 295
 
291 296
 #define READOLD8(x, p) CHECK_GT(func->numBytes, p);\
292 297
     x = *(uint8_t*)&old_values[p];\
... ...
@@ -436,6 +444,101 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack,
436 436
 		break;\
437 437
 	    }
438 438
 
439
+struct ptr_info {
440
+    uint8_t *base;
441
+    uint32_t size;
442
+};
443
+
444
+struct ptr_infos {
445
+    struct ptr_info *stack_infos;
446
+    struct ptr_info *glob_infos;
447
+    unsigned nstacks, nglobs;
448
+};
449
+
450
+static inline int64_t ptr_compose(int32_t id, uint32_t offset)
451
+{
452
+    uint64_t i = id;
453
+    return (i << 32) | offset;
454
+}
455
+
456
+static inline int32_t ptr_register_stack(struct ptr_infos *infos,
457
+					 unsigned char *values,
458
+					 uint32_t off, uint32_t size)
459
+{
460
+    int16_t id;
461
+    unsigned n = infos->nstacks + 1;
462
+    struct ptr_info *sinfos = cli_realloc(infos->stack_infos,
463
+					  sizeof(*sinfos)*n);
464
+    if (!sinfos)
465
+	return 0;
466
+    infos->stack_infos = sinfos;
467
+    infos->nstacks = n;
468
+    sinfos = &sinfos[n-1];
469
+    sinfos->base = values + off;
470
+    sinfos->size = size;
471
+    return ptr_compose(-(n-1), 0);
472
+}
473
+
474
+static inline int64_t ptr_register_glob(struct ptr_infos *infos,
475
+					void *values, uint32_t size)
476
+{
477
+    unsigned n = infos->nstacks + 1;
478
+    struct ptr_info *sinfos = cli_realloc(infos->stack_infos,
479
+					  sizeof(*sinfos)*n);
480
+    if (!sinfos)
481
+	return 0;
482
+    infos->stack_infos = sinfos;
483
+    infos->nstacks = n;
484
+    sinfos = &sinfos[n-1];
485
+    sinfos->base = values;
486
+    sinfos->size = size;
487
+    return ptr_compose(n, 0);
488
+}
489
+
490
+static inline int64_t ptr_index(int64_t ptr, uint32_t off)
491
+{
492
+    int32_t ptrid = ptr >> 32;
493
+    uint32_t ptroff = (uint32_t)ptr;
494
+    return ptr_compose(ptrid, ptroff+off);
495
+}
496
+
497
+static inline void* ptr_torealptr(const struct ptr_infos *infos, int64_t ptr,
498
+				  uint32_t read_size)
499
+{
500
+    struct ptr_info *info;
501
+    int32_t ptrid = ptr >> 32;
502
+    uint32_t ptroff = (uint32_t)ptr;
503
+    if (UNLIKELY(!ptrid)) {
504
+	bcfail("nullptr", ptrid, 0, __FILE__, __LINE__);
505
+	return NULL;
506
+    }
507
+    if (ptrid < 0) {
508
+	ptrid = -ptrid;
509
+	if (UNLIKELY(ptrid >= infos->nstacks)) {
510
+	    bcfail("ptr", ptrid, infos->nstacks, __FILE__, __LINE__);
511
+	    return NULL;
512
+	}
513
+	info = &infos->stack_infos[ptrid];
514
+    } else {
515
+	ptrid--;
516
+	if (UNLIKELY(ptrid >= infos->nglobs)) {
517
+	    bcfail("ptr", ptrid, infos->nglobs, __FILE__, __LINE__);
518
+	    return NULL;
519
+	}
520
+	info = &infos->glob_infos[ptrid];
521
+    }
522
+    if (LIKELY(ptroff < info->size &&
523
+	read_size < info->size &&
524
+	ptroff + read_size <= info->size)) {
525
+	return info->base+ptroff;
526
+    }
527
+
528
+    bcfail("ptr1", ptroff, info->size, __FILE__, __LINE__);
529
+    bcfail("ptr2", read_size, info->size, __FILE__, __LINE__);
530
+    bcfail("ptr3", ptroff+read_size, info->size, __FILE__, __LINE__);
531
+    return NULL;
532
+}
533
+
439 534
 static always_inline int check_sdivops(int64_t op0, int64_t op1)
440 535
 {
441 536
     return op1 == 0 || (op0 == -1 && op1 ==  (-9223372036854775807LL-1LL));
... ...
@@ -450,7 +553,9 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
450 450
     struct cli_bc_bb *bb = NULL;
451 451
     char *values = ctx->values;
452 452
     char *old_values;
453
+    struct ptr_infos ptrinfos;
453 454
 
455
+    memset(&ptrinfos, 0, sizeof(ptrinfos));
454 456
     memset(&stack, 0, sizeof(stack));
455 457
     do {
456 458
 	pc++;
... ...
@@ -721,32 +826,28 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
721 721
 	    case OP_BC_LOAD*5+1:
722 722
 	    {
723 723
 		uint8_t *ptr;
724
-		READP(ptr, inst->u.unaryop);
724
+		READP(ptr, inst->u.unaryop, 1);
725 725
 		WRITE8(inst->dest, (*ptr));
726 726
 		break;
727 727
 	    }
728 728
 	    case OP_BC_LOAD*5+2:
729 729
 	    {
730 730
 		const union unaligned_16 *ptr;
731
-		READP(ptr, inst->u.unaryop);
731
+		READP(ptr, inst->u.unaryop, 2);
732 732
 		WRITE16(inst->dest, (ptr->una_u16));
733 733
 		break;
734 734
 	    }
735 735
 	    case OP_BC_LOAD*5+3:
736 736
 	    {
737 737
 		const union unaligned_32 *ptr;
738
-		READP(ptr, inst->u.unaryop);
739
-		if (!ptr) {
740
-		    cli_dbgmsg("Bytecode attempted to load from null pointer!\n");
741
-		    return CL_EBYTECODE;
742
-		}
738
+		READP(ptr, inst->u.unaryop, 4);
743 739
 		WRITE32(inst->dest, (ptr->una_u32));
744 740
 		break;
745 741
 	    }
746 742
 	    case OP_BC_LOAD*5+4:
747 743
 	    {
748 744
 		const union unaligned_64 *ptr;
749
-		READP(ptr, inst->u.unaryop);
745
+		READP(ptr, inst->u.unaryop, 8);
750 746
 		WRITE64(inst->dest, (ptr->una_u64));
751 747
 		break;
752 748
 	    }
... ...
@@ -755,7 +856,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
755 755
 	    {
756 756
 		uint8_t *ptr;
757 757
 		uint8_t v;
758
-		READP(ptr, BINOP(0));
758
+		READP(ptr, BINOP(0), 1);
759 759
 		READ1(v, BINOP(1));
760 760
 		*ptr = v;
761 761
 		break;
... ...
@@ -764,7 +865,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
764 764
 	    {
765 765
 		uint8_t *ptr;
766 766
 		uint8_t v;
767
-		READP(ptr, BINOP(0));
767
+		READP(ptr, BINOP(0), 1);
768 768
 		READ8(v, BINOP(1));
769 769
 		*ptr = v;
770 770
 		break;
... ...
@@ -773,7 +874,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
773 773
 	    {
774 774
 		union unaligned_16 *ptr;
775 775
 		uint16_t v;
776
-		READP(ptr, BINOP(0));
776
+		READP(ptr, BINOP(0), 2);
777 777
 		READ16(v, BINOP(1));
778 778
 		ptr->una_s16 = v;
779 779
 		break;
... ...
@@ -782,7 +883,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
782 782
 	    {
783 783
 		union unaligned_32 *ptr;
784 784
 		uint32_t v;
785
-		READP(ptr, BINOP(0));
785
+		READP(ptr, BINOP(0), 4);
786 786
 		READ32(v, BINOP(1));
787 787
 		ptr->una_u32 = v;
788 788
 		break;
... ...
@@ -791,7 +892,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
791 791
 	    {
792 792
 		union unaligned_64 *ptr;
793 793
 		uint64_t v;
794
-		READP(ptr, BINOP(0));
794
+		READP(ptr, BINOP(0), 8);
795 795
 		READ64(v, BINOP(1));
796 796
 		ptr->una_u64 = v;
797 797
 		break;
... ...
@@ -419,6 +419,7 @@ void cli_errmsg(const char *str, ...);
419 419
 
420 420
 #ifdef __GNUC__
421 421
 #define always_inline inline __attribute__((always_inline))
422
+#define never_inline __attribute__((noinline))
422 423
 #else
423 424
 #define always_inline inline
424 425
 #endif