From 4d49508a2e5909e23e0fa62fa5e3461e3261ae76 Mon Sep 17 00:00:00 2001 From: Michael Starzinger Date: Tue, 13 Jan 2009 16:30:34 +0100 Subject: [PATCH] Fixes PR102 and PR119. * src/vm/primitive.hpp (Primitive::unbox_typed): Added new method. * src/vm/primitive.cpp: Implemented above method for typesafe unboxing of primitive values with conversion. * src/vm/array.cpp (Array::set_boxed_element): Use new unboxing function and special handling for object arrays. --HG-- branch : michi --- src/vm/array.cpp | 25 ++++++- src/vm/primitive.cpp | 155 +++++++++++++++++++++++++++++++++++++++++++ src/vm/primitive.hpp | 1 + 3 files changed, 180 insertions(+), 1 deletion(-) diff --git a/src/vm/array.cpp b/src/vm/array.cpp index fc40745f9..560c400f8 100644 --- a/src/vm/array.cpp +++ b/src/vm/array.cpp @@ -70,9 +70,32 @@ java_handle_t* Array::get_boxed_element(int32_t index) */ void Array::set_boxed_element(int32_t index, java_handle_t *o) { + vftbl_t *v; + int type; imm_union value; - value = Primitive::unbox(o); + if (is_null()) { + exceptions_throw_nullpointerexception(); + return; + } + + v = LLNI_vftbl_direct(_handle); + + type = v->arraydesc->arraytype; + + // Special handling for object arrays. + if (type == ARRAYTYPE_OBJECT) { + ObjectArray array(_handle); + array.set_element(index, o); + return; + } + + // Check if primitive type can be stored. + if (!Primitive::unbox_typed(o, type, &value)) { +/* exceptions_throw_illegalargumentexception("argument type mismatch"); */ + exceptions_throw_illegalargumentexception(); + return; + } set_primitive_element(index, value); } diff --git a/src/vm/primitive.cpp b/src/vm/primitive.cpp index 4d3c6542c..388c08e2a 100644 --- a/src/vm/primitive.cpp +++ b/src/vm/primitive.cpp @@ -480,6 +480,161 @@ imm_union Primitive::unbox(java_handle_t *h) } +/** + * 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. */ diff --git a/src/vm/primitive.hpp b/src/vm/primitive.hpp index 314bb05d4..a0c97176e 100644 --- a/src/vm/primitive.hpp +++ b/src/vm/primitive.hpp @@ -63,6 +63,7 @@ public: static java_handle_t* box(double value); static imm_union unbox(java_handle_t *o); + static bool unbox_typed(java_handle_t *o, int type, imm_union* value); static uint8_t unbox_boolean(java_handle_t* o); static int8_t unbox_byte(java_handle_t* o); -- 2.25.1