#include <assert.h>
#include <stdint.h>
-#include "native/jni.h"
#include "native/llni.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
+};
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/utf8.h"
+
+/**
+ * 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;
+ }
+ }
+
+ /* 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;
+ }
+}
/**
break;
default:
o = NULL;
- vm_abort("primitive_box: invalid primitive type %d", type);
+ os::abort("Primitive::box: Invalid primitive type %d", type);
}
return o;
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;
}
+/**
+ * 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);
+
+ 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;
+ }
+
+ 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;
+ }
+}
+
+
/**
* Box a primitive type.
*/
extern "C" {
- classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
+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); }
}