X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fprimitive.cpp;h=59c97eb205c0be159669b7a6bf40c952ae17abc2;hb=c83bff94e40ee0a218a39931af17814d1a42cb5c;hp=ae64eb8272895e923184baec8370ee610a2b2940;hpb=4581ac4227827bfa36f7ca376258deeb019908b2;p=cacao.git diff --git a/src/vm/primitive.cpp b/src/vm/primitive.cpp index ae64eb827..59c97eb20 100644 --- a/src/vm/primitive.cpp +++ b/src/vm/primitive.cpp @@ -30,14 +30,200 @@ #include "native/llni.h" -#include "vm/builtin.h" -#include "vm/class.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/utf8.h" -#include "vm/vm.hpp" + + +/* 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; + } + } + + /* 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; + } +} /** @@ -183,6 +369,27 @@ int Primitive::get_type_by_wrapperclass(classinfo *c) } +/** + * Returns the primitive type of the given primitive-class. + * + * @param c Class structure. + * + * @return Integer type of the class. + */ +int Primitive::get_type_by_primitiveclass(classinfo *c) +{ + /* Search primitive table. */ + + for (int i = 0; i < PRIMITIVETYPE_COUNT; i++) + if (primitivetype_table[i].class_primitive == c) + return i; + + /* Invalid primitive class. */ + + return -1; +} + + /** * Box a primitive of the given type. If the type is an object, * simply return it. @@ -226,7 +433,7 @@ java_handle_t* Primitive::box(int type, imm_union value) break; default: o = NULL; - VM::get_current()->abort("primitive_box: invalid primitive type %d", type); + os::abort("Primitive::box: Invalid primitive type %d", type); } return o; @@ -287,13 +494,168 @@ imm_union Primitive::unbox(java_handle_t *h) value.a = h; break; default: - VM::get_current()->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. */ @@ -461,22 +823,6 @@ inline double Primitive::unbox_double(java_handle_t *h) } - -// Legacy C interface. - -extern "C" { - - 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); } -} - - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where