From: Michael Starzinger Date: Wed, 15 Apr 2009 15:04:15 +0000 (+0200) Subject: Merged with new-trap-decoding branch at rev a792088a3f04 (branch closed). X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=ad591a0456199cfbc13b0b3e034cdd3fc567caa6;hp=801435c96d4060aaa43ebd7d4d8252405c9460d6;p=cacao.git Merged with new-trap-decoding branch at rev a792088a3f04 (branch closed). --- diff --git a/src/mm/boehm-gc/os_dep.c b/src/mm/boehm-gc/os_dep.c index 5aa41f3e7..321aba94b 100644 --- a/src/mm/boehm-gc/os_dep.c +++ b/src/mm/boehm-gc/os_dep.c @@ -1077,7 +1077,7 @@ ptr_t GC_get_main_stack_base(void) c = stat_buf[buf_offset++]; } close(f); - if (result < 0x10000000) ABORT("Absurd stack bottom value"); + if (result < 0x100000) ABORT("Absurd stack bottom value"); return (ptr_t)result; } diff --git a/src/native/jni.cpp b/src/native/jni.cpp index e048a216d..d33892469 100644 --- a/src/native/jni.cpp +++ b/src/native/jni.cpp @@ -2482,22 +2482,25 @@ void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len) { TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len)); - - java_handle_chararray_t* a = builtin_newarray_char(len); - if (a == NULL) + CharArray ca(len); + + if (ca.is_null()) return NULL; /* copy text */ + + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); for (jsize i = 0; i < len; i++) - LLNI_array_direct(a, i) = buf[i]; + ptr[i] = buf[i]; java_handle_t* h = builtin_new(class_java_lang_String); if (h == NULL) return NULL; - java_lang_String s(h, a, len, 0); + java_lang_String s(h, ca.get_handle(), len, 0); return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle()); } @@ -2545,11 +2548,12 @@ const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) java_lang_String s(str); - java_handle_chararray_t* ca = s.get_value(); - int32_t count = s.get_count(); - int32_t offset = s.get_offset(); + CharArray ca(s.get_value()); + + int32_t count = s.get_count(); + int32_t offset = s.get_offset(); - if (ca == NULL) + if (ca.is_null()) return NULL; /* allocate memory */ @@ -2558,8 +2562,10 @@ const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) /* copy text */ + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); for (i = 0; i < count; i++) - stringbuffer[i] = LLNI_array_direct(ca, offset + i); + stringbuffer[i] = ptr[offset + i]; /* terminate string */ @@ -2619,11 +2625,12 @@ jsize jni_GetStringUTFLength(JNIEnv *env, jstring string) TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string)); java_lang_String s(string); - java_handle_chararray_t* ca = s.get_value(); - int32_t count = s.get_count(); + CharArray ca(s.get_value()); + int32_t count = s.get_count(); // FIXME GC critical section! - int32_t length = u2_utflength(ca->data, count); + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + int32_t length = u2_utflength(ptr, count); return length; } @@ -2687,14 +2694,11 @@ void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array) { - java_handle_t *a; - jsize size; - TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array)); - a = (java_handle_t *) array; + Array a(array); - size = LLNI_array_size(a); + jsize size = a.get_length(); return size; } @@ -2710,10 +2714,9 @@ jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array) jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) { - classinfo *c; - java_handle_t *o; - java_handle_objectarray_t *oa; - s4 i; + classinfo* c; + java_handle_t* o; + s4 i; STATISTICS(jniinvokation()); @@ -2725,36 +2728,33 @@ jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length, return NULL; } - oa = builtin_anewarray(length, c); + ObjectArray oa(length, c); - if (oa == NULL) + if (oa.is_null()) return NULL; /* set all elements to initialElement */ for (i = 0; i < length; i++) - array_objectarray_element_set(oa, i, o); + oa.set_element(i, o); - return (jobjectArray) jni_NewLocalRef(env, (jobject) oa); + return (jobjectArray) jni_NewLocalRef(env, (jobject) oa.get_handle()); } jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { - java_handle_objectarray_t *oa; - java_handle_t *o; - STATISTICS(jniinvokation()); - oa = (java_handle_objectarray_t *) array; + ObjectArray oa(array); - if (index >= LLNI_array_size(oa)) { + if (index >= oa.get_length()) { exceptions_throw_arrayindexoutofboundsexception(); return NULL; } - o = array_objectarray_element_get(oa, index); + java_handle_t* o = oa.get_element(index); return jni_NewLocalRef(env, (jobject) o); } @@ -2763,15 +2763,11 @@ jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array, void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val) { - java_handle_objectarray_t *oa; - java_handle_t *o; - STATISTICS(jniinvokation()); - oa = (java_handle_objectarray_t *) array; - o = (java_handle_t *) val; + ObjectArray oa(array); - if (index >= LLNI_array_size(oa)) { + if (index >= oa.get_length()) { exceptions_throw_arrayindexoutofboundsexception(); return; } @@ -2779,18 +2775,18 @@ void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array, /* check if the class of value is a subclass of the element class of the array */ - if (!builtin_canstore(oa, o)) + java_handle_t* o = (java_handle_t *) val; + + if (!builtin_canstore(oa.get_handle(), o)) return; - array_objectarray_element_set(oa, index, o); + oa.set_element(index, o); } -#define JNI_NEW_ARRAY(name, type, intern) \ +#define JNI_NEW_ARRAY(name, type) \ type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len) \ { \ - java_handle_##intern##array_t *a; \ - \ STATISTICS(jniinvokation()); \ \ if (len < 0) { \ @@ -2798,19 +2794,20 @@ type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len) \ return NULL; \ } \ \ - a = builtin_newarray_##intern(len); \ + name##Array a(len); \ \ - return (type) jni_NewLocalRef(env, (jobject) a); \ + return (type) jni_NewLocalRef(env, \ + (jobject) a.get_handle()); \ } -JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean) -JNI_NEW_ARRAY(Byte, jbyteArray, byte) -JNI_NEW_ARRAY(Char, jcharArray, char) -JNI_NEW_ARRAY(Short, jshortArray, short) -JNI_NEW_ARRAY(Int, jintArray, int) -JNI_NEW_ARRAY(Long, jlongArray, long) -JNI_NEW_ARRAY(Float, jfloatArray, float) -JNI_NEW_ARRAY(Double, jdoubleArray, double) +JNI_NEW_ARRAY(Boolean, jbooleanArray) +JNI_NEW_ARRAY(Byte, jbyteArray) +JNI_NEW_ARRAY(Char, jcharArray) +JNI_NEW_ARRAY(Short, jshortArray) +JNI_NEW_ARRAY(Int, jintArray) +JNI_NEW_ARRAY(Long, jlongArray) +JNI_NEW_ARRAY(Float, jfloatArray) +JNI_NEW_ARRAY(Double, jdoubleArray) /* GetArrayElements ********************************************* @@ -2823,16 +2820,14 @@ JNI_NEW_ARRAY(Double, jdoubleArray, double) type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \ jboolean *isCopy) \ { \ - java_handle_##intern##array_t *a; \ - \ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \ \ - a = (java_handle_##intern##array_t *) array; \ + name##Array a(array); \ \ if (isCopy) \ *isCopy = JNI_FALSE; \ \ - return (type *) LLNI_array_data(a); \ + return (type *) a.get_raw_data_ptr(); \ } JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean) @@ -2860,19 +2855,17 @@ JNI_GET_ARRAY_ELEMENTS(Double, jdouble, double) void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array, \ type *elems, jint mode) \ { \ - java_handle_##intern##array_t *a; \ - \ STATISTICS(jniinvokation()); \ \ - a = (java_handle_##intern##array_t *) array; \ + name##Array a(array); \ \ - if (elems != (type *) LLNI_array_data(a)) { \ + if (elems != (type *) a.get_raw_data_ptr()) { \ switch (mode) { \ case JNI_COMMIT: \ - MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \ + a.set_region(0, a.get_length(), (intern2 *) elems); \ break; \ case 0: \ - MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \ + a.set_region(0, a.get_length(), (intern2 *) elems); \ /* XXX TWISTI how should it be freed? */ \ break; \ case JNI_ABORT: \ @@ -2903,16 +2896,14 @@ JNI_RELEASE_ARRAY_ELEMENTS(Double, jdouble, double, double) void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array, \ jsize start, jsize len, type *buf) \ { \ - java_handle_##intern##array_t *a; \ - \ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \ \ - a = (java_handle_##intern##array_t *) array; \ + name##Array a(array); \ \ - if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \ + if ((start < 0) || (len < 0) || (start + len > a.get_length())) \ exceptions_throw_arrayindexoutofboundsexception(); \ else \ - MCOPY(buf, &LLNI_array_direct(a, start), intern2, len); \ + a.get_region(start, len, (intern2 *) buf); \ } JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1) @@ -2936,16 +2927,14 @@ JNI_GET_ARRAY_REGION(Double, jdouble, double, double) void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array, \ jsize start, jsize len, const type *buf) \ { \ - java_handle_##intern##array_t *a; \ - \ STATISTICS(jniinvokation()); \ \ - a = (java_handle_##intern##array_t *) array; \ + name##Array a(array); \ \ - if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \ + if ((start < 0) || (len < 0) || (start + len > a.get_length())) \ exceptions_throw_arrayindexoutofboundsexception(); \ else \ - MCOPY(&LLNI_array_direct(a, start), buf, intern2, len); \ + a.set_region(start, len, (intern2 *) buf); \ } JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1) @@ -3092,15 +3081,15 @@ jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm) void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) { java_lang_String s(str); - java_handle_chararray_t* ca = s.get_value(); - int32_t count = s.get_count(); + CharArray ca(s.get_value()); + int32_t count = s.get_count(); if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) { exceptions_throw_stringindexoutofboundsexception(); return; } - MCOPY(buf, &LLNI_array_direct(ca, start), u2, len); + ca.get_region(start, len, buf); } @@ -3119,9 +3108,11 @@ void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, ch TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf)); java_lang_String s(str); - java_handle_chararray_t* ca = s.get_value(); - int32_t count = s.get_count(); - int32_t offset = s.get_offset(); + + CharArray ca(s.get_value()); + + int32_t count = s.get_count(); + int32_t offset = s.get_offset(); if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) { exceptions_throw_stringindexoutofboundsexception(); @@ -3130,8 +3121,10 @@ void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, ch int32_t i; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); for (i = 0; i < len; i++) - buf[i] = LLNI_array_direct(ca, offset + start + i); + buf[i] = ptr[offset + start + i]; buf[i] = '\0'; } diff --git a/src/native/llni.h b/src/native/llni.h index 6112dfbfe..77cb9299b 100644 --- a/src/native/llni.h +++ b/src/native/llni.h @@ -117,9 +117,6 @@ #define LLNI_field_direct(obj, field) (LLNI_DIRECT(obj)->field) #define LLNI_vftbl_direct(obj) (LLNI_DIRECT((java_handle_t *) (obj))->vftbl) -#define LLNI_array_direct(arr, index) (LLNI_DIRECT(arr)->data[(index)]) -#define LLNI_array_data(arr) (LLNI_DIRECT(arr)->data) -#define LLNI_array_size(arr) (LLNI_DIRECT((java_handle_objectarray_t *) (arr))->header.size) /* LLNI critical sections ****************************************************** diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp index ac12cc835..30efeaa2c 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp @@ -34,7 +34,6 @@ #include "mm/memory.hpp" #include "native/jni.hpp" -#include "native/llni.h" #include "native/native.hpp" #if defined(ENABLE_JNI_HEADERS) @@ -43,7 +42,7 @@ #include "threads/mutex.hpp" -#include "vm/jit/builtin.hpp" +#include "vm/array.hpp" #include "vm/exceptions.hpp" #include "vm/javaobjects.hpp" #include "vm/string.hpp" @@ -305,8 +304,9 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_ResourceInputStream_readBytes(JNIEnv { /* get pointer to the buffer */ // XXX Not GC safe. - void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) byteArray, off)); - + ByteArray ba(byteArray); + void* buf = (void*) (((int8_t*) ba.get_raw_data_ptr()) + off); + com_sun_cldchi_jvm_FileDescriptor fd(jobj); int64_t filep = fd.get_pointer(); diff --git a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp index 860d88d5d..cf99a13a9 100644 --- a/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp +++ b/src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp @@ -37,13 +37,13 @@ #include "mm/memory.hpp" #include "native/jni.hpp" -#include "native/llni.h" #include "native/native.hpp" #if defined(ENABLE_JNI_HEADERS) # include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h" #endif +#include "vm/array.hpp" #include "vm/global.h" #include "vm/os.hpp" #include "vm/vm.hpp" /* REMOVE ME: temporarily */ @@ -64,7 +64,8 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_open0(JNIEnv *e // The hostname byte-array is a NULL terminated C-string. // XXX Not GC safe. - char* name = (char*) &(LLNI_array_data((java_handle_bytearray_t*) hostname)); + ByteArray ba(hostname); + char* name = (char*) ba.get_raw_data_ptr(); /* get the host */ @@ -107,7 +108,8 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv { // Get pointer to the buffer. // XXX Not GC safe. - void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) b, off)); + ByteArray ba(b); + void* buf = (void*) (((int8_t*) ba.get_raw_data_ptr()) + off); // Receive from the socket. ssize_t result = recv(handle, buf, len, 0); @@ -158,7 +160,8 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv { // Get pointer to the buffer. // XXX Not GC safe. - void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) b, off)); + ByteArray ba(b); + void* buf = (void*) (((int8_t*) ba.get_raw_data_ptr()) + off); // Send the given byte to the socket. ssize_t result = send(handle, buf, len, 0); diff --git a/src/native/vm/cldc1.1/java_lang_String.cpp b/src/native/vm/cldc1.1/java_lang_String.cpp index b86e539d4..a46149081 100644 --- a/src/native/vm/cldc1.1/java_lang_String.cpp +++ b/src/native/vm/cldc1.1/java_lang_String.cpp @@ -30,13 +30,13 @@ #include #include "native/jni.hpp" -#include "native/llni.h" #include "native/native.hpp" #if defined(ENABLE_JNI_HEADERS) # include "native/include/java_lang_String.h" #endif +#include "vm/array.hpp" #include "vm/javaobjects.hpp" #include "vm/string.hpp" @@ -53,14 +53,15 @@ JNIEXPORT jint JNICALL Java_java_lang_String_hashCode(JNIEnv *env, jstring _this { java_lang_String jls(_this); - java_handle_chararray_t* value = jls.get_value(); + CharArray value(jls.get_value()); + int32_t offset = jls.get_offset(); int32_t count = jls.get_count(); int32_t hash = 0; for (int32_t i = 0; i < count; i++) { - hash = (31 * hash) + LLNI_array_direct(value, offset + i); + hash = (31 * hash) + value.get_element(offset + i); } return hash; @@ -76,12 +77,13 @@ JNIEXPORT jint JNICALL Java_java_lang_String_indexOf__I(JNIEnv *env, jstring _th { java_lang_String jls(_this); - java_handle_chararray_t* value = jls.get_value(); + CharArray value(jls.get_value()); + int32_t offset = jls.get_offset(); int32_t count = jls.get_count(); for (int32_t i = 0; i < count; i++) { - if (LLNI_array_direct(value, offset + i) == ch) { + if (value.get_element(offset + i) == ch) { return i; } } @@ -99,7 +101,8 @@ JNIEXPORT jint JNICALL Java_java_lang_String_indexOf__II(JNIEnv *env, jstring _t { java_lang_String jls(_this); - java_handle_chararray_t* value = jls.get_value(); + CharArray value(jls.get_value()); + int32_t offset = jls.get_offset(); int32_t count = jls.get_count(); @@ -112,7 +115,7 @@ JNIEXPORT jint JNICALL Java_java_lang_String_indexOf__II(JNIEnv *env, jstring _t } for (int32_t i = fromIndex ; i < count ; i++) { - if (LLNI_array_direct(value, offset + i) == ch) { + if (value.get_element(offset + i) == ch) { return i; } } @@ -130,14 +133,15 @@ JNIEXPORT jint JNICALL Java_java_lang_String_lastIndexOf__II(JNIEnv *env, jstrin { java_lang_String jls(_this); - java_handle_chararray_t* value = jls.get_value(); + CharArray value(jls.get_value()); + int32_t offset = jls.get_offset(); int32_t count = jls.get_count(); int32_t start = ((fromIndex >= count) ? count - 1 : fromIndex); for (int32_t i = start; i >= 0; i--) { - if (LLNI_array_direct(value, offset + i) == ch) { + if (value.get_element(offset + i) == ch) { return i; } } diff --git a/src/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp b/src/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp index c0b341942..59ba4e704 100644 --- a/src/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp +++ b/src/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp @@ -35,6 +35,7 @@ # include "native/vm/include/gnu_java_lang_VMCPStringBuilder.h" #endif +#include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" #include "vm/globals.hpp" @@ -51,13 +52,13 @@ JNIEXPORT jstring JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv * /* This is a native version of java.lang.String.([CIIZ)Ljava/lang/String; */ - if (startIndex < 0) { + if (startIndex < 0) { /* exceptions_throw_stringindexoutofboundsexception("offset: " + offset); */ exceptions_throw_stringindexoutofboundsexception(); return NULL; } - if (count < 0) { + if (count < 0) { /* exceptions_throw_stringindexoutofboundsexception("count: " + count); */ exceptions_throw_stringindexoutofboundsexception(); return NULL; @@ -65,13 +66,9 @@ JNIEXPORT jstring JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv * /* equivalent to: offset + count < 0 || offset + count > data.length */ - java_handle_chararray_t* ca = (java_handle_chararray_t*) value; + CharArray ca(value); - LLNI_CRITICAL_START; - int32_t length = LLNI_array_size(ca); - LLNI_CRITICAL_END; - - if (length - startIndex < count) { + if (ca.get_length() - startIndex < count) { /* exceptions_throw_stringindexoutofboundsexception("offset + count: " + (offset + count)); */ exceptions_throw_stringindexoutofboundsexception(); return NULL; @@ -82,7 +79,7 @@ JNIEXPORT jstring JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv * if (h == NULL) return NULL; - java_lang_String s(h, ca, (int32_t) count, (int32_t) startIndex); + java_lang_String s(h, ca.get_handle(), (int32_t) count, (int32_t) startIndex); return (jstring) s.get_handle(); } diff --git a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp index c17382a54..0bca5347c 100644 --- a/src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp +++ b/src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp @@ -34,6 +34,7 @@ # include "native/vm/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h" #endif +#include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/global.h" #include "vm/globals.hpp" @@ -53,7 +54,9 @@ JNIEXPORT java_handle_objectarray_t* JNICALL Java_gnu_java_lang_management_VMRun { log_println("Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments: IMPLEMENT ME!"); - return builtin_anewarray(0, class_java_lang_String); + ObjectArray oa(0, class_java_lang_String); + + return oa.get_handle(); } diff --git a/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp b/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp index 2c3bc5125..10e2d63eb 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp @@ -46,6 +46,7 @@ #include "vm/assertion.hpp" #endif +#include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/class.hpp" #include "vm/classcache.hpp" @@ -79,11 +80,10 @@ extern "C" { */ JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, jobject cl, jstring name, jbyteArray data, jint offset, jint len, jobject pd) { - utf *utfname; - classinfo *c; - classloader_t *loader; - java_handle_bytearray_t* ba; - uint8_t* stream; + utf* utfname; + classinfo* c; + classloader_t* loader; + uint8_t* stream; #if defined(ENABLE_JVMTI) jint new_class_data_len = 0; @@ -99,7 +99,9 @@ JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, j /* check the indexes passed */ - if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) { + ByteArray ba(data); + + if ((offset < 0) || (len < 0) || ((offset + len) > ba.get_length())) { exceptions_throw_arrayindexoutofboundsexception(); return NULL; } @@ -138,8 +140,7 @@ JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, j else #endif { - ba = (java_handle_bytearray_t*) data; - stream = (uint8_t *) &LLNI_array_direct(ba, offset); + stream = ((uint8_t *) ba.get_raw_data_ptr()) + offset; c = class_define(utfname, loader, len, stream, (java_handle_t *) pd); } diff --git a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp index fca7f8d1d..2e2bae366 100644 --- a/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp +++ b/src/native/vm/gnuclasspath/java_lang_VMThrowable.cpp @@ -94,10 +94,10 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv * // Get the stacktrace from the VMThrowable object. - java_handle_bytearray_t* ba = vmt.get_vmdata(); + ByteArray ba(vmt.get_vmdata()); // XXX Critical GC section? - stacktrace_t* st = (stacktrace_t*) LLNI_array_data(ba); + stacktrace_t* st = (stacktrace_t*) ba.get_raw_data_ptr(); assert(st != NULL); diff --git a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp index 234007759..48b777086 100644 --- a/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp +++ b/src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.cpp @@ -38,6 +38,7 @@ #include "toolbox/logging.hpp" +#include "vm/array.hpp" #include "vm/globals.hpp" #include "vm/vm.hpp" @@ -54,13 +55,11 @@ extern "C" { */ JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz) { - java_handle_objectarray_t *oa; - log_println("Java_java_lang_management_VMManagementFactory_getMemoryPoolNames: IMPLEMENT ME!"); - oa = builtin_anewarray(0, class_java_lang_String); + ObjectArray oa(0, class_java_lang_String); - return oa; + return oa.get_handle(); } @@ -71,13 +70,11 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_get */ JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz) { - java_handle_objectarray_t *oa; - log_println("Java_java_lang_management_VMManagementFactory_getMemoryManagerNames: IMPLEMENT ME!"); - oa = builtin_anewarray(0, class_java_lang_String); + ObjectArray oa(0, class_java_lang_String); - return oa; + return oa.get_handle(); } @@ -88,13 +85,11 @@ JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_get */ JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz) { - java_handle_objectarray_t *oa; - log_println("Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames: IMPLEMENT ME!"); - oa = builtin_anewarray(0, class_java_lang_String); + ObjectArray oa(0, class_java_lang_String); - return oa; + return oa.get_handle(); } } // extern "C" diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index cc4312631..596b3df83 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -2,6 +2,7 @@ Copyright (C) 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -129,12 +130,12 @@ } \ } while (0) -# define PRINTJVMWARNINGS(x) -/* do { \ */ -/* if (opt_PrintJVMWarnings) { \ */ -/* log_println x; \ */ -/* } \ */ -/* } while (0) */ +# define PRINTJVMWARNINGS(x) \ + do { \ + if (opt_PrintWarnings) { \ + log_println x; \ + } \ + } while (0) #else @@ -409,9 +410,9 @@ jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable) return 0; } - java_handle_bytearray_t* ba = jlt.get_backtrace(); + ByteArray ba(jlt.get_backtrace()); - if (ba == NULL) + if (ba.is_null()) return 0; // We need a critical section here as the stacktrace structure is @@ -419,7 +420,7 @@ jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable) LLNI_CRITICAL_START; - stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba); + stacktrace_t* st = (stacktrace_t *) ba.get_raw_data_ptr(); int32_t depth = st->length; @@ -436,11 +437,11 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index) TRACEJVMCALLS(("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index)); java_lang_Throwable jlt(throwable); - java_handle_bytearray_t* ba = jlt.get_backtrace(); + ByteArray ba(jlt.get_backtrace()); // XXX We need a critical section here as the stacktrace structure is // mapped onto a Java byte-array. - stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba); + stacktrace_t* st = (stacktrace_t *) ba.get_raw_data_ptr(); return stacktrace_get_StackTraceElement(st, index); } @@ -777,7 +778,7 @@ jobjectArray JVM_GetClassInterfaces(JNIEnv *env, jclass cls) oa = class_get_interfaces(c); - return (jobjectArray) oa; + return oa; } @@ -827,14 +828,11 @@ jobjectArray JVM_GetClassSigners(JNIEnv *env, jclass cls) void JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers) { - classinfo *c; - java_handle_objectarray_t *hoa; - TRACEJVMCALLS(("JVM_SetClassSigners(env=%p, cls=%p, signers=%p)", env, cls, signers)); - c = LLNI_classinfo_unwrap(cls); + classinfo* c = LLNI_classinfo_unwrap(cls); - hoa = (java_handle_objectarray_t *) signers; + ObjectArray oa(signers); /* This call is ignored for primitive types and arrays. Signers are only set once, ClassLoader.java, and thus shouldn't be @@ -844,7 +842,8 @@ void JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers) if (class_is_primitive(c) || class_is_array(c)) return; - LLNI_classinfo_field_set(c, signers, hoa); + // XXX: Fix this! + LLNI_classinfo_field_set(c, signers, (java_objectarray_t*) oa.get_handle()); } @@ -1030,7 +1029,7 @@ jobjectArray JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass) oa = class_get_declaredclasses(c, false); - return (jobjectArray) oa; + return oa; } @@ -1179,7 +1178,7 @@ jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean pu oa = class_get_declaredfields(c, publicOnly); - return (jobjectArray) oa; + return oa; } @@ -1193,7 +1192,7 @@ jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean p java_handle_objectarray_t* oa = class_get_declaredmethods(c, publicOnly); - return (jobjectArray) oa; + return oa; } @@ -1210,7 +1209,7 @@ jobjectArray JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jbool oa = class_get_declaredconstructors(c, publicOnly); - return (jobjectArray) oa; + return oa; } @@ -1623,47 +1622,43 @@ jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls) jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused) { - java_handle_objectarray_t *classes; - java_handle_objectarray_t *packages; - java_booleanarray_t *classEnabled; - java_booleanarray_t *packageEnabled; #if defined(ENABLE_ASSERTION) - java_handle_t *js; - s4 i, j; + java_handle_t* js; + s4 i, j; #endif TRACEJVMCALLS(("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused)); #if defined(ENABLE_ASSERTION) - classes = builtin_anewarray(assertion_class_count, class_java_lang_Object); + ObjectArray classes(assertion_class_count, class_java_lang_Object); #else - classes = builtin_anewarray(0, class_java_lang_Object); + ObjectArray classes(0, class_java_lang_Object); #endif - if (classes == NULL) + if (classes.is_null()) return NULL; #if defined(ENABLE_ASSERTION) - packages = builtin_anewarray(assertion_package_count, class_java_lang_Object); + ObjectArray packages(assertion_package_count, class_java_lang_Object); #else - packages = builtin_anewarray(0, class_java_lang_Object); + ObjectArray packages(0, class_java_lang_Object); #endif - if (packages == NULL) + if (packages.is_null()) return NULL; #if defined(ENABLE_ASSERTION) - classEnabled = builtin_newarray_boolean(assertion_class_count); + BooleanArray classEnabled(assertion_class_count); #else - classEnabled = builtin_newarray_boolean(0); + BooleanArray classEnabled(0); #endif - if (classEnabled == NULL) + if (classEnabled.is_null()) return NULL; #if defined(ENABLE_ASSERTION) - packageEnabled = builtin_newarray_boolean(assertion_package_count); + BooleanArray packageEnabled(assertion_package_count); #else - packageEnabled = builtin_newarray_boolean(0); + BooleanArray packageEnabled(0); #endif - if (packageEnabled == NULL) + if (packageEnabled.is_null()) return NULL; #if defined(ENABLE_ASSERTION) @@ -1682,13 +1677,13 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused) } if (item->package == false) { - classes->data[i] = js; - classEnabled->data[i] = (jboolean) item->enabled; + classes.set_element(i, js); + classEnabled.set_element(i, (jboolean) item->enabled); i += 1; } else { - packages->data[j] = js; - packageEnabled->data[j] = (jboolean) item->enabled; + packages.set_element(j, js); + packageEnabled.set_element(j, (jboolean) item->enabled); j += 1; } } @@ -1697,7 +1692,11 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused) /* set instance fields */ - java_lang_AssertionStatusDirectives jlasd(classes, classEnabled, packages, packageEnabled); + java_lang_AssertionStatusDirectives jlasd( + classes.get_handle(), + classEnabled.get_handle(), + packages.get_handle(), + packageEnabled.get_handle()); return (jobject) jlasd.get_handle(); } @@ -2318,12 +2317,10 @@ jclass JVM_CurrentLoadedClass(JNIEnv *env) jobject JVM_CurrentClassLoader(JNIEnv *env) { - /* XXX if a method in a class in a trusted loader is in a - doPrivileged, return NULL */ + TRACEJVMCALLS(("JVM_CurrentClassLoader(env=%p)", env)); + PRINTJVMWARNINGS(("JVM_CurrentClassLoader is deprecated, do not use it.")); - log_println("JVM_CurrentClassLoader: IMPLEMENT ME!"); - - return NULL; + return stacktrace_first_nonsystem_classloader(); } @@ -2333,7 +2330,7 @@ jobjectArray JVM_GetClassContext(JNIEnv *env) { TRACEJVMCALLS(("JVM_GetClassContext(env=%p)", env)); - return (jobjectArray) stacktrace_getClassContext(); + return stacktrace_getClassContext(); } @@ -2415,13 +2412,9 @@ jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint le jobject JVM_LatestUserDefinedLoader(JNIEnv *env) { - classloader_t *cl; - TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env)); - cl = stacktrace_first_nonnull_classloader(); - - return (jobject) cl; + return stacktrace_first_nonnull_classloader(); } @@ -2439,13 +2432,21 @@ jclass JVM_LoadClass0(JNIEnv *env, jobject receiver, jclass currClass, jstring c jint JVM_GetArrayLength(JNIEnv *env, jobject arr) { - java_handle_t *a; - TRACEJVMCALLS(("JVM_GetArrayLength(arr=%p)", arr)); - a = (java_handle_t *) arr; + if (arr == NULL) { + exceptions_throw_nullpointerexception(); + return -1; + } + + Array a(arr); - return array_length_get(a); + // Check for exception in constructor. + if (a.is_null()) { + return -1; + } + + return a.get_length(); } @@ -2453,21 +2454,16 @@ jint JVM_GetArrayLength(JNIEnv *env, jobject arr) jobject JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) { - java_handle_t *a; - java_handle_t *o; - TRACEJVMCALLS(("JVM_GetArrayElement(env=%p, arr=%p, index=%d)", env, arr, index)); - a = (java_handle_t *) arr; + Array a(arr); /* if (!class_is_array(a->objheader.vftbl->class)) { */ /* exceptions_throw_illegalargumentexception(); */ /* return NULL; */ /* } */ - o = array_element_get(a, index); - - return (jobject) o; + return a.get_boxed_element(index); } @@ -2489,15 +2485,11 @@ jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint w void JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val) { - java_handle_t *a; - java_handle_t *value; - TRACEJVMCALLS(("JVM_SetArrayElement(env=%p, arr=%p, index=%d, val=%p)", env, arr, index, val)); - a = (java_handle_t *) arr; - value = (java_handle_t *) val; + Array a(arr); - array_element_set(a, index, value); + a.set_boxed_element(index, val); } @@ -2513,11 +2505,6 @@ void JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length) { - classinfo *c; - classinfo *pc; - java_handle_t *a; - java_handle_objectarray_t *oa; - TRACEJVMCALLS(("JVM_NewArray(env=%p, eltClass=%p, length=%d)", env, eltClass, length)); if (eltClass == NULL) { @@ -2525,14 +2512,14 @@ jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length) return NULL; } - /* NegativeArraySizeException is checked in builtin_newarray. */ + /* NegativeArraySizeException is checked by array constructor. */ - c = LLNI_classinfo_unwrap(eltClass); + classinfo* c = LLNI_classinfo_unwrap(eltClass); /* Create primitive or object array. */ if (class_is_primitive(c)) { - pc = Primitive::get_arrayclass_by_name(c->name); + classinfo* pc = Primitive::get_arrayclass_by_name(c->name); /* void arrays are not allowed. */ @@ -2541,14 +2528,14 @@ jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length) return NULL; } - a = builtin_newarray(length, pc); + Array a(length, pc); - return (jobject) a; + return (jobject) a.get_handle(); } else { - oa = builtin_anewarray(length, c); + ObjectArray oa(length, c); - return (jobject) oa; + return (jobject) oa.get_handle(); } } @@ -2558,7 +2545,6 @@ jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length) jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim) { classinfo *c; - java_handle_intarray_t *ia; int32_t length; long *dims; int32_t value; @@ -2577,17 +2563,17 @@ jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim) c = LLNI_classinfo_unwrap(eltClass); - ia = (java_handle_intarray_t *) dim; - - length = array_length_get((java_handle_t *) ia); + IntArray ia(dim); /* We check here for exceptions thrown in array_length_get, otherwise these exceptions get overwritten by the following IllegalArgumentException. */ - if (length < 0) + if (ia.is_null()) return NULL; + length = ia.get_length(); + if ((length <= 0) || (length > /* MAX_DIM */ 255)) { exceptions_throw_illegalargumentexception(); return NULL; @@ -2598,7 +2584,7 @@ jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim) dims = MNEW(long, length); for (i = 0; i < length; i++) { - value = LLNI_array_direct(ia, i); + value = ia.get_element(i); dims[i] = (long) value; } @@ -3205,9 +3191,9 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) // Allocate array to hold the java.lang.Thread objects. int32_t length = active_threads.size(); - java_handle_objectarray_t* oa = builtin_anewarray(length, class_java_lang_Thread); + ObjectArray oa(length, class_java_lang_Thread); - if (oa == NULL) + if (oa.is_null()) return NULL; // Iterate over all threads (which were active just a second ago). @@ -3218,12 +3204,12 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy) java_handle_t* h = thread_get_object(t); assert(h != NULL); - array_objectarray_element_set(oa, index, h); + oa.set_element(index, h); index++; } - return oa; + return oa.get_handle(); } @@ -3240,8 +3226,10 @@ jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threa return NULL; } + ObjectArray oa(threads); + // Get length of the threads array. - int32_t length = array_length_get((java_handle_t*) threads); + int32_t length = oa.get_length(); if (length <= 0) { exceptions_throw_illegalargumentexception(); @@ -3250,15 +3238,15 @@ jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threa // Allocate array to hold stacktraces. classinfo* arrayclass = class_array_of(class_java_lang_StackTraceElement, true); - java_handle_objectarray_t* oas = builtin_anewarray(length, arrayclass); + ObjectArray oaresult(length, arrayclass); - if (oas == NULL) { + if (oaresult.is_null()) { return NULL; } // Iterate over all passed thread objects. for (i = 0; i < length; i++) { - java_handle_t* thread = array_objectarray_element_get(threads, i); + java_handle_t* thread = oa.get_element(i); // Get thread for the given thread object. threadobject* t = thread_get_thread(thread); @@ -3271,15 +3259,15 @@ jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threa stacktrace_t* st = stacktrace_get_of_thread(t); // Convert stacktrace into array of StackTraceElements. - java_handle_objectarray_t* oa = stacktrace_get_StackTraceElements(st); + java_handle_objectarray_t* oaste = stacktrace_get_StackTraceElements(st); - if (oa == NULL) + if (oaste == NULL) return NULL; - array_objectarray_element_set(oas, i, (java_handle_t*) oa); + oaresult.set_element(i, oaste); } - return oas; + return oaresult.get_handle(); } @@ -3307,32 +3295,28 @@ jobject JVM_InitAgentProperties(JNIEnv *env, jobject properties) jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass) { - classinfo *c; - methodinfo *m; - java_handle_objectarray_t *oa; - TRACEJVMCALLS(("JVM_GetEnclosingMethodInfo(env=%p, ofClass=%p)", env, ofClass)); - c = LLNI_classinfo_unwrap(ofClass); + classinfo* c = LLNI_classinfo_unwrap(ofClass); if ((c == NULL) || class_is_primitive(c)) return NULL; - m = class_get_enclosingmethod_raw(c); + methodinfo* m = class_get_enclosingmethod_raw(c); if (m == NULL) return NULL; - oa = builtin_anewarray(3, class_java_lang_Object); + ObjectArray oa(3, class_java_lang_Object); - if (oa == NULL) + if (oa.is_null()) return NULL; - array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->clazz)); - array_objectarray_element_set(oa, 1, javastring_new(m->name)); - array_objectarray_element_set(oa, 2, javastring_new(m->descriptor)); + oa.set_element(0, (java_handle_t *) LLNI_classinfo_wrap(m->clazz)); + oa.set_element(1, javastring_new(m->name)); + oa.set_element(2, javastring_new(m->descriptor)); - return (jobjectArray) oa; + return oa.get_handle(); } @@ -3340,8 +3324,6 @@ jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass) jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) { - java_handle_intarray_t *ia; - TRACEJVMCALLS(("JVM_GetThreadStateValues(env=%p, javaThreadState=%d)", env, javaThreadState)); @@ -3354,69 +3336,79 @@ jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) switch (javaThreadState) { case THREAD_STATE_NEW: - ia = builtin_newarray_int(1); + { + IntArray ia(1); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - array_intarray_element_set(ia, 0, THREAD_STATE_NEW); - break; + ia.set_element(0, THREAD_STATE_NEW); + return ia.get_handle(); + } case THREAD_STATE_RUNNABLE: - ia = builtin_newarray_int(1); + { + IntArray ia(1); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - array_intarray_element_set(ia, 0, THREAD_STATE_RUNNABLE); - break; + ia.set_element(0, THREAD_STATE_RUNNABLE); + return ia.get_handle(); + } case THREAD_STATE_BLOCKED: - ia = builtin_newarray_int(1); + { + IntArray ia(1); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - array_intarray_element_set(ia, 0, THREAD_STATE_BLOCKED); - break; + ia.set_element(0, THREAD_STATE_BLOCKED); + return ia.get_handle(); + } case THREAD_STATE_WAITING: - ia = builtin_newarray_int(2); + { + IntArray ia(2); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - array_intarray_element_set(ia, 0, THREAD_STATE_WAITING); - array_intarray_element_set(ia, 1, THREAD_STATE_PARKED); - break; + ia.set_element(0, THREAD_STATE_WAITING); + ia.set_element(1, THREAD_STATE_PARKED); + return ia.get_handle(); + } case THREAD_STATE_TIMED_WAITING: - ia = builtin_newarray_int(2); + { + IntArray ia(2); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - /* XXX Not sure about that one. */ -/* array_intarray_element_set(ia, 0, SLEEPING); */ - array_intarray_element_set(ia, 0, THREAD_STATE_TIMED_WAITING); - array_intarray_element_set(ia, 1, THREAD_STATE_TIMED_PARKED); - break; + /* XXX Not sure about that one. */ +/* ia.set_element(0, SLEEPING); */ + ia.set_element(0, THREAD_STATE_TIMED_WAITING); + ia.set_element(1, THREAD_STATE_TIMED_PARKED); + return ia.get_handle(); + } case THREAD_STATE_TERMINATED: - ia = builtin_newarray_int(1); + { + IntArray ia(1); - if (ia == NULL) - return NULL; + if (ia.is_null()) + return NULL; - array_intarray_element_set(ia, 0, THREAD_STATE_TERMINATED); - break; + ia.set_element(0, THREAD_STATE_TERMINATED); + return ia.get_handle(); + } default: /* Unknown state - probably incompatible JDK version */ return NULL; } - - return (jintArray) ia; } @@ -3424,14 +3416,12 @@ jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values) { - java_handle_intarray_t *ia; - java_handle_objectarray_t *oa; - java_object_t *s; + java_object_t* s; TRACEJVMCALLS(("JVM_GetThreadStateNames(env=%p, javaThreadState=%d, values=%p)", env, javaThreadState, values)); - ia = (java_handle_intarray_t *) values; + IntArray ia(values); /* If new thread states are added in future JDK and VM versions, this should check if the JDK version is compatible with thread @@ -3447,112 +3437,122 @@ jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArra switch (javaThreadState) { case THREAD_STATE_NEW: - assert(ia->header.size == 1 && ia->data[0] == THREAD_STATE_NEW); + { + assert(ia.get_length() == 1 && ia.get_element(0) == THREAD_STATE_NEW); - oa = builtin_anewarray(1, class_java_lang_String); + ObjectArray oa(1, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; - s = javastring_new(utf_new_char("NEW")); + s = javastring_new(utf_new_char("NEW")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); - break; + oa.set_element(0, s); + return oa.get_handle(); + } case THREAD_STATE_RUNNABLE: - oa = builtin_anewarray(1, class_java_lang_String); + { + ObjectArray oa(1, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; - s = javastring_new(utf_new_char("RUNNABLE")); + s = javastring_new(utf_new_char("RUNNABLE")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); - break; + oa.set_element(0, s); + return oa.get_handle(); + } case THREAD_STATE_BLOCKED: - oa = builtin_anewarray(1, class_java_lang_String); + { + ObjectArray oa(1, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; - s = javastring_new(utf_new_char("BLOCKED")); + s = javastring_new(utf_new_char("BLOCKED")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); - break; + oa.set_element(0, s); + return oa.get_handle(); + } case THREAD_STATE_WAITING: - oa = builtin_anewarray(2, class_java_lang_String); + { + ObjectArray oa(2, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; - s = javastring_new(utf_new_char("WAITING.OBJECT_WAIT")); + s = javastring_new(utf_new_char("WAITING.OBJECT_WAIT")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); + oa.set_element(0, s); - s = javastring_new(utf_new_char("WAITING.PARKED")); + s = javastring_new(utf_new_char("WAITING.PARKED")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 1, s); - break; + oa.set_element(1, s); + return oa.get_handle(); + } case THREAD_STATE_TIMED_WAITING: - oa = builtin_anewarray(2, class_java_lang_String); + { + ObjectArray oa(2, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; -/* s = javastring_new(utf_new_char("TIMED_WAITING.SLEEPING")); */ - s = javastring_new(utf_new_char("TIMED_WAITING.OBJECT_WAIT")); +/* s = javastring_new(utf_new_char("TIMED_WAITING.SLEEPING")); */ + s = javastring_new(utf_new_char("TIMED_WAITING.OBJECT_WAIT")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); + oa.set_element(0, s); - s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); + s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 1, s); - break; + oa.set_element(1, s); + return oa.get_handle(); + } case THREAD_STATE_TERMINATED: - oa = builtin_anewarray(1, class_java_lang_String); + { + ObjectArray oa(1, class_java_lang_String); - if (oa == NULL) - return NULL; + if (oa.is_null()) + return NULL; - s = javastring_new(utf_new_char("TERMINATED")); + s = javastring_new(utf_new_char("TERMINATED")); - if (s == NULL) - return NULL; + if (s == NULL) + return NULL; - array_objectarray_element_set(oa, 0, s); - break; + oa.set_element(0, s); + return oa.get_handle(); + } default: /* Unknown state - probably incompatible JDK version */ return NULL; } - - return (jobjectArray) oa; } diff --git a/src/native/vm/reflection.cpp b/src/native/vm/reflection.cpp index 73a8545b8..0cc2d4144 100644 --- a/src/native/vm/reflection.cpp +++ b/src/native/vm/reflection.cpp @@ -37,6 +37,7 @@ #include "native/vm/reflection.hpp" #include "vm/access.hpp" +#include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" #include "vm/global.h" @@ -85,8 +86,10 @@ java_handle_t* Reflection::invoke(methodinfo *m, java_handle_t *o, java_handle_o /* check if we got the right number of arguments */ + ObjectArray oa(params); + if (((params == NULL) && (paramcount != 0)) || - (params && (LLNI_array_size(params) != paramcount))) + (params && (oa.get_length() != paramcount))) { exceptions_throw_illegalargumentexception(); return NULL; diff --git a/src/native/vm/sun_misc_Unsafe.cpp b/src/native/vm/sun_misc_Unsafe.cpp index 63ec0c201..bcbfe0fec 100644 --- a/src/native/vm/sun_misc_Unsafe.cpp +++ b/src/native/vm/sun_misc_Unsafe.cpp @@ -40,6 +40,7 @@ # include "native/include/sun_misc_Unsafe.h" #endif +#include "vm/array.hpp" #include "vm/jit/builtin.hpp" #include "vm/exceptions.hpp" #include "vm/initialize.hpp" @@ -825,7 +826,9 @@ JNIEXPORT jclass JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3 /* check the indexes passed */ - if ((off < 0) || (len < 0) || ((off + len) > LLNI_array_size(b))) { + ByteArray ba(b); + + if ((off < 0) || (len < 0) || ((off + len) > ba.get_length())) { exceptions_throw_arrayindexoutofboundsexception(); return NULL; } @@ -841,7 +844,8 @@ JNIEXPORT jclass JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3 /* define the class */ - c = class_define(utfname, cl, len, (uint8_t *) &(LLNI_array_direct((java_handle_bytearray_t*) b, off)), + uint8_t* ptr = ((uint8_t*) ba.get_raw_data_ptr()) + off; + c = class_define(utfname, cl, len, ptr, (java_handle_t *) protectionDomain); if (c == NULL) diff --git a/src/vm/annotation.cpp b/src/vm/annotation.cpp index 2a5fafdff..7e930ab05 100644 --- a/src/vm/annotation.cpp +++ b/src/vm/annotation.cpp @@ -65,34 +65,37 @@ static java_handle_objectarray_t *annotation_bytearrays_resize( java_handle_objectarray_t *bytearrays, uint32_t size) { - java_handle_objectarray_t *newbas = NULL; /* new array */ uint32_t minsize = 0; /* count of object refs to copy */ uint32_t oldsize = 0; /* size of old array */ + ObjectArray bas(bytearrays); + if (bytearrays != NULL) { - oldsize = array_length_get((java_handle_t*)bytearrays); + oldsize = bas.get_length(); /* if the size already fits do nothing */ if (size == oldsize) { return bytearrays; } } - - newbas = builtin_anewarray(size, + + // Allocate new array on the heap. + + ObjectArray newbas(size, Primitive::get_arrayclass_by_type(PRIMITIVETYPE_BYTE)); - + /* is there a old byte array array? */ - if (newbas != NULL && bytearrays != NULL) { + if (newbas.is_non_null() && bytearrays != NULL) { minsize = size < oldsize ? size : oldsize; LLNI_CRITICAL_START; MCOPY( - LLNI_array_data(newbas), LLNI_array_data(bytearrays), + newbas.get_raw_data_ptr(), bas.get_raw_data_ptr(), java_object_t*, minsize); LLNI_CRITICAL_END; } - return newbas; + return newbas.get_handle(); } @@ -118,7 +121,6 @@ static java_handle_t *annotation_bytearrays_insert( java_handle_t *bytearrays, uint32_t index, java_handle_bytearray_t *bytearray) { - java_handle_objectarray_t *bas; /* bytearrays */ uint32_t size = 0; /* current size of the array */ /* do nothing if NULL is inserted but no array exists */ @@ -126,34 +128,35 @@ static java_handle_t *annotation_bytearrays_insert( return NULL; } + ObjectArray bas(bytearrays); + /* get lengths if array exists */ if (bytearrays != NULL) { - size = array_length_get(bytearrays); + size = bas.get_length(); } - bas = (java_handle_objectarray_t*)bytearrays; - if (bytearray == NULL) { /* insert NULL only if array is big enough */ if (size > index) { - array_objectarray_element_set(bas, index, NULL); + bas.set_element(index, NULL); } } else { + // XXX: We should use a clone function here!!! /* resize array if it's not enough for inserted value */ if (size <= index) { - bas = annotation_bytearrays_resize(bas, index + 1); + bas = annotation_bytearrays_resize(bas.get_handle(), index + 1); - if (bas == NULL) { + if (bas.is_null()) { /* out of memory */ return NULL; } } - array_objectarray_element_set(bas, index, (java_handle_t*)bytearray); + bas.set_element(index, (java_handle_t*) bytearray); } - return (java_handle_t*)bas; + return bas.get_handle(); } @@ -186,7 +189,6 @@ static bool annotation_load_attribute_body(classbuffer *cb, java_handle_bytearray_t **attribute, const char *errormsg_prefix) { uint32_t size = 0; /* size of the attribute */ - java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */ assert(cb != NULL); assert(attribute != NULL); @@ -207,9 +209,9 @@ static bool annotation_load_attribute_body(classbuffer *cb, /* if attribute_length == 0 then NULL is * the right value for this attribute */ if (size > 0) { - ba = builtin_newarray_byte(size); + ByteArray ba(size); - if (ba == NULL) { + if (ba.is_null()) { /* out of memory */ return false; } @@ -217,12 +219,13 @@ static bool annotation_load_attribute_body(classbuffer *cb, /* load data */ LLNI_CRITICAL_START; - suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size); + uint8_t* ptr = (uint8_t*) ba.get_raw_data_ptr(); + suck_nbytes(ptr, cb, size); LLNI_CRITICAL_END; /* return data */ - *attribute = ba; + *attribute = ba.get_handle(); } return true; diff --git a/src/vm/array.cpp b/src/vm/array.cpp index de602db14..560c400f8 100644 --- a/src/vm/array.cpp +++ b/src/vm/array.cpp @@ -2,6 +2,7 @@ Copyright (C) 2007 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2008 Theobroma Systems Ltd. This file is part of CACAO. @@ -32,33 +33,31 @@ #include "vm/array.hpp" #include "vm/exceptions.hpp" #include "vm/global.h" +#include "vm/globals.hpp" #include "vm/primitive.hpp" #include "vm/vm.hpp" -/* array_element_get *********************************************************** - - Returns a boxed element of the given Java array. - -*******************************************************************************/ - -java_handle_t *array_element_get(java_handle_t *a, int32_t index) +/** + * Returns a boxed element of the given Java array. + */ +java_handle_t* Array::get_boxed_element(int32_t index) { vftbl_t *v; int type; imm_union value; java_handle_t *o; - if (a == NULL) { + if (is_null()) { exceptions_throw_nullpointerexception(); return NULL; } - v = LLNI_vftbl_direct(a); + v = LLNI_vftbl_direct(_handle); type = v->arraydesc->arraytype; - value = array_element_primitive_get(a, index); + value = get_primitive_element(index); o = Primitive::box(type, value); @@ -66,82 +65,120 @@ java_handle_t *array_element_get(java_handle_t *a, int32_t index) } -/* array_element_set *********************************************************** - - Sets a boxed element in the given Java array. - -*******************************************************************************/ - -void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o) +/** + * Sets a boxed element in the given Java array. + */ +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; + } - array_element_primitive_set(a, index, value); -} + v = LLNI_vftbl_direct(_handle); + type = v->arraydesc->arraytype; -/* array_element_primitive_get ************************************************* + // Special handling for object arrays. + if (type == ARRAYTYPE_OBJECT) { + ObjectArray array(_handle); + array.set_element(index, o); + return; + } - Returns a primitive element of the given Java array. + // 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); +} -*******************************************************************************/ -imm_union array_element_primitive_get(java_handle_t *a, int32_t index) +/** + * Returns a primitive element of the given Java array. + */ +imm_union Array::get_primitive_element(int32_t index) { vftbl_t *v; int type; imm_union value; - if (a == NULL) { + if (is_null()) { exceptions_throw_nullpointerexception(); value.a = NULL; return value; } + java_handle_array_t* a = _handle; + v = LLNI_vftbl_direct(a); type = v->arraydesc->arraytype; switch (type) { case ARRAYTYPE_BOOLEAN: - value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index); + { + BooleanArray array(a); + value.i = array.get_element(index); + } break; case ARRAYTYPE_BYTE: - value.i = array_bytearray_element_get((java_handle_bytearray_t *) a, - index); + { + ByteArray array(a); + value.i = array.get_element(index); + } break; case ARRAYTYPE_CHAR: - value.i = array_chararray_element_get((java_handle_chararray_t *) a, - index); + { + CharArray array(a); + value.i = array.get_element(index); + } break; case ARRAYTYPE_SHORT: - value.i = array_shortarray_element_get((java_handle_shortarray_t *) a, - index); + { + ShortArray array(a); + value.i = array.get_element(index); + } break; case ARRAYTYPE_INT: - value.i = array_intarray_element_get((java_handle_intarray_t *) a, - index); + { + IntArray array(a); + value.i = array.get_element(index); + } break; case ARRAYTYPE_LONG: - value.l = array_longarray_element_get((java_handle_longarray_t *) a, - index); + { + LongArray array(a); + value.l = array.get_element(index); + } break; case ARRAYTYPE_FLOAT: - value.f = array_floatarray_element_get((java_handle_floatarray_t *) a, - index); + { + FloatArray array(a); + value.f = array.get_element(index); + } break; case ARRAYTYPE_DOUBLE: - value.d = array_doublearray_element_get((java_handle_doublearray_t *) a, - index); + { + DoubleArray array(a); + value.d = array.get_element(index); + } break; case ARRAYTYPE_OBJECT: - value.a = array_objectarray_element_get((java_handle_objectarray_t *) a, - index); + { + ObjectArray array(a); + value.a = array.get_element(index); + } break; default: - vm_abort("array_element_primitive_get: invalid array element type %d", + vm_abort("Array::primitive_element_get: invalid array element type %d", type); } @@ -149,62 +186,79 @@ imm_union array_element_primitive_get(java_handle_t *a, int32_t index) } -/* array_element_primitive_set ************************************************* - - Sets a primitive element in the given Java array. - -*******************************************************************************/ - -void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value) +/** + * Sets a primitive element in the given Java array. + */ +void Array::set_primitive_element(int32_t index, imm_union value) { vftbl_t *v; int type; - if (a == NULL) { + if (is_null()) { exceptions_throw_nullpointerexception(); return; } + java_handle_array_t* a = _handle; + v = LLNI_vftbl_direct(a); type = v->arraydesc->arraytype; switch (type) { case ARRAYTYPE_BOOLEAN: - array_booleanarray_element_set((java_handle_booleanarray_t *) a, - index, value.i); + { + BooleanArray array(a); + array.set_element(index, value.i); + } break; case ARRAYTYPE_BYTE: - array_bytearray_element_set((java_handle_bytearray_t *) a, - index, value.i); + { + ByteArray array(a); + array.set_element(index, value.i); + } break; case ARRAYTYPE_CHAR: - array_chararray_element_set((java_handle_chararray_t *) a, - index, value.i); + { + CharArray array(a); + array.set_element(index, value.i); + } break; case ARRAYTYPE_SHORT: - array_shortarray_element_set((java_handle_shortarray_t *) a, - index, value.i); + { + ShortArray array(a); + array.set_element(index, value.i); + } break; case ARRAYTYPE_INT: - array_intarray_element_set((java_handle_intarray_t *) a, - index, value.i); + { + IntArray array(a); + array.set_element(index, value.i); + } break; case ARRAYTYPE_LONG: - array_longarray_element_set((java_handle_longarray_t *) a, - index, value.l); + { + LongArray array(a); + array.set_element(index, value.l); + } break; case ARRAYTYPE_FLOAT: - array_floatarray_element_set((java_handle_floatarray_t *) a, - index, value.f); + { + FloatArray array(a); + array.set_element(index, value.f); + } break; case ARRAYTYPE_DOUBLE: - array_doublearray_element_set((java_handle_doublearray_t *) a, - index, value.d); + { + DoubleArray array(a); + array.set_element(index, value.d); + } break; case ARRAYTYPE_OBJECT: - array_objectarray_element_set((java_handle_objectarray_t *) a, - index, static_cast(value.a)); + { + ObjectArray array(a); + array.set_element(index, static_cast(value.a)); + } break; default: vm_abort("array_element_primitive_set: invalid array element type %d", @@ -213,171 +267,48 @@ void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union valu } -/* array_xxxarray_element_get ************************************************** - - Returns a primitive element of the given Java array. - -*******************************************************************************/ - -#define ARRAY_TYPEARRAY_ELEMENT_GET(name, type) \ -type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \ -{ \ - type value; \ - int32_t size; \ - \ - if (a == NULL) { \ - exceptions_throw_nullpointerexception(); \ - return (type) 0; \ - } \ - \ - size = LLNI_array_size(a); \ - \ - if ((index < 0) || (index >= size)) { \ - exceptions_throw_arrayindexoutofboundsexception(); \ - return (type) 0; \ - } \ - \ - value = LLNI_array_direct(a, index); \ - \ - return value; \ -} - -java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index) -{ - java_handle_t *value; - int32_t size; - - if (a == NULL) { - exceptions_throw_nullpointerexception(); - return NULL; - } - - size = LLNI_array_size(a); - - if ((index < 0) || (index >= size)) { - exceptions_throw_arrayindexoutofboundsexception(); - return NULL; - } - - LLNI_CRITICAL_START; - value = LLNI_WRAP(LLNI_array_direct(a, index)); - LLNI_CRITICAL_END; - - return value; -} - -ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t) -ARRAY_TYPEARRAY_ELEMENT_GET(byte, int8_t) -ARRAY_TYPEARRAY_ELEMENT_GET(char, uint16_t) -ARRAY_TYPEARRAY_ELEMENT_GET(short, int16_t) -ARRAY_TYPEARRAY_ELEMENT_GET(int, int32_t) -ARRAY_TYPEARRAY_ELEMENT_GET(long, int64_t) -ARRAY_TYPEARRAY_ELEMENT_GET(float, float) -ARRAY_TYPEARRAY_ELEMENT_GET(double, double) - - -/* array_xxxarray_element_set ************************************************** - - Sets a primitive element in the given Java array. - -*******************************************************************************/ - -#define ARRAY_TYPEARRAY_ELEMENT_SET(name, type) \ -void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \ -{ \ - int32_t size; \ - \ - if (a == NULL) { \ - exceptions_throw_nullpointerexception(); \ - return; \ - } \ - \ - size = LLNI_array_size(a); \ - \ - if ((index < 0) || (index >= size)) { \ - exceptions_throw_arrayindexoutofboundsexception(); \ - return; \ - } \ - \ - LLNI_array_direct(a, index) = value; \ -} - -void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value) +/** + * Creates an array of references to the given class type on the heap. + * The handle pointer to the array can be NULL in case of an exception. + */ +ObjectArray::ObjectArray(int32_t length, classinfo* componentclass) + : ArrayTemplate(NULL) { - int32_t size; + // Is class loaded? + assert(componentclass->state & CLASS_LOADED); - if (a == NULL) { - exceptions_throw_nullpointerexception(); - return; - } - - /* Sanity check. */ - - assert(a->header.objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT); - - if (value != NULL) { - if (builtin_canstore(a, value) == false) { - exceptions_throw_illegalargumentexception(); + // Is class linked? + if (!(componentclass->state & CLASS_LINKED)) + if (!link_class(componentclass)) { + _handle = NULL; return; } - } - size = LLNI_array_size(a); + classinfo* arrayclass = class_array_of(componentclass, true); - if ((index < 0) || (index >= size)) { - exceptions_throw_arrayindexoutofboundsexception(); + if (arrayclass == NULL) { + _handle = NULL; return; } - LLNI_CRITICAL_START; - LLNI_array_direct(a, index) = LLNI_UNWRAP(value); - LLNI_CRITICAL_END; -} - -ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t) -ARRAY_TYPEARRAY_ELEMENT_SET(byte, int8_t) -ARRAY_TYPEARRAY_ELEMENT_SET(char, uint16_t) -ARRAY_TYPEARRAY_ELEMENT_SET(short, int16_t) -ARRAY_TYPEARRAY_ELEMENT_SET(int, int32_t) -ARRAY_TYPEARRAY_ELEMENT_SET(long, int64_t) -ARRAY_TYPEARRAY_ELEMENT_SET(float, float) -ARRAY_TYPEARRAY_ELEMENT_SET(double, double) - - -/* array_length_get *********************************************************** - - Returns a the length of the given Java array. + // Delegate allocation to generic array class + Array a(length, arrayclass); - ARGUMENTS: - a ... Java array - - RETURN VALUE: - -1 ... exception thrown - >= 0 ... length of the Java array + _handle = a.get_handle(); +} -*******************************************************************************/ -int32_t array_length_get(java_handle_t *a) +/** + * Creates an array of references to classinfos on the heap. + * The handle pointer to the array can be NULL in case of an exception. + */ +ClassArray::ClassArray(int32_t length) + : ArrayTemplate(NULL) { - classinfo *c; - int32_t size; - - if (a == NULL) { - exceptions_throw_nullpointerexception(); - return -1; - } - - LLNI_class_get(a, c); - - if (!class_is_array(c)) { -/* exceptions_throw_illegalargumentexception("Argument is not an array"); */ - exceptions_throw_illegalargumentexception(); - return -1; - } - - size = LLNI_array_size(a); + // Delegate allocation to object array class + ObjectArray oa(length, class_java_lang_Class); - return size; + _handle = oa.get_handle(); } diff --git a/src/vm/array.hpp b/src/vm/array.hpp index 86f10843b..ced1ab3a7 100644 --- a/src/vm/array.hpp +++ b/src/vm/array.hpp @@ -2,6 +2,7 @@ Copyright (C) 2007 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2008 Theobroma Systems Ltd. This file is part of CACAO. @@ -30,6 +31,12 @@ #include +#include "mm/gc.hpp" // XXX Remove me! + +#include "native/llni.h" // XXX Remove me! + +#include "vm/class.hpp" +#include "vm/exceptions.hpp" #include "vm/global.h" #include "vm/primitive.hpp" @@ -51,42 +58,327 @@ #define ARRAYTYPE_OBJECT PRIMITIVETYPE_VOID /* don't use as index! */ -/* function prototypes ********************************************************/ - #ifdef __cplusplus -extern "C" { + +/** + * This is a generic accessor class for Java arrays (of unspecified type), + * which can be used to safely operate on Java arrays in native code. + */ +class Array { +protected: + // Handle of Java array. + java_handle_array_t* _handle; + +private: + // We don't want a Java arrays to be copied. + Array(Array* a) {} + Array(Array& a) {} + +public: + Array(java_handle_t* h); + Array(int32_t length, classinfo* arrayclass); + virtual ~Array() {} + + // Getters. + virtual java_handle_array_t* get_handle() const { return _handle; } + int32_t get_length() const; + + // Null checks. + bool is_null () const; + bool is_non_null() const; + + // Safe element modification functions for primitive values + imm_union get_primitive_element(int32_t index); + void set_primitive_element(int32_t index, imm_union value); + + // Safe element modification functions for boxed values + java_handle_t* get_boxed_element(int32_t index); + void set_boxed_element(int32_t index, java_handle_t *o); +}; + + +/** + * Constructor checks if passed handle really is a Java array. + */ +inline Array::Array(java_handle_t* h) +{ + if (h == NULL) { + _handle = NULL; + return; + } + +#if 0 + classinfo* c; + LLNI_class_get(h, c); + if (!class_is_array(c)) { + printf("Array::Array(): WARNING, passed handle is not an array\n"); + //exceptions_throw_illegalargumentexception("Argument is not an array"); + exceptions_throw_illegalargumentexception(); + _handle = NULL; + return; + } #endif -java_handle_t *array_element_get(java_handle_t *a, int32_t index); -void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o); - -imm_union array_element_primitive_get(java_handle_t *a, int32_t index); -void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value); - -uint8_t array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index); -int8_t array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index); -uint16_t array_chararray_element_get(java_handle_chararray_t *a, int32_t index); -int16_t array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index); -int32_t array_intarray_element_get(java_handle_intarray_t *a, int32_t index); -int64_t array_longarray_element_get(java_handle_longarray_t *a, int32_t index); -float array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index); -double array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index); -java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index); - -void array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value); -void array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value); -void array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value); -void array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value); -void array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value); -void array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value); -void array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value); -void array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value); -void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value); - -int32_t array_length_get(java_handle_t *a); + _handle = h; +} -#ifdef __cplusplus -} // extern "C" +/** + * Creates an array of the given array type on the heap. + * The handle pointer to the array can be NULL in case of an exception. + */ +inline Array::Array(int32_t size, classinfo* arrayclass) +{ + // Sanity check. + assert(class_is_array(arrayclass)); + + if (size < 0) { + exceptions_throw_negativearraysizeexception(); + _handle = NULL; + return; + } + + arraydescriptor* desc = arrayclass->vftbl->arraydesc; + int32_t dataoffset = desc->dataoffset; + int32_t componentsize = desc->componentsize; + int32_t actualsize = dataoffset + size * componentsize; + + // Check for overflow. + + if (((u4) actualsize) < ((u4) size)) { + exceptions_throw_outofmemoryerror(); + _handle = NULL; + return; + } + + java_array_t* a = (java_array_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true); + + if (a == NULL) { + _handle = NULL; + return; + } + + LLNI_vftbl_direct(a) = arrayclass->vftbl; + +#if defined(ENABLE_THREADS) + a->objheader.lockword.init(); +#endif + + a->size = size; + + _handle = (java_handle_array_t*) a; +} + +inline int32_t Array::get_length() const +{ + if (is_null()) { + printf("Array::get_length(): WARNING, got null-pointer\n"); + exceptions_throw_nullpointerexception(); + return -1; + } + + // XXX Fix me! + int32_t length = ((java_array_t*) _handle)->size; + + return length; +} + +inline bool Array::is_null() const +{ + return (_handle == NULL); +} + +inline bool Array::is_non_null() const +{ + return (_handle != NULL); +} + + +/** + * This is a template of an accessor class for Java arrays + * of a specific type. + */ +template class ArrayTemplate : public Array { +protected: + ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {} + +public: + ArrayTemplate(java_handle_array_t* h) : Array(h) {} + + // XXX This should be protected or private! + virtual T* get_raw_data_ptr() = 0; + + // Safe element modification functions + T get_element(int32_t index); + void set_element(int32_t index, T value); + + // Region copy functions + void get_region(int32_t offset, int32_t count, T* buffer); + void set_region(int32_t offset, int32_t count, const T* buffer); +}; + + +template inline T ArrayTemplate::get_element(int32_t index) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return 0; + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return 0; + } + + T* ptr = get_raw_data_ptr(); + + return ptr[index]; +} + +template inline void ArrayTemplate::set_element(int32_t index, T value) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return; + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } + + T* ptr = get_raw_data_ptr(); + + ptr[index] = value; +} + +template<> inline void ArrayTemplate::set_element(int32_t index, java_handle_t* value) +{ + if (is_null()) { + exceptions_throw_nullpointerexception(); + return; + } + + // Sanity check. + assert(((java_array_t*) get_handle())->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT); + + // Check if value can be stored + if (!builtin_canstore(get_handle(), value)) { + exceptions_throw_illegalargumentexception(); + return; + } + + if ((index < 0) || (index >= get_length())) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } + + java_handle_t** ptr = get_raw_data_ptr(); + + ptr[index] = value; +} + +template inline void ArrayTemplate::get_region(int32_t offset, int32_t count, T* buffer) +{ + // Copy the array region inside a GC critical section. + GCCriticalSection cs; + + const T* ptr = get_raw_data_ptr(); + + os::memcpy(buffer, ptr + offset, sizeof(T) * count); +} + +template inline void ArrayTemplate::set_region(int32_t offset, int32_t count, const T* buffer) +{ + // Copy the array region inside a GC critical section. + GCCriticalSection cs; + + T* ptr = get_raw_data_ptr(); + + os::memcpy(ptr + offset, buffer, sizeof(T) * count); +} + + +/** + * Actual implementations of common Java array access classes. + */ +class BooleanArray : public ArrayTemplate { +public: + BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate(h) {} + BooleanArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {} + uint8_t* get_raw_data_ptr() { return ((java_booleanarray_t*) get_handle())->data; } +}; + +class ByteArray : public ArrayTemplate { +public: + ByteArray(java_handle_bytearray_t* h) : ArrayTemplate(h) {} + ByteArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {} + int8_t* get_raw_data_ptr() { return ((java_bytearray_t*) get_handle())->data; } +}; + +class CharArray : public ArrayTemplate { +public: + CharArray(java_handle_chararray_t* h) : ArrayTemplate(h) {} + CharArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {} + uint16_t* get_raw_data_ptr() { return ((java_chararray_t*) get_handle())->data; } +}; + +class ShortArray : public ArrayTemplate { +public: + ShortArray(java_handle_shortarray_t* h) : ArrayTemplate(h) {} + ShortArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {} + int16_t* get_raw_data_ptr() { return ((java_shortarray_t*) get_handle())->data; } +}; + +class IntArray : public ArrayTemplate { +public: + IntArray(java_handle_intarray_t* h) : ArrayTemplate(h) {} + IntArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {} + int32_t* get_raw_data_ptr() { return ((java_intarray_t*) get_handle())->data; } +}; + +class LongArray : public ArrayTemplate { +public: + LongArray(java_handle_longarray_t* h) : ArrayTemplate(h) {} + LongArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {} + int64_t* get_raw_data_ptr() { return ((java_longarray_t*) get_handle())->data; } +}; + +class FloatArray : public ArrayTemplate { +public: + FloatArray(java_handle_floatarray_t* h) : ArrayTemplate(h) {} + FloatArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {} + float* get_raw_data_ptr() { return ((java_floatarray_t*) get_handle())->data; } +}; + +class DoubleArray : public ArrayTemplate { +public: + DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate(h) {} + DoubleArray(int32_t length) : ArrayTemplate(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {} + double* get_raw_data_ptr() { return ((java_doublearray_t*) get_handle())->data; } +}; + +/** + * Actual implementation of access class for Java Object arrays. + */ +class ObjectArray : public ArrayTemplate { +public: + ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate(h) {} + ObjectArray(int32_t length, classinfo* componentclass); + java_handle_t** get_raw_data_ptr() { return ((java_objectarray_t*) get_handle())->data; } +}; + +/** + * Actual implementation of access class for java.lang.Class arrays. + */ +class ClassArray : public ArrayTemplate { +public: + ClassArray(int32_t length); + classinfo** get_raw_data_ptr() { return (classinfo**) ((java_objectarray_t*) get_handle())->data; } +}; + + +#else +# warning No legacy C functions for array access classes. #endif #endif // _VM_ARRAY_HPP diff --git a/src/vm/class.cpp b/src/vm/class.cpp index 0c1739a3c..ee17a20ca 100644 --- a/src/vm/class.cpp +++ b/src/vm/class.cpp @@ -1643,7 +1643,6 @@ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOn utf *outername; int declaredclasscount; /* number of declared classes */ int pos; /* current declared class */ - java_handle_objectarray_t *oa; /* array of declared classes */ int i; classinfo *ic; @@ -1676,9 +1675,9 @@ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOn /* Allocate Class[] and check for OOM. */ - oa = builtin_anewarray(declaredclasscount, class_java_lang_Class); + ClassArray declaredclasses(declaredclasscount); - if (oa == NULL) + if (declaredclasses.is_null()) return NULL; for (i = 0, pos = 0; i < c->innerclasscount; i++) { @@ -1710,11 +1709,11 @@ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOn if (!link_class(ic)) return NULL; - LLNI_array_direct(oa, pos++) = (java_object_t *) ic; + declaredclasses.set_element(pos++, ic); } } - return oa; + return declaredclasses.get_handle(); } @@ -1729,11 +1728,10 @@ java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOn #if defined(ENABLE_JAVASE) java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly) { - methodinfo* m; - java_handle_objectarray_t* oa; - int count; - int index; - int i; + methodinfo* m; + int count; + int index; + int i; /* Determine number of constructors. */ @@ -1749,9 +1747,9 @@ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool pub /* Create array of constructors. */ - oa = builtin_anewarray(count, class_java_lang_reflect_Constructor); + ObjectArray oa(count, class_java_lang_reflect_Constructor); - if (oa == NULL) + if (oa.is_null()) return NULL; /* Get the constructors and store them in the array. */ @@ -1767,12 +1765,12 @@ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool pub /* Store object into array. */ - array_objectarray_element_set(oa, index, rc.get_handle()); + oa.set_element(index, rc.get_handle()); index++; } } - return oa; + return oa.get_handle(); } #endif @@ -1793,11 +1791,10 @@ java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool pub #if defined(ENABLE_JAVASE) java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly) { - java_handle_objectarray_t *oa; - fieldinfo *f; - int count; - int index; - int i; + fieldinfo* f; + int count; + int index; + int i; /* Determine number of fields. */ @@ -1809,9 +1806,9 @@ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnl /* Create array of fields. */ - oa = builtin_anewarray(count, class_java_lang_reflect_Field); + ObjectArray oa(count, class_java_lang_reflect_Field); - if (oa == NULL) + if (oa.is_null()) return NULL; /* Get the fields and store them in the array. */ @@ -1826,12 +1823,12 @@ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnl /* Store object into array. */ - array_objectarray_element_set(oa, index, rf.get_handle()); + oa.set_element(index, rf.get_handle()); index++; } } - return oa; + return oa.get_handle(); } #endif @@ -1852,19 +1849,20 @@ java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnl #if defined(ENABLE_JAVASE) java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly) { - java_handle_objectarray_t *oa; /* result: array of Method-objects */ - methodinfo *m; /* the current method to be represented */ - int count; - int index; - int i; + methodinfo* m; /* the current method to be represented */ + int count; + int index; + int i; /* JOWENN: array classes do not declare methods according to mauve test. It should be considered, if we should return to my old clone method overriding instead of declaring it as a member function. */ - if (class_is_array(c)) - return builtin_anewarray(0, class_java_lang_reflect_Method); + if (class_is_array(c)) { + ObjectArray oa(0, class_java_lang_reflect_Method); + return oa.get_handle(); + } /* Determine number of methods. */ @@ -1881,9 +1879,9 @@ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOn /* Create array of methods. */ - oa = builtin_anewarray(count, class_java_lang_reflect_Method); + ObjectArray oa(count, class_java_lang_reflect_Method); - if (oa == NULL) + if (oa.is_null()) return NULL; /* Get the methods and store them in the array. */ @@ -1900,12 +1898,12 @@ java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOn /* Store object into array. */ - array_objectarray_element_set(oa, index, rm.get_handle()); + oa.set_element(index, rm.get_handle()); index++; } } - return oa; + return oa.get_handle(); } #endif @@ -2103,28 +2101,27 @@ java_handle_t* class_get_enclosingmethod(classinfo *c) *******************************************************************************/ -java_handle_objectarray_t *class_get_interfaces(classinfo *c) +java_handle_objectarray_t* class_get_interfaces(classinfo *c) { - classinfo *ic; - java_handle_objectarray_t *oa; - u4 i; + classinfo* ic; + u4 i; if (!(c->state & CLASS_LINKED)) if (!link_class(c)) return NULL; - oa = builtin_anewarray(c->interfacescount, class_java_lang_Class); + ClassArray interfaces(c->interfacescount); - if (oa == NULL) + if (interfaces.is_null()) return NULL; for (i = 0; i < c->interfacescount; i++) { ic = c->interfaces[i]; - LLNI_array_direct(oa, i) = (java_object_t *) ic; + interfaces.set_element(i, ic); } - return oa; + return interfaces.get_handle(); } @@ -2149,7 +2146,7 @@ java_handle_bytearray_t *class_get_annotations(classinfo *c) LLNI_classinfo_field_get(c, annotations, annotations); - return (java_handle_bytearray_t*)annotations; + return (java_handle_bytearray_t*) annotations; #else return NULL; #endif diff --git a/src/vm/field.cpp b/src/vm/field.cpp index 6b6b4ed43..9d034b36c 100644 --- a/src/vm/field.cpp +++ b/src/vm/field.cpp @@ -405,26 +405,24 @@ java_handle_bytearray_t *field_get_annotations(fieldinfo *f) #if defined(ENABLE_ANNOTATIONS) classinfo *c; /* declaring class */ int slot; /* slot of this field */ - java_handle_bytearray_t *annotations; /* unparsed annotations */ java_handle_t *field_annotations; /* array of unparsed */ /* annotations of all fields of the declaring class */ - c = f->clazz; - slot = f - c->fields; - annotations = NULL; + c = f->clazz; + slot = f - c->fields; LLNI_classinfo_field_get(c, field_annotations, field_annotations); + ObjectArray oa(field_annotations); + /* the field_annotations array might be shorter then the field * count if the fields above a certain index have no annotations. */ - if (field_annotations != NULL && - array_length_get(field_annotations) > slot) { - annotations = (java_handle_bytearray_t*)array_objectarray_element_get( - (java_handle_objectarray_t*)field_annotations, slot); + if (field_annotations != NULL && oa.get_length() > slot) { + return (java_handle_bytearray_t*) oa.get_element(slot); + } else { + return NULL; } - - return annotations; #else return NULL; #endif diff --git a/src/vm/global.h b/src/vm/global.h index 011d9b4a0..33b7fb1e7 100644 --- a/src/vm/global.h +++ b/src/vm/global.h @@ -323,34 +323,17 @@ struct java_objectarray_t { *******************************************************************************/ -#if defined(ENABLE_HANDLES) -typedef struct java_handle_t { - java_object_t *heap_object; -} java_handle_t; - -typedef struct java_handle_array_t { java_array_t *heap_object; } java_handle_array_t; -typedef struct java_handle_objectarray_t { java_objectarray_t *heap_object; } java_handle_objectarray_t; -typedef struct java_handle_booleanarray_t { java_booleanarray_t *heap_object; } java_handle_booleanarray_t; -typedef struct java_handle_bytearray_t { java_bytearray_t *heap_object; } java_handle_bytearray_t; -typedef struct java_handle_chararray_t { java_chararray_t *heap_object; } java_handle_chararray_t; -typedef struct java_handle_shortarray_t { java_shortarray_t *heap_object; } java_handle_shortarray_t; -typedef struct java_handle_intarray_t { java_intarray_t *heap_object; } java_handle_intarray_t; -typedef struct java_handle_longarray_t { java_longarray_t *heap_object; } java_handle_longarray_t; -typedef struct java_handle_floatarray_t { java_floatarray_t *heap_object; } java_handle_floatarray_t; -typedef struct java_handle_doublearray_t { java_doublearray_t *heap_object; } java_handle_doublearray_t; -#else typedef java_object_t java_handle_t; -typedef java_array_t java_handle_array_t; -typedef java_objectarray_t java_handle_objectarray_t; -typedef java_booleanarray_t java_handle_booleanarray_t; -typedef java_bytearray_t java_handle_bytearray_t; -typedef java_chararray_t java_handle_chararray_t; -typedef java_shortarray_t java_handle_shortarray_t; -typedef java_intarray_t java_handle_intarray_t; -typedef java_longarray_t java_handle_longarray_t; -typedef java_floatarray_t java_handle_floatarray_t; -typedef java_doublearray_t java_handle_doublearray_t; -#endif +typedef java_handle_t java_handle_array_t; +typedef java_handle_array_t java_handle_objectarray_t; +typedef java_handle_array_t java_handle_booleanarray_t; +typedef java_handle_array_t java_handle_bytearray_t; +typedef java_handle_array_t java_handle_chararray_t; +typedef java_handle_array_t java_handle_shortarray_t; +typedef java_handle_array_t java_handle_intarray_t; +typedef java_handle_array_t java_handle_longarray_t; +typedef java_handle_array_t java_handle_floatarray_t; +typedef java_handle_array_t java_handle_doublearray_t; /* global constants related to the verifier ***********************************/ diff --git a/src/vm/javaobjects.cpp b/src/vm/javaobjects.cpp index b8a0d6013..901756534 100644 --- a/src/vm/javaobjects.cpp +++ b/src/vm/javaobjects.cpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.cpp - functions to create and access Java objects - Copyright (C) 2008 Theobroma Systems Ltd. + Copyright (C) 2008, 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -38,6 +38,42 @@ #if defined(ENABLE_JAVASE) +/** + * Invokes the static Java method getSystemClassLoader(). + * + * @return Return value of the invocation or NULL in + * case of an exception. + */ +java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader() +{ + methodinfo *m; + java_handle_t *clo; + classloader_t *cl; + + assert(class_java_lang_Object); + assert(class_java_lang_ClassLoader); + assert(class_java_lang_ClassLoader->state & CLASS_LINKED); + + m = class_resolveclassmethod(class_java_lang_ClassLoader, + utf_getSystemClassLoader, + utf_void__java_lang_ClassLoader, + class_java_lang_Object, + false); + + if (m == NULL) + return NULL; + + clo = vm_call_method(m, NULL); + + if (clo == NULL) + return NULL; + + cl = loader_hashtable_classloader_add(clo); + + return cl; +} + + /** * Constructs a Java object with the given * java.lang.reflect.Constructor. @@ -67,7 +103,7 @@ java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarr if (h == NULL) return NULL; - + // Call initializer. (void) Reflection::invoke(m, h, args); diff --git a/src/vm/javaobjects.hpp b/src/vm/javaobjects.hpp index b8ee1215a..71f58abb1 100644 --- a/src/vm/javaobjects.hpp +++ b/src/vm/javaobjects.hpp @@ -1,6 +1,6 @@ /* src/vm/javaobjects.hpp - functions to create and access Java objects - Copyright (C) 2008 Theobroma Systems Ltd. + Copyright (C) 2008, 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -590,6 +590,39 @@ inline void java_lang_Class::set_pd(java_handle_t* value) } +/** + * GNU Classpath java/lang/ClassLoader + * + * Object layout: + * + * 0. object header + * 1. java.util.HashMap definedPackages + * 2. java.lang.ClassLoader parent + * [other fields are not used] + */ +class java_lang_ClassLoader : public java_lang_Object, private FieldAccess { +private: + // Static offsets of the object's instance fields. + // TODO These offsets need to be checked on VM startup. + static const off_t offset_definedPackages = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P); + static const off_t offset_parent = MEMORY_ALIGN(offset_definedPackages + SIZEOF_VOID_P, SIZEOF_VOID_P); + +public: + java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {} + + // Getters. + java_handle_t* get_parent() const; + + // Invocation wrappers for static methods. + static java_handle_t* invoke_getSystemClassLoader(); +}; + +inline java_handle_t* java_lang_ClassLoader::get_parent() const +{ + return get(_handle, offset_parent); +} + + /** * GNU Classpath java/lang/StackTraceElement * @@ -1715,7 +1748,7 @@ public: gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {} gnu_classpath_Pointer(java_handle_t* h, void* data); - // Setters. + // Getters. void* get_data() const; // Setters. @@ -1788,6 +1821,39 @@ inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives( } +/** + * OpenJDK java/lang/ClassLoader + * + * Object layout: + * + * 0. object header + * 1. boolean initialized + * 2. java.lang.ClassLoader parent + * [other fields are not used] + */ +class java_lang_ClassLoader : public java_lang_Object, private FieldAccess { +private: + // Static offsets of the object's instance fields. + // TODO These offsets need to be checked on VM startup. + static const off_t offset_initialized = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t)); + static const off_t offset_parent = MEMORY_ALIGN(offset_initialized + sizeof(int32_t), SIZEOF_VOID_P); + +public: + java_lang_ClassLoader(java_handle_t* h) : java_lang_Object(h) {} + + // Getters. + java_handle_t* get_parent() const; + + // Invocation wrappers for static methods. + static java_handle_t* invoke_getSystemClassLoader(); +}; + +inline java_handle_t* java_lang_ClassLoader::get_parent() const +{ + return get(_handle, offset_parent); +} + + /** * OpenJDK java/lang/StackTraceElement * diff --git a/src/vm/jit/argument.cpp b/src/vm/jit/argument.cpp index 5ee7ca6d5..9736c1e24 100644 --- a/src/vm/jit/argument.cpp +++ b/src/vm/jit/argument.cpp @@ -582,10 +582,12 @@ uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o, i++; } + ObjectArray oa(params); + for (j = 0; i < md->paramcount; i++, j++, pd++, td++) { /* XXX This function can throw an exception, which should not happend here, since we are outside the nativeworld. */ - param = array_objectarray_element_get(params, j); + param = oa.get_element(j); switch (td->type) { case TYPE_INT: diff --git a/src/vm/jit/builtin.cpp b/src/vm/jit/builtin.cpp index bdfb79a4b..ff1e2dd9c 100644 --- a/src/vm/jit/builtin.cpp +++ b/src/vm/jit/builtin.cpp @@ -581,7 +581,7 @@ bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o) LLNI_CRITICAL_START; - result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o)); + result = builtin_fast_canstore((java_objectarray_t*) LLNI_DIRECT(oa), LLNI_UNWRAP(o)); LLNI_CRITICAL_END; @@ -1036,7 +1036,7 @@ java_object_t *builtin_fast_new(classinfo *c) } -/* builtin_newarray ************************************************************ +/* builtin_java_newarray ******************************************************* Creates an array with the given vftbl on the heap. This function takes as class argument an array class. @@ -1044,111 +1044,27 @@ java_object_t *builtin_fast_new(classinfo *c) RETURN VALUE: pointer to the array or NULL if no memory is available - NOTE: This builtin can be called from NATIVE code only. + NOTE: This is a SLOW builtin and can be called from JIT code only. *******************************************************************************/ -java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass) +java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz) { - arraydescriptor *desc; - s4 dataoffset; - s4 componentsize; - s4 actualsize; - java_handle_t *a; #if defined(ENABLE_RT_TIMING) struct timespec time_start, time_end; #endif RT_TIMING_GET_TIME(time_start); - desc = arrayclass->vftbl->arraydesc; - dataoffset = desc->dataoffset; - componentsize = desc->componentsize; - - if (size < 0) { - exceptions_throw_negativearraysizeexception(); - return NULL; - } - - actualsize = dataoffset + size * componentsize; + classinfo* arrayclass = LLNI_classinfo_unwrap(arrayclazz); - /* check for overflow */ - - if (((u4) actualsize) < ((u4) size)) { - exceptions_throw_outofmemoryerror(); - return NULL; - } - - a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true); - - if (a == NULL) - return NULL; - -#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES) - /* XXX this is only a dirty hack to make Boehm work with handles */ - - a = LLNI_WRAP((java_object_t *) a); -#endif - - LLNI_vftbl_direct(a) = arrayclass->vftbl; - -#if defined(ENABLE_THREADS) - LLNI_DIRECT(a)->lockword.init(); -#endif - - LLNI_array_size(a) = size; + // Allocate a new array with given size and class on the heap + Array a(size, arrayclass); RT_TIMING_GET_TIME(time_end); RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY); - return a; -} - - -/* builtin_java_newarray ******************************************************* - - NOTE: This is a SLOW builtin and can be called from JIT code only. - -*******************************************************************************/ - -java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz) -{ - return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz)); -} - - -/* builtin_anewarray *********************************************************** - - Creates an array of references to the given class type on the heap. - - RETURN VALUE: - pointer to the array or NULL if no memory is - available - - NOTE: This builtin can be called from NATIVE code only. - -*******************************************************************************/ - -java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass) -{ - classinfo *arrayclass; - - /* is class loaded */ - - assert(componentclass->state & CLASS_LOADED); - - /* is class linked */ - - if (!(componentclass->state & CLASS_LINKED)) - if (!link_class(componentclass)) - return NULL; - - arrayclass = class_array_of(componentclass, true); - - if (!arrayclass) - return NULL; - - return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass); + return a.get_handle(); } @@ -1163,21 +1079,21 @@ java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentc *******************************************************************************/ -#define BUILTIN_NEWARRAY_TYPE(type, arraytype) \ -java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \ -{ \ - return (java_handle_##type##array_t *) \ - builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \ +#define BUILTIN_NEWARRAY_TYPE(type, name) \ +java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \ +{ \ + name##Array a(size); \ + return a.get_handle(); \ } -BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN) -BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE) -BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR) -BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT) -BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT) -BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG) -BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT) -BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE) +BUILTIN_NEWARRAY_TYPE(boolean, Boolean) +BUILTIN_NEWARRAY_TYPE(byte, Byte) +BUILTIN_NEWARRAY_TYPE(char, Char) +BUILTIN_NEWARRAY_TYPE(short, Short) +BUILTIN_NEWARRAY_TYPE(int, Int) +BUILTIN_NEWARRAY_TYPE(long, Long) +BUILTIN_NEWARRAY_TYPE(float, Float) +BUILTIN_NEWARRAY_TYPE(double, Double) /* builtin_multianewarray_intern *********************************************** @@ -1195,38 +1111,37 @@ BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE) ******************************************************************************/ -static java_handle_t *builtin_multianewarray_intern(int n, +static java_handle_array_t *builtin_multianewarray_intern(int n, classinfo *arrayclass, long *dims) { - s4 size; - java_handle_t *a; - classinfo *componentclass; - s4 i; + int32_t i; /* create this dimension */ - size = (s4) dims[0]; - a = builtin_newarray(size, arrayclass); + int32_t size = (int32_t) dims[0]; + Array a(size, arrayclass); - if (!a) + if (a.is_null()) return NULL; /* if this is the last dimension return */ if (!--n) - return a; + return a.get_handle(); /* get the class of the components to create */ - componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz; + classinfo* componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz; /* The verifier guarantees that the dimension count is in the range. */ /* create the component arrays */ + ObjectArray oa(a.get_handle()); + for (i = 0; i < size; i++) { - java_handle_t *ea = + java_handle_array_t *ea = #if defined(__MIPS__) && (SIZEOF_VOID_P == 4) /* we save an s4 to a s8 slot, 8-byte aligned */ @@ -1238,10 +1153,10 @@ static java_handle_t *builtin_multianewarray_intern(int n, if (!ea) return NULL; - array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea); + oa.set_element(i, (java_handle_t*) ea); } - return a; + return a.get_handle(); } @@ -2086,6 +2001,9 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart, return; } + Array sa(src); + Array da(dest); + sdesc = LLNI_vftbl_direct(src)->arraydesc; ddesc = LLNI_vftbl_direct(dest)->arraydesc; @@ -2101,8 +2019,8 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart, } // Check if ranges are valid. - if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) || - (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) { + if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) sa.get_length()) || + (((uint32_t) destStart + (uint32_t) len) > (uint32_t) da.get_length())) { exceptions_throw_arrayindexoutofboundsexception(); return; } @@ -2129,19 +2047,17 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart, else { /* We copy references of different type */ - java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src; - java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest; + ObjectArray oas((java_handle_objectarray_t*) src); + ObjectArray oad((java_handle_objectarray_t*) dest); if (destStart <= srcStart) { for (i = 0; i < len; i++) { - java_handle_t *o; + java_handle_t* o = oas.get_element(srcStart + i); - o = array_objectarray_element_get(oas, srcStart + i); - - if (!builtin_canstore(oad, o)) + if (!builtin_canstore(oad.get_handle(), o)) return; - array_objectarray_element_set(oad, destStart + i, o); + oad.set_element(destStart + i, o); } } else { @@ -2152,14 +2068,12 @@ void builtin_arraycopy(java_handle_t *src, s4 srcStart, index have been copied before the throw. */ for (i = len - 1; i >= 0; i--) { - java_handle_t *o; - - o = array_objectarray_element_get(oas, srcStart + i); + java_handle_t* o = oas.get_element(srcStart + i); - if (!builtin_canstore(oad, o)) + if (!builtin_canstore(oad.get_handle(), o)) return; - array_objectarray_element_set(oad, destStart + i, o); + oad.set_element(destStart + i, o); } } } @@ -2224,7 +2138,9 @@ java_handle_t *builtin_clone(void *env, java_handle_t *o) /* we are cloning an array */ if (ad != NULL) { - size = ad->dataoffset + ad->componentsize * LLNI_array_size(o); + Array a(o); + + size = ad->dataoffset + ad->componentsize * a.get_length(); co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true); diff --git a/src/vm/jit/builtin.hpp b/src/vm/jit/builtin.hpp index 60b58e25c..af81aced2 100644 --- a/src/vm/jit/builtin.hpp +++ b/src/vm/jit/builtin.hpp @@ -168,14 +168,9 @@ java_handle_t *builtin_escape_reason_new(classinfo *c); java_object_t *builtin_fast_new(classinfo *c); #define BUILTIN_FAST_new (functionptr) builtin_fast_new -java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass); -/* NOT AN OP */ -java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass); +java_handle_array_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass); #define BUILTIN_newarray (functionptr) builtin_java_newarray -java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass); -/* NOT AN OP */ - java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size); #define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean java_handle_chararray_t *builtin_newarray_char(int32_t size); diff --git a/src/vm/jit/stacktrace.cpp b/src/vm/jit/stacktrace.cpp index 8efa4b25b..b51154ed2 100644 --- a/src/vm/jit/stacktrace.cpp +++ b/src/vm/jit/stacktrace.cpp @@ -2,6 +2,7 @@ Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -516,15 +517,14 @@ static int stacktrace_depth(stackframeinfo_t *sfi) java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi) { - stackframeinfo_t tmpsfi; - int depth; - java_handle_bytearray_t *ba; - int32_t ba_size; - stacktrace_t *st; - stacktrace_entry_t *ste; - methodinfo *m; - bool skip_fillInStackTrace; - bool skip_init; + stackframeinfo_t tmpsfi; + int depth; + int32_t ba_size; + stacktrace_t *st; + stacktrace_entry_t *ste; + methodinfo *m; + bool skip_fillInStackTrace; + bool skip_init; CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD @@ -550,9 +550,9 @@ java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi) ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth; - ba = builtin_newarray_byte(ba_size); + ByteArray ba(ba_size); - if (ba == NULL) + if (ba.is_null()) goto return_NULL; /* Get a stacktrace entry pointer. */ @@ -561,7 +561,7 @@ java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi) LLNI_CRITICAL_START; - st = (stacktrace_t *) LLNI_array_data(ba); + st = (stacktrace_t *) ba.get_raw_data_ptr(); ste = st->entries; @@ -639,7 +639,7 @@ java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi) CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace, stacktrace_overhead) - return ba; + return ba.get_handle(); return_NULL: /* dump_release(dumpsize); */ @@ -774,9 +774,9 @@ java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st) int32_t length = (st != NULL) ? st->length : 0; // Create the stacktrace element array. - java_handle_objectarray_t* oa = builtin_anewarray(length, class_java_lang_StackTraceElement); + ObjectArray oa(length, class_java_lang_StackTraceElement); - if (oa == NULL) + if (oa.is_null()) return NULL; // Iterate over all stacktrace elements. @@ -789,10 +789,10 @@ java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t* st) return NULL; // Store stacktrace element in array. - array_objectarray_element_set(oa, i, h); + oa.set_element(i, h); } - return oa; + return oa.get_handle(); } #endif @@ -873,17 +873,12 @@ classinfo *stacktrace_get_caller_class(int depth) #endif -/* stacktrace_first_nonnull_classloader **************************************** - - Returns the first non-null (user-defined) classloader on the stack. - If none is found NULL is returned. - - RETURN: - classloader - -*******************************************************************************/ - -classloader_t *stacktrace_first_nonnull_classloader(void) +/** + * Returns the first non-null (user-defined) classloader on the stack. + * + * @return The first non-null classloader or NULL if none is found. + */ +classloader_t* stacktrace_first_nonnull_classloader(void) { stackframeinfo_t *sfi; stackframeinfo_t tmpsfi; @@ -916,6 +911,82 @@ classloader_t *stacktrace_first_nonnull_classloader(void) } +/** + * Checks if a given classloader is equal to the the second classloader + * or one of its ancestors (parents). + * + * XXX: This helper method should be moved to java_lang_Classloader. + */ +#if defined(ENABLE_JAVASE) +static bool is_ancestor_of(classloader_t* loader, classloader_t* parent) +{ + // Iterate over chain of possible parents. + while (parent != NULL) { + + // Check if given loader is parent. + if (loader == parent) + return true; + + // Jump to next parent. + java_lang_ClassLoader jlcl(parent); + parent = jlcl.get_parent(); + } + + return false; +} +#endif /* defined(ENABLE_JAVASE) */ + + +/** + * Returns the first non-system (user-defined) classloader on the stack. + * A non-system classloader is a non-null classloader being not equal to + * the system classloader (or one of its ancestors). + * + * @return The first non-system classloader or NULL if none is found. + */ +#if defined(ENABLE_JAVASE) +classloader_t* stacktrace_first_nonsystem_classloader(void) +{ + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + methodinfo *m; + classloader_t *cl; + classloader_t *syscl; + +#if !defined(NDEBUG) + if (opt_DebugStackTrace) + log_println("[stacktrace_first_nonsystem_classloader]"); +#endif + + // Get the stackframeinfo of the current thread. + sfi = threads_get_current_stackframeinfo(); + + // Get the system class class loader. + syscl = java_lang_ClassLoader::invoke_getSystemClassLoader(); + + // Iterate over the whole stack. + for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi); + stacktrace_stackframeinfo_end_check(&tmpsfi) == false; + stacktrace_stackframeinfo_next(&tmpsfi)) { + + m = tmpsfi.code->m; + cl = class_get_classloader(m->clazz); + + if (cl == NULL) + continue; + + // XXX if a method in a class in a trusted loader is in a + // doPrivileged, return NULL (or break) here. + + if (!is_ancestor_of(cl, syscl)) + return cl; + } + + return NULL; +} +#endif /* defined(ENABLE_JAVASE) */ + + /* stacktrace_getClassContext ************************************************** Creates a Class context array. @@ -931,8 +1002,6 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) stackframeinfo_t *sfi; stackframeinfo_t tmpsfi; int depth; - java_handle_objectarray_t *oa; - java_object_t **data; int i; methodinfo *m; @@ -959,20 +1028,15 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) /* Allocate the Class array. */ - oa = builtin_anewarray(depth, class_java_lang_Class); + ClassArray ca(depth); - if (oa == NULL) { + if (ca.is_null()) { CYCLES_STATS_END(stacktrace_getClassContext); return NULL; } /* Fill the Class array from the stacktrace list. */ - - LLNI_CRITICAL_START; - - data = LLNI_array_data(oa); - /* Iterate over the whole stack. */ i = 0; @@ -991,7 +1055,7 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) /* Store the class in the array. */ - data[i] = (java_object_t *) m->clazz; + ca.set_element(i, m->clazz); i++; } @@ -1000,7 +1064,7 @@ java_handle_objectarray_t *stacktrace_getClassContext(void) CYCLES_STATS_END(stacktrace_getClassContext) - return oa; + return ca.get_handle(); } @@ -1092,15 +1156,12 @@ classinfo *stacktrace_get_current_class(void) #if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) java_handle_objectarray_t *stacktrace_get_stack(void) { - stackframeinfo_t *sfi; - stackframeinfo_t tmpsfi; - int depth; - java_handle_objectarray_t *oa; - java_handle_objectarray_t *classes; - java_handle_objectarray_t *methodnames; - methodinfo *m; - java_handle_t *string; - int i; + stackframeinfo_t *sfi; + stackframeinfo_t tmpsfi; + int depth; + methodinfo *m; + java_handle_t *string; + int i; CYCLES_STATS_DECLARE_AND_START @@ -1122,25 +1183,23 @@ java_handle_objectarray_t *stacktrace_get_stack(void) /* Allocate the required arrays. */ - oa = builtin_anewarray(2, arrayclass_java_lang_Object); + ObjectArray oa(2, arrayclass_java_lang_Object); + ClassArray classes(depth); + ObjectArray methodnames(depth, class_java_lang_String); - if (oa == NULL) + if (oa.is_null()) goto return_NULL; - classes = builtin_anewarray(depth, class_java_lang_Class); - - if (classes == NULL) + if (classes.is_null()) goto return_NULL; - methodnames = builtin_anewarray(depth, class_java_lang_String); - - if (methodnames == NULL) + if (methodnames.is_null()) goto return_NULL; /* Set up the 2-dimensional array. */ - array_objectarray_element_set(oa, 0, (java_handle_t *) classes); - array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames); + oa.set_element(0, (java_handle_t *) classes.get_handle()); + oa.set_element(1, (java_handle_t *) methodnames.get_handle()); /* Iterate over the whole stack. */ /* TODO We should use a critical section here to speed things @@ -1161,10 +1220,8 @@ java_handle_objectarray_t *stacktrace_get_stack(void) continue; /* Store the class in the array. */ - /* NOTE: We use a LLNI-macro here, because a classinfo is not - a handle. */ - LLNI_array_direct(classes, i) = (java_object_t *) m->clazz; + classes.set_element(i, m->clazz); /* Store the name in the array. */ @@ -1173,14 +1230,14 @@ java_handle_objectarray_t *stacktrace_get_stack(void) if (string == NULL) goto return_NULL; - array_objectarray_element_set(methodnames, i, string); + methodnames.set_element(i, string); i++; } CYCLES_STATS_END(stacktrace_get_stack) - return oa; + return oa.get_handle(); return_NULL: CYCLES_STATS_END(stacktrace_get_stack) @@ -1324,16 +1381,18 @@ void stacktrace_print_current(void) stacktrace_t* stacktrace_get_of_thread(threadobject* t) { stackframeinfo_t* sfi; - java_handle_bytearray_t* ba; + java_handle_bytearray_t* stba; stacktrace_t* st; - sfi = t->_stackframeinfo; - ba = stacktrace_get(sfi); + sfi = t->_stackframeinfo; + stba = stacktrace_get(sfi); + + ByteArray ba(stba); - if (ba == NULL) + if (ba.is_null()) return NULL; - st = (stacktrace_t*) LLNI_array_data(ba); + st = (stacktrace_t*) ba.get_raw_data_ptr(); return st; } @@ -1407,11 +1466,11 @@ void stacktrace_print_exception(java_handle_t *h) #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) java_lang_VMThrowable vmt(t.get_vmState()); - java_handle_bytearray_t* backtrace = vmt.get_vmdata(); + ByteArray backtrace(vmt.get_vmdata()); #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1) - java_handle_bytearray_t* backtrace = t.get_backtrace(); + ByteArray backtrace(t.get_backtrace()); #else # error unknown classpath configuration @@ -1419,14 +1478,14 @@ void stacktrace_print_exception(java_handle_t *h) // Sanity check. - assert(backtrace != NULL); + assert(backtrace.is_non_null()); /* We need a critical section here as we use the byte-array data pointer directly. */ LLNI_CRITICAL_START; - stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace); + stacktrace_t* st = (stacktrace_t*) backtrace.get_raw_data_ptr(); stacktrace_print(st); diff --git a/src/vm/jit/stacktrace.hpp b/src/vm/jit/stacktrace.hpp index 2c2920c82..ee032b2a2 100644 --- a/src/vm/jit/stacktrace.hpp +++ b/src/vm/jit/stacktrace.hpp @@ -110,6 +110,7 @@ java_handle_t* stacktrace_get_StackTraceElement(stacktrace_t *st, in java_handle_objectarray_t* stacktrace_get_StackTraceElements(stacktrace_t *st); classinfo *stacktrace_get_caller_class(int depth); classloader_t *stacktrace_first_nonnull_classloader(void); +classloader_t *stacktrace_first_nonsystem_classloader(void); java_handle_objectarray_t *stacktrace_getClassContext(void); classinfo *stacktrace_get_current_class(void); java_handle_objectarray_t *stacktrace_get_stack(void); diff --git a/src/vm/jit/trace.cpp b/src/vm/jit/trace.cpp index 98667f76c..f6dd77aba 100644 --- a/src/vm/jit/trace.cpp +++ b/src/vm/jit/trace.cpp @@ -38,6 +38,7 @@ #include "toolbox/logging.hpp" +#include "vm/array.hpp" #include "vm/global.h" #include "vm/globals.hpp" #include "vm/javaobjects.hpp" @@ -569,9 +570,11 @@ void trace_exception_builtin(java_handle_t* h) logtextlen += utf_bytes(jlt.get_vftbl()->clazz->name); if (jls.get_handle()) { + CharArray ca(jls.get_value()); // FIXME This is not handle capable! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); logtextlen += strlen(": ") + - u2_utflength(jls.get_value()->data + jls.get_offset(), jls.get_count()); + u2_utflength(ptr + jls.get_offset(), jls.get_count()); } } else { diff --git a/src/vm/loader.cpp b/src/vm/loader.cpp index 083f00b30..e697a97dd 100644 --- a/src/vm/loader.cpp +++ b/src/vm/loader.cpp @@ -2,6 +2,7 @@ Copyright (C) 1996-2005, 2006, 2007, 2008 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. @@ -47,6 +48,7 @@ #include "vm/field.hpp" #include "vm/global.h" #include "vm/globals.hpp" +#include "vm/javaobjects.hpp" #include "vm/linker.hpp" #include "vm/loader.hpp" #include "vm/method.hpp" @@ -991,37 +993,22 @@ bool loader_load_attribute_signature(classbuffer *cb, utf **signature) *******************************************************************************/ +#if defined(ENABLE_JAVASE) classinfo *load_class_from_sysloader(utf *name) { - methodinfo *m; - java_handle_t *clo; classloader_t *cl; classinfo *c; - assert(class_java_lang_Object); - assert(class_java_lang_ClassLoader); - assert(class_java_lang_ClassLoader->state & CLASS_LINKED); - - m = class_resolveclassmethod(class_java_lang_ClassLoader, - utf_getSystemClassLoader, - utf_void__java_lang_ClassLoader, - class_java_lang_Object, - false); + cl = java_lang_ClassLoader::invoke_getSystemClassLoader(); - if (!m) - return false; - - clo = vm_call_method(m, NULL); - - if (!clo) + if (cl == NULL) return false; - cl = loader_hashtable_classloader_add(clo); - c = load_class_from_classloader(name, cl); return c; } +#endif /* defined(ENABLE_JAVASE) */ /* load_class_from_classloader ************************************************* @@ -1188,6 +1175,18 @@ classinfo *load_class_from_classloader(utf *name, classloader_t *cl) c = tmpc; } + else { + // Expected behavior for the classloader is to throw an exception + // and never return NULL. If the classloader shows a different + // behavior, we are correcting it here (see PR126). + if (exceptions_get_exception() == NULL) { +#if !defined(NDEBUG) + if (opt_PrintWarnings) + log_message_utf("load_class_from_classloader: Correcting faulty classloader behavior (PR126) for ", name); +#endif + exceptions_throw_classnotfoundexception(name); + } + } RT_TIMING_GET_TIME(time_cache); diff --git a/src/vm/method.cpp b/src/vm/method.cpp index 21f542400..4a1660201 100644 --- a/src/vm/method.cpp +++ b/src/vm/method.cpp @@ -201,7 +201,15 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool) } } #endif /* ENABLE_VERIFIER */ - + + /* Ignore flags for class initializer according to section 4.6 + of "The Java Virtual Machine Specification, 2nd Edition" (see PR125). */ + + if (m->name == utf_clinit) { + m->flags &= ACC_STRICT; + m->flags |= ACC_STATIC; + } + if (!(m->flags & ACC_STATIC)) argcount++; /* count the 'this' argument */ @@ -699,12 +707,11 @@ int32_t method_get_parametercount(methodinfo *m) java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m) { - methoddesc *md; - typedesc *paramtypes; - int32_t paramcount; - java_handle_objectarray_t *oa; - int32_t i; - classinfo *c; + methoddesc* md; + typedesc* paramtypes; + int32_t paramcount; + int32_t i; + classinfo* c; md = m->parseddesc; @@ -726,9 +733,9 @@ java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m) /* create class-array */ - oa = builtin_anewarray(paramcount, class_java_lang_Class); + ClassArray ca(paramcount); - if (oa == NULL) + if (ca.is_null()) return NULL; /* get classes */ @@ -737,10 +744,10 @@ java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m) if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c)) return NULL; - LLNI_array_direct(oa, i) = (java_object_t *) c; + ca.set_element(i, c); } - return oa; + return ca.get_handle(); } @@ -752,15 +759,14 @@ java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m) java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m) { - java_handle_objectarray_t *oa; - classinfo *c; - s4 i; + classinfo* c; + s4 i; /* create class-array */ - oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class); + ClassArray ca(m->thrownexceptionscount); - if (oa == NULL) + if (ca.is_null()) return NULL; /* iterate over all exceptions and store the class in the array */ @@ -771,10 +777,10 @@ java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m) if (c == NULL) return NULL; - LLNI_array_direct(oa, i) = (java_object_t *) c; + ca.set_element(i, c); } - return oa; + return ca.get_handle(); } @@ -864,26 +870,24 @@ java_handle_bytearray_t *method_get_annotations(methodinfo *m) #if defined(ENABLE_ANNOTATIONS) classinfo *c; /* methods' declaring class */ int slot; /* methods' slot */ - java_handle_t *annotations; /* methods' unparsed annotations */ java_handle_t *method_annotations; /* all methods' unparsed annotations */ /* of the declaring class */ - c = m->clazz; - slot = m - c->methods; - annotations = NULL; + c = m->clazz; + slot = m - c->methods; LLNI_classinfo_field_get(c, method_annotations, method_annotations); + ObjectArray oa((java_handle_objectarray_t*) method_annotations); + /* the method_annotations array might be shorter then the method * count if the methods above a certain index have no annotations. */ - if (method_annotations != NULL && - array_length_get(method_annotations) > slot) { - annotations = array_objectarray_element_get( - (java_handle_objectarray_t*)method_annotations, slot); + if (method_annotations != NULL && oa.get_length() > slot) { + return (java_handle_bytearray_t*) oa.get_element(slot); + } else { + return NULL; } - - return (java_handle_bytearray_t*)annotations; #else return NULL; #endif @@ -910,30 +914,26 @@ java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m) #if defined(ENABLE_ANNOTATIONS) classinfo *c; /* methods' declaring class */ int slot; /* methods' slot */ - java_handle_t *parameterAnnotations; /* methods' unparsed */ - /* parameter annotations */ java_handle_t *method_parameterannotations; /* all methods' unparsed */ /* parameter annotations of */ /* the declaring class */ - c = m->clazz; - slot = m - c->methods; - parameterAnnotations = NULL; + c = m->clazz; + slot = m - c->methods; LLNI_classinfo_field_get( c, method_parameterannotations, method_parameterannotations); + ObjectArray oa((java_handle_objectarray_t*) method_parameterannotations); + /* the method_annotations array might be shorter then the method * count if the methods above a certain index have no annotations. */ - if (method_parameterannotations != NULL && - array_length_get(method_parameterannotations) > slot) { - parameterAnnotations = array_objectarray_element_get( - (java_handle_objectarray_t*)method_parameterannotations, - slot); + if (method_parameterannotations != NULL && oa.get_length() > slot) { + return (java_handle_bytearray_t*) oa.get_element(slot); + } else { + return NULL; } - - return (java_handle_bytearray_t*)parameterAnnotations; #else return NULL; #endif @@ -959,29 +959,26 @@ java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m) #if defined(ENABLE_ANNOTATIONS) classinfo *c; /* methods' declaring class */ int slot; /* methods' slot */ - java_handle_t *annotationDefault; /* methods' unparsed */ - /* annotation default value */ java_handle_t *method_annotationdefaults; /* all methods' unparsed */ /* annotation default values of */ /* the declaring class */ - c = m->clazz; - slot = m - c->methods; - annotationDefault = NULL; + c = m->clazz; + slot = m - c->methods; LLNI_classinfo_field_get( c, method_annotationdefaults, method_annotationdefaults); + ObjectArray oa((java_handle_objectarray_t*) method_annotationdefaults); + /* the method_annotations array might be shorter then the method * count if the methods above a certain index have no annotations. - */ - if (method_annotationdefaults != NULL && - array_length_get(method_annotationdefaults) > slot) { - annotationDefault = array_objectarray_element_get( - (java_handle_objectarray_t*)method_annotationdefaults, slot); + */ + if (method_annotationdefaults != NULL && oa.get_length() > slot) { + return (java_handle_bytearray_t*) oa.get_element(slot); + } else { + return NULL; } - - return (java_handle_bytearray_t*)annotationDefault; #else return NULL; #endif diff --git a/src/vm/options.c b/src/vm/options.c index 7ead267c6..cc94d11cd 100644 --- a/src/vm/options.c +++ b/src/vm/options.c @@ -190,6 +190,7 @@ int opt_InlineMinSize = 0; #endif #endif int opt_PrintConfig = 0; +int opt_PrintWarnings = 0; int opt_ProfileGCMemoryUsage = 0; int opt_ProfileMemoryUsage = 0; FILE *opt_ProfileMemoryUsageGNUPlot = NULL; @@ -254,6 +255,7 @@ enum { OPT_InlineMaxSize, OPT_InlineMinSize, OPT_PrintConfig, + OPT_PrintWarnings, OPT_ProfileGCMemoryUsage, OPT_ProfileMemoryUsage, OPT_ProfileMemoryUsageGNUPlot, @@ -321,6 +323,7 @@ option_t options_XX[] = { #endif #endif { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" }, + { "PrintWarnings", OPT_PrintWarnings, OPT_TYPE_BOOLEAN, "print warnings about suspicious behavior"}, { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, is in seconds (default: 5)" }, { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" }, { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" }, @@ -735,6 +738,10 @@ void options_xx(JavaVMInitArgs *vm_args) opt_PrintConfig = enable; break; + case OPT_PrintWarnings: + opt_PrintWarnings = enable; + break; + case OPT_ProfileGCMemoryUsage: if (value == NULL) opt_ProfileGCMemoryUsage = 5; diff --git a/src/vm/options.h b/src/vm/options.h index 18c1c0013..a5b693270 100644 --- a/src/vm/options.h +++ b/src/vm/options.h @@ -212,6 +212,7 @@ extern int opt_InlineMinSize; #endif #endif extern int opt_PrintConfig; +extern int opt_PrintWarnings; extern int opt_ProfileGCMemoryUsage; extern int opt_ProfileMemoryUsage; extern FILE *opt_ProfileMemoryUsageGNUPlot; 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); diff --git a/src/vm/string.cpp b/src/vm/string.cpp index 632f69e04..45b4ad46e 100644 --- a/src/vm/string.cpp +++ b/src/vm/string.cpp @@ -93,7 +93,6 @@ bool string_init(void) void stringtable_update(void) { - java_chararray_t *a; literalstring *s; /* hashtable entry */ for (unsigned int i = 0; i < hashtable_string.size; i++) { @@ -109,7 +108,7 @@ void stringtable_update(void) os::abort("stringtable_update: invalid literalstring in hashtable"); } - a = LLNI_UNWRAP(js.get_value()); + java_chararray_t* a = (java_chararray_t*) js.get_value(); if (js.get_vftbl() == NULL) // FIXME @@ -150,23 +149,26 @@ static java_handle_t *javastring_new_from_utf_buffer(const char *buffer, u4 blen int32_t utflength = utf_get_number_of_u2s_for_buffer(buffer, blength); java_handle_t* h = builtin_new(class_java_lang_String); - java_handle_chararray_t* ca = builtin_newarray_char(utflength); + CharArray ca(utflength); /* javastring or character-array could not be created */ - if ((h == NULL) || (ca == NULL)) + if ((h == NULL) || ca.is_null()) return NULL; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + /* decompress utf-string */ utf_ptr = buffer; for (int32_t i = 0; i < utflength; i++) - LLNI_array_direct(ca, i) = utf_nextu2((char **) &utf_ptr); + ptr[i] = utf_nextu2((char **) &utf_ptr); /* set fields of the javastring-object */ - java_lang_String jls(h, ca, utflength); + java_lang_String jls(h, ca.get_handle(), utflength); return jls.get_handle(); } @@ -204,20 +206,23 @@ java_handle_t *javastring_safe_new_from_utf8(const char *text) /* allocate the String object and the char array */ java_handle_t* h = builtin_new(class_java_lang_String); - java_handle_chararray_t* ca = builtin_newarray_char(len); + CharArray ca(len); /* javastring or character-array could not be created? */ - if ((h == NULL) || (ca == NULL)) + if ((h == NULL) || ca.is_null()) return NULL; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + /* decompress UTF-8 string */ - utf8_safe_convert_to_u2s(text, nbytes, LLNI_array_data(ca)); + utf8_safe_convert_to_u2s(text, nbytes, ptr); /* set fields of the String object */ - java_lang_String jls(h, ca, len); + java_lang_String jls(h, ca.get_handle(), len); return jls.get_handle(); } @@ -266,21 +271,24 @@ java_handle_t *javastring_new(utf *u) int32_t utflength = utf_get_number_of_u2s(u); java_handle_t* h = builtin_new(class_java_lang_String); - java_handle_chararray_t* ca = builtin_newarray_char(utflength); + CharArray ca(utflength); /* javastring or character-array could not be created */ - if ((h == NULL) || (ca == NULL)) + if ((h == NULL) || ca.is_null()) return NULL; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + /* decompress utf-string */ for (int32_t i = 0; i < utflength; i++) - LLNI_array_direct(ca, i) = utf_nextu2(&utf_ptr); + ptr[i] = utf_nextu2(&utf_ptr); /* set fields of the javastring-object */ - java_lang_String jls(h, ca, utflength); + java_lang_String jls(h, ca.get_handle(), utflength); return jls.get_handle(); } @@ -306,12 +314,15 @@ java_handle_t *javastring_new_slash_to_dot(utf *u) int32_t utflength = utf_get_number_of_u2s(u); java_handle_t* h = builtin_new(class_java_lang_String); - java_handle_chararray_t* ca = builtin_newarray_char(utflength); + CharArray ca(utflength); /* javastring or character-array could not be created */ - if ((h == NULL) || (ca == NULL)) + if ((h == NULL) || ca.is_null()) return NULL; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + /* decompress utf-string */ for (int32_t i = 0; i < utflength; i++) { @@ -320,12 +331,12 @@ java_handle_t *javastring_new_slash_to_dot(utf *u) if (ch == '/') ch = '.'; - LLNI_array_direct(ca, i) = ch; + ptr[i] = ch; } /* set fields of the javastring-object */ - java_lang_String jls(h, ca, utflength); + java_lang_String jls(h, ca.get_handle(), utflength); return jls.get_handle(); } @@ -355,21 +366,24 @@ java_handle_t *javastring_new_from_ascii(const char *text) int32_t len = strlen(text); java_handle_t* h = builtin_new(class_java_lang_String); - java_handle_chararray_t* ca = builtin_newarray_char(len); + CharArray ca(len); /* javastring or character-array could not be created */ - if ((h == NULL) || (ca == NULL)) + if ((h == NULL) || ca.is_null()) return NULL; + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + /* copy text */ for (int32_t i = 0; i < len; i++) - LLNI_array_direct(ca, i) = text[i]; + ptr[i] = text[i]; /* set fields of the javastring-object */ - java_lang_String jls(h, ca, len); + java_lang_String jls(h, ca.get_handle(), len); return jls.get_handle(); } @@ -392,9 +406,9 @@ char* javastring_tochar(java_handle_t* h) if (jls.is_null()) return (char*) ""; - java_handle_chararray_t* ca = jls.get_value(); + CharArray ca(jls.get_value()); - if (ca == NULL) + if (ca.is_null()) return (char*) ""; int32_t count = jls.get_count(); @@ -402,9 +416,12 @@ char* javastring_tochar(java_handle_t* h) char* buf = MNEW(char, count + 1); + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + int32_t i; for (i = 0; i < count; i++) - buf[i] = LLNI_array_direct(ca, offset + i); + buf[i] = ptr[offset + i]; buf[i] = '\0'; @@ -425,15 +442,18 @@ utf *javastring_toutf(java_handle_t *string, bool isclassname) if (jls.is_null()) return utf_null; - java_handle_chararray_t* value = jls.get_value(); + CharArray ca(jls.get_value()); - if (jls.get_value() == NULL) + if (ca.is_null()) return utf_null; int32_t count = jls.get_count(); int32_t offset = jls.get_offset(); - return utf_new_u2(LLNI_array_data(value) + offset, count, isclassname); + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + + return utf_new_u2(ptr + offset, count, isclassname); } @@ -446,35 +466,41 @@ utf *javastring_toutf(java_handle_t *string, bool isclassname) *******************************************************************************/ -static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length, +static java_handle_t *literalstring_u2(java_handle_chararray_t *a, int32_t length, u4 offset, bool copymode) { - literalstring *s; /* hashtable element */ - java_chararray_t *ca; /* copy of u2-array */ - u4 key; - u4 slot; - u2 i; + literalstring *s; /* hashtable element */ + u4 key; + u4 slot; + u2 i; mutex->lock(); - /* find location in hashtable */ + // XXX: Fix me! + CharArray ca(a); + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + + /* find location in hashtable */ - key = unicode_hashkey(a->data + offset, length); - slot = key & (hashtable_string.size - 1); - s = (literalstring*) hashtable_string.ptr[slot]; + key = unicode_hashkey(ptr + offset, length); + slot = key & (hashtable_string.size - 1); + s = (literalstring*) hashtable_string.ptr[slot]; - while (s) { + while (s) { // FIXME java_lang_String js(LLNI_WRAP(s->string)); if (length == js.get_count()) { /* compare text */ - for (i = 0; i < length; i++) + for (i = 0; i < length; i++) { // FIXME This is not handle capable! + CharArray jsca(js.get_value()); + uint16_t* sptr = (uint16_t*) jsca.get_raw_data_ptr(); - if (a->data[offset + i] != ((java_chararray_t*) LLNI_UNWRAP(js.get_value()))->data[i]) + if (ptr[offset + i] != sptr[i]) goto nomatch; + } /* string already in hashtable, free memory */ @@ -483,38 +509,37 @@ static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length, mutex->unlock(); - return (java_object_t*) LLNI_UNWRAP(js.get_handle()); + return js.get_handle(); } nomatch: /* follow link in external hash chain */ s = s->hashlink; - } + } - if (copymode) { + java_chararray_t* acopy; + if (copymode) { /* create copy of u2-array for new javastring */ u4 arraysize = sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10; - ca = (java_chararray_t*) mem_alloc(arraysize); + acopy = (java_chararray_t*) mem_alloc(arraysize); /* memcpy(ca, a, arraysize); */ - memcpy(&(ca->header), &(a->header), sizeof(java_array_t)); - memcpy(&(ca->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10); - } + memcpy(&(acopy->header), &(((java_chararray_t*) a)->header), sizeof(java_array_t)); + memcpy(&(acopy->data), &(((java_chararray_t*) a)->data) + offset, sizeof(u2) * (length - 1) + 10); + } else { - ca = a; + acopy = (java_chararray_t*) a; } - /* location in hashtable found, complete arrayheader */ + /* location in hashtable found, complete arrayheader */ - ca->header.objheader.vftbl = Primitive::get_arrayclass_by_type(ARRAYTYPE_CHAR)->vftbl; - ca->header.size = length; + acopy->header.objheader.vftbl = Primitive::get_arrayclass_by_type(ARRAYTYPE_CHAR)->vftbl; + acopy->header.size = length; assert(class_java_lang_String); assert(class_java_lang_String->state & CLASS_LOADED); // Create a new java.lang.String object on the system heap. java_object_t* o = (java_object_t*) MNEW(uint8_t, class_java_lang_String->instancesize); - // FIXME - java_handle_t* h = LLNI_WRAP(o); #if defined(ENABLE_STATISTICS) if (opt_stat) @@ -527,8 +552,8 @@ static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length, o->vftbl = class_java_lang_String->vftbl; - // FIXME - java_lang_String jls(h, LLNI_WRAP(ca), length); + CharArray cacopy((java_handle_chararray_t*) acopy); + java_lang_String jls(o, cacopy.get_handle(), length); /* create new literalstring */ @@ -603,23 +628,23 @@ static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length, java_object_t *literalstring_new(utf *u) { - char *utf_ptr; /* pointer to current unicode character */ + char *utf_ptr; /* pointer to current unicode character */ /* utf string */ - u4 utflength; /* length of utf-string if uncompressed */ - java_chararray_t *a; /* u2-array constructed from utf string */ - u4 i; + u4 utflength; /* length of utf-string if uncompressed */ + java_chararray_t *a; /* u2-array constructed from utf string */ + u4 i; utf_ptr = u->text; utflength = utf_get_number_of_u2s(u); - /* allocate memory */ - a = (java_chararray_t*) mem_alloc(sizeof(java_chararray_t) + sizeof(u2) * (utflength - 1) + 10); + /* allocate memory */ + a = (java_chararray_t*) mem_alloc(sizeof(java_chararray_t) + sizeof(u2) * (utflength - 1) + 10); - /* convert utf-string to u2-array */ - for (i = 0; i < utflength; i++) + /* convert utf-string to u2-array */ + for (i = 0; i < utflength; i++) a->data[i] = utf_nextu2(&utf_ptr); - return literalstring_u2(a, utflength, 0, false); + return literalstring_u2((java_handle_chararray_t*) a, utflength, 0, false); } @@ -653,25 +678,20 @@ static void literalstring_free(java_object_t* string) Intern the given Java string. - XXX NOTE: Literal Strings are direct references since they are not placed - onto the GC-Heap. That's why this function looks so "different". - *******************************************************************************/ java_handle_t *javastring_intern(java_handle_t *string) { java_lang_String jls(string); - java_handle_chararray_t* value = jls.get_value(); - // FIXME - java_chararray_t* ca = LLNI_UNWRAP(value); /* XXX see note above */ + CharArray ca(jls.get_value()); int32_t count = jls.get_count(); int32_t offset = jls.get_offset(); - java_object_t* o = literalstring_u2(ca, count, offset, true); /* XXX see note above */ + java_handle_t* o = literalstring_u2(ca.get_handle(), count, offset, true); - return LLNI_WRAP(o); /* XXX see note above */ + return o; } @@ -685,13 +705,16 @@ void javastring_fprint(java_handle_t *s, FILE *stream) { java_lang_String jls(s); - java_handle_chararray_t* value = jls.get_value(); + CharArray ca(jls.get_value()); int32_t count = jls.get_count(); int32_t offset = jls.get_offset(); + // XXX: Fix me! + uint16_t* ptr = (uint16_t*) ca.get_raw_data_ptr(); + for (int32_t i = offset; i < offset + count; i++) { - uint16_t c = LLNI_array_direct(value, i); + uint16_t c = ptr[i]; fputc(c, stream); } } diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 8cbc0ed5c..1239da685 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -1577,21 +1577,8 @@ void VM::print_run_time_config() void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) { - char* option; - char* mainname; - char* p; - utf *mainutf; - classinfo *mainclass; - java_handle_t *e; - methodinfo *m; - java_handle_objectarray_t *oa; - s4 oalength; - utf *u; - java_handle_t *s; - int status; - - // Prevent compiler warnings. - oa = NULL; + methodinfo* m; + int status; #if !defined(NDEBUG) if (opt_CompileAll) { @@ -1600,9 +1587,9 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) } #endif - /* Get the main class plus it's arguments. */ + /* Get the main class or jar file argument. */ - mainname = NULL; + char* mainname = NULL; if (opt_index < vm_args->nOptions) { /* Get main-class argument. */ @@ -1613,7 +1600,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) classpath. */ if (opt_jar == true) { - p = MNEW(char, strlen(mainname) + strlen("0")); + char* p = MNEW(char, strlen(mainname) + strlen("0")); strcpy(p, mainname); @@ -1629,22 +1616,9 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) mainname[i] = '/'; } - /* Build argument array. Move index to first argument. */ + /* Move index to first argument. */ opt_index++; - - oalength = vm_args->nOptions - opt_index; - - oa = builtin_anewarray(oalength, class_java_lang_String); - - for (int i = 0; i < oalength; i++) { - option = vm_args->options[opt_index + i].optionString; - - u = utf_new_char(option); - s = javastring_new(u); - - array_objectarray_element_set(oa, i, s); - } } /* Do we have a main-class argument? */ @@ -1659,6 +1633,24 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) } #endif + /* Build argument array. */ + + int32_t oalength = vm_args->nOptions - opt_index; + + ObjectArray oa(oalength, class_java_lang_String); + + if (oa.is_null()) + vm_exit(1); + + for (int i = 0; i < oalength; i++) { + char* option = vm_args->options[opt_index + i].optionString; + + utf* u = utf_new_char(option); + java_handle_t* s = javastring_new(u); + + oa.set_element(i, s); + } + /* set return value to OK */ status = 0; @@ -1674,17 +1666,17 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) /* load the main class */ - mainutf = utf_new_char(mainname); + utf* mainutf = utf_new_char(mainname); #if defined(ENABLE_JAVAME_CLDC1_1) - mainclass = load_class_bootstrap(mainutf); + classinfo* mainclass = load_class_bootstrap(mainutf); #else - mainclass = load_class_from_sysloader(mainutf); + classinfo* mainclass = load_class_from_sysloader(mainutf); #endif /* error loading class */ - e = exceptions_get_and_clear_exception(); + java_handle_t* e = exceptions_get_and_clear_exception(); if ((e != NULL) || (mainclass == NULL)) { exceptions_throw_noclassdeffounderror_cause(e); @@ -1744,7 +1736,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args) /* start the main thread */ - (void) vm_call_method(m, NULL, oa); + (void) vm_call_method(m, NULL, oa.get_handle()); /* exception occurred? */ @@ -2019,7 +2011,11 @@ static char *vm_get_mainclass_from_jar(char *mainname) methodinfo *m; java_handle_t *s; +#if defined(ENABLE_JAVAME_CLDC1_1) + c = load_class_bootstrap(utf_new_char("java/util/jar/JarFile")); +#else c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile")); +#endif if (c == NULL) { exceptions_print_stacktrace(); diff --git a/tests/regression/bugzilla/All.java b/tests/regression/bugzilla/All.java index defe754e6..c7df40860 100644 --- a/tests/regression/bugzilla/All.java +++ b/tests/regression/bugzilla/All.java @@ -1,6 +1,6 @@ /* tests/regression/bugzilla/All.java - runs all CACAO regression unit tests - Copyright (C) 2008 + Copyright (C) 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO This file is part of CACAO. @@ -39,7 +39,8 @@ PR112.class, PR113.class, PR114.class, PR116.class, -PR119.class +PR119.class, +PR125.class }) public class All { diff --git a/tests/regression/bugzilla/PR125.java b/tests/regression/bugzilla/PR125.java new file mode 100644 index 000000000..92a646f50 --- /dev/null +++ b/tests/regression/bugzilla/PR125.java @@ -0,0 +1,84 @@ +/* tests/regression/bugzilla/PR125.java + + Copyright (C) 2009 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + + +import org.junit.Test; +import static org.junit.Assert.*; + +import java.lang.reflect.Field; + +public class PR125 extends ClassLoader { + @Test + public void test() throws NoSuchFieldException, IllegalAccessException { + Class cls = super.defineClass(null, bytecode, 0, bytecode.length); + Field fld = cls.getDeclaredField("val"); + assertEquals(42, fld.getInt(null)); + } + + /* + * The following Bytecode was derived from a class like this: + * public class Foo { + * public static int val = 42; + * } + * + * The access_flags of the were modified by hand to + * not contain the ACC_STATIC flag. + */ + static byte[] bytecode = { + (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x31, + (byte)0x00, (byte)0x12, (byte)0x0a, (byte)0x00, (byte)0x04, (byte)0x00, (byte)0x0e, (byte)0x09, + (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x0f, (byte)0x07, (byte)0x00, (byte)0x10, (byte)0x07, + (byte)0x00, (byte)0x11, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x76, (byte)0x61, (byte)0x6c, + (byte)0x01, (byte)0x00, (byte)0x01, (byte)0x49, (byte)0x01, (byte)0x00, (byte)0x06, (byte)0x3c, + (byte)0x69, (byte)0x6e, (byte)0x69, (byte)0x74, (byte)0x3e, (byte)0x01, (byte)0x00, (byte)0x03, + (byte)0x28, (byte)0x29, (byte)0x56, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x43, (byte)0x6f, + (byte)0x64, (byte)0x65, (byte)0x01, (byte)0x00, (byte)0x0f, (byte)0x4c, (byte)0x69, (byte)0x6e, + (byte)0x65, (byte)0x4e, (byte)0x75, (byte)0x6d, (byte)0x62, (byte)0x65, (byte)0x72, (byte)0x54, + (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x01, (byte)0x00, (byte)0x08, (byte)0x3c, + (byte)0x63, (byte)0x6c, (byte)0x69, (byte)0x6e, (byte)0x69, (byte)0x74, (byte)0x3e, (byte)0x01, + (byte)0x00, (byte)0x0a, (byte)0x53, (byte)0x6f, (byte)0x75, (byte)0x72, (byte)0x63, (byte)0x65, + (byte)0x46, (byte)0x69, (byte)0x6c, (byte)0x65, (byte)0x01, (byte)0x00, (byte)0x08, (byte)0x46, + (byte)0x6f, (byte)0x6f, (byte)0x2e, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x0c, + (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x08, (byte)0x0c, (byte)0x00, (byte)0x05, (byte)0x00, + (byte)0x06, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x46, (byte)0x6f, (byte)0x6f, (byte)0x01, + (byte)0x00, (byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, + (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x4f, (byte)0x62, (byte)0x6a, (byte)0x65, + (byte)0x63, (byte)0x74, (byte)0x00, (byte)0x21, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x04, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, (byte)0x00, (byte)0x05, + (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1d, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x2a, (byte)0xb7, (byte)0x00, (byte)0x01, + (byte)0xb1, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x0a, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x00, (byte)/*0x08*/0x00, (byte)0x00, (byte)0x0b, (byte)0x00, (byte)0x08, (byte)0x00, + (byte)0x01, (byte)0x00, (byte)0x09, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1e, (byte)0x00, + (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x10, + (byte)0x2a, (byte)0xb3, (byte)0x00, (byte)0x02, (byte)0xb1, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x01, (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x00, + (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x01, (byte)0x00, + (byte)0x0c, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x0d, + }; +} +