Merged with tip.
[cacao.git] / src / native / vm / sun / jvm.c
index af73be21aad5e40939fa48ca83bc51dc2190b62b..18c4df92ac885a0aad5cde820ab4ca9ba0cfa388 100644 (file)
 #include "native/include/sun_reflect_ConstantPool.h"
 #endif
 
-#include "native/vm/java_lang_Class.h"
-#include "native/vm/java_lang_reflect_Constructor.h"
-#include "native/vm/java_lang_reflect_Method.h"
 #include "native/vm/reflect.h"
 
+#include "native/vm/sun/hpi.h"
+
 #include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
 
 #include "toolbox/logging.h"
 #include "toolbox/list.h"
         }                                                                                                              \
     } while (0)
 
+# define TRACEJVMCALLSENTER(x)                                                                 \
+    do {                                                                                                               \
+        if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) {   \
+                       log_start();                                                                            \
+            log_print x;                                                                               \
+        }                                                                                                              \
+    } while (0)
+
+# define TRACEJVMCALLSEXIT(x)                                                                  \
+    do {                                                                                                               \
+        if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) {   \
+                       log_print x;                                                                            \
+                       log_finish();                                                                           \
+        }                                                                                                              \
+    } while (0)
+
 # define TRACEJVMCALLSVERBOSE(x)                               \
     do {                                                                               \
         if (opt_TraceJVMCallsVerbose) {                        \
 #else
 
 # define TRACEJVMCALLS(x)
+# define TRACEJVMCALLSENTER(x)
+# define TRACEJVMCALLSEXIT(x)
 # define TRACEJVMCALLSVERBOSE(x)
 # define PRINTJVMWARNINGS(x)
 
@@ -265,11 +282,22 @@ void JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, jobje
 jobject JVM_InitProperties(JNIEnv *env, jobject properties)
 {
        java_handle_t *h;
+       char           buf[256];
 
        TRACEJVMCALLS(("JVM_InitProperties(env=%p, properties=%p)", env, properties));
 
        h = (java_handle_t *) properties;
 
+       /* Convert the -XX:MaxDirectMemorySize= command line flag to the
+          sun.nio.MaxDirectMemorySize property.  Do this after setting
+          user properties to prevent people from setting the value with a
+          -D option, as requested. */
+
+       jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
+       properties_add("sun.nio.MaxDirectMemorySize", buf);
+
+       /* Add all properties. */
+
        properties_system_add_all(h);
 
        return properties;
@@ -461,7 +489,7 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
        methodinfo                  *m;
        classinfo                   *c;
        java_lang_StackTraceElement *steo;
-       java_lang_String            *declaringclass;
+       java_handle_t*               declaringclass;
        java_lang_String            *filename;
        int32_t                      linenumber;
 
@@ -493,7 +521,7 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 
        code = ste->code;
        m    = code->m;
-       c    = m->class;
+       c    = m->clazz;
 
        /* allocate a new StackTraceElement */
 
@@ -529,14 +557,14 @@ jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
 
        /* get declaring class name */
 
-       declaringclass = _Jv_java_lang_Class_getName(LLNI_classinfo_wrap(c));
+       declaringclass = class_get_classname(c);
 
        /* fill the java.lang.StackTraceElement element */
 
        /* FIXME critical section */
 
-       steo->declaringClass = declaringclass;
-       steo->methodName     = (java_lang_String *) javastring_new(m->name);
+       steo->declaringClass = (java_lang_String*) declaringclass;
+       steo->methodName     = (java_lang_String*) javastring_new(m->name);
        steo->fileName       = filename;
        steo->lineNumber     = linenumber;
 
@@ -693,25 +721,9 @@ void JVM_DisableCompiler(JNIEnv *env, jclass compCls)
 
 jint JVM_GetLastErrorString(char *buf, int len)
 {
-       const char *s;
-       int n;
+       TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
 
-    if (errno == 0) {
-               return 0;
-    }
-       else {
-               s = strerror(errno);
-               n = strlen(s);
-
-               if (n >= len)
-                       n = len - 1;
-
-               strncpy(buf, s, n);
-
-               buf[n] = '\0';
-
-               return n;
-    }
+       return hpi_system->GetLastErrorString(buf, len);
 }
 
 
@@ -721,9 +733,7 @@ char *JVM_NativePath(char *path)
 {
        TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
 
-       /* XXX is this correct? */
-
-       return path;
+       return hpi_file->NativePath(path);
 }
 
 
@@ -770,12 +780,17 @@ void JVM_ResolveClass(JNIEnv* env, jclass cls)
 
 jclass JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)
 {
-       classinfo   *c;
-       utf         *u;
-       classloader *cl;
+       classinfo     *c;
+       utf           *u;
+       classloader_t *cl;
 
        TRACEJVMCALLS(("JVM_FindClassFromClassLoader(name=%s, init=%d, loader=%p, throwError=%d)", name, init, loader, throwError));
 
+       /* As of now, OpenJDK does not call this function with throwError
+          is true. */
+
+       assert(throwError == false);
+
        u  = utf_new_char(name);
        cl = loader_hashtable_classloader_add((java_handle_t *) loader);
 
@@ -817,9 +832,9 @@ jclass JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyt
 
 jclass JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)
 {
-       classinfo   *c;
-       utf         *u;
-       classloader *cl;
+       classinfo     *c;
+       utf           *u;
+       classloader_t *cl;
 
        TRACEJVMCALLS(("JVM_DefineClassWithSource(env=%p, name=%s, loader=%p, buf=%p, len=%d, pd=%p, source=%s)", env, name, loader, buf, len, pd, source));
 
@@ -842,9 +857,9 @@ jclass JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
 
 jclass JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
 {
-       classloader *cl;
-       utf         *u;
-       classinfo   *c;
+       classloader_t *cl;
+       utf           *u;
+       classinfo     *c;
 
        TRACEJVMCALLS(("JVM_FindLoadedClass(env=%p, loader=%p, name=%p)", env, loader, name));
 
@@ -861,9 +876,13 @@ jclass JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
 
 jstring JVM_GetClassName(JNIEnv *env, jclass cls)
 {
+       classinfo* c;
+
        TRACEJVMCALLS(("JVM_GetClassName(env=%p, cls=%p)", env, cls));
 
-       return (jstring) _Jv_java_lang_Class_getName((java_lang_Class *) cls);
+       c = LLNI_classinfo_unwrap(cls);
+
+       return (jstring) class_get_classname(c);
 }
 
 
@@ -888,14 +907,16 @@ jobjectArray JVM_GetClassInterfaces(JNIEnv *env, jclass cls)
 
 jobject JVM_GetClassLoader(JNIEnv *env, jclass cls)
 {
-       classinfo   *c;
-       classloader *cl;
+       classinfo     *c;
+       classloader_t *cl;
 
-       TRACEJVMCALLS(("JVM_GetClassLoader(env=%p, cls=%p)", env, cls));
+       TRACEJVMCALLSENTER(("JVM_GetClassLoader(env=%p, cls=%p)", env, cls));
 
        c  = LLNI_classinfo_unwrap(cls);
        cl = class_get_classloader(c);
 
+       TRACEJVMCALLSEXIT(("->%p", cl));
+
        return (jobject) cl;
 }
 
@@ -985,7 +1006,7 @@ void JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)
 
 jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)
 {
-       java_handle_t *o;
+       java_handle_t *h;
        classinfo     *c;
        methodinfo    *m;
        java_handle_t *result;
@@ -993,8 +1014,8 @@ jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject contex
 
        TRACEJVMCALLS(("JVM_DoPrivileged(env=%p, cls=%p, action=%p, context=%p, wrapException=%d)", env, cls, action, context, wrapException));
 
-       o = (java_handle_t *) action;
-       c = o->vftbl->class;
+       h = (java_handle_t *) action;
+       LLNI_class_get(h, c);
 
        if (action == NULL) {
                exceptions_throw_nullpointerexception();
@@ -1014,12 +1035,17 @@ jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject contex
        /* XXX It seems something with a privileged stack needs to be done
           here. */
 
-       result = vm_call_method(m, o);
+       result = vm_call_method(m, h);
 
-       e = exceptions_get_and_clear_exception();
+       e = exceptions_get_exception();
 
        if (e != NULL) {
-               exceptions_throw_privilegedactionexception(e);
+               if ( builtin_instanceof(e, class_java_lang_Exception) &&
+                       !builtin_instanceof(e, class_java_lang_RuntimeException)) {
+                       exceptions_clear_exception();
+                       exceptions_throw_privilegedactionexception(e);
+               }
+
                return NULL;
        }
 
@@ -1289,9 +1315,16 @@ jbyteArray JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method)
 
 jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)
 {
+       classinfo                 *c;
+       java_handle_objectarray_t *oa;
+
        TRACEJVMCALLS(("JVM_GetClassDeclaredFields(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
 
-       return (jobjectArray) _Jv_java_lang_Class_getDeclaredFields((java_lang_Class *) ofClass, publicOnly);
+       c = LLNI_classinfo_unwrap(ofClass);
+
+       oa = class_get_declaredfields(c, publicOnly);
+
+       return (jobjectArray) oa;
 }
 
 
@@ -1299,9 +1332,16 @@ jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean pu
 
 jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)
 {
+       classinfo                 *c;
+       java_handle_objectarray_t *oa;
+
        TRACEJVMCALLS(("JVM_GetClassDeclaredMethods(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
 
-       return (jobjectArray) _Jv_java_lang_Class_getDeclaredMethods((java_lang_Class *) ofClass, publicOnly);
+       c = LLNI_classinfo_unwrap(ofClass);
+
+       oa = class_get_declaredmethods(c, publicOnly);
+
+       return (jobjectArray) oa;
 }
 
 
@@ -1309,9 +1349,16 @@ jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean p
 
 jobjectArray JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)
 {
+       classinfo                 *c;
+       java_handle_objectarray_t *oa;
+
        TRACEJVMCALLS(("JVM_GetClassDeclaredConstructors(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
 
-       return (jobjectArray) _Jv_java_lang_Class_getDeclaredConstructors((java_lang_Class *) ofClass, publicOnly);
+       c = LLNI_classinfo_unwrap(ofClass);
+
+       oa = class_get_declaredconstructors(c, publicOnly);
+
+       return (jobjectArray) oa;
 }
 
 
@@ -2124,7 +2171,7 @@ jint JVM_Open(const char *fname, jint flags, jint mode)
 
        TRACEJVMCALLS(("JVM_Open(fname=%s, flags=%d, mode=%d)", fname, flags, mode));
 
-       result = system_open(fname, flags, mode);
+       result = hpi_file->Open(fname, flags, mode);
 
        if (result >= 0) {
                return result;
@@ -2146,7 +2193,7 @@ jint JVM_Close(jint fd)
 {
        TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
 
-       return system_close(fd);
+       return hpi_file->Close(fd);
 }
 
 
@@ -2156,7 +2203,7 @@ jint JVM_Read(jint fd, char *buf, jint nbytes)
 {
        TRACEJVMCALLS(("JVM_Read(fd=%d, buf=%p, nbytes=%d)", fd, buf, nbytes));
 
-       return system_read(fd, buf, nbytes);
+       return (jint) hpi_file->Read(fd, buf, nbytes);
 }
 
 
@@ -2166,7 +2213,7 @@ jint JVM_Write(jint fd, char *buf, jint nbytes)
 {
        TRACEJVMCALLS(("JVM_Write(fd=%d, buf=%s, nbytes=%d)", fd, buf, nbytes));
 
-       return system_write(fd, buf, nbytes);
+       return (jint) hpi_file->Write(fd, buf, nbytes);
 }
 
 
@@ -2174,25 +2221,9 @@ jint JVM_Write(jint fd, char *buf, jint nbytes)
 
 jint JVM_Available(jint fd, jlong *pbytes)
 {
-#if defined(FIONREAD)
-       int bytes;
-       int result;
-
        TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
 
-       *pbytes = 0;
-
-       result = ioctl(fd, FIONREAD, &bytes);
-
-       if (result < 0)
-               return 0;
-
-       *pbytes = bytes;
-
-       return 1;
-#else
-# error FIONREAD not defined
-#endif
+       return hpi_file->Available(fd, pbytes);
 }
 
 
@@ -2202,7 +2233,7 @@ jlong JVM_Lseek(jint fd, jlong offset, jint whence)
 {
        TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
 
-       return (jlong) system_lseek(fd, (off_t) offset, whence);
+       return hpi_file->Seek(fd, (off_t) offset, whence);
 }
 
 
@@ -2212,7 +2243,7 @@ jint JVM_SetLength(jint fd, jlong length)
 {
        TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
 
-       return system_ftruncate(fd, length);
+       return hpi_file->SetLength(fd, length);
 }
 
 
@@ -2222,7 +2253,7 @@ jint JVM_Sync(jint fd)
 {
        TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
 
-       return system_fsync(fd);
+       return hpi_file->Sync(fd);
 }
 
 
@@ -2335,7 +2366,7 @@ jobject JVM_CurrentThread(JNIEnv* env, jclass threadClass)
 
        TRACEJVMCALLSVERBOSE(("JVM_CurrentThread(env=%p, threadClass=%p)", env, threadClass));
 
-       o = threads_get_current_object();
+       o = thread_get_current_object();
 
        return (jobject) o;
 }
@@ -2376,15 +2407,19 @@ jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrup
 {
        java_handle_t *h;
        threadobject  *t;
+       jboolean       interrupted;
 
        TRACEJVMCALLS(("JVM_IsInterrupted(env=%p, jthread=%p, clear_interrupted=%d)", env, jthread, clear_interrupted));
 
        h = (java_handle_t *) jthread;
        t = thread_get_thread(h);
 
-       /* XXX do something with clear_interrupted */
+       interrupted = thread_is_interrupted(t);
 
-       return threads_thread_has_been_interrupted(t);
+       if (interrupted && clear_interrupted)
+               thread_set_interrupted(t, false);
+
+       return interrupted;
 }
 
 
@@ -2529,7 +2564,7 @@ jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint le
 
 jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
 {
-       classloader *cl;
+       classloader_t *cl;
 
        TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env));
 
@@ -2695,9 +2730,18 @@ jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)
 
        length = array_length_get((java_handle_t *) ia);
 
-       if (length == 0)
+       /* We check here for exceptions thrown in array_length_get,
+          otherwise these exceptions get overwritten by the following
+          IllegalArgumentException. */
+
+       if (length < 0)
                return NULL;
 
+       if ((length <= 0) || (length > /* MAX_DIM */ 255)) {
+               exceptions_throw_illegalargumentexception();
+               return NULL;
+       }
+
        /* XXX This is just a quick hack to get it working. */
 
        dims = MNEW(long, length);
@@ -2727,9 +2771,9 @@ jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)
 
 jint JVM_InitializeSocketLibrary()
 {
-       log_println("JVM_InitializeSocketLibrary: IMPLEMENT ME!");
+       TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
 
-       return 0;
+       return hpi_initialize_socket_library();
 }
 
 
@@ -2913,9 +2957,15 @@ jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int opt
 
 int JVM_GetHostName(char *name, int namelen)
 {
-       TRACEJVMCALLS(("JVM_GetHostName(name=%s, namelen=%d)", name, namelen));
+       int result;
+
+       TRACEJVMCALLSENTER(("JVM_GetHostName(name=%s, namelen=%d)", name, namelen));
+
+       result = system_gethostname(name, namelen);
 
-       return system_gethostname(name, namelen);
+       TRACEJVMCALLSEXIT(("->%d (name=%s)", result, name));
+
+       return result;
 }
 
 
@@ -2953,13 +3003,18 @@ struct protoent *JVM_GetProtoByName(char* name)
 
 void *JVM_LoadLibrary(const char *name)
 {
-       utf *u;
+       utf*  u;
+       void* handle;
 
-       TRACEJVMCALLS(("JVM_LoadLibrary(name=%s)", name));
+       TRACEJVMCALLSENTER(("JVM_LoadLibrary(name=%s)", name));
 
        u = utf_new_char(name);
 
-       return native_library_open(u);
+       handle = native_library_open(u);
+
+       TRACEJVMCALLSEXIT(("->%p", handle));
+
+       return handle;
 }
 
 
@@ -2979,10 +3034,12 @@ void *JVM_FindLibraryEntry(void *handle, const char *name)
 {
        lt_ptr symbol;
 
-       TRACEJVMCALLS(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
+       TRACEJVMCALLSENTER(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
 
        symbol = lt_dlsym(handle, name);
 
+       TRACEJVMCALLSEXIT(("->%p", symbol));
+
        return symbol;
 }
 
@@ -3223,19 +3280,53 @@ void JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, un
 
 jobject JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)
 {
+       java_lang_reflect_Method *rm;
+       classinfo     *c;
+       int32_t        slot;
+       int32_t        override;
+       methodinfo    *m;
+       java_handle_t *ro;
+
        TRACEJVMCALLS(("JVM_InvokeMethod(env=%p, method=%p, obj=%p, args0=%p)", env, method, obj, args0));
 
-       return (jobject) _Jv_java_lang_reflect_Method_invoke((java_lang_reflect_Method *) method, (java_lang_Object *) obj, (java_handle_objectarray_t *) args0);
+       rm = (java_lang_reflect_Method *) method;
+
+       LLNI_field_get_cls(rm, clazz,    c);
+       LLNI_field_get_val(rm, slot,     slot);
+       LLNI_field_get_val(rm, override, override);
+
+       m = &(c->methods[slot]);
+
+       ro = reflect_method_invoke(m, (java_handle_t *) obj, (java_handle_objectarray_t *) args0, override);
+
+       return (jobject) ro;
 }
 
 
 /* JVM_NewInstanceFromConstructor */
 
-jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0)
+jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject con, jobjectArray args0)
 {
-       TRACEJVMCALLS(("JVM_NewInstanceFromConstructor(env=%p, c=%p, args0=%p)", env, c, args0));
+       java_lang_reflect_Constructor *rc;
+       classinfo                     *c;
+       int32_t                        slot;
+       int32_t                        override;
+       methodinfo                    *m;
+       java_handle_t                 *o;
 
-       return (jobject) _Jv_java_lang_reflect_Constructor_newInstance(env, (java_lang_reflect_Constructor *) c, (java_handle_objectarray_t *) args0);
+       TRACEJVMCALLS(("JVM_NewInstanceFromConstructor(env=%p, c=%p, args0=%p)", env, con, args0));
+
+       rc = (java_lang_reflect_Constructor *) con;
+
+       LLNI_field_get_cls(rc, clazz,    c);
+       LLNI_field_get_val(rc, slot,     slot);
+       LLNI_field_get_val(rc, override, override);
+
+       m = &(c->methods[slot]);
+
+       o = reflect_constructor_newinstance(m, (java_handle_objectarray_t *) args0, override);
+
+       return (jobject) o;
 }
 
 
@@ -3328,7 +3419,7 @@ jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)
        if (oa == NULL)
                return NULL;
 
-       array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->class));
+       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));