Browse Source

Saved IP before invoking runtime error in order to correctly resolve line number

Marco Bambini 6 years ago
parent
commit
5741aa5bd8

+ 12 - 7
src/compiler/gravity_ircode.c

@@ -256,9 +256,9 @@ uint8_t opcode_numop (opcode_t op) {
     return 0;
     return 0;
 }
 }
 
 
-void ircode_dump  (void *_code) {
+void ircode_dump (void *_code) {
     ircode_t    *code = (ircode_t *)_code;
     ircode_t    *code = (ircode_t *)_code;
-    code_r        *list = code->list;
+    code_r      *list = code->list;
     uint32_t    count = ircode_count(code);
     uint32_t    count = ircode_count(code);
 
 
     if (count == 0) {
     if (count == 0) {
@@ -267,18 +267,23 @@ void ircode_dump  (void *_code) {
     }
     }
 
 
     for (uint32_t i=0, line=0; i<count; ++i) {
     for (uint32_t i=0, line=0; i<count; ++i) {
-        inst_t *inst = marray_get(*list, i);
+        inst_t      *inst = marray_get(*list, i);
         opcode_t    op = inst->op;
         opcode_t    op = inst->op;
-        int32_t        p1 = inst->p1;
-        int32_t        p2 = inst->p2;
-        int32_t        p3 = inst->p3;
+        int32_t     p1 = inst->p1;
+        int32_t     p2 = inst->p2;
+        int32_t     p3 = inst->p3;
         if (inst->tag == SKIP_TAG) continue;
         if (inst->tag == SKIP_TAG) continue;
         if (inst->tag == PRAGMA_MOVE_OPTIMIZATION) continue;
         if (inst->tag == PRAGMA_MOVE_OPTIMIZATION) continue;
         if (inst->tag == LABEL_TAG) {printf("LABEL %d:\n", p1); continue;}
         if (inst->tag == LABEL_TAG) {printf("LABEL %d:\n", p1); continue;}
 
 
         uint8_t n = opcode_numop(op);
         uint8_t n = opcode_numop(op);
         if ((op == SETLIST) && (p2 == 0)) n = 2;
         if ((op == SETLIST) && (p2 == 0)) n = 2;
-
+        
+        // set to 1 to debug line number for each instruction
+        #if 0
+        printf("(%d)\t\t", inst->lineno);
+        #endif
+        
         switch (n) {
         switch (n) {
             case 0: {
             case 0: {
                 printf("%05d\t%s\n", line, opcode_name(op));
                 printf("%05d\t%s\n", line, opcode_name(op));

+ 20 - 7
src/runtime/gravity_vm.c

@@ -265,8 +265,10 @@ static inline bool gravity_check_stack (gravity_vm *vm, gravity_fiber_t *fiber,
         fiber->stacktop -= stacktopdelta;
         fiber->stacktop -= stacktopdelta;
 
 
         // stack reallocation failed means that there is a very high probability to be into an infinite loop
         // stack reallocation failed means that there is a very high probability to be into an infinite loop
-        RUNTIME_ERROR("Infinite loop detected. Current execution must be aborted.");
+        // so return false and let the calling function (vm_exec) raise a runtime error
+        return false;
     }
     }
+    
     fiber->stack = (gravity_value_t *)ptr;
     fiber->stack = (gravity_value_t *)ptr;
     fiber->stackalloc = new_size;
     fiber->stackalloc = new_size;
     STAT_STACK_REALLOCATED(vm);
     STAT_STACK_REALLOCATED(vm);
@@ -1079,7 +1081,9 @@ static bool gravity_vm_exec (gravity_vm *vm) {
                         uint32_t rwin = FN_COUNTREG(func, frame->nargs);
                         uint32_t rwin = FN_COUNTREG(func, frame->nargs);
                         uint32_t _rneed = FN_COUNTREG(closure->f, 1);
                         uint32_t _rneed = FN_COUNTREG(closure->f, 1);
 						uint32_t stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - fiber->stacktop, 0);
 						uint32_t stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - fiber->stacktop, 0);
-                        if (!gravity_check_stack(vm, fiber, stacktopdelta, &stackstart)) return false;
+                        if (!gravity_check_stack(vm, fiber, stacktopdelta, &stackstart)) {
+                            RUNTIME_ERROR("Infinite loop detected. Current execution must be aborted.");
+                        }
                         SETVALUE(rwin, v1);
                         SETVALUE(rwin, v1);
 
 
                         // call func and check result
                         // call func and check result
@@ -1137,7 +1141,9 @@ static bool gravity_vm_exec (gravity_vm *vm) {
                 // check stack size
                 // check stack size
                 uint32_t _rneed = FN_COUNTREG(closure->f, r3);
                 uint32_t _rneed = FN_COUNTREG(closure->f, r3);
 				uint32_t stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - fiber->stacktop, 0);
 				uint32_t stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - fiber->stacktop, 0);
-                if (!gravity_check_stack(vm, fiber, stacktopdelta, &stackstart)) return false;
+                if (!gravity_check_stack(vm, fiber, stacktopdelta, &stackstart)) {
+                    RUNTIME_ERROR("Infinite loop detected. Current execution must be aborted.");
+                }
 
 
                 // if less arguments are passed then fill the holes with UNDEFINED values
                 // if less arguments are passed then fill the holes with UNDEFINED values
                 while (r3 < closure->f->nparams) {
                 while (r3 < closure->f->nparams) {
@@ -1606,6 +1612,10 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
     gravity_value_t     *stackstart = NULL;
     gravity_value_t     *stackstart = NULL;
     uint32_t            rwin = 0;
     uint32_t            rwin = 0;
 	uint32_t			stacktopdelta = 0;
 	uint32_t			stacktopdelta = 0;
+    
+    // current frame and current instruction pointer
+    gravity_callframe_t *frame;
+    uint32_t            *ip;
 	
 	
     DEBUG_STACK();
     DEBUG_STACK();
 
 
@@ -1623,13 +1633,13 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
     // the new activation frame
     // the new activation frame
     if (fiber->nframes) {
     if (fiber->nframes) {
         // current call frame
         // current call frame
-        gravity_callframe_t *frame = &fiber->frames[fiber->nframes - 1];
+        frame = &fiber->frames[fiber->nframes - 1];
 
 
         // current top of the stack
         // current top of the stack
         stackstart = frame->stackstart;
         stackstart = frame->stackstart;
 
 
         // current instruction pointer
         // current instruction pointer
-        uint32_t *ip = frame->ip;
+        ip = frame->ip;
 
 
         // compute register window
         // compute register window
         rwin = FN_COUNTREG(frame->closure->f, frame->nargs);
         rwin = FN_COUNTREG(frame->closure->f, frame->nargs);
@@ -1637,7 +1647,9 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
         // check stack size
         // check stack size
         uint32_t _rneed = FN_COUNTREG(f,nparams+1);
         uint32_t _rneed = FN_COUNTREG(f,nparams+1);
 		stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - vm->fiber->stacktop, 0);
 		stacktopdelta = (uint32_t)MAXNUM(stackstart + rwin + _rneed - vm->fiber->stacktop, 0);
-        if (!gravity_check_stack(vm, vm->fiber, stacktopdelta, &stackstart)) return false;
+        if (!gravity_check_stack(vm, vm->fiber, stacktopdelta, &stackstart)) {
+            RUNTIME_ERROR("Infinite loop detected. Current execution must be aborted.");
+        }
 		
 		
         // setup params (first param is self)
         // setup params (first param is self)
         SETVALUE(rwin, selfvalue);
         SETVALUE(rwin, selfvalue);
@@ -1661,7 +1673,8 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
         }
         }
 
 
         // check if closure uses the special _args instruction
         // check if closure uses the special _args instruction
-        gravity_callframe_t *frame = &fiber->frames[0];
+        frame = &fiber->frames[0];
+        ip = frame->ip;
         frame->args = (USE_ARGS(closure)) ? gravity_list_from_array(vm, nparams, &stackstart[rwin]+1) : NULL;
         frame->args = (USE_ARGS(closure)) ? gravity_list_from_array(vm, nparams, &stackstart[rwin]+1) : NULL;
     }
     }
 
 

+ 7 - 2
src/runtime/gravity_vmmacros.h

@@ -34,7 +34,7 @@
 #define OPCODE_GET_FOUR8bit(op,r1,r2,r3,r4)             r1 = (op >> 24) & 0xFF; r2 = (op >> 16) & 0xFF; r3 = (op >> 8) & 0xFF; r4 = (op & 0xFF)
 #define OPCODE_GET_FOUR8bit(op,r1,r2,r3,r4)             r1 = (op >> 24) & 0xFF; r2 = (op >> 16) & 0xFF; r3 = (op >> 8) & 0xFF; r4 = (op & 0xFF)
 #define OPCODE_GET_THREE8bit_ONE2bit(op,r1,r2,r3,r4)    r1 = (op >> 18) & 0xFF; r2 = (op >> 10) & 0xFF; r3 = (op >> 2) & 0xFF; r4 = (op & 0x03)
 #define OPCODE_GET_THREE8bit_ONE2bit(op,r1,r2,r3,r4)    r1 = (op >> 18) & 0xFF; r2 = (op >> 10) & 0xFF; r3 = (op >> 2) & 0xFF; r4 = (op & 0x03)
 
 
-#define GRAVITY_VM_DEGUB                0               // print each VM instruction
+#define GRAVITY_VM_DEBUG                0               // print each VM instruction
 #define GRAVITY_VM_STATS                0               // print VM related stats after each execution
 #define GRAVITY_VM_STATS                0               // print VM related stats after each execution
 #define GRAVITY_GC_STATS                0               // print useful stats each time GC runs
 #define GRAVITY_GC_STATS                0               // print useful stats each time GC runs
 #define GRAVITY_GC_STRESSTEST           0               // force a GC run after each memory allocation
 #define GRAVITY_GC_STRESSTEST           0               // force a GC run after each memory allocation
@@ -56,7 +56,7 @@
 #define DEBUG_GC(...)
 #define DEBUG_GC(...)
 #endif
 #endif
 
 
-#if GRAVITY_VM_DEGUB
+#if GRAVITY_VM_DEBUG
 #define DEBUG_VM(...)                   DEBUG_STACK();printf("%06u\t",vm->pc); printf(__VA_ARGS__);printf("\n");fflush(stdout)
 #define DEBUG_VM(...)                   DEBUG_STACK();printf("%06u\t",vm->pc); printf(__VA_ARGS__);printf("\n");fflush(stdout)
 #define DEBUG_VM_NOCR(...)              DEBUG_STACK();printf("%06u\t",vm->pc); printf(__VA_ARGS__);fflush(stdout)
 #define DEBUG_VM_NOCR(...)              DEBUG_STACK();printf("%06u\t",vm->pc); printf(__VA_ARGS__);fflush(stdout)
 #define DEBUG_VM_RAW(...)               printf(__VA_ARGS__);fflush(stdout)
 #define DEBUG_VM_RAW(...)               printf(__VA_ARGS__);fflush(stdout)
@@ -92,7 +92,12 @@
 #define STAT_STACK_REALLOCATED(_vm)
 #define STAT_STACK_REALLOCATED(_vm)
 #endif
 #endif
 
 
+// starting from version 0.6.3 a call to STORE_FRAME macro has been added in order to syncronize current IP
+// for a better line number computation in case of runtime error (as a consequence ip and frame variables
+// has been explicitly exposed in the gravity_vm_runclosure function and the infinite loop error message
+// has been moved outside the gravity_check_stack function)
 #define RUNTIME_ERROR(...)              do {                                                                \
 #define RUNTIME_ERROR(...)              do {                                                                \
+                                            STORE_FRAME();                                                  \
                                             report_runtime_error(vm, GRAVITY_ERROR_RUNTIME, __VA_ARGS__);   \
                                             report_runtime_error(vm, GRAVITY_ERROR_RUNTIME, __VA_ARGS__);   \
                                             return false;                                                   \
                                             return false;                                                   \
                                         } while (0)
                                         } while (0)

+ 2 - 0
src/shared/gravity_value.c

@@ -1321,6 +1321,7 @@ void gravity_fiber_free (gravity_vm *vm, gravity_fiber_t *fiber) {
     mem_free(fiber->frames);
     mem_free(fiber->frames);
     
     
     // free upvalues
     // free upvalues
+    /*
     if (fiber->upvalues) {
     if (fiber->upvalues) {
         gravity_upvalue_t *upvalue = fiber->upvalues;
         gravity_upvalue_t *upvalue = fiber->upvalues;
         gravity_upvalue_t *tempvalue;
         gravity_upvalue_t *tempvalue;
@@ -1330,6 +1331,7 @@ void gravity_fiber_free (gravity_vm *vm, gravity_fiber_t *fiber) {
             gravity_upvalue_free(vm, tempvalue);
             gravity_upvalue_free(vm, tempvalue);
         }
         }
     }
     }
+     */
     
     
     mem_free(fiber);
     mem_free(fiber);
 }
 }

+ 2 - 2
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define GRAVITY_VERSION						"0.6.2"     // git tag 0.6.2
-#define GRAVITY_VERSION_NUMBER				0x000602    // git push --tags
+#define GRAVITY_VERSION						"0.6.3"     // git tag 0.6.3
+#define GRAVITY_VERSION_NUMBER				0x000603    // git push --tags
 #define GRAVITY_BUILD_DATE                  __DATE__
 #define GRAVITY_BUILD_DATE                  __DATE__
 
 
 #ifndef GRAVITY_ENABLE_DOUBLE
 #ifndef GRAVITY_ENABLE_DOUBLE