Next save, with linking started.
[cacao.git] / jni.c
diff --git a/jni.c b/jni.c
index fe9e3defc2cba77a40f0440e8143bf2eb0d32c83..265a28a8c9c01c4ec6ba15b9347703c461285667 100644 (file)
--- a/jni.c
+++ b/jni.c
@@ -3,7 +3,7 @@
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   P. Tomsich, J. Wenninger, M. Platter
 
    This file is part of CACAO.
 
 
    Authors: ?
 
-   Changes: Joseph Wenninger
+   Changes: Joseph Wenninger, Martin Platter
 
-   $Id: jni.c 1005 2004-03-30 23:01:45Z twisti $
+   $Id: jni.c 1384 2004-08-02 11:41:26Z motse $
 
 */
 
 
 #include <string.h>
+#include "exceptions.h"
+#include "main.h"
 #include "jni.h"
 #include "global.h"
 #include "loader.h"
 #include "tables.h"
 #include "native.h"
 #include "builtin.h"
+#include "options.h"
+#include "statistics.h"
 #include "threads/thread.h"
-#include "toolbox/loging.h"
+#include "toolbox/logging.h"
 #include "toolbox/memory.h"
 #include "nat/java_lang_Byte.h"
 #include "nat/java_lang_Character.h"
@@ -505,6 +509,7 @@ jmethodID get_virtual(jobject obj,jmethodID methodID) {
 
 jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) {
        if (clazz==methodID->class) return methodID;
+/*class_resolvemethod -> classfindmethod? (JOWENN)*/
        return class_resolvemethod (clazz, methodID->name, methodID->descriptor);
 }
 
@@ -544,7 +549,7 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args)
        }
 
        if (argcount > 3) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
@@ -605,7 +610,7 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar
 
 
        if (argcount > 3) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallIntegerMethod does not support that");
                return 0;
        }
@@ -634,14 +639,14 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
        jni_callblock *blk;
        jlong ret;
 
-       /*
+/*     
         log_text("JNI-Call: CallObjectMethodV");
         utf_display(methodID->name);
         utf_display(methodID->descriptor);
         printf("\nParmaeter count: %d\n",argcount);
         utf_display(obj->vftbl->class->name);
         printf("\n");
-        */
+*/      
        if (methodID == 0) {
                *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); 
                return 0;
@@ -662,14 +667,14 @@ jlong callLongMethod(jobject obj, jmethodID methodID, va_list args)
 
 
        if (argcount > 3) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
 
        blk = MNEW(jni_callblock, 4 /*argcount+2*/);
 
-       fill_callblock(obj, methodID->descriptor, blk, args, 'L');
+       fill_callblock(obj, methodID->descriptor, blk, args, 'J');
 
        /*      printf("parameter: obj: %p",blk[0].item); */
        ret = asm_calljavafunction2long(methodID,
@@ -701,7 +706,7 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy
         */
 
        if (argcount > 3) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. CallObjectMethod does not support that");
                return 0;
        }
@@ -756,20 +761,70 @@ jint GetVersion (JNIEnv* env)
        return JNI_VERSION;
 }
 
+
 /****************** loads a class from a buffer of raw class data *****************/
 
 jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) 
 {
-        jclass clazz; 
+       jclass clazz; 
+       classbuffer *cb;
+       s8 starttime;
+       s8 stoptime;
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       compiler_lock();
+       tables_lock();
+#else
+       intsDisable();
+#endif
+#endif
+
+       /* measure time */
+       if (getloadingtime)
+               starttime = getcputime();
+
+       clazz = class_new(utf_new_char((char *) name));
 
-       /* change suck-mode, so subsequent class_load will read from memory-buffer */
-       classload_buffer( (u1*) buf,len);
+       /* build a classbuffer with the given data */
+       cb = NEW(classbuffer);
+       cb->class = clazz;
+       cb->size = len;
+       cb->data = (u1 *) buf;
+       cb->pos = cb->data - 1;
 
-        clazz = loader_load(utf_new_char ((char *) name));
+       class_load_intern(cb);
+
+       /* free memory */
+       FREE(cb, classbuffer);
+
+       /* measure time */
+       if (getloadingtime) {
+               stoptime = getcputime();
+               loadingtime += (stoptime - starttime);
+       }
+
+#if defined(USE_THREADS)
+#if defined(NATIVE_THREADS)
+       tables_unlock();
+       compiler_unlock();
+#else
+       intsRestore();
+#endif
+#endif
+
+       if (*exceptionptr)
+               return NULL;
+
+       /* XXX link the class here? */
+       class_link(clazz);
+
+       if (*exceptionptr)
+               return NULL;
+
+       if (clazz)
+               clazz->classloader = loader;
 
-       /* restore old suck-mode */
-       classload_buffer(NULL,0);
-       if (clazz) clazz->classloader=loader;
        return clazz;
 }
 
@@ -780,14 +835,17 @@ jclass FindClass(JNIEnv* env, const char *name)
 {
        classinfo *c;  
   
-/*     if (strcmp(name,"[B")==0) {
-               c = loader_load(utf_new_char("The_Array_Class"));
-       }
-       else*/
-               c = loader_load(utf_new_char_classname((char *) name));
+       c = class_new(utf_new_char_classname((char *) name));
+
+       class_load(c);
+
+       if (*exceptionptr)
+               return NULL;
+
+       class_link(c);
 
-       if (!c)
-               *exceptionptr = new_exception(string_java_lang_ClassFormatError);
+       if (*exceptionptr)
+               return NULL;
 
        return c;
 }
@@ -1002,8 +1060,8 @@ jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...)
 
        /* log_text("JNI-Call: NewObject"); */
 
-       if  (argcount>3) {
-               *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+       if (argcount > 3) {
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. NewObject does not support that");
                return 0;
        }
@@ -1112,8 +1170,11 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *s
                utf_new_char ((char*) sig)
        );
 
-       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);      
-
+       if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       else if (m->flags & ACC_STATIC)   {
+               m=0;
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       }
        return m;
 }
 
@@ -1297,17 +1358,20 @@ jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args)
 
 jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallLongMethod");
+       jlong ret;
+       va_list vaargs;
+       
+       va_start(vaargs,methodID);
+       ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs);
+       va_end(vaargs);
 
-       return 0;
+       return ret;
 }
 
 
 jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallLongMethodV");
-
-       return 0;
+       return  callLongMethod(obj,get_virtual(obj, methodID),args);
 }
 
 
@@ -1858,6 +1922,10 @@ jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const c
                                                        utf_new_char((char *) sig));
 
        if (!m) *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       else if (!(m->flags & ACC_STATIC))   {
+               m=0;
+               *exceptionptr = new_exception(string_java_lang_NoSuchMethodError);
+       }
 
        return m;
 }
@@ -1865,17 +1933,24 @@ jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const c
 
 jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
 {
-       log_text("JNI-Call: CallStaticObjectMethod");
+       jobject ret;
+       va_list vaargs;
 
-       return NULL;
+       /* log_text("JNI-Call: CallStaticObjectMethod");*/
+
+       va_start(vaargs, methodID);
+       ret = callObjectMethod(0, methodID, vaargs);
+       va_end(vaargs);
+
+       return ret;
 }
 
 
 jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)
 {
-       log_text("JNI-Call: CallStaticObjectMethodV");
-
-       return NULL;
+       /* log_text("JNI-Call: CallStaticObjectMethodV"); */
+       
+       return callObjectMethod(0,methodID,args);
 }
 
 
@@ -1892,8 +1967,6 @@ jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID,
        jboolean ret;
        va_list vaargs;
 
-       /*      log_text("JNI-Call: CallStaticBooleanMethod");*/
-
        va_start(vaargs, methodID);
        ret = (jboolean) callIntegerMethod(0, methodID, 'Z', vaargs);
        va_end(vaargs);
@@ -2453,9 +2526,6 @@ jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init)
 
     j = builtin_anewarray(len, clazz);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2501,9 +2571,6 @@ jbooleanArray NewBooleanArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_boolean(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2519,9 +2586,6 @@ jbyteArray NewByteArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_byte(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2537,9 +2601,6 @@ jcharArray NewCharArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_char(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2555,9 +2616,6 @@ jshortArray NewShortArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_short(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2573,9 +2631,6 @@ jintArray NewIntArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_int(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2591,9 +2646,6 @@ jlongArray NewLongArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_long(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2609,9 +2661,6 @@ jfloatArray NewFloatArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_float(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -2627,9 +2676,6 @@ jdoubleArray NewDoubleArray(JNIEnv *env, jsize len)
 
     j = builtin_newarray_double(len);
 
-    if (!j)
-               *exceptionptr = new_exception(string_java_lang_OutOfMemoryError);
-
     return j;
 }
 
@@ -3334,28 +3380,28 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        argcount = get_parametercount(methodID);
 
        if (obj && (!builtin_instanceof((java_objectheader *) obj, methodID->class))) {
-               (*env)->ThrowNew(env, loader_load(utf_new_char("java/lang/IllegalArgumentException")),
-                                                "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
+               *exceptionptr = new_exception_message(string_java_lang_IllegalArgumentException,
+                                                                                         "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative");
                return 0;
        }
 
 
 
        if (argcount > 3) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                log_text("Too many arguments. invokeNativeHelper does not support that");
                return 0;
        }
 
        if (((!params) && (argcount != 0)) || (params && (params->header.size != argcount))) {
-               *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException")));
+               *exceptionptr = new_exception(string_java_lang_IllegalArgumentException);
                return 0;
        }
 
 
        if (!(methodID->flags & ACC_STATIC) && (!obj))  {
-               (*env)->ThrowNew(env, loader_load(utf_new_char("java/lang/NullPointerException")),
-                                                "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
+               *exceptionptr = new_exception_message(string_java_lang_NullPointerException,
+                                                                                         "Static mismatch in Java_java_lang_reflect_Method_invokeNative");
                return 0;
        }
 
@@ -3380,8 +3426,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Integer")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Integer")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3397,8 +3442,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Byte")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Byte")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3414,8 +3458,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Character")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Character")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3431,8 +3474,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Short")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Short")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3448,8 +3490,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                        argcount + 1,
                                                                                        (argcount + 1) * sizeof(jni_callblock),
                                                                                        blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Boolean")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Boolean")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3465,8 +3506,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                   argcount + 1,
                                                                                   (argcount + 1) * sizeof(jni_callblock),
                                                                                   blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Long")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Long")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3482,8 +3522,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                           argcount + 1,
                                                                                           (argcount + 1) * sizeof(jni_callblock),
                                                                                           blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Float")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Float")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3499,8 +3538,7 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
                                                                                           argcount + 1,
                                                                                           (argcount + 1) * sizeof(jni_callblock),
                                                                                           blk);
-               retVal = builtin_new(loader_load_sysclass(NULL,
-                                                                                                 utf_new_char("java/lang/Double")));
+               retVal = builtin_new(class_new(utf_new_char("java/lang/Double")));
                CallVoidMethod(env,
                                           retVal,
                                           class_resolvemethod(retVal->vftbl->class,
@@ -3527,13 +3565,12 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID,
        MFREE(blk, jni_callblock, 4 /*argcount+2*/);
 
        if (*exceptionptr) {
-               java_objectheader *exceptionToWrap=*exceptionptr;
+               java_objectheader *exceptionToWrap = *exceptionptr;
                classinfo *ivtec;
                java_objectheader *ivte;
 
-               *exceptionptr=0;
-               ivtec = loader_load_sysclass(NULL,
-                                                                                               utf_new_char("java/lang/reflect/InvocationTargetException"));
+               *exceptionptr = NULL;
+               ivtec = class_new(utf_new_char("java/lang/reflect/InvocationTargetException"));
                ivte = builtin_new(ivtec);
                asm_calljavafunction(class_resolvemethod(ivtec,
                                                                                                 utf_new_char("<init>"),