* src/vm/primitive.cpp: Removed obsolete legacy C interface.
[cacao.git] / src / vm / primitive.cpp
index 1fe9e6d0b1b788118558c4f21a1f0b19dd6b50a9..9d6b79200e7ea2bcb753cbc69a915dee1869a12f 100644 (file)
 #include <assert.h>
 #include <stdint.h>
 
-#include "native/jni.h"
 #include "native/llni.h"
 
-#include "native/include/java_lang_Boolean.h"
-#include "native/include/java_lang_Byte.h"
-#include "native/include/java_lang_Short.h"
-#include "native/include/java_lang_Character.h"
-#include "native/include/java_lang_Integer.h"
-#include "native/include/java_lang_Long.h"
-#include "native/include/java_lang_Float.h"
-#include "native/include/java_lang_Double.h"
-
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.hpp"
 #include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
 #include "vm/primitive.hpp"
-#include "vm/vm.hpp"
+#include "vm/utf8.h"
+
+
+/* primitivetype_table *********************************************************
+
+   Structure for primitive classes: contains the class for wrapping
+   the primitive type, the primitive class, the name of the class for
+   wrapping, the one character type signature and the name of the
+   primitive class.
+   CAUTION: Don't change the order of the types. This table is indexed
+   by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
+
+*******************************************************************************/
+
+primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
+       { "int"     , NULL, NULL, NULL, "java/lang/Integer",   'I', "[I", NULL },
+       { "long"    , NULL, NULL, NULL, "java/lang/Long",      'J', "[J", NULL },
+       { "float"   , NULL, NULL, NULL, "java/lang/Float",     'F', "[F", NULL },
+       { "double"  , NULL, NULL, NULL, "java/lang/Double",    'D', "[D", NULL },
+       { NULL      , NULL, NULL, NULL, NULL,                   0 , NULL, NULL },
+       { "byte"    , NULL, NULL, NULL, "java/lang/Byte",      'B', "[B", NULL },
+       { "char"    , NULL, NULL, NULL, "java/lang/Character", 'C', "[C", NULL },
+       { "short"   , NULL, NULL, NULL, "java/lang/Short",     'S', "[S", NULL },
+       { "boolean" , NULL, NULL, NULL, "java/lang/Boolean",   'Z', "[Z", NULL },
+       { NULL      , NULL, NULL, NULL, NULL,                   0 , NULL, NULL },
+#if defined(ENABLE_JAVASE)
+       { "void"    , NULL, NULL, NULL, "java/lang/Void",      'V', NULL, NULL }
+#else
+       { NULL      , NULL, NULL, NULL, NULL,                   0 , NULL, NULL },
+#endif
+};
+
+
+/**
+ * Fill the primitive type table with the primitive-type classes,
+ * array-classes and wrapper classes.  This is important in the VM
+ * startup.
+ *
+ * We split this primitive-type table initialization because of
+ * annotations in the bootstrap classes.
+ *
+ * But we may get a problem if we have annotations in:
+ *
+ * java/lang/Object
+ * java/lang/Cloneable
+ * java/io/Serializable
+ *
+ * Also see: loader_preinit and linker_preinit.
+ */
+void Primitive::initialize_table()
+{  
+       utf       *name;
+       classinfo *c;
+       utf       *u;
+       classinfo *ac;
+
+       TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
+       /* Load and link primitive-type classes and array-classes. */
+
+       for (int i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+               /* Skip dummy entries. */
+
+               if (primitivetype_table[i].cname == NULL)
+                       continue;
+
+               /* create UTF-8 name */
+
+               name = utf_new_char(primitivetype_table[i].cname);
+
+               primitivetype_table[i].name = name;
+
+               /* create primitive class */
+
+               c = class_create_classinfo(name);
+
+               /* Primitive type classes don't have a super class. */
+
+               c->super = NULL;
+
+               /* set flags and mark it as primitive class */
+
+               c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE;
+               
+               /* prevent loader from loading primitive class */
+
+               c->state |= CLASS_LOADED;
+
+               /* INFO: don't put primitive classes into the classcache */
+
+               if (!link_class(c))
+                       vm_abort("linker_init: linking failed");
+
+               /* Just to be sure. */
+
+               assert(c->state & CLASS_LOADED);
+               assert(c->state & CLASS_LINKED);
+
+               primitivetype_table[i].class_primitive = c;
+
+               /* Create primitive array class. */
+
+               if (primitivetype_table[i].arrayname != NULL) {
+                       u  = utf_new_char(primitivetype_table[i].arrayname);
+                       ac = class_create_classinfo(u);
+                       ac = load_newly_created_array(ac, NULL);
+
+                       if (ac == NULL)
+                               vm_abort("primitive_init: loading failed");
+
+                       assert(ac->state & CLASS_LOADED);
+
+                       if (!link_class(ac))
+                               vm_abort("primitive_init: linking failed");
+
+                       /* Just to be sure. */
+
+                       assert(ac->state & CLASS_LOADED);
+                       assert(ac->state & CLASS_LINKED);
+
+                       primitivetype_table[i].arrayclass = ac;
+               }
+       }
 
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/utf8.h"
+       /* We use two for-loops to have the array-classes already in the
+          primitive-type table (hint: annotations in wrapper-classes). */
+
+       for (int i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+               /* Skip dummy entries. */
+
+               if (primitivetype_table[i].cname == NULL)
+                       continue;
+
+               /* Create class for wrapping the primitive type. */
+
+               u = utf_new_char(primitivetype_table[i].wrapname);
+               c = load_class_bootstrap(u);
+
+               if (c == NULL)
+                       vm_abort("primitive_init: loading failed");
+
+               if (!link_class(c))
+                       vm_abort("primitive_init: linking failed");
+
+               /* Just to be sure. */
+
+               assert(c->state & CLASS_LOADED);
+               assert(c->state & CLASS_LINKED);
+
+               primitivetype_table[i].class_wrap = c;
+       }
+}
+
+
+/**
+ * Finish the primitive-type table initialization.  In this step we
+ * set the vftbl of the primitive-type classes.
+ *
+ * This is necessary because java/lang/Class is loaded and linked
+ * after the primitive types have been linked.
+ *
+ * We have to do that in an extra function, as the primitive types are
+ * not stored in the classcache.
+ */
+void Primitive::post_initialize_table()
+{
+       classinfo *c;
+       int        i;
+
+       TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
+
+       assert(class_java_lang_Class);
+       assert(class_java_lang_Class->vftbl);
+
+       for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+               /* Skip dummy entries. */
+
+               if (primitivetype_table[i].cname == NULL)
+                       continue;
+
+               c = primitivetype_table[i].class_primitive;
+
+               c->object.header.vftbl = class_java_lang_Class->vftbl;
+       }
+}
 
 
 /**
@@ -236,7 +412,7 @@ java_handle_t* Primitive::box(int type, imm_union value)
                break;
        default:
                o = NULL;
-               vm_abort("primitive_box: invalid primitive type %d", type);
+               os::abort("Primitive::box: Invalid primitive type %d", type);
        }
 
        return o;
@@ -297,88 +473,332 @@ imm_union Primitive::unbox(java_handle_t *h)
                value.a = h;
                break;
        default:
-               vm_abort("Primitive::unbox: invalid primitive type %d", type);
+               os::abort("Primitive::unbox: Invalid primitive type %d", type);
        }
 
        return value;
 }
 
 
-/* primitive_box_xxx ***********************************************************
+/**
+ * Unbox a primitive of the given type. Also checks if the
+ * boxed primitive type can be widened into the destination
+ * type. This conversion is done according to
+ * "The Java Language Specification, Third Edition,
+ * $5.1.2 Widening Primitive Conversion".
+ *
+ * @param h Handle of the boxing Java object.
+ * @param type Destination type of the conversion.
+ * @param value Pointer to union where the resulting primitive
+ * value will be stored will.
+ *
+ * @return True of the conversion is allowed, false otherwise.
+ */
+bool Primitive::unbox_typed(java_handle_t *h, int type, imm_union* value)
+{
+       classinfo *c;
+       int        src_type;
+
+       if (h == NULL)
+               return false;
+
+       LLNI_class_get(h, c);
+
+       src_type = get_type_by_wrapperclass(c);
 
-   Box a primitive type.
+       switch (src_type) {
+       case PRIMITIVETYPE_BOOLEAN:
+               switch (type) {
+                       case PRIMITIVETYPE_BOOLEAN:
+                               value->i = unbox_boolean(h);
+                               return true;
+                       default:
+                               return false;
+               }
 
-*******************************************************************************/
+       case PRIMITIVETYPE_BYTE:
+               switch (type) {
+                       case PRIMITIVETYPE_BYTE:
+                       case PRIMITIVETYPE_SHORT:
+                       case PRIMITIVETYPE_INT:
+                               value->i = unbox_byte(h);
+                               return true;
+                       case PRIMITIVETYPE_LONG:
+                               value->l = unbox_byte(h);
+                               return true;
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_byte(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_byte(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       case PRIMITIVETYPE_CHAR:
+               switch (type) {
+                       case PRIMITIVETYPE_CHAR:
+                       case PRIMITIVETYPE_INT:
+                               value->i = unbox_char(h);
+                               return true;
+                       case PRIMITIVETYPE_LONG:
+                               value->l = unbox_char(h);
+                               return true;
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_char(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_char(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       case PRIMITIVETYPE_SHORT:
+               switch (type) {
+                       case PRIMITIVETYPE_SHORT:
+                       case PRIMITIVETYPE_INT:
+                               value->i = unbox_short(h);
+                               return true;
+                       case PRIMITIVETYPE_LONG:
+                               value->l = unbox_short(h);
+                               return true;
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_short(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_short(h);
+                               return true;
+                       default:
+                               return false;
+               }
 
-#define PRIMITIVE_BOX_TYPE(name, object, type) \
-java_handle_t* Primitive::box(type value)      \
-{                                                   \
-       java_handle_t      *o;                          \
-       java_lang_##object *jo;                         \
-                                                    \
-       o = builtin_new(class_java_lang_##object);      \
-                                                    \
-       if (o == NULL)                                  \
-               return NULL;                                \
-                                                    \
-       jo = (java_lang_##object *) o;                  \
-                                                    \
-       LLNI_field_set_val(jo, value, value);                   \
-                                                    \
-       return o;                                       \
+       case PRIMITIVETYPE_INT:
+               switch (type) {
+                       case PRIMITIVETYPE_INT:
+                               value->i = unbox_int(h);
+                               return true;
+                       case PRIMITIVETYPE_LONG:
+                               value->l = unbox_int(h);
+                               return true;
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_int(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_int(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       case PRIMITIVETYPE_LONG:
+               switch (type) {
+                       case PRIMITIVETYPE_LONG:
+                               value->l = unbox_long(h);
+                               return true;
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_long(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_long(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       case PRIMITIVETYPE_FLOAT:
+               switch (type) {
+                       case PRIMITIVETYPE_FLOAT:
+                               value->f = unbox_float(h);
+                               return true;
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_float(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       case PRIMITIVETYPE_DOUBLE:
+               switch (type) {
+                       case PRIMITIVETYPE_DOUBLE:
+                               value->d = unbox_double(h);
+                               return true;
+                       default:
+                               return false;
+               }
+
+       default:
+               os::abort("Primitive::unbox_typed: Invalid primitive type %d", type);
+               return false;
+       }
 }
 
-PRIMITIVE_BOX_TYPE(boolean, Boolean,   uint8_t)
-PRIMITIVE_BOX_TYPE(byte,    Byte,      int8_t)
-PRIMITIVE_BOX_TYPE(char,    Character, uint16_t)
-PRIMITIVE_BOX_TYPE(short,   Short,     int16_t)
-PRIMITIVE_BOX_TYPE(int,     Integer,   int32_t)
-PRIMITIVE_BOX_TYPE(long,    Long,      int64_t)
-PRIMITIVE_BOX_TYPE(float,   Float,     float)
-PRIMITIVE_BOX_TYPE(double,  Double,    double)
 
+/**
+ * Box a primitive type.
+ */
+java_handle_t* Primitive::box(uint8_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Boolean);
+
+       if (h == NULL)
+               return NULL;
 
-/* primitive_unbox_xxx *********************************************************
+       java_lang_Boolean b(h);
+       b.set_value(value);
 
-   Unbox a primitive type.
+       return h;
+}
 
-*******************************************************************************/
+java_handle_t* Primitive::box(int8_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Byte);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Byte b(h);
+       b.set_value(value);
+
+       return h;
+}
+
+java_handle_t* Primitive::box(uint16_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Character);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Character c(h);
+       c.set_value(value);
+
+       return h;
+}
+
+java_handle_t* Primitive::box(int16_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Short);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Short s(h);
+       s.set_value(value);
 
-#define PRIMITIVE_UNBOX_TYPE(name, object, type)       \
-type Primitive::unbox_##name(java_handle_t *h) \
-{                                                 \
-       java_lang_##object *jo;                       \
-       type                value;                    \
-                                                  \
-       jo = (java_lang_##object *) h;                \
-                                                  \
-       LLNI_field_get_val(jo, value, value);         \
-                                                  \
-       return value;                                 \
+       return h;
 }
 
-PRIMITIVE_UNBOX_TYPE(boolean, Boolean,   uint8_t)
-PRIMITIVE_UNBOX_TYPE(byte,    Byte,      int8_t)
-PRIMITIVE_UNBOX_TYPE(char,    Character, uint16_t)
-PRIMITIVE_UNBOX_TYPE(short,   Short,     int16_t)
-PRIMITIVE_UNBOX_TYPE(int,     Integer,   int32_t)
-PRIMITIVE_UNBOX_TYPE(long,    Long,      int64_t)
-PRIMITIVE_UNBOX_TYPE(float,   Float,     float)
-PRIMITIVE_UNBOX_TYPE(double,  Double,    double)
+java_handle_t* Primitive::box(int32_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Integer);
 
+       if (h == NULL)
+               return NULL;
 
-// Legacy C interface.
+       java_lang_Integer i(h);
+       i.set_value(value);
 
-extern "C" {
+       return h;
+}
 
-       classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
-classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
-classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
-classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
-classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
-int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
-java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
-imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(h); }
+java_handle_t* Primitive::box(int64_t value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Long);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Long l(h);
+       l.set_value(value);
+
+       return h;
+}
+
+java_handle_t* Primitive::box(float value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Float);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Float f(h);
+       f.set_value(value);
+
+       return h;
+}
+
+java_handle_t* Primitive::box(double value)
+{
+       java_handle_t *h = builtin_new(class_java_lang_Double);
+
+       if (h == NULL)
+               return NULL;
+
+       java_lang_Double d(h);
+       d.set_value(value);
+
+       return h;
+}
+
+
+
+/**
+ * Unbox a primitive type.
+ */
+
+// template<class T> T Primitive::unbox(java_handle_t *h)
+// {
+//     return java_lang_Boolean::get_value(h);
+// }
+
+inline uint8_t Primitive::unbox_boolean(java_handle_t *h)
+{
+       java_lang_Boolean b(h);
+       return b.get_value();
+}
+
+inline int8_t Primitive::unbox_byte(java_handle_t *h)
+{
+       java_lang_Byte b(h);
+       return b.get_value();
+}
+
+inline uint16_t Primitive::unbox_char(java_handle_t *h)
+{
+       java_lang_Character c(h);
+       return c.get_value();
+}
+
+inline int16_t Primitive::unbox_short(java_handle_t *h)
+{
+       java_lang_Short s(h);
+       return s.get_value();
+}
+
+inline int32_t Primitive::unbox_int(java_handle_t *h)
+{
+       java_lang_Integer i(h);
+       return i.get_value();
+}
+
+inline int64_t Primitive::unbox_long(java_handle_t *h)
+{
+       java_lang_Long l(h);
+       return l.get_value();
+}
+
+inline float Primitive::unbox_float(java_handle_t *h)
+{
+       java_lang_Float f(h);
+       return f.get_value();
+}
+
+inline double Primitive::unbox_double(java_handle_t *h)
+{
+       java_lang_Double d(h);
+       return d.get_value();
 }