Browse Source

Fixed an issue with custom setter and improved GC.

Marco Bambini 6 years ago
parent
commit
dcfcd36dfe

+ 5 - 2
src/runtime/gravity_core.c

@@ -1140,9 +1140,11 @@ static bool list_filter(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
 static bool list_reduce(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
   if (nargs != 3) RETURN_ERROR("Two arguments are needed by the reduce function.");
   if (!VALUE_ISA_CLOSURE(GET_VALUE(2))) RETURN_ERROR("Argument 2 must be a Closure.");
-  gravity_value_t selfvalue = GET_VALUE(0);    // self parameter
-  gravity_value_t start = GET_VALUE(1);    // start parameter
+    
+  gravity_value_t selfvalue = GET_VALUE(0); // self parameter
+  gravity_value_t start = GET_VALUE(1);     // start parameter
   gravity_closure_t *predicate = VALUE_AS_CLOSURE(GET_VALUE(2));
+    
   gravity_list_t *list = VALUE_AS_LIST(selfvalue);
   size_t count = marray_size(list->array);
   for (uint32_t i = 0; i < count; i++) {
@@ -1150,6 +1152,7 @@ static bool list_reduce(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
     if (!gravity_vm_runclosure(vm, predicate, selfvalue, params, 2)) return false;
     start = gravity_vm_result(vm);
   }
+    
   RETURN_VALUE(start, rindex);
 }
 

+ 17 - 3
src/runtime/gravity_vm.c

@@ -433,7 +433,7 @@ static bool gravity_vm_exec (gravity_vm *vm) {
                 execute_load_function:
                 switch(closure->f->tag) {
                     case EXEC_TYPE_NATIVE: {
-                        // invalidate current_fiber because it does not need to be synced in this case
+                        // invalidate current_fiber because it does not need to be in sync in this case
                         current_fiber = NULL;
                         PUSH_FRAME(closure, &stackstart[rwin], r1, 2);
                     } break;
@@ -567,14 +567,21 @@ static bool gravity_vm_exec (gravity_vm *vm) {
                 // save currently executing fiber (that can change!)
                 gravity_fiber_t *current_fiber = fiber;
                 
+                // in case of computed property what happens is that EXEC_TYPE_INTERNAL returns false
+                // and the initial closure variable is overwritten by the closure to be executed returned
+                // in the r1 registed. The goto execute_store_function take cares of re-executing the code
+                // with the updated closure (that contains the computed property code) but the r1 register
+                // must be re-set with its initial value backed-up in the r1copy variable
+                bool reset_r1 = false;
+                
                 // call function f (do not use a macro here because we want to handle both the bridged and special cases)
                 STORE_FRAME();
                 execute_store_function:
                 switch(closure->f->tag) {
                     case EXEC_TYPE_NATIVE: {
-                        // invalidate current_fiber because it does not need to be synced in this case
+                        // invalidate current_fiber because it does not need to be in sync in this case
                         current_fiber = NULL;
-                        SETVALUE(rwin+1, v1);
+                        if (reset_r1) SETVALUE(rwin+1, v1);
                         PUSH_FRAME(closure, &stackstart[rwin], r1, 2);
                     } break;
 
@@ -591,6 +598,7 @@ static bool gravity_vm_exec (gravity_vm *vm) {
                             if (VALUE_ISA_CLOSURE(STACK_GET(r1))) {
                                 closure = VALUE_AS_CLOSURE(STACK_GET(r1));
                                 SETVALUE(r1, r1copy);
+                                reset_r1 = true;
                                 goto execute_store_function;
                             }
 
@@ -2140,6 +2148,10 @@ static void gravity_gc_transfer_object (gravity_vm *vm, gravity_object_t *obj) {
     vm->gchead = obj;
 }
 
+static void gravity_gc_check (gravity_vm *vm) {
+	if (vm->memallocated >= vm->gcthreshold) gravity_gc_start(vm);
+}
+
 static void gravity_gc_transfer (gravity_vm *vm, gravity_object_t *obj) {
     if (vm->gcenabled > 0) {
         #if GRAVITY_GC_STRESSTEST
@@ -2293,6 +2305,8 @@ static void gravity_gc_cleanup (gravity_vm *vm) {
 void gravity_gc_setenabled (gravity_vm *vm, bool enabled) {
     if (!vm) return;
     (enabled) ? ++vm->gcenabled : --vm->gcenabled ;
+    
+	if (vm->gcenabled > 0 && (!vm->delegate->disable_gccheck_1)) gravity_gc_check(vm);
 }
 
 void gravity_gc_temppush (gravity_vm *vm, gravity_object_t *obj) {

+ 2 - 1
src/shared/gravity_delegate.h

@@ -59,7 +59,8 @@ typedef struct {
     // user data
     void                        *xdata;                 // optional user data transparently passed between callbacks
     bool                        report_null_errors;     // by default messages sent to null objects are silently ignored (if this flag is false)
-
+    bool                        disable_gccheck_1;      // memory allocations are protected so it could be useful to automatically check gc when enabled is restored
+    
     // callbacks
     gravity_log_callback        log_callback;           // log reporting callback
     gravity_log_clear           log_clear;              // log reset callback

+ 0 - 1
src/shared/gravity_opcodes.h

@@ -200,7 +200,6 @@ typedef enum {
 #define GRAVITY_INTERNAL_STOREAT_NAME   "storeat"
 #define GRAVITY_INTERNAL_NOTFOUND_NAME  "notfound"
 #define GRAVITY_INTERNAL_EXEC_NAME      "exec"
-#define GRAVITY_INTERNAL_FREE_NAME      "free"
 #define GRAVITY_INTERNAL_LOOP_NAME      "loop"
 
 #define GRAVITY_CLASS_INT_NAME          "Int"

+ 12 - 5
src/shared/gravity_value.c

@@ -1319,6 +1319,18 @@ void gravity_fiber_free (gravity_vm *vm, gravity_fiber_t *fiber) {
     if (fiber->error) mem_free(fiber->error);
     mem_free(fiber->stack);
     mem_free(fiber->frames);
+    
+    // free upvalues
+    if (fiber->upvalues) {
+        gravity_upvalue_t *upvalue = fiber->upvalues;
+        gravity_upvalue_t *tempvalue;
+        while (upvalue) {
+            tempvalue = upvalue;
+            upvalue = upvalue->next;
+            gravity_upvalue_free(vm, tempvalue);
+        }
+    }
+    
     mem_free(fiber);
 }
 
@@ -1617,11 +1629,6 @@ void gravity_instance_free (gravity_vm *vm, gravity_instance_t *i) {
     if (i->xdata && vm) {
         gravity_delegate_t *delegate = gravity_vm_delegate(vm);
         if (delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)i);
-        else {
-            // check if closure implements a free method
-            gravity_closure_t *closure = gravity_instance_lookup_event (i, GRAVITY_INTERNAL_FREE_NAME);
-            if (closure) gravity_vm_runclosure(vm, closure, VALUE_FROM_OBJECT(i), NULL, 0);
-        }
     }
 
     if (i->ivars) mem_free(i->ivars);

+ 26 - 0
test/unittest/custom_load_storeat.gravity

@@ -0,0 +1,26 @@
+#unittest {
+	name: "Custom load/store";
+	error: NONE;
+	result: "bar";
+};
+
+class A {
+    private var storage;
+    
+    func init() {
+        storage = [:];
+    }
+    func storeat(key, value) {
+        storage[key] = value;
+    }
+    
+    func loadat(key) {
+        return storage[key];
+    }
+}
+
+func main() {
+    var inst = A();
+    inst["foo"] = "bar";
+    return inst["foo"];
+}