* src/native/vm/sun/jvm.c (JVM_GetManagement): Implemented (only
[cacao.git] / src / native / vm / sun / jvm.c
index d2d9d3352bc11325f715e367669486ec89cbfd45..c40b089f8af9461a8bf4c29e7543fac6925dec76 100644 (file)
 #include "threads/threads-common.h"
 
 #include "toolbox/logging.h"
+#include "toolbox/list.h"
 
 #include "vm/array.h"
+
+#if defined(ENABLE_ASSERTION)
+#include "vm/assertion.h"
+#endif
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
@@ -385,18 +391,16 @@ void JVM_FillInStackTrace(JNIEnv *env, jobject receiver)
        java_lang_Throwable     *o;
        java_handle_bytearray_t *ba;
 
-#if PRINTJVM
-       log_println("JVM_FillInStackTrace: receiver=%p", receiver);
-#endif
+       TRACEJVMCALLS("JVM_FillInStackTrace(env=%p, receiver=%p)", env, receiver);
 
        o = (java_lang_Throwable *) receiver;
 
-       ba = stacktrace_fillInStackTrace();
+       ba = stacktrace_get();
 
        if (ba == NULL)
                return;
 
-       o->backtrace = (java_lang_Object *) ba;
+       LLNI_field_set_ref(o, backtrace, ba);
 }
 
 
@@ -412,9 +416,10 @@ void JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)
 
 jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
 {
-       java_lang_Throwable     *o;
+       java_lang_Throwable     *t;
        java_handle_bytearray_t *ba;
-       stacktracebuffer        *stb;
+       stacktrace_t            *st;
+       int32_t                  depth;
 
        TRACEJVMCALLS("JVM_GetStackTraceDepth(env=%p, throwable=%p)", env, throwable);
 
@@ -423,15 +428,25 @@ jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
                return 0;
        }
 
-       o   = (java_lang_Throwable *) throwable;
-       ba  = (java_handle_bytearray_t *) o->backtrace;
+       t = (java_lang_Throwable *) throwable;
+
+       LLNI_field_get_ref(t, backtrace, ba);
 
        if (ba == NULL)
                return 0;
 
-       stb = (stacktracebuffer *) LLNI_array_data(ba);
+       /* We need a critical section here as the stacktrace structure is
+          mapped onto a Java byte-array. */
+
+       LLNI_CRITICAL_START;
+
+       st = (stacktrace_t *) LLNI_array_data(ba);
+
+       depth = st->length;
+
+       LLNI_CRITICAL_END;
 
-       return stb->used;
+       return depth;
 }
 
 
@@ -439,24 +454,29 @@ jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
 
 jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 {
-       java_lang_Throwable *t;
+       java_lang_Throwable         *t;
        java_handle_bytearray_t     *ba;
-       stacktracebuffer            *stb;
-       stacktrace_entry            *ste;
+       stacktrace_t                *st;
+       stacktrace_entry_t          *ste;
+       codeinfo                    *code;
+       methodinfo                  *m;
+       classinfo                   *c;
        java_lang_StackTraceElement *o;
        java_lang_String            *declaringclass;
        java_lang_String            *filename;
-       s4                           linenumber;
+       int32_t                      linenumber;
 
-#if PRINTJVM
-       log_println("JVM_GetStackTraceElement: throwable=%p, index=%d", throwable, index);
-#endif
+       TRACEJVMCALLS("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index);
+
+       t = (java_lang_Throwable *) throwable;
 
-       t   = (java_lang_Throwable *) throwable;
-       ba  = (java_handle_bytearray_t *) t->backtrace;
-       stb = (stacktracebuffer *) LLNI_array_data(ba);
+       LLNI_field_get_ref(t, backtrace, ba);
 
-       if ((index < 0) || (index >= stb->used)) {
+       /* FIXME critical section */
+
+       st = (stacktrace_t *) LLNI_array_data(ba);
+
+       if ((index < 0) || (index >= st->length)) {
                /* XXX This should be an IndexOutOfBoundsException (check this
                   again). */
 
@@ -464,7 +484,15 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
                return NULL;
        }
 
-       ste = &(stb->entries[index]);
+       /* Get the stacktrace entry. */
+
+       ste = &(st->entries[index]);
+
+       /* Get the codeinfo, methodinfo and classinfo. */
+
+       code = ste->code;
+       m    = code->m;
+       c    = m->class;
 
        /* allocate a new StackTraceElement */
 
@@ -476,9 +504,9 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 
        /* get filename */
 
-       if (!(ste->method->flags & ACC_NATIVE)) {
-               if (ste->method->class->sourcefile)
-                       filename = (java_lang_String *) javastring_new(ste->method->class->sourcefile);
+       if (!(m->flags & ACC_NATIVE)) {
+               if (c->sourcefile != NULL)
+                       filename = (java_lang_String *) javastring_new(c->sourcefile);
                else
                        filename = NULL;
        }
@@ -487,20 +515,27 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 
        /* get line number */
 
-       if (ste->method->flags & ACC_NATIVE)
+       if (m->flags & ACC_NATIVE) {
                linenumber = -2;
-       else
-               linenumber = (ste->linenumber == 0) ? -1 : ste->linenumber;
+       }
+       else {
+               /* FIXME The linenumbertable_linenumber_for_pc could change
+                  the methodinfo pointer when hitting an inlined method. */
+
+               linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+               linenumber = (linenumber == 0) ? -1 : linenumber;
+       }
 
        /* get declaring class name */
 
-       declaringclass =
-               _Jv_java_lang_Class_getName(LLNI_classinfo_wrap(ste->method->class));
+       declaringclass = _Jv_java_lang_Class_getName(LLNI_classinfo_wrap(c));
 
        /* fill the java.lang.StackTraceElement element */
 
+       /* FIXME critical section */
+
        o->declaringClass = declaringclass;
-       o->methodName     = (java_lang_String *) javastring_new(ste->method->name);
+       o->methodName     = (java_lang_String *) javastring_new(m->name);
        o->fileName       = filename;
        o->lineNumber     = linenumber;
 
@@ -512,9 +547,8 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 
 jint JVM_IHashCode(JNIEnv* env, jobject handle)
 {
-#if PRINTJVM
-       log_println("JVM_IHashCode: jobject=%p", handle);
-#endif
+       TRACEJVMCALLS("JVM_IHashCode(env=%p, jobject=%p)", env, handle);
+
        return (jint) ((ptrint) handle);
 }
 
@@ -1643,11 +1677,42 @@ jstring JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, j
 
 jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
 {
+#if defined(ENABLE_ASSERTION)
+       assertion_name_t  *item;
+       classinfo         *c;
+       jboolean           status;
+       utf               *name;
+
        TRACEJVMCALLS("JVM_DesiredAssertionStatus(env=%p, unused=%p, cls=%p)", env, unused, cls);
 
-       /* TODO: Implement this one, but false should be OK. */
+       c = LLNI_classinfo_unwrap(cls);
 
-       return false;
+       if (c->classloader == NULL) {
+               status = (jboolean)assertion_system_enabled;
+       }
+       else {
+               status = (jboolean)assertion_user_enabled;
+       }
+
+       if (list_assertion_names != NULL) {
+               item = (assertion_name_t *)list_first(list_assertion_names);
+               while (item != NULL) {
+                       name = utf_new_char(item->name);
+                       if (name == c->packagename) {
+                               status = (jboolean)item->enabled;
+                       }
+                       else if (name == c->name) {
+                               status = (jboolean)item->enabled;
+                       }
+
+                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+               }
+       }
+
+       return status;
+#else
+       return (jboolean)false;
+#endif
 }
 
 
@@ -1655,14 +1720,19 @@ jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
 
 jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
 {
-       classinfo                           *c;
-       java_lang_AssertionStatusDirectives *o;
-       java_handle_objectarray_t           *classes;
-       java_handle_objectarray_t           *packages;
-
-       TRACEJVMCALLS("JVM_AssertionStatusDirectives(env=%p, unused=%p): COMPLETE ME!", env, unused);
+       classinfo                             *c;
+       java_lang_AssertionStatusDirectives   *o;
+       java_handle_objectarray_t             *classes;
+       java_handle_objectarray_t             *packages;
+       java_booleanarray_t                   *classEnabled;
+       java_booleanarray_t                   *packageEnabled;
+#if defined(ENABLE_ASSERTION)
+       assertion_name_t                      *item;
+       java_handle_t                         *js;
+       s4                                     i, j;
+#endif
 
-       /* XXX this is not completely implemented */
+       TRACEJVMCALLS("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused);
 
        c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
 
@@ -1674,20 +1744,74 @@ jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
        if (o == NULL)
                return NULL;
 
+#if defined(ENABLE_ASSERTION)
+       classes = builtin_anewarray(assertion_class_count, class_java_lang_Object);
+#else
        classes = builtin_anewarray(0, class_java_lang_Object);
-
+#endif
        if (classes == NULL)
                return NULL;
 
+#if defined(ENABLE_ASSERTION)
+       packages = builtin_anewarray(assertion_package_count, class_java_lang_Object);
+#else
        packages = builtin_anewarray(0, class_java_lang_Object);
-
+#endif
        if (packages == NULL)
                return NULL;
+       
+#if defined(ENABLE_ASSERTION)
+       classEnabled = builtin_newarray_boolean(assertion_class_count);
+#else
+       classEnabled = builtin_newarray_boolean(0);
+#endif
+       if (classEnabled == NULL)
+               return NULL;
+
+#if defined(ENABLE_ASSERTION)
+       packageEnabled = builtin_newarray_boolean(assertion_package_count);
+#else
+       packageEnabled = builtin_newarray_boolean(0);
+#endif
+       if (packageEnabled == NULL)
+               return NULL;
+
+#if defined(ENABLE_ASSERTION)
+       /* initialize arrays */
+
+       if (list_assertion_names != NULL) {
+               i = 0;
+               j = 0;
+               
+               item = (assertion_name_t *)list_first(list_assertion_names);
+               while (item != NULL) {
+                       js = javastring_new_from_ascii(item->name);
+                       if (js == NULL) {
+                               return NULL;
+                       }
+
+                       if (item->package == false) {
+                               classes->data[i] = js;
+                               classEnabled->data[i] = (jboolean) item->enabled;
+                               i += 1;
+                       }
+                       else {
+                               packages->data[j] = js;
+                               packageEnabled->data[j] = (jboolean) item->enabled;
+                               j += 1;
+                       }
+
+                       item = (assertion_name_t *)list_next(list_assertion_names, item);
+               }
+       }
+#endif
 
        /* set instance fields */
 
        o->classes  = classes;
        o->packages = packages;
+       o->classEnabled = classEnabled;
+       o->packageEnabled = packageEnabled;
 
        return (jobject) o;
 }
@@ -2310,7 +2434,13 @@ jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint le
 
 jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
 {
-       log_println("JVM_LatestUserDefinedLoader: IMPLEMENT ME!");
+       classloader *cl;
+
+       TRACEJVMCALLS("JVM_LatestUserDefinedLoader(env=%p)", env);
+
+       cl = stacktrace_first_nonnull_classloader();
+
+       return (jobject) cl;
 }
 
 
@@ -2708,7 +2838,9 @@ void *JVM_LoadLibrary(const char *name)
 
 void JVM_UnloadLibrary(void* handle)
 {
-       log_println("JVM_UnloadLibrary: IMPLEMENT ME!");
+       TRACEJVMCALLS("JVM_UnloadLibrary(handle=%p)", handle);
+
+       native_library_close(handle);
 }
 
 
@@ -2995,9 +3127,13 @@ jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threa
 
 /* JVM_GetManagement */
 
-voidJVM_GetManagement(jint version)
+void *JVM_GetManagement(jint version)
 {
-       log_println("JVM_GetManagement: IMPLEMENT ME!");
+       TRACEJVMCALLS("JVM_GetManagement(version=%d)", version);
+
+       /* TODO We current don't support the management interface. */
+
+       return NULL;
 }
 
 
@@ -3013,7 +3149,32 @@ jobject JVM_InitAgentProperties(JNIEnv *env, jobject properties)
 
 jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)
 {
-       log_println("JVM_GetEnclosingMethodInfo: IMPLEMENT ME!");
+       classinfo                 *c;
+       methodinfo                *m;
+       java_handle_objectarray_t *oa;
+
+       TRACEJVMCALLS("JVM_GetEnclosingMethodInfo(env=%p, ofClass=%p)", env, ofClass);
+
+       c = LLNI_classinfo_unwrap(ofClass);
+
+       if ((c == NULL) || class_is_primitive(c))
+               return NULL;
+
+       m = class_get_enclosingmethod(c);
+
+       if (m == NULL)
+               return NULL;
+
+       oa = builtin_anewarray(3, class_java_lang_Object);
+
+       if (oa == NULL)
+               return NULL;
+
+       array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->class));
+       array_objectarray_element_set(oa, 1, javastring_new(m->name));
+       array_objectarray_element_set(oa, 2, javastring_new(m->descriptor));
+
+       return (jobjectArray) oa;
 }