Signed-off-by: Vegard Nossum <vegard.nos...@gmail.com>
---
 include/vm/object.h    |    2 +
 test/vm/preload-stub.c |    1 +
 vm/class.c             |    5 ++-
 vm/jato.c              |    9 ++++-
 vm/object.c            |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/include/vm/object.h b/include/vm/object.h
index 7f49c52..9bb4b93 100644
--- a/include/vm/object.h
+++ b/include/vm/object.h
@@ -30,6 +30,8 @@ struct vm_object *vm_object_alloc_multi_array(struct vm_class 
*class,
        int nr_dimensions, int *count);
 struct vm_object *vm_object_alloc_array(struct vm_class *class, int count);
 
+struct vm_object *vm_object_clone(struct vm_object *obj);
+
 struct vm_object *
 vm_object_alloc_string_from_utf8(const uint8_t bytes[], unsigned int length);
 struct vm_object *vm_object_alloc_string_from_c(const char *bytes);
diff --git a/test/vm/preload-stub.c b/test/vm/preload-stub.c
index a4befac..ea53d09 100644
--- a/test/vm/preload-stub.c
+++ b/test/vm/preload-stub.c
@@ -4,6 +4,7 @@
 struct vm_class *vm_java_lang_Object;
 struct vm_class *vm_java_lang_Class;
 struct vm_field *vm_java_lang_Class_vmdata;
+struct vm_class *vm_java_lang_Cloneable;
 struct vm_class *vm_java_lang_String;
 
 struct vm_field *vm_java_lang_String_offset;
diff --git a/vm/class.c b/vm/class.c
index 72cf18b..c153fe4 100644
--- a/vm/class.c
+++ b/vm/class.c
@@ -350,8 +350,9 @@ int vm_class_link_array_class(struct vm_class *vmc, const 
char *class_name)
        vmc->state = VM_CLASS_LINKED;
 
        vmc->super = vm_java_lang_Object;
-       vmc->nr_interfaces = 0;
-       vmc->interfaces = NULL;
+       /* XXX: Actually, arrays should implement Serializable as well. */
+       vmc->nr_interfaces = 1;
+       vmc->interfaces = &vm_java_lang_Cloneable;
        vmc->fields = NULL;
        vmc->methods = NULL;
 
diff --git a/vm/jato.c b/vm/jato.c
index e28e808..9889079 100644
--- a/vm/jato.c
+++ b/vm/jato.c
@@ -265,8 +265,13 @@ static int32_t __vm_native 
native_vmsystem_identityhashcode(struct vm_object *ob
 static struct vm_object * __vm_native
 native_vmobject_clone(struct vm_object *object)
 {
-       NOT_IMPLEMENTED;
-       return vm_object_alloc(object->class);
+       if (!object) {
+               signal_new_exception(vm_java_lang_NullPointerException, NULL);
+               throw_from_native(sizeof object);
+               return NULL;
+       }
+
+       return vm_object_clone(object);
 }
 
 static struct vm_object * __vm_native
diff --git a/vm/object.c b/vm/object.c
index 555983d..54c022a 100644
--- a/vm/object.c
+++ b/vm/object.c
@@ -184,6 +184,84 @@ struct vm_object *vm_object_alloc_array(struct vm_class 
*class, int count)
        return res;
 }
 
+struct vm_object *clone_regular(struct vm_object *obj)
+{
+       struct vm_class *vmc = obj->class;
+       struct vm_object *new = vm_object_alloc(vmc);
+
+       /* XXX: What do we do about exceptions? */
+       if (new)
+               memcpy(new + 1, obj + 1, vmc->object_size);
+
+       return new;
+}
+
+struct vm_object *clone_array(struct vm_object *obj)
+{
+       struct vm_class *vmc = obj->class;
+       struct vm_class *e_vmc = vmc->array_element_class;
+       int count = obj->array_length;
+
+       if (e_vmc->kind == VM_CLASS_KIND_PRIMITIVE) {
+               enum vm_type vmtype;
+               int type;
+               struct vm_object *new;
+
+               vmtype = e_vmc->primitive_vm_type;
+               type = vmtype_to_bytecode_type(vmtype);
+
+               /* XXX: This could be optimized by not doing the memset() in
+                * object_alloc_native_array. */
+               new = vm_object_alloc_native_array(type, count);
+               if (new) {
+                       memcpy(new + 1, obj + 1,
+                               get_vmtype_size(vmtype) * count);
+               }
+
+               return new;
+       } else {
+               struct vm_object *new;
+
+               new = vm_object_alloc_array(vmc, count);
+               if (new) {
+                       memcpy(new + 1, obj + 1,
+                               sizeof(struct vm_object *) * count);
+               }
+
+               return new;
+       }
+}
+
+struct vm_object *clone_primitive(struct vm_object *obj)
+{
+       /* XXX: Is it even possible to create instances of primitive classes?
+        * I suspect it will be just the same as a normal object clone,
+        * though. Let's do that for now... */
+       NOT_IMPLEMENTED;
+       return clone_regular(obj);
+}
+
+struct vm_object *vm_object_clone(struct vm_object *obj)
+{
+       struct vm_class *vmc;
+
+       assert(obj);
+
+       /* (In order of likelyhood:) */
+       switch (obj->class->kind) {
+       case VM_CLASS_KIND_REGULAR:
+               return clone_regular(obj);
+       case VM_CLASS_KIND_ARRAY:
+               return clone_array(obj);
+       case VM_CLASS_KIND_PRIMITIVE:
+               return clone_primitive(obj);
+       }
+
+       /* Shouldn't happen. */
+       assert(0);
+       return NULL;
+}
+
 void vm_object_lock(struct vm_object *obj)
 {
        if (pthread_mutex_lock(&obj->mutex))
-- 
1.6.0.4


------------------------------------------------------------------------------
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to