Jelajahi Sumber

VM delegate is now guaratee to be non null (to speedup checks). Improved instance clone function.

Marco Bambini 7 tahun lalu
induk
melakukan
0d22f9c7bf

+ 3 - 3
src/runtime/gravity_core.c

@@ -556,7 +556,7 @@ static bool object_real_load (gravity_vm *vm, gravity_value_t *args, uint16_t na
     if (!obj) {
         // not explicitly declared so check for dynamic property in bridge case
         gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-        if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_getundef)) {
+        if (instance && instance->xdata && delegate->bridge_getundef) {
             if (delegate->bridge_getundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), rindex)) return true;
         }
     }
@@ -651,7 +651,7 @@ static bool object_store (gravity_vm *vm, gravity_value_t *args, uint16_t nargs,
     if (!obj) {
         // not explicitly declared so check for dynamic property in bridge case
         gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-        if ((instance) && (instance->xdata) && (delegate) && (delegate->bridge_setundef)) {
+        if (instance && instance->xdata && delegate->bridge_setundef) {
             if (delegate->bridge_setundef(vm, instance->xdata, target, VALUE_AS_CSTRING(key), value)) RETURN_NOVALUE();
         }
     }
@@ -1439,7 +1439,7 @@ static bool class_exec (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
 
 	// no closure found (means no constructor found in this class)
 	gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-	if (c->xdata && delegate && delegate->bridge_initinstance) {
+	if (c->xdata && delegate->bridge_initinstance) {
 		// even if no closure is found try to execute the default bridge init instance (if class is bridged)
 		if (nargs != 1) RETURN_ERROR("No init with %d parameters found in class %s", nargs-1, c->identifier);
 		delegate->bridge_initinstance(vm, c->xdata, instance, args, nargs);

+ 8 - 7
src/runtime/gravity_vm.c

@@ -28,6 +28,9 @@ static void gravity_gc_transform (gravity_hash_t *hashtable, gravity_value_t key
 static uint32_t cache_refcount = 0;
 static gravity_value_t cache[GRAVITY_VTABLE_SIZE];
 
+// Used in order to guarantee a NON NULL delegate (so I can speedup comparisons)
+static gravity_delegate_t empty_delegate;
+
 // Opaque VM struct
 struct gravity_vm {
 	gravity_hash_t		*context;							// context hash table
@@ -86,12 +89,10 @@ static void report_runtime_error (gravity_vm *vm, error_type_t error_type, const
 		va_end (arg);
 	}
 
-	gravity_error_callback errorf = NULL;
-	if (vm->delegate) errorf = ((gravity_delegate_t *)vm->delegate)->error_callback;
-
-	if (errorf) {
+	gravity_error_callback error_cb = ((gravity_delegate_t *)vm->delegate)->error_callback;
+	if (error_cb) {
 		void *data = ((gravity_delegate_t *)vm->delegate)->xdata;
-		errorf(error_type, buffer, ERROR_DESC_NONE, data);
+		error_cb(error_type, buffer, ERROR_DESC_NONE, data);
 	} else {
 		printf("%s\n", buffer);
 		fflush(stdout);
@@ -1329,7 +1330,7 @@ gravity_vm *gravity_vm_new (gravity_delegate_t *delegate) {
     vm->maxccalls = MAX_CCALLS;
 
 	vm->pc = 0;
-	vm->delegate = delegate;
+    vm->delegate = (delegate) ? delegate : &empty_delegate;
 	vm->context = gravity_hash_create(DEFAULT_CONTEXT_SIZE, gravity_value_hash, gravity_value_equals, NULL, NULL);
 
 	// garbage collector
@@ -1549,7 +1550,7 @@ bool gravity_vm_runclosure (gravity_vm *vm, gravity_closure_t *closure, gravity_
 			break;
 
 		case EXEC_TYPE_BRIDGED:
-			if (vm && vm->delegate && vm->delegate->bridge_execute)
+			if (vm && vm->delegate->bridge_execute)
 				result = vm->delegate->bridge_execute(vm, f->xdata, &stackstart[rwin], nparams, GRAVITY_FIBER_REGISTER);
 			break;
 

+ 2 - 0
src/shared/gravity_delegate.h

@@ -49,6 +49,7 @@ typedef bool				(*gravity_bridge_getundef) (gravity_vm *vm, void *xdata, gravity
 typedef bool				(*gravity_bridge_execute)  (gravity_vm *vm, void *xdata, gravity_value_t args[], int16_t nargs, uint32_t vindex);
 typedef bool                (*gravity_bridge_equals) (gravity_vm *vm, void *obj1, void *obj2);
 typedef const char*         (*gravity_bridge_string) (gravity_vm *vm, void *xdata, uint32_t *len);
+typedef void*               (*gravity_bridge_clone)  (gravity_vm *vm, void *xdata);
 typedef uint32_t			(*gravity_bridge_size) (gravity_vm *vm, gravity_object_t *obj);
 typedef void				(*gravity_bridge_free) (gravity_vm *vm, gravity_object_t *obj);
 
@@ -75,6 +76,7 @@ typedef struct {
 	gravity_bridge_execute		bridge_execute;			// execute a method/function
     gravity_bridge_string       bridge_string;          // instance string conversion
     gravity_bridge_equals       bridge_equals;          // check if two objects are equals
+    gravity_bridge_clone        bridge_clone;           // clone
 	gravity_bridge_size			bridge_size;			// size of obj
 	gravity_bridge_free			bridge_free;			// free obj
 } gravity_delegate_t;

+ 15 - 11
src/shared/gravity_value.c

@@ -380,7 +380,7 @@ static void gravity_class_free_internal (gravity_vm *vm, gravity_class_t *c, boo
 	// check if bridged data needs to be freed too
 	if (c->xdata && vm) {
 		gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-		if (delegate && delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)c);
+		if (delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)c);
 	}
 
 	if (c->identifier) mem_free((void *)c->identifier);
@@ -446,7 +446,7 @@ uint32_t gravity_class_size (gravity_vm *vm, gravity_class_t *c) {
 	hash_size += gravity_hash_memsize(c->htable);
 
 	gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-	if ((c->xdata) && (delegate) && (delegate->bridge_size))
+	if (c->xdata && delegate->bridge_size)
 		class_size += delegate->bridge_size(vm, c->xdata);
 
 	return class_size;
@@ -932,7 +932,7 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
 			continue;
 		}
 
-        // names
+        // arguments names
         if (string_casencmp(label, GRAVITY_JSON_LABELPNAMES, label_size) == 0) {
             if (value->type != json_array) goto abort_load;
             if (f->tag != EXEC_TYPE_NATIVE) goto abort_load;
@@ -944,7 +944,7 @@ gravity_function_t *gravity_function_deserialize (gravity_vm *vm, json_value *js
             }
         }
         
-        // defaults
+        // arguments default values
         if (string_casencmp(label, GRAVITY_JSON_LABELPVALUES, label_size) == 0) {
             if (value->type != json_array) goto abort_load;
             if (f->tag != EXEC_TYPE_NATIVE) goto abort_load;
@@ -1067,7 +1067,7 @@ void gravity_function_free (gravity_vm *vm, gravity_function_t *f) {
 	// check if bridged data needs to be freed too
 	if (f->xdata && vm) {
 		gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-		if (delegate && delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)f);
+		if (delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)f);
 	}
 
 	if (f->identifier) mem_free((void *)f->identifier);
@@ -1112,7 +1112,7 @@ uint32_t gravity_function_size (gravity_vm *vm, gravity_function_t *f) {
 		if ((f->special[1]) && (f->special[0] != f->special[1])) func_size += gravity_closure_size(vm, (gravity_closure_t *)f->special[1]);
 	} else if (f->tag == EXEC_TYPE_BRIDGED) {
 		gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-		if ((f->xdata) && (delegate) && (delegate->bridge_size))
+		if (f->xdata && delegate->bridge_size)
 			func_size += delegate->bridge_size(vm, f->xdata);
 	}
 
@@ -1513,11 +1513,15 @@ gravity_instance_t *gravity_instance_new (gravity_vm *vm, gravity_class_t *c) {
 	return instance;
 }
 
-gravity_instance_t *gravity_instance_dup (gravity_vm *vm, gravity_instance_t *src) {
+gravity_instance_t *gravity_instance_clone (gravity_vm *vm, gravity_instance_t *src) {
 	gravity_class_t *c = src->objclass;
 
 	gravity_instance_t *instance = (gravity_instance_t *)mem_alloc(NULL, sizeof(gravity_instance_t) + (c->nivars * sizeof(gravity_value_t)));
-	instance->objclass = c;
+	instance->isa = gravity_class_instance;
+    instance->objclass = c; // TODO: if gravity_class_is_anon(c) then c must be deeply copied
+    
+    gravity_delegate_t *delegate = gravity_vm_delegate(vm);
+    instance->xdata = (src->xdata && delegate->bridge_clone) ? delegate->bridge_clone(vm, src->xdata) : NULL;
 	for (uint32_t i=0; i<c->nivars; ++i) instance->ivars[i] = src->ivars[i];
 
 	if (vm) gravity_vm_transfer(vm, (gravity_object_t*) instance);
@@ -1538,7 +1542,7 @@ void gravity_instance_free (gravity_vm *vm, gravity_instance_t *i) {
 	// check if bridged data needs to be freed too
 	if (i->xdata && vm) {
 		gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-		if (delegate && delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)i);
+		if (delegate->bridge_free) delegate->bridge_free(vm, (gravity_object_t *)i);
 	}
 
 	mem_free((void *)i);
@@ -1562,7 +1566,7 @@ uint32_t gravity_instance_size (gravity_vm *vm, gravity_instance_t *i) {
 	uint32_t instance_size = sizeof(gravity_instance_t) + (i->objclass->nivars * sizeof(gravity_value_t));
 
 	gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-	if ((i->xdata) && (delegate) && (delegate->bridge_size))
+	if (i->xdata && delegate->bridge_size)
 		instance_size += delegate->bridge_size(vm, i->xdata);
 
 	return instance_size;
@@ -1598,7 +1602,7 @@ bool gravity_value_vm_equals (gravity_vm *vm, gravity_value_t v1, gravity_value_
     gravity_instance_t *obj2 = (gravity_instance_t *)VALUE_AS_OBJECT(v2);
 
     gravity_delegate_t *delegate = gravity_vm_delegate(vm);
-    if (delegate && obj1->xdata && obj2->xdata && delegate->bridge_equals) {
+    if (obj1->xdata && obj2->xdata && delegate->bridge_equals) {
         return delegate->bridge_equals(vm, obj1->xdata, obj2->xdata);
     }
 

+ 3 - 3
src/shared/gravity_value.h

@@ -66,8 +66,8 @@
 extern "C" {
 #endif
 
-#define GRAVITY_VERSION						"0.4.2"     // git tag 0.4.2
-#define GRAVITY_VERSION_NUMBER				0x000402    // git push --tags
+#define GRAVITY_VERSION						"0.4.3"     // git tag 0.4.3
+#define GRAVITY_VERSION_NUMBER				0x000403    // git push --tags
 #define GRAVITY_BUILD_DATE					__DATE__
 
 #ifndef GRAVITY_ENABLE_DOUBLE
@@ -464,7 +464,7 @@ GRAVITY_API uint32_t			gravity_fiber_size (gravity_vm *vm, gravity_fiber_t *fibe
 
 // MARK: - INSTANCE -
 GRAVITY_API gravity_instance_t	*gravity_instance_new (gravity_vm *vm, gravity_class_t *c);
-GRAVITY_API gravity_instance_t	*gravity_instance_dup (gravity_vm *vm, gravity_instance_t *src);
+GRAVITY_API gravity_instance_t	*gravity_instance_clone (gravity_vm *vm, gravity_instance_t *instance);
 GRAVITY_API void				gravity_instance_setivar (gravity_instance_t *instance, uint32_t idx, gravity_value_t value);
 GRAVITY_API void				gravity_instance_setxdata (gravity_instance_t *i, void *xdata);
 GRAVITY_API void				gravity_instance_free (gravity_vm *vm, gravity_instance_t *i);