Fixes PR102 and PR119.
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Tue, 13 Jan 2009 15:30:34 +0000 (16:30 +0100)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Tue, 13 Jan 2009 15:30:34 +0000 (16:30 +0100)
* 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
src/vm/primitive.cpp
src/vm/primitive.hpp

index fc40745f9b6e836f4487404a5c41981a07abfd26..560c400f8117ffde6fd1015cfba35cde3c0fd706 100644 (file)
@@ -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);
 }
index 4d3c6542c18226cea5af4b51524d700c3adac8d0..388c08e2aa945e14d36db662e748568355999ed8 100644 (file)
@@ -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.
  */
index 314bb05d47b4d598f5c73834ba9a1981dbbad0b7..a0c97176e7dc37387b4ead2897a6b5b08e87d6fc 100644 (file)
@@ -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);