Selaa lähdekoodia

Fixed some memory leaks related to core (and opt) classes.

Marco Bambini 7 vuotta sitten
vanhempi
commit
e41bfbb8a3

+ 1 - 13
src/optionals/gravity_math.c

@@ -689,14 +689,6 @@ static bool math_SQRT1_2 (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 
 // MARK: - Internals -
 
-//static void free_computed_property (gravity_class_t *c, const char *name) {
-//    // computed properties are not registered inside VM gc so they need to be manually freed here
-//    STATICVALUE_FROM_STRING(key, name, strlen(name));
-//    gravity_closure_t *closure = gravity_class_lookup_closure(c, key);
-//    computed_property_free(closure);
-//    gravity_hash_remove(c->htable, key);
-//}
-
 static void create_optional_class (void) {
     gravity_class_math = gravity_class_new_pair(NULL, MATH_CLASS_NAME, NULL, 0, 0);
     gravity_class_t *meta = gravity_class_get_meta(gravity_class_math);
@@ -767,11 +759,8 @@ void gravity_math_register (gravity_vm *vm) {
 
 void gravity_math_free (void) {
     if (!gravity_class_math) return;
+    if (--refcount) return;
 
-    --refcount;
-    if (refcount) return;
-
-    mem_check(false);
     gravity_class_t *meta = gravity_class_get_meta(gravity_class_math);
     computed_property_free(meta, "PI", true);
     computed_property_free(meta, "E", true);
@@ -783,7 +772,6 @@ void gravity_math_free (void) {
     computed_property_free(meta, "SQRT1_2", true);
     gravity_class_free_core(NULL, meta);
     gravity_class_free_core(NULL, gravity_class_math);
-    mem_check(true);
 
     gravity_class_math = NULL;
 }

+ 6 - 6
src/runtime/gravity_core.c

@@ -717,7 +717,7 @@ static bool object_bind (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
 	}
 
 	// check if instance has already an anonymous class added to its hierarchy
-	if (string_casencmp(c->identifier, GRAVITY_VM_ANONYMOUS_PREFIX, strlen(GRAVITY_VM_ANONYMOUS_PREFIX) != 0)) {
+	if (!gravity_class_is_anon(c)) {
 		// no super anonymous class found so create a new one, set its super as c, and add it to the hierarchy
 		char *name = gravity_vm_anonymous(vm);
 		gravity_class_t *anon = gravity_class_new_pair(NULL, name, c, 0, 0);
@@ -2532,7 +2532,7 @@ static void gravity_core_init (void) {
 	if (core_inited) return;
 	core_inited = true;
 
-	mem_check(false);
+	//mem_check(false);
 
 	// Creation order here is very important
 	// for example in a earlier version the intrinsic classes
@@ -2838,7 +2838,7 @@ static void gravity_core_init (void) {
 	SETMETA_INITED(gravity_class_system);
 	//SETMETA_INITED(gravity_class_module);
 
-	mem_check(true);
+	//mem_check(true);
 }
 
 void gravity_core_free (void) {
@@ -2848,13 +2848,13 @@ void gravity_core_free (void) {
 	if (!core_inited) return;
 
 	// check if others VM are still running
-	if (--refcount != 0) return;
+	if (--refcount) return;
 
 	// this function should never be called
 	// it is just called when we need to internally check for memory leaks
 
     // computed properties are not registered inside VM gc so they need to be manually freed here
-	mem_check(false);
+	//mem_check(false);
     computed_property_free(gravity_class_list, "count", true);
     computed_property_free(gravity_class_map, "count", true);
     computed_property_free(gravity_class_range, "count", true);
@@ -2905,7 +2905,7 @@ void gravity_core_free (void) {
 	// object must be the last class to be freed
 	gravity_class_free_core(NULL, gravity_class_class);
 	gravity_class_free_core(NULL, gravity_class_object);
-	mem_check(true);
+	//mem_check(true);
 
 	gravity_class_int = NULL;
 	gravity_class_float = NULL;

+ 11 - 8
src/runtime/gravity_vm.c

@@ -1417,9 +1417,11 @@ void gravity_vm_seterror_string (gravity_vm* vm, const char *s) {
 
 #if GRAVITY_VM_STATS
 static void gravity_vm_stats (gravity_vm *vm) {
-	printf("\n============================================\n");
-	printf("%12s %10s %20s\n", "OPCODE", "USAGE", "MICROBENCH (ms)");
-	printf("============================================\n");
+    printf("\n=======================================================\n");
+    printf("                   GRAVITY VM STATS\n");
+	printf("=======================================================\n");
+	printf("%12s %10s %10s %20s\n", "OPCODE", "USAGE", "MEAN", "MICROBENCH (ms)");
+	printf("=======================================================\n");
 
 	double total = 0.0;
 	for (uint32_t i=0; i<GRAVITY_LATEST_OPCODE; ++i) {
@@ -1431,15 +1433,16 @@ static void gravity_vm_stats (gravity_vm *vm) {
 	for (uint32_t i=0; i<GRAVITY_LATEST_OPCODE; ++i) {
 		if (vm->nstat[i]) {
 			uint32_t n = vm->nstat[i];
-			double d = vm->tstat[i] / (double)n;
-			double p = (vm->tstat[i] * 100) / total;
-			printf("%12s %*d %*.4f (%.2f%%)\n", opcode_name((opcode_t)i), 10, n, 11, d, p);
+            double d = vm->tstat[i];
+            double m = d / (double)n;
+			double p = (d * 100) / total;
+			printf("%12s %*d %*.4f %*.4f (%.2f%%)\n", opcode_name((opcode_t)i), 10, n, 11, m, 10, d, p);
 		}
 	}
-	printf("============================================\n");
+	printf("=======================================================\n");
 	printf("# Frames reallocs: %d (%d)\n", vm->nfrealloc, vm->fiber->framesalloc);
 	printf("# Stack  reallocs: %d (%d)\n", vm->nsrealloc, vm->fiber->stackalloc);
-	printf("============================================\n");
+	printf("=======================================================\n");
 }
 #endif
 

+ 17 - 1
src/shared/gravity_value.c

@@ -58,6 +58,17 @@ void gravity_hash_keyfree (gravity_hash_t *table, gravity_value_t key, gravity_v
 	gravity_value_free(vm, key);
 }
 
+void gravity_hash_finteralfree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data) {
+    #pragma unused(table, key, data)
+    if (gravity_value_isobject(value)) {
+        gravity_object_t *obj = VALUE_AS_OBJECT(value);
+        if (OBJECT_ISA_CLOSURE(obj)) {
+            gravity_closure_t *closure = (gravity_closure_t *)obj;
+            if (closure->f && closure->f->tag == EXEC_TYPE_INTERNAL) gravity_function_free(NULL, closure->f);
+        }
+    }
+}
+
 void gravity_hash_valuefree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data) {
 	#pragma unused(table, key)
 	gravity_vm *vm = (gravity_vm *)data;
@@ -205,6 +216,10 @@ bool gravity_class_is_meta (gravity_class_t *c) {
 	return (c->objclass == gravity_class_object);
 }
 
+bool gravity_class_is_anon (gravity_class_t *c) {
+    return (string_casencmp(c->identifier, GRAVITY_VM_ANONYMOUS_PREFIX, strlen(GRAVITY_VM_ANONYMOUS_PREFIX)) == 0);
+}
+
 uint32_t gravity_class_count_ivars (gravity_class_t *c) {
 	return (uint32_t)c->nivars;
 }
@@ -371,6 +386,7 @@ static void gravity_class_free_internal (gravity_vm *vm, gravity_class_t *c, boo
 	if (c->identifier) mem_free((void *)c->identifier);
 	if (!skip_base) {
 		// base classes have functions not registered inside VM so manually free all of them
+        gravity_hash_iterate(c->htable, gravity_hash_finteralfree, NULL);
 		gravity_hash_iterate(c->htable, gravity_hash_valuefree, NULL);
 	}
 
@@ -1658,7 +1674,7 @@ bool gravity_value_isobject (gravity_value_t v) {
 	// return true;
 
 	if ((v.isa == NULL) || (v.isa == gravity_class_int) || (v.isa == gravity_class_float) ||
-		(v.isa == gravity_class_bool) || (v.isa == gravity_class_null)) return false;
+		(v.isa == gravity_class_bool) || (v.isa == gravity_class_null) || (v.p == NULL)) return false;
 	return true;
 }
 

+ 4 - 2
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 #endif
 
-#define GRAVITY_VERSION						"0.3.8"     // git tag 0.3.8
-#define GRAVITY_VERSION_NUMBER				0x000308    // git push --tags
+#define GRAVITY_VERSION						"0.3.9"     // git tag 0.3.8
+#define GRAVITY_VERSION_NUMBER				0x000309    // git push --tags
 #define GRAVITY_BUILD_DATE					__DATE__
 
 #ifndef GRAVITY_ENABLE_DOUBLE
@@ -437,6 +437,7 @@ GRAVITY_API gravity_class_t		*gravity_class_new_single (gravity_vm *vm, const ch
 GRAVITY_API gravity_class_t		*gravity_class_new_pair (gravity_vm *vm, const char *identifier, gravity_class_t *superclass, uint32_t nivar, uint32_t nsvar);
 GRAVITY_API gravity_class_t		*gravity_class_get_meta (gravity_class_t *c);
 GRAVITY_API bool				gravity_class_is_meta (gravity_class_t *c);
+GRAVITY_API bool                gravity_class_is_anon (gravity_class_t *c);
 GRAVITY_API uint32_t			gravity_class_count_ivars (gravity_class_t *c);
 GRAVITY_API void				gravity_class_dump (gravity_class_t *c);
 GRAVITY_API void				gravity_class_setxdata (gravity_class_t *c, void *xdata);
@@ -526,6 +527,7 @@ GRAVITY_API uint32_t			gravity_string_size (gravity_vm *vm, gravity_string_t *st
 GRAVITY_API void				gravity_hash_keyvaluefree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data);
 GRAVITY_API void				gravity_hash_keyfree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data);
 GRAVITY_API void				gravity_hash_valuefree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data);
+GRAVITY_API void                gravity_hash_finteralfree (gravity_hash_t *table, gravity_value_t key, gravity_value_t value, void *data);
 
 #ifdef __cplusplus
 }