X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fnative%2Fjni.c;h=c1711f00ada23c40ad4bb476e2b3fb52a9745c6c;hb=c0aaa24c579ed715a85b7e477adaede38ab103d0;hp=e3e5ca983d59496c49b1c19b4c1834f09f319e94;hpb=d6f3d91d455659f715248fb1727274c05f8c0b84;p=cacao.git diff --git a/src/native/jni.c b/src/native/jni.c index e3e5ca983..c1711f00a 100644 --- a/src/native/jni.c +++ b/src/native/jni.c @@ -1,9 +1,9 @@ -/* jni.c - implementation of the Java Native Interface functions +/* src/native/jni.c - implementation of the Java Native Interface functions - 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 + Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, + R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, + C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, + Institut f. Computersprachen - TU Wien This file is part of CACAO. @@ -24,523 +24,516 @@ Contact: cacao@complang.tuwien.ac.at - Authors: ? + Authors: Rainhard Grafl + Roman Obermaisser Changes: Joseph Wenninger + Martin Platter + Christian Thalinger - $Id: jni.c 897 2004-01-21 00:49:42Z stefan $ + $Id: jni.c 4123 2006-01-10 20:46:50Z twisti $ */ +#include "config.h" + +#include #include -#include "jni.h" -#include "global.h" -#include "loader.h" -#include "tables.h" -#include "native.h" -#include "builtin.h" -#include "threads/thread.h" -#include "toolbox/loging.h" -#include "toolbox/memory.h" -#include "nat/java_lang_Byte.h" -#include "nat/java_lang_Character.h" -#include "nat/java_lang_Short.h" -#include "nat/java_lang_Integer.h" -#include "nat/java_lang_Boolean.h" -#include "nat/java_lang_Long.h" -#include "nat/java_lang_Float.h" -#include "nat/java_lang_Double.h" -#include "nat/java_lang_Throwable.h" -#include "jit/jit.h" -#include "asmpart.h" -#define JNI_VERSION 0x00010002 + +#include "vm/types.h" + +#include "mm/boehm.h" +#include "mm/memory.h" +#include "native/jni.h" +#include "native/native.h" + +#include "native/include/gnu_classpath_Pointer.h" + +#if SIZEOF_VOID_P == 8 +# include "native/include/gnu_classpath_Pointer64.h" +#else +# include "native/include/gnu_classpath_Pointer32.h" +#endif + +#include "native/include/java_lang_Object.h" +#include "native/include/java_lang_Byte.h" +#include "native/include/java_lang_Character.h" +#include "native/include/java_lang_Short.h" +#include "native/include/java_lang_Integer.h" +#include "native/include/java_lang_Boolean.h" +#include "native/include/java_lang_Long.h" +#include "native/include/java_lang_Float.h" +#include "native/include/java_lang_Double.h" +#include "native/include/java_lang_Throwable.h" +#include "native/include/java_lang_reflect_Method.h" +#include "native/include/java_lang_reflect_Constructor.h" +#include "native/include/java_lang_reflect_Field.h" + +#include "native/include/java_lang_Class.h" /* for java_lang_VMClass.h */ +#include "native/include/java_lang_VMClass.h" +#include "native/include/java_lang_VMClassLoader.h" +#include "native/include/java_nio_Buffer.h" +#include "native/include/java_nio_DirectByteBufferImpl.h" + +#if defined(ENABLE_JVMTI) +# include "native/jvmti/jvmti.h" +#endif + +#if defined(USE_THREADS) +# if defined(NATIVE_THREADS) +# include "threads/native/threads.h" +# else +# include "threads/green/threads.h" +# endif +#endif + +#include "toolbox/logging.h" +#include "vm/builtin.h" +#include "vm/exceptions.h" +#include "vm/global.h" +#include "vm/initialize.h" +#include "vm/loader.h" +#include "vm/options.h" +#include "vm/resolve.h" +#include "vm/statistics.h" +#include "vm/stringlocal.h" +#include "vm/jit/asmpart.h" +#include "vm/jit/jit.h" +#include "vm/statistics.h" + + +/* XXX TWISTI hack: define it extern so they can be found in this file */ + +extern const struct JNIInvokeInterface JNI_JavaVMTable; +extern struct JNINativeInterface JNI_JNIEnvTable; + +/* pointers to VM and the environment needed by GetJavaVM and GetEnv */ + +static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable; +void *ptr_env = (void*) &JNI_JNIEnvTable; #define PTR_TO_ITEM(ptr) ((u8)(size_t)(ptr)) -static utf* utf_char = 0; -static utf* utf_bool = 0; -static utf* utf_byte =0; -static utf* utf_short = 0; -static utf* utf_int = 0; -static utf* utf_long = 0; -static utf* utf_float = 0; -static utf* utf_double = 0; +/* global variables ***********************************************************/ + +/* global reference table *****************************************************/ + +static java_objectheader **global_ref_table; + +/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/ +static classinfo *ihmclass = NULL; +static methodinfo *putmid = NULL; +static methodinfo *getmid = NULL; +static methodinfo *removemid = NULL; + + +/* direct buffer stuff ********************************************************/ + +static utf *utf_java_nio_DirectByteBufferImpl_ReadWrite; +#if SIZEOF_VOID_P == 8 +static utf *utf_gnu_classpath_Pointer64; +#else +static utf *utf_gnu_classpath_Pointer32; +#endif + +static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite; +#if SIZEOF_VOID_P == 8 +static classinfo *class_gnu_classpath_Pointer64; +#else +static classinfo *class_gnu_classpath_Pointer32; +#endif + +static methodinfo *dbbirw_init; + + +/* local reference table ******************************************************/ + +#if !defined(USE_THREADS) +localref_table *_no_threads_localref_table; +#endif + + +/* accessing instance fields macros *******************************************/ + +#define SET_FIELD(obj,type,var,value) \ + *((type *) ((ptrint) (obj) + (ptrint) (var)->offset)) = (type) (value) +#define GET_FIELD(obj,type,var) \ + *((type *) ((ptrint) (obj) + (ptrint) (var)->offset)) -/********************* accessing instance-fields **********************************/ -#define setField(obj,typ,var,val) *((typ*) ((long int) obj + (long int) var->offset))=val; -#define getField(obj,typ,var) *((typ*) ((long int) obj + (long int) var->offset)) -#define setfield_critical(clazz,obj,name,sig,jdatatype,val) setField(obj,jdatatype,getFieldID_critical(env,clazz,name,sig),val); +/* some forward declarations **************************************************/ +jobject NewLocalRef(JNIEnv *env, jobject ref); -u4 get_parametercount(methodinfo *m) +/* jni_init ******************************************************************** + + Initialize the JNI subsystem. + +*******************************************************************************/ + +bool jni_init(void) { - utf *descr = m->descriptor; /* method-descriptor */ - char *utf_ptr = descr->text; /* current position in utf-text */ - char *desc_end = utf_end(descr); /* points behind utf string */ - java_objectarray* result; - int parametercount = 0; - int i; + /* initalize global reference table */ - /* skip '(' */ - utf_nextu2(&utf_ptr); + if (!(ihmclass = + load_class_bootstrap(utf_new_char("java/util/IdentityHashMap")))) + return false; - /* determine number of parameters */ - while ( *utf_ptr != ')' ) { - get_type(&utf_ptr,desc_end,true); - parametercount++; - } + global_ref_table = GCNEW(jobject, 1); - return parametercount; -} + if (!(*global_ref_table = native_new_and_init(ihmclass))) + return false; + + if (!(getmid = class_resolvemethod(ihmclass, utf_get, + utf_java_lang_Object__java_lang_Object))) + return false; + + if (!(putmid = class_resolvemethod(ihmclass, utf_put, + utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;")))) + return false; + + if (!(removemid = + class_resolvemethod(ihmclass, utf_remove, + utf_java_lang_Object__java_lang_Object))) + return false; + + + /* direct buffer stuff */ + + utf_java_nio_DirectByteBufferImpl_ReadWrite = + utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"); + + if (!(class_java_nio_DirectByteBufferImpl_ReadWrite = + load_class_bootstrap(utf_java_nio_DirectByteBufferImpl_ReadWrite))) + return false; + if (!link_class(class_java_nio_DirectByteBufferImpl_ReadWrite)) + return false; + if (!(dbbirw_init = + class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite, + utf_init, + utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V")))) + return false; -void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret) +#if SIZEOF_VOID_P == 8 + utf_gnu_classpath_Pointer64 = utf_new_char("gnu/classpath/Pointer64"); + + if (!(class_gnu_classpath_Pointer64 = + load_class_bootstrap(utf_gnu_classpath_Pointer64))) + return false; + + if (!link_class(class_gnu_classpath_Pointer64)) + return false; +#else + utf_gnu_classpath_Pointer32 = utf_new_char("gnu/classpath/Pointer32"); + + if (!(class_gnu_classpath_Pointer32 = + load_class_bootstrap(utf_gnu_classpath_Pointer32))) + return false; + + if (!link_class(class_gnu_classpath_Pointer32)) + return false; +#endif + + return true; +} + + +static void fill_callblock_from_vargs(void *obj, methoddesc *descr, + jni_callblock blk[], va_list data, + s4 rettype) { - char *utf__ptr = descr->text; /* current position in utf-text */ - char **utf_ptr = &utf__ptr; - char *desc_end = utf_end(descr); /* points behind utf string */ + typedesc *paramtypes; + s4 i; - int cnt; + paramtypes = descr->paramtypes; - jdouble d; - jlong l; - u4 dummy; - char c; - /* - log_text("fill_callblock"); - utf_display(descr); - log_text("===="); - */ - /* skip '(' */ - utf_nextu2(utf_ptr); + /* if method is non-static fill first block and skip `this' pointer */ + + i = 0; - /* determine number of parameters */ if (obj) { + /* the `this' pointer */ blk[0].itemtype = TYPE_ADR; blk[0].item = PTR_TO_ITEM(obj); - cnt = 1; - } else cnt = 0; - while (**utf_ptr != ')') { - if (*utf_ptr >= desc_end) - panic("illegal method descriptor"); - - switch (utf_nextu2(utf_ptr)) { - /* primitive types */ - case 'B' : - case 'C' : - case 'S' : - case 'Z' : - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item=(u8) va_arg(data,int); - break; - case 'I' : - blk[cnt].itemtype=TYPE_INT; - dummy=va_arg(data,u4); - /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/ - blk[cnt].item=(u8)dummy; + paramtypes++; + i++; + } + + for (; i < descr->paramcount; i++, paramtypes++) { + switch (paramtypes->decltype) { + /* primitive types */ + case PRIMITIVETYPE_BYTE: + case PRIMITIVETYPE_CHAR: + case PRIMITIVETYPE_SHORT: + case PRIMITIVETYPE_BOOLEAN: + blk[i].itemtype = TYPE_INT; + blk[i].item = (s8) va_arg(data, s4); break; - case 'J' : - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item=(u8)va_arg(data,jlong); + case PRIMITIVETYPE_INT: + blk[i].itemtype = TYPE_INT; + blk[i].item = (s8) va_arg(data, s4); break; - case 'F' : - blk[cnt].itemtype=TYPE_FLT; - *((jfloat*)(&blk[cnt].item))=((jfloat)va_arg(data,jdouble)); + + case PRIMITIVETYPE_LONG: + blk[i].itemtype = TYPE_LNG; + blk[i].item = (s8) va_arg(data, s8); break; - case 'D' : - blk[cnt].itemtype=TYPE_DBL; - *((jdouble*)(&blk[cnt].item))=(jdouble)va_arg(data,jdouble); + case PRIMITIVETYPE_FLOAT: + blk[i].itemtype = TYPE_FLT; +#if defined(__ALPHA__) + /* this keeps the assembler function much simpler */ + + *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble); +#else + *((jfloat *) (&blk[i].item)) = (jfloat) va_arg(data, jdouble); +#endif break; - case 'V' : panic ("V not allowed as function parameter"); + + case PRIMITIVETYPE_DOUBLE: + blk[i].itemtype = TYPE_DBL; + *((jdouble *) (&blk[i].item)) = (jdouble) va_arg(data, jdouble); break; - case 'L' : { - while (utf_nextu2(utf_ptr)!=';') - blk[cnt].itemtype=TYPE_ADR; - blk[cnt].item=PTR_TO_ITEM(va_arg(data,void*)); - break; - } - case '[' : { - /* XXX */ - /* arrayclass */ - char *start = *utf_ptr; - char ch; - while ((ch = utf_nextu2(utf_ptr))=='[') - if (ch == 'L') { - while (utf_nextu2(utf_ptr)!=';') {} - } - - ch=utf_nextu2(utf_ptr); - blk[cnt].itemtype=TYPE_ADR; - blk[cnt].item=PTR_TO_ITEM(va_arg(data,void*)); - break; - } + case TYPE_ADR: + blk[i].itemtype = TYPE_ADR; + blk[i].item = PTR_TO_ITEM(va_arg(data, void*)); + break; } - cnt++; } - /*the standard doesn't say anything about return value checking, but it appears to be usefull*/ - c = utf_nextu2(utf_ptr); - c = utf_nextu2(utf_ptr); - /*printf("%c %c\n",ret,c);*/ - if (ret=='O') { - if (!((c=='L') || (c=='['))) log_text("\n====\nWarning call*Method called for function with wrong return type\n===="); - } else if (ret != c) log_text("\n====\nWarning call*Method called for function with wrong return type\n===="); + /* The standard doesn't say anything about return value checking, but it */ + /* appears to be useful. */ + + if (rettype != descr->returntype.decltype) + log_text("\n====\nWarning call*Method called for function with wrong return type\n===="); } /* XXX it could be considered if we should do typechecking here in the future */ -char fill_callblock_objA(void *obj, utf *descr, jni_callblock blk[], java_objectarray* params) + +static bool fill_callblock_from_objectarray(void *obj, methoddesc *descr, + jni_callblock blk[], + java_objectarray *params) { - char *utf__ptr = descr->text; /* current position in utf-text */ - char **utf_ptr = &utf__ptr; - char *desc_end = utf_end(descr); /* points behind utf string */ + jobject param; + s4 paramcount; + typedesc *paramtypes; + classinfo *c; + s4 i; + s4 j; - jobject param; - int cnt; - int cnts; + paramcount = descr->paramcount; + paramtypes = descr->paramtypes; - u4 dummy; - char c; - char *cp; -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) - intsDisable(); -#endif - if (utf_char==0) { - utf_char=utf_new_char("java/lang/Character"); - utf_bool=utf_new_char("java/lang/Boolean"); - utf_byte=utf_new_char("java/lang/Byte"); - utf_short=utf_new_char("java/lang/Short"); - utf_int=utf_new_char("java/lang/Integer"); - utf_long=utf_new_char("java/lang/Long"); - utf_float=utf_new_char("java/lang/Float"); - utf_double=utf_new_char("java/lang/Double"); - } -#if defined(USE_THREADS) && !defined(NATIVE_THREADS) - intsRestore(); -#endif + /* if method is non-static fill first block and skip `this' pointer */ - /* - log_text("fill_callblock"); - utf_display(descr); - log_text("===="); - */ - /* skip '(' */ - utf_nextu2(utf_ptr); + i = 0; - /* determine number of parameters */ if (obj) { + /* this pointer */ blk[0].itemtype = TYPE_ADR; blk[0].item = PTR_TO_ITEM(obj); - cnt=1; - } else { - cnt = 0; + paramtypes++; + paramcount--; + i++; } - cnts=0; - while (**utf_ptr != ')') { - if (*utf_ptr >= desc_end) - panic("illegal method descriptor"); - + for (j = 0; j < paramcount; i++, j++, paramtypes++) { + switch (paramtypes->type) { /* primitive types */ - switch (utf_nextu2(utf_ptr)) { - case 'B': - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - case 'C': - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_char) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Character * )param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - - case 'S': - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - break; - - case 'Z': - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_bool) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Boolean * )param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - - case 'I': - /*log_text("fill_callblock_objA: param 'I'");*/ - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_int) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Integer * )param)->value; - /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/ - } else { - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - } - break; - case 'J': - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_long) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Long * )param)->value; - } else { - if (param->vftbl->class->name==utf_int) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Integer * )param)->value; - } else { - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - } - - } - break; - - case 'F' : - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - - if (param->vftbl->class->name==utf_float) { - blk[cnt].itemtype=TYPE_FLT; - *((jfloat*)(&blk[cnt].item))=(jfloat) ((struct java_lang_Float*)param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - case 'D' : - param=params->data[cnts]; - if (param==0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } + case TYPE_INT: + case TYPE_LONG: + case TYPE_FLOAT: + case TYPE_DOUBLE: + param = params->data[j]; + if (!param) + goto illegal_arg; + + /* internally used data type */ + blk[i].itemtype = paramtypes->type; + + /* convert the value according to its declared type */ + + c = param->vftbl->class; + + switch (paramtypes->decltype) { + case PRIMITIVETYPE_BOOLEAN: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Boolean *) param)->value; + else + goto illegal_arg; + break; - if (param->vftbl->class->name==utf_double) { - blk[cnt].itemtype=TYPE_DBL; - *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value; - } else { - if (param->vftbl->class->name==utf_float) { - blk[cnt].itemtype=TYPE_DBL; - *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value; - } else { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - break; - case 'V': - panic("V not allowed as function parameter"); - break; + case PRIMITIVETYPE_BYTE: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; - case 'L': { - char *start=(*utf_ptr)-1; - char *end; - - while (utf_nextu2(utf_ptr) != ';') - end=(*utf_ptr)+1; - if (!builtin_instanceof(params->data[cnts],class_from_descriptor(start,end,0,CLASSLOAD_LOAD))) { - if (params->data[cnts]!=0) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item= PTR_TO_ITEM(params->data[cnts]); - break; + case PRIMITIVETYPE_CHAR: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Character *) param)->value; + else + goto illegal_arg; + break; - } - case '[' : - { - char *start=(*utf_ptr)-1; - char *end; + case PRIMITIVETYPE_SHORT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + blk[i].item = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; - char ch; - while ((ch = utf_nextu2(utf_ptr)) == '[') - if (ch == 'L') { - while (utf_nextu2(utf_ptr) != ';') {} - } - end=(*utf_ptr)-1; - ch = utf_nextu2(utf_ptr); - if (!builtin_arrayinstanceof(params->data[cnts],class_from_descriptor(start,end,0,CLASSLOAD_LOAD)->vftbl)) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - - } - - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item = PTR_TO_ITEM(params->data[cnts]); + case PRIMITIVETYPE_INT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Integer *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap) + blk[i].item = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + blk[i].item = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; break; - } - } - cnt++; - cnts++; - } - c = utf_nextu2(utf_ptr); - c = utf_nextu2(utf_ptr); - return c; /*return type needed usage of the right lowlevel methods*/ -} + case PRIMITIVETYPE_LONG: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + blk[i].item = (s8) ((java_lang_Long *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap) + blk[i].item = (s8) ((java_lang_Integer *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap) + blk[i].item = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + blk[i].item = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; + case PRIMITIVETYPE_FLOAT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value; + else + goto illegal_arg; + break; + case PRIMITIVETYPE_DOUBLE: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + *((jdouble *) (&blk[i].item)) = (jdouble) ((java_lang_Float *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap) + *((jfloat *) (&blk[i].item)) = (jfloat) ((java_lang_Float *) param)->value; + else + goto illegal_arg; + break; + default: + goto illegal_arg; + } /* end declared type switch */ + break; + + case TYPE_ADDRESS: + if (!resolve_class_from_typedesc(paramtypes, true, true, &c)) + return false; + if (params->data[j] != 0) { + if (paramtypes->arraydim > 0) { + if (!builtin_arrayinstanceof(params->data[j], c)) + goto illegal_arg; + } else { + if (!builtin_instanceof(params->data[j], c)) + goto illegal_arg; + } + } + blk[i].itemtype = TYPE_ADR; + blk[i].item = PTR_TO_ITEM(params->data[j]); + break; + default: + goto illegal_arg; + } /* end param type switch */ + } /* end param loop */ +/* if (rettype) */ +/* *rettype = descr->returntype.decltype; */ + return true; +illegal_arg: + exceptions_throw_illegalargumentexception(); + return false; +} +static jmethodID get_virtual(jobject obj, jmethodID methodID) +{ + if (obj->vftbl->class == methodID->class) + return methodID; + return class_resolvemethod(obj->vftbl->class, methodID->name, + methodID->descriptor); +} -jmethodID get_virtual(jobject obj,jmethodID methodID) { - if (obj->vftbl->class==methodID->class) return methodID; - return class_resolvemethod (obj->vftbl->class, methodID->name, methodID->descriptor); -} +static jmethodID get_nonvirtual(jclass clazz, jmethodID methodID) +{ + if (clazz == methodID->class) + return methodID; -jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) { - if (clazz==methodID->class) return methodID; - return class_resolvemethod (clazz, methodID->name, methodID->descriptor); + /* class_resolvemethod -> classfindmethod? (JOWENN) */ + return class_resolvemethod(clazz, methodID->name, methodID->descriptor); } - -jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args) +static jobject callObjectMethod(jobject obj, jmethodID methodID, va_list args) { int argcount; jni_callblock *blk; jobject 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 = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - argcount = get_parametercount(methodID); - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - + if (obj && !builtin_instanceof(obj, methodID->class)) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - if (argcount > 3) { - *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } + argcount = methodID->parseddesc->paramcount; - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + blk = MNEW(jni_callblock, argcount); - fill_callblock(obj, methodID->descriptor, blk, args, 'O'); + fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_ADR); + + STATISTICS(jnicallXmethodnvokation()); - /* printf("parameter: obj: %p",blk[0].item); */ ret = asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), + argcount, + argcount * sizeof(jni_callblock), blk); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + MFREE(blk, jni_callblock, argcount); + return ret; } @@ -549,13 +542,13 @@ jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args) core function for integer class methods (bool, byte, short, integer) This is basically needed for i386 */ -jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list args) +static jint callIntegerMethod(jobject obj, jmethodID methodID, int retType, va_list args) { int argcount; jni_callblock *blk; jint ret; -/* printf("%p, %c\n",retType,methodID,retType);*/ + STATISTICS(jniinvokation()); /* log_text("JNI-Call: CallObjectMethodV"); @@ -566,131 +559,114 @@ jint callIntegerMethod(jobject obj, jmethodID methodID, char retType, va_list ar printf("\n"); */ if (methodID == 0) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - argcount = get_parametercount(methodID); - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } if (obj && !builtin_instanceof(obj, methodID->class)) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } + argcount = methodID->parseddesc->paramcount; - if (argcount > 3) { - *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } + blk = MNEW(jni_callblock, argcount); - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType); - fill_callblock(obj, methodID->descriptor, blk, args, retType); + STATISTICS(jnicallXmethodnvokation()); - /* printf("parameter: obj: %p",blk[0].item); */ - ret = (jint) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + ret = asm_calljavafunction2int(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + MFREE(blk, jni_callblock, argcount); return ret; } -/*core function for long class functions*/ -jlong callLongMethod(jobject obj, jmethodID methodID, va_list args) +/* callLongMethod ************************************************************** + + Core function for long class functions. + +*******************************************************************************/ + +static jlong callLongMethod(jobject obj, jmethodID methodID, va_list args) { - int argcount; + s4 argcount; jni_callblock *blk; - jlong ret; + jlong ret; + + STATISTICS(jniinvokation()); - /* - 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 = native_new_and_init(class_java_lang_NoSuchMethodError); + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - argcount = get_parametercount(methodID); - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } - if (obj && !builtin_instanceof(obj,methodID->class)) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + if (obj && !builtin_instanceof(obj, methodID->class)) { + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); return 0; } + argcount = methodID->parseddesc->paramcount; - if (argcount > 3) { - *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } + blk = MNEW(jni_callblock, argcount); - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, TYPE_LNG); - fill_callblock(obj, methodID->descriptor, blk, args, 'L'); + STATISTICS(jnicallXmethodnvokation()); - /* printf("parameter: obj: %p",blk[0].item); */ ret = asm_calljavafunction2long(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), + argcount, + argcount * sizeof(jni_callblock), blk); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + MFREE(blk, jni_callblock, argcount); return ret; } /*core function for float class methods (float,double)*/ -jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType) +static jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,int retType) { - int argcount = get_parametercount(methodID); + int argcount = methodID->parseddesc->paramcount; jni_callblock *blk; jdouble 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"); - */ + STATISTICS(jniinvokation()); + + assert(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. CallObjectMethod does not support that"); return 0; } - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + blk = MNEW(jni_callblock, /*4 */ argcount+2); - fill_callblock(obj, methodID->descriptor, blk, args, retType); + fill_callblock_from_vargs(obj, methodID->parseddesc, blk, args, retType); /* printf("parameter: obj: %p",blk[0].item); */ + + STATISTICS(jnicallXmethodnvokation()); + ret = asm_calljavafunction2double(methodID, argcount + 1, (argcount + 1) * sizeof(jni_callblock), @@ -703,303 +679,597 @@ jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retTy } -/*************************** function: jclass_findfield **************************** - - searches for field with specified name and type in a 'classinfo'-structur - if no such field is found NULL is returned +static void cacao_jni_CallVoidMethod(jobject obj, jmethodID m, va_list ap) +{ + s4 paramcount; + jni_callblock *blk; -************************************************************************************/ + if (m == 0) { + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); + return; + } -fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc) -{ - s4 i; -/* printf(" FieldCount: %d\n",c->fieldscount); - utf_display(c->name); */ - for (i = 0; i < c->fieldscount; i++) { -/* utf_display(c->fields[i].name); - printf("\n"); - utf_display(c->fields[i].descriptor); - printf("\n");*/ - if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) - return &(c->fields[i]); - } + if (!( ((m->flags & ACC_STATIC) && (obj == 0)) || + ((!(m->flags & ACC_STATIC)) && (obj != 0)) )) { + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); + return; + } + + if (obj && !builtin_instanceof(obj, m->class)) { + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); + return; + } - if (c->super) return jclass_findfield(c->super,name,desc); + paramcount = m->parseddesc->paramcount; - return NULL; +/* #error XXX does not work on intrp, but on JIT */ + if (!(m->flags & ACC_STATIC)) + paramcount++; + + blk = MNEW(jni_callblock, paramcount); + + fill_callblock_from_vargs(obj, m->parseddesc, blk, ap, TYPE_VOID); + + STATISTICS(jnicallXmethodnvokation()); + + (void) asm_calljavafunction2(m, + paramcount, + paramcount * sizeof(jni_callblock), + blk); + + MFREE(blk, jni_callblock, paramcount); + + return; } -/********************* returns version of native method interface *****************/ -jint GetVersion (JNIEnv* env) +/* GetVersion ****************************************************************** + + Returns the major version number in the higher 16 bits and the + minor version number in the lower 16 bits. + +*******************************************************************************/ + +jint GetVersion(JNIEnv *env) { - return JNI_VERSION; + STATISTICS(jniinvokation()); + + /* we support JNI 1.4 */ + + return JNI_VERSION_1_4; } -/****************** loads a class from a buffer of raw class data *****************/ -jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) +/* Class Operations ***********************************************************/ + +/* DefineClass ***************************************************************** + + Loads a class from a buffer of raw class data. The buffer + containing the raw class data is not referenced by the VM after the + DefineClass call returns, and it may be discarded if desired. + +*******************************************************************************/ + +jclass DefineClass(JNIEnv *env, const char *name, jobject loader, + const jbyte *buf, jsize bufLen) { - jclass clazz; + java_lang_ClassLoader *cl; + java_lang_String *s; + java_bytearray *ba; + jclass c; - /* change suck-mode, so subsequent class_load will read from memory-buffer */ - classload_buffer( (u1*) buf,len); + STATISTICS(jniinvokation()); - clazz = loader_load(utf_new_char ((char *) name)); + cl = (java_lang_ClassLoader *) loader; + s = javastring_new_char(name); + ba = (java_bytearray *) buf; - /* restore old suck-mode */ - classload_buffer(NULL,0); + c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba, + 0, bufLen, NULL); - return clazz; + return (jclass) NewLocalRef(env, (jobject) c); } -/*************** loads locally defined class with the specified name **************/ +/* FindClass ******************************************************************* + + This function loads a locally-defined class. It searches the + directories and zip files specified by the CLASSPATH environment + variable for the class with the specified name. -jclass FindClass (JNIEnv* env, const char *name) +*******************************************************************************/ + +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)); + utf *u; + classinfo *c; + java_objectheader *cl; + + STATISTICS(jniinvokation()); + + u = utf_new_char_classname((char *) name); + + /* check stacktrace for classloader, if one found use it, otherwise use */ + /* the system classloader */ + +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__) + /* these JITs support stacktraces, and so does the interpreter */ + + cl = cacao_currentClassLoader(); +#else +# if defined(ENABLE_INTRP) + /* the interpreter supports stacktraces, even if the JIT does not */ + + if (opt_intrp) + cl = cacao_currentClassLoader(); + else +# endif + cl = NULL; +#endif - if (!c) *exceptionptr = native_new_and_init(class_java_lang_ClassFormatError); + if (!(c = load_class_from_classloader(u, cl))) + return NULL; + + if (!link_class(c)) + return NULL; - return c; + return (jclass) NewLocalRef(env, (jobject) c); } -/*********************************************************************************** +/* FromReflectedMethod ********************************************************* - converts java.lang.reflect.Method or - java.lang.reflect.Constructor object to a method ID + Converts java.lang.reflect.Method or java.lang.reflect.Constructor + object to a method ID. - **********************************************************************************/ +*******************************************************************************/ -jmethodID FromReflectedMethod(JNIEnv* env, jobject method) +jmethodID FromReflectedMethod(JNIEnv *env, jobject method) { - /* log_text("JNI-Call: FromReflectedMethod"); */ + methodinfo *mi; + classinfo *c; + s4 slot; - return 0; + STATISTICS(jniinvokation()); + + if (method == NULL) + return NULL; + + if (builtin_instanceof(method, class_java_lang_reflect_Method)) { + java_lang_reflect_Method *rm; + + rm = (java_lang_reflect_Method *) method; + c = (classinfo *) (rm->declaringClass); + slot = rm->slot; + + } else if (builtin_instanceof(method, class_java_lang_reflect_Constructor)) { + java_lang_reflect_Constructor *rc; + + rc = (java_lang_reflect_Constructor *) method; + c = (classinfo *) (rc->clazz); + slot = rc->slot; + + } else + return NULL; + + if ((slot < 0) || (slot >= c->methodscount)) { + /* this usually means a severe internal cacao error or somebody + tempered around with the reflected method */ + log_text("error illegal slot for method in class(FromReflectedMethod)"); + assert(0); + } + + mi = &(c->methods[slot]); + + return mi; } -/*************** return superclass of the class represented by sub ****************/ +/* GetSuperclass *************************************************************** + + If clazz represents any class other than the class Object, then + this function returns the object that represents the superclass of + the class specified by clazz. + +*******************************************************************************/ -jclass GetSuperclass(JNIEnv* env, jclass sub) +jclass GetSuperclass(JNIEnv *env, jclass sub) { classinfo *c; - c = ((classinfo*) sub)->super; + STATISTICS(jniinvokation()); - if (!c) return NULL; + c = ((classinfo *) sub)->super.cls; - use_class_as_object(c); + if (!c) + return NULL; - return c; + return (jclass) NewLocalRef(env, (jobject) c); } -/*********************** check whether sub can be cast to sup ********************/ - -jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup) -{ - return builtin_isanysubclass(sub, sup); -} +/* IsAssignableFrom ************************************************************ + Determines whether an object of sub can be safely cast to sup. -/***** converts a field ID derived from cls to a java.lang.reflect.Field object ***/ +*******************************************************************************/ -jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic) +jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) { - /* log_text("JNI-Call: ToReflectedField"); */ + STATISTICS(jniinvokation()); - return NULL; + return Java_java_lang_VMClass_isAssignableFrom(env, + NULL, + (java_lang_Class *) sup, + (java_lang_Class *) sub); } -/***************** throw java.lang.Throwable object ******************************/ +/* Throw *********************************************************************** -jint Throw(JNIEnv* env, jthrowable obj) + Causes a java.lang.Throwable object to be thrown. + +*******************************************************************************/ + +jint Throw(JNIEnv *env, jthrowable obj) { - *exceptionptr = (java_objectheader*) obj; + STATISTICS(jniinvokation()); - return 0; + *exceptionptr = (java_objectheader *) obj; + + return JNI_OK; } -/*********************************************************************************** +/* ThrowNew ******************************************************************** - create exception object from the class clazz with the - specified message and cause it to be thrown + Constructs an exception object from the specified class with the + message specified by message and causes that exception to be + thrown. - **********************************************************************************/ +*******************************************************************************/ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) { java_lang_Throwable *o; + java_lang_String *s; + + STATISTICS(jniinvokation()); + + s = (java_lang_String *) javastring_new_char(msg); /* instantiate exception object */ - o = (java_lang_Throwable *) native_new_and_init ((classinfo*) clazz); - if (!o) return (-1); + o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz, + s); - o->detailMessage = (java_lang_String*) javastring_new_char((char *) msg); + if (!o) + return -1; - *exceptionptr = (java_objectheader*) o; + *exceptionptr = (java_objectheader *) o; return 0; } -/************************* check if exception occured *****************************/ +/* ExceptionOccurred *********************************************************** -jthrowable ExceptionOccurred (JNIEnv* env) -{ - return (jthrowable) *exceptionptr; + Determines if an exception is being thrown. The exception stays + being thrown until either the native code calls ExceptionClear(), + or the Java code handles the exception. + +*******************************************************************************/ + +jthrowable ExceptionOccurred(JNIEnv *env) +{ + java_objectheader *e; + + STATISTICS(jniinvokation()); + + e = *exceptionptr; + + return NewLocalRef(env, (jthrowable) e); } -/********** print exception and a backtrace of the stack (for debugging) **********/ -void ExceptionDescribe (JNIEnv* env) +/* ExceptionDescribe *********************************************************** + + Prints an exception and a backtrace of the stack to a system + error-reporting channel, such as stderr. This is a convenience + routine provided for debugging. + +*******************************************************************************/ + +void ExceptionDescribe(JNIEnv *env) { - utf_display((*exceptionptr)->vftbl->class->name); - printf ("\n"); - fflush (stdout); + java_objectheader *e; + methodinfo *m; + + STATISTICS(jniinvokation()); + + e = *exceptionptr; + + if (e) { + /* clear exception, because we are calling jit code again */ + + *exceptionptr = NULL; + + /* get printStackTrace method from exception class */ + + m = class_resolveclassmethod(e->vftbl->class, + utf_printStackTrace, + utf_void__void, + NULL, + true); + + if (!m) + /* XXX what should we do? */ + return; + + /* print the stacktrace */ + + asm_calljavafunction(m, e, NULL, NULL, NULL); + } } -/******************* clear any exception currently being thrown *******************/ +/* ExceptionClear ************************************************************** + + Clears any exception that is currently being thrown. If no + exception is currently being thrown, this routine has no effect. -void ExceptionClear (JNIEnv* env) +*******************************************************************************/ + +void ExceptionClear(JNIEnv *env) { - *exceptionptr = NULL; + STATISTICS(jniinvokation()); + + *exceptionptr = NULL; } -/********** raises a fatal error and does not expect the VM to recover ************/ +/* FatalError ****************************************************************** + + Raises a fatal error and does not expect the VM to recover. This + function does not return. + +*******************************************************************************/ -void FatalError (JNIEnv* env, const char *msg) +void FatalError(JNIEnv *env, const char *msg) { - panic((char *) msg); + STATISTICS(jniinvokation()); + + throw_cacao_exception_exit(string_java_lang_InternalError, msg); } -/******************* creates a new local reference frame **************************/ + +/* PushLocalFrame ************************************************************** + + Creates a new local reference frame, in which at least a given + number of local references can be created. + +*******************************************************************************/ jint PushLocalFrame(JNIEnv* env, jint capacity) { - /* empty */ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!"); + + assert(0); return 0; } -/**************** Pops off the current local reference frame **********************/ +/* PopLocalFrame *************************************************************** + + Pops off the current local reference frame, frees all the local + references, and returns a local reference in the previous local + reference frame for the given result object. + +*******************************************************************************/ jobject PopLocalFrame(JNIEnv* env, jobject result) { - /* empty */ + STATISTICS(jniinvokation()); - return NULL; -} - + log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!"); -/** Creates a new global reference to the object referred to by the obj argument **/ - -jobject NewGlobalRef(JNIEnv* env, jobject lobj) -{ - return lobj; -} + assert(0); -/************* Deletes the global reference pointed to by globalRef **************/ + /* add local reference and return the value */ -void DeleteGlobalRef (JNIEnv* env, jobject gref) -{ - /* empty */ + return NewLocalRef(env, NULL); } -/*************** Deletes the local reference pointed to by localRef ***************/ +/* DeleteLocalRef ************************************************************** + + Deletes the local reference pointed to by localRef. -void DeleteLocalRef (JNIEnv* env, jobject localRef) +*******************************************************************************/ + +void DeleteLocalRef(JNIEnv *env, jobject localRef) { - /* empty */ + java_objectheader *o; + localref_table *lrt; + s4 i; + + STATISTICS(jniinvokation()); + + o = (java_objectheader *) localRef; + + /* get local reference table (thread specific) */ + + lrt = LOCALREFTABLE; + + /* remove the reference */ + + for (i = 0; i < lrt->capacity; i++) { + if (lrt->refs[i] == o) { + lrt->refs[i] = NULL; + lrt->used--; + + return; + } + } + + /* this should not happen */ + +/* if (opt_checkjni) */ +/* FatalError(env, "Bad global or local ref passed to JNI"); */ + log_text("JNI-DeleteLocalRef: Bad global or local ref passed to JNI"); } -/********** Tests whether two references refer to the same Java object ************/ -jboolean IsSameObject (JNIEnv* env, jobject obj1, jobject obj2) +/* IsSameObject **************************************************************** + + Tests whether two references refer to the same Java object. + +*******************************************************************************/ + +jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) { - return (obj1==obj2); + STATISTICS(jniinvokation()); + + if (ref1 == ref2) + return JNI_TRUE; + else + return JNI_FALSE; } -/***** Creates a new local reference that refers to the same object as ref *******/ -jobject NewLocalRef (JNIEnv* env, jobject ref) +/* NewLocalRef ***************************************************************** + + Creates a new local reference that refers to the same object as ref. + +*******************************************************************************/ + +jobject NewLocalRef(JNIEnv *env, jobject ref) { - return ref; + localref_table *lrt; + s4 i; + + STATISTICS(jniinvokation()); + + if (ref == NULL) + return NULL; + + /* get local reference table (thread specific) */ + + lrt = LOCALREFTABLE; + + /* check if we have space for the requested reference */ + + if (lrt->used == lrt->capacity) + throw_cacao_exception_exit(string_java_lang_InternalError, + "Too many local references"); + + /* insert the reference */ + + for (i = 0; i < lrt->capacity; i++) { + if (lrt->refs[i] == NULL) { + lrt->refs[i] = (java_objectheader *) ref; + lrt->used++; + + return ref; + } + } + + /* should not happen, just to be sure */ + + assert(0); + + /* keep compiler happy */ + + return NULL; } -/*********************************************************************************** - Ensures that at least a given number of local references can - be created in the current thread +/* EnsureLocalCapacity ********************************************************* - **********************************************************************************/ + Ensures that at least a given number of local references can be + created in the current thread -jint EnsureLocalCapacity (JNIEnv* env, jint capacity) +*******************************************************************************/ + +jint EnsureLocalCapacity(JNIEnv* env, jint capacity) { - return 0; /* return 0 on success */ + localref_table *lrt; + + STATISTICS(jniinvokation()); + + /* get local reference table (thread specific) */ + + lrt = LOCALREFTABLE; + + /* check if capacity elements are available in the local references table */ + + if ((lrt->used + capacity) > lrt->capacity) { + *exceptionptr = new_exception(string_java_lang_OutOfMemoryError); + return -1; + } + + return 0; } -/********* Allocates a new Java object without invoking a constructor *************/ +/* AllocObject ***************************************************************** + + Allocates a new Java object without invoking any of the + constructors for the object. Returns a reference to the object. -jobject AllocObject (JNIEnv* env, jclass clazz) +*******************************************************************************/ + +jobject AllocObject(JNIEnv *env, jclass clazz) { - java_objectheader *o = builtin_new(clazz); - return o; + java_objectheader *o; + + STATISTICS(jniinvokation()); + + if ((clazz->flags & ACC_INTERFACE) || (clazz->flags & ACC_ABSTRACT)) { + *exceptionptr = + new_exception_utfmessage(string_java_lang_InstantiationException, + clazz->name); + return NULL; + } + + o = builtin_new(clazz); + + return NewLocalRef(env, o); } -/*********************************************************************************** +/* NewObject ******************************************************************* - Constructs a new Java object - arguments that are to be passed to the constructor are placed after methodID + Programmers place all arguments that are to be passed to the + constructor immediately following the methodID + argument. NewObject() accepts these arguments and passes them to + the Java method that the programmer wishes to invoke. -***********************************************************************************/ +*******************************************************************************/ -jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...) +jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { java_objectheader *o; - void* args[3]; - int argcount=get_parametercount(methodID); - int i; - va_list vaargs; + va_list ap; - /* log_text("JNI-Call: NewObject"); */ + STATISTICS(jniinvokation()); - if (argcount>3) { - *exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. NewObject does not support that"); - return 0; - } + /* create object */ + o = builtin_new(clazz); - o = builtin_new (clazz); /* create object */ - - if (!o) return NULL; + if (!o) + return NULL; - va_start(vaargs,methodID); - for (i=0;ivftbl->class; -/* log_text("GetObjectClass"); - utf_display(obj->vftbl->class->name);*/ - use_class_as_object(c); + classinfo *c; + + STATISTICS(jniinvokation()); + + if (!obj || !obj->vftbl) + return NULL; + + c = obj->vftbl->class; - /*printf("\nPointer: %p\n",c);*/ - return c; + return (jclass) NewLocalRef(env, (jobject) c); } -/************* tests whether an object is an instance of a class ******************/ +/* IsInstanceOf **************************************************************** -jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) + Tests whether an object is an instance of a class. + +*******************************************************************************/ + +jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) { - return builtin_instanceof(obj,clazz); + STATISTICS(jniinvokation()); + + return Java_java_lang_VMClass_isInstance(env, + NULL, + (java_lang_Class *) clazz, + (java_lang_Object *) obj); } @@ -1060,40 +1350,108 @@ jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) jfieldID FromReflectedField(JNIEnv* env, jobject field) { - log_text("JNI-Call: FromReflectedField"); + java_lang_reflect_Field *f; + classinfo *c; + jfieldID fid; /* the JNI-fieldid of the wrapping object */ - return 0; + STATISTICS(jniinvokation()); + + /*log_text("JNI-Call: FromReflectedField");*/ + + f=(java_lang_reflect_Field *)field; + if (f==0) return 0; + c=(classinfo*)(f->declaringClass); + if ( (f->slot<0) || (f->slot>=c->fieldscount)) { + /*this usually means a severe internal cacao error or somebody + tempered around with the reflected method*/ + log_text("error illegal slot for field in class(FromReflectedField)"); + assert(0); + } + fid=&(c->fields[f->slot]); + return fid; } -/********************************************************************************** +/* ToReflectedMethod *********************************************************** - converts a method ID to a java.lang.reflect.Method or - java.lang.reflect.Constructor object + Converts a method ID derived from cls to an instance of the + java.lang.reflect.Method class or to an instance of the + java.lang.reflect.Constructor class. -**********************************************************************************/ +*******************************************************************************/ jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic) { - log_text("JNI-Call: ToReflectedMethod"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: ToReflectedMethod: IMPLEMENT ME!"); + + return NULL; +} + + +/* ToReflectedField ************************************************************ + + Converts a field ID derived from cls to an instance of the + java.lang.reflect.Field class. + +*******************************************************************************/ + +jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, + jboolean isStatic) +{ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!"); return NULL; } -/**************** returns the method ID for an instance method ********************/ +/* Calling Instance Methods ***************************************************/ + +/* GetMethodID ***************************************************************** -jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig) + Returns the method ID for an instance (nonstatic) method of a class + or interface. The method may be defined in one of the clazz's + superclasses and inherited by clazz. The method is determined by + its name and signature. + + GetMethodID() causes an uninitialized class to be initialized. + +*******************************************************************************/ + +jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, + const char *sig) { - jmethodID m; + classinfo *c; + utf *uname; + utf *udesc; + methodinfo *m; + + STATISTICS(jniinvokation()); - m = class_resolvemethod ( - clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); + c = (classinfo *) clazz; - if (!m) *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + if (!c) + return NULL; + + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; + + /* try to get the method of the class or one of it's superclasses */ + + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); + + m = class_resolvemethod(clazz, uname, udesc); + + if (!m || (m->flags & ACC_STATIC)) { + *exceptionptr = exceptions_new_nosuchmethoderror(c, uname, udesc); + + return NULL; + } return m; } @@ -1103,30 +1461,38 @@ jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *s jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { - jobject ret; - va_list vaargs; + java_objectheader* ret; + va_list vaargs; -/* log_text("JNI-Call: CallObjectMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); ret = callObjectMethod(obj, methodID, vaargs); va_end(vaargs); - return ret; + return NewLocalRef(env, ret); } jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - return callObjectMethod(obj,methodID,args); + java_objectheader* ret; + + STATISTICS(jniinvokation()); + + ret = callObjectMethod(obj, methodID, args); + + return NewLocalRef(env, ret); } jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) { - log_text("JNI-Call: CallObjectMethodA"); + STATISTICS(jniinvokation()); - return NULL; + log_text("JNI-Call: CallObjectMethodA: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); } @@ -1137,10 +1503,12 @@ jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) jboolean ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallBooleanMethod");*/ va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs); + ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,vaargs); va_end(vaargs); return ret; @@ -1148,12 +1516,16 @@ jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args); + STATISTICS(jniinvokation()); + + return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BOOLEAN,args); } jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) { + STATISTICS(jniinvokation()); + log_text("JNI-Call: CallBooleanMethodA"); return 0; @@ -1164,10 +1536,12 @@ jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) jbyte ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallVyteMethod");*/ va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs); + ret = callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_BYTE,vaargs); va_end(vaargs); return ret; @@ -1176,13 +1550,18 @@ jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { /* log_text("JNI-Call: CallByteMethodV");*/ - return callIntegerMethod(obj,methodID,'B',args); + + STATISTICS(jniinvokation()); + + return callIntegerMethod(obj,methodID,PRIMITIVETYPE_BYTE,args); } jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallByteMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!"); return 0; } @@ -1193,10 +1572,12 @@ jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jchar ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallCharMethod");*/ va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs); + ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_CHAR, vaargs); va_end(vaargs); return ret; @@ -1205,14 +1586,19 @@ jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallCharMethodV");*/ - return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args); + + return callIntegerMethod(obj,get_virtual(obj,methodID),PRIMITIVETYPE_CHAR,args); } jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallCharMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!"); return 0; } @@ -1223,10 +1609,12 @@ jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jshort ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallShortMethod");*/ va_start(vaargs, methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs); + ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, vaargs); va_end(vaargs); return ret; @@ -1235,13 +1623,17 @@ jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args); + STATISTICS(jniinvokation()); + + return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_SHORT, args); } jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallShortMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!"); return 0; } @@ -1253,8 +1645,10 @@ jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jint ret; va_list vaargs; + STATISTICS(jniinvokation()); + va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs); + ret = callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, vaargs); va_end(vaargs); return ret; @@ -1263,13 +1657,17 @@ jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args); + STATISTICS(jniinvokation()); + + return callIntegerMethod(obj, get_virtual(obj, methodID),PRIMITIVETYPE_INT, args); } jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallIntMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!"); return 0; } @@ -1278,23 +1676,32 @@ 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; - return 0; + STATISTICS(jniinvokation()); + + va_start(vaargs,methodID); + ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs); + va_end(vaargs); + + return ret; } jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallLongMethodV"); + STATISTICS(jniinvokation()); - return 0; + return callLongMethod(obj,get_virtual(obj, methodID),args); } jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallLongMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!"); return 0; } @@ -1306,10 +1713,12 @@ jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jfloat ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallFloatMethod");*/ va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F'); + ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_FLOAT); va_end(vaargs); return ret; @@ -1318,14 +1727,19 @@ jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallFloatMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F'); + STATISTICS(jniinvokation()); + +/* log_text("JNI-Call: CallFloatMethodV"); */ + + return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_FLOAT); } jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallFloatMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!"); return 0; } @@ -1337,10 +1751,12 @@ jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jdouble ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallDoubleMethod");*/ va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D'); + ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, PRIMITIVETYPE_DOUBLE); va_end(vaargs); return ret; @@ -1349,14 +1765,20 @@ jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallDoubleMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D'); + STATISTICS(jniinvokation()); + +/* log_text("JNI-Call: CallDoubleMethodV"); */ + + return callFloatMethod(obj, get_virtual(obj, methodID), args, PRIMITIVETYPE_DOUBLE); } jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallDoubleMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!"); + return 0; } @@ -1366,49 +1788,60 @@ void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) { va_list vaargs; -/* log_text("JNI-Call: CallVoidMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs,methodID); - (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs); + (void) callIntegerMethod(obj, get_virtual(obj, methodID),TYPE_VOID, vaargs); va_end(vaargs); } -void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallVoidMethodV"); - (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args); + STATISTICS(jniinvokation()); + +/* log_text("JNI-Call: CallVoidMethodV"); */ + + (void) callIntegerMethod(obj, get_virtual(obj, methodID), TYPE_VOID,args); } -void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) +void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallVoidMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallVoidMethodA: IMPLEMENT ME!"); } -jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { - log_text("JNI-Call: CallNonvirtualObjectMethod"); + STATISTICS(jniinvokation()); - return NULL; + log_text("JNI-Call: CallNonvirtualObjectMethod: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); } -jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallNonvirtualObjectMethodV"); + STATISTICS(jniinvokation()); - return NULL; + log_text("JNI-Call: CallNonvirtualObjectMethodV: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); } -jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualObjectMethodA"); + STATISTICS(jniinvokation()); - return NULL; + log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); } @@ -1418,11 +1851,14 @@ jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jm jboolean ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallNonvirtualBooleanMethod");*/ va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs); + ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,vaargs); va_end(vaargs); + return ret; } @@ -1430,75 +1866,94 @@ jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jm jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/ - return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args); + + return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BOOLEAN,args); } -jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualBooleanMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!"); return 0; } - jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { jbyte ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallNonvirutalByteMethod");*/ va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs); + ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,vaargs); va_end(vaargs); + return ret; } jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',args); + return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_BYTE,args); } -jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualByteMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!"); return 0; } -jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { jchar ret; va_list vaargs; + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallNonVirtualCharMethod");*/ va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs); + ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,vaargs); va_end(vaargs); + return ret; } jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args); + + return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_CHAR,args); } jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualCharMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!"); return 0; } @@ -1510,25 +1965,33 @@ jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho jshort ret; va_list vaargs; + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualShortMethod");*/ va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs); + ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,vaargs); va_end(vaargs); + return ret; } jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args); + + return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_SHORT,args); } jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualShortMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!"); return 0; } @@ -1537,29 +2000,36 @@ jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmeth jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { + jint ret; + va_list vaargs; - jint ret; - va_list vaargs; + STATISTICS(jniinvokation()); /*log_text("JNI-Call: CallNonvirtualIntMethod");*/ - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs); - va_end(vaargs); - return ret; + va_start(vaargs,methodID); + ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,vaargs); + va_end(vaargs); + + return ret; } jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',args); + + return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),PRIMITIVETYPE_INT,args); } jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualIntMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!"); return 0; } @@ -1568,7 +2038,9 @@ jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { - log_text("JNI-Call: CallNonvirtualLongMethod"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualLongMethod: IMPLEMENT ME!"); return 0; } @@ -1576,7 +2048,9 @@ jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodI jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallNonvirtualLongMethodV"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualLongMethodV: IMPLEMENT ME!"); return 0; } @@ -1584,7 +2058,9 @@ jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethod jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualLongMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!"); return 0; } @@ -1596,27 +2072,33 @@ jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmetho jfloat ret; va_list vaargs; - /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/ + STATISTICS(jniinvokation()); + /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/ va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F'); + ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_FLOAT); va_end(vaargs); - return ret; + return ret; } jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallNonvirtualFloatMethodV"); - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F'); + STATISTICS(jniinvokation()); + +/* log_text("JNI-Call: CallNonvirtualFloatMethodV"); */ + + return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_FLOAT); } jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualFloatMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!"); return 0; } @@ -1627,26 +2109,34 @@ jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmet { jdouble ret; va_list vaargs; - log_text("JNI-Call: CallNonvirtualDoubleMethod"); + + STATISTICS(jniinvokation()); + +/* log_text("JNI-Call: CallNonvirtualDoubleMethod"); */ va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D'); + ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,PRIMITIVETYPE_DOUBLE); va_end(vaargs); - return ret; + return ret; } jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); + /* log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/ - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D'); + + return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,PRIMITIVETYPE_DOUBLE); } jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualDoubleMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!"); return 0; } @@ -1655,243 +2145,377 @@ jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jme void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { - va_list vaargs; + va_list vaargs; -/* log_text("JNI-Call: CallNonvirtualVoidMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs); - va_end(vaargs); +/* log_text("JNI-Call: CallNonvirtualVoidMethod");*/ -} + va_start(vaargs,methodID); + (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,vaargs); + va_end(vaargs); +} void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { -/* log_text("JNI-Call: CallNonvirtualVoidMethodV");*/ + STATISTICS(jniinvokation()); - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args); +/* log_text("JNI-Call: CallNonvirtualVoidMethodV");*/ + (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),TYPE_VOID,args); } void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) { - log_text("JNI-Call: CallNonvirtualVoidMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallNonvirtualVoidMethodA: IMPLEMENT ME!"); } -/************************* JNI-functions for accessing fields ************************/ -jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) +/* Accessing Fields of Objects ************************************************/ + +/* GetFieldID ****************************************************************** + + Returns the field ID for an instance (nonstatic) field of a + class. The field is specified by its name and signature. The + GetField and SetField families of accessor functions + use field IDs to retrieve object fields. + +*******************************************************************************/ + +jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - jfieldID f; + fieldinfo *f; + utf *uname; + utf *udesc; + + STATISTICS(jniinvokation()); -/* log_text("========================= searching for:"); - log_text(name); - log_text(sig);*/ - f = jclass_findfield(clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); + + f = class_findfield(clazz, uname, udesc); - if (!f) { -/* utf_display(clazz->name); - log_text(name); - log_text(sig);*/ - *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldError); - } + if (!f) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); + return f; } -/*************************** retrieve fieldid, abort on error ************************/ -jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig) -{ - jfieldID id = GetFieldID(env, clazz, name, sig); +/* GetField Routines ***************************************************** - if (!id) { - log_text("class:"); - utf_display(clazz->name); - log_text("\nfield:"); - log_text(name); - log_text("sig:"); - log_text(sig); + This family of accessor routines returns the value of an instance + (nonstatic) field of an object. The field to access is specified by + a field ID obtained by calling GetFieldID(). - panic("setfield_critical failed"); - } - return id; -} +*******************************************************************************/ -jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID) +jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jobject,fieldID); + java_objectheader *o; + + STATISTICS(jniinvokation()); + + o = GET_FIELD(obj, java_objectheader*, fieldID); + + return NewLocalRef(env, o); } -jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID) + +jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jboolean,fieldID); + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jboolean) i; } -jbyte GetByteField (JNIEnv *env, jobject obj, jfieldID fieldID) +jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jbyte,fieldID); + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jbyte) i; } -jchar GetCharField (JNIEnv *env, jobject obj, jfieldID fieldID) +jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jchar,fieldID); + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jchar) i; } -jshort GetShortField (JNIEnv *env, jobject obj, jfieldID fieldID) +jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jshort,fieldID); + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jshort) i; } -jint GetIntField (JNIEnv *env, jobject obj, jfieldID fieldID) +jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jint,fieldID); + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return i; } -jlong GetLongField (JNIEnv *env, jobject obj, jfieldID fieldID) +jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jlong,fieldID); + s8 l; + + STATISTICS(jniinvokation()); + + l = GET_FIELD(obj, s8, fieldID); + + return l; } -jfloat GetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID) +jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jfloat,fieldID); + float f; + + STATISTICS(jniinvokation()); + + f = GET_FIELD(obj, float, fieldID); + + return f; } -jdouble GetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID) +jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return getField(obj,jdouble,fieldID); + double d; + + STATISTICS(jniinvokation()); + + d = GET_FIELD(obj, double, fieldID); + + return d; } -void SetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val) + +/* SetField Routines ***************************************************** + + This family of accessor routines sets the value of an instance + (nonstatic) field of an object. The field to access is specified by + a field ID obtained by calling GetFieldID(). + +*******************************************************************************/ + +void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) { - setField(obj,jobject,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, java_objectheader*, fieldID, value); } -void SetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val) +void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value) { - setField(obj,jboolean,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -void SetByteField (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val) +void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value) { - setField(obj,jbyte,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -void SetCharField (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val) +void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value) { - setField(obj,jchar,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -void SetShortField (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val) +void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value) { - setField(obj,jshort,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -void SetIntField (JNIEnv *env, jobject obj, jfieldID fieldID, jint val) +void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value) { - setField(obj,jint,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -void SetLongField (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val) +void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value) { - setField(obj,jlong,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s8, fieldID, value); } -void SetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val) +void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value) { - setField(obj,jfloat,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, float, fieldID, value); } -void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val) +void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value) { - setField(obj,jdouble,fieldID,val); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, double, fieldID, value); } -/**************** JNI-functions for calling static methods **********************/ +/* Calling Static Methods *****************************************************/ + +/* GetStaticMethodID *********************************************************** + + Returns the method ID for a static method of a class. The method is + specified by its name and signature. + + GetStaticMethodID() causes an uninitialized class to be + initialized. -jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) +*******************************************************************************/ + +jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - jmethodID m; + classinfo *c; + utf *uname; + utf *udesc; + methodinfo *m; + + STATISTICS(jniinvokation()); + + c = (classinfo *) clazz; + + if (!c) + return NULL; + + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; + + /* try to get the static method of the class */ + + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); - m = class_resolvemethod( - clazz, - utf_new_char((char*) name), - utf_new_char((char*) sig)); + m = class_resolvemethod(c, uname, udesc); - if (!m) *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + if (!m || !(m->flags & ACC_STATIC)) { + *exceptionptr = exceptions_new_nosuchmethoderror(c, uname, udesc); + + return NULL; + } return m; } -jobject CallStaticObjectMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - log_text("JNI-Call: CallStaticObjectMethod"); + java_objectheader *ret; + va_list vaargs; - return NULL; + STATISTICS(jniinvokation()); + + va_start(vaargs, methodID); + ret = callObjectMethod(0, methodID, vaargs); + va_end(vaargs); + + return NewLocalRef(env, ret); } -jobject CallStaticObjectMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallStaticObjectMethodV"); + java_objectheader *ret; - return NULL; + STATISTICS(jniinvokation()); + + ret = callObjectMethod(0, methodID, args); + + return NewLocalRef(env, ret); } -jobject CallStaticObjectMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) +jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticObjectMethodA"); + STATISTICS(jniinvokation()); - return NULL; + log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); } -jboolean CallStaticBooleanMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jboolean ret; - va_list vaargs; + va_list vaargs; + jboolean ret; -/* log_text("JNI-Call: CallStaticBooleanMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(0,methodID,'Z',vaargs); - va_end(vaargs); - return ret; + va_start(vaargs, methodID); + ret = (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, vaargs); + va_end(vaargs); + return ret; } jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - return (jboolean) callIntegerMethod(0, methodID, 'Z', args); + STATISTICS(jniinvokation()); + + return (jboolean) callIntegerMethod(0, methodID, PRIMITIVETYPE_BOOLEAN, args); } + jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticBooleanMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!"); return 0; } @@ -1899,13 +2523,13 @@ jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jbyte ret; va_list vaargs; + jbyte ret; - /* log_text("JNI-Call: CallStaticByteMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); - ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs); + ret = (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, vaargs); va_end(vaargs); return ret; @@ -1914,13 +2538,17 @@ jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - return (jbyte) callIntegerMethod(0, methodID, 'B', args); + STATISTICS(jniinvokation()); + + return (jbyte) callIntegerMethod(0, methodID, PRIMITIVETYPE_BYTE, args); } jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticByteMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!"); return 0; } @@ -1928,13 +2556,13 @@ jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalu jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jchar ret; va_list vaargs; + jchar ret; - /* log_text("JNI-Call: CallStaticByteMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); - ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs); + ret = (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, vaargs); va_end(vaargs); return ret; @@ -1943,28 +2571,31 @@ jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - return (jchar) callIntegerMethod(0, methodID, 'C', args); + STATISTICS(jniinvokation()); + + return (jchar) callIntegerMethod(0, methodID, PRIMITIVETYPE_CHAR, args); } jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticCharMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!"); return 0; } - jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jshort ret; va_list vaargs; + jshort ret; - /* log_text("JNI-Call: CallStaticByteMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs); + va_start(vaargs, methodID); + ret = (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, vaargs); va_end(vaargs); return ret; @@ -1973,29 +2604,31 @@ jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - /*log_text("JNI-Call: CallStaticShortMethodV");*/ - return (jshort) callIntegerMethod(0, methodID, 'S', args); + STATISTICS(jniinvokation()); + + return (jshort) callIntegerMethod(0, methodID, PRIMITIVETYPE_SHORT, args); } jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticShortMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!"); return 0; } - jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jint ret; va_list vaargs; + jint ret; - /* log_text("JNI-Call: CallStaticIntMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); - ret = callIntegerMethod(0, methodID, 'I', vaargs); + ret = callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, vaargs); va_end(vaargs); return ret; @@ -2004,27 +2637,28 @@ jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallStaticIntMethodV"); + STATISTICS(jniinvokation()); - return callIntegerMethod(0, methodID, 'I', args); + return callIntegerMethod(0, methodID, PRIMITIVETYPE_INT, args); } jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticIntMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!"); return 0; } - jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jlong ret; va_list vaargs; + jlong ret; - /* log_text("JNI-Call: CallStaticLongMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); ret = callLongMethod(0, methodID, vaargs); @@ -2034,17 +2668,20 @@ jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) } -jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { - log_text("JNI-Call: CallStaticLongMethodV"); + STATISTICS(jniinvokation()); - return callLongMethod(0,methodID,args); + return callLongMethod(0, methodID, args); } jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticLongMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!"); return 0; } @@ -2053,13 +2690,13 @@ jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalu jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jfloat ret; va_list vaargs; + jfloat ret; - /* log_text("JNI-Call: CallStaticLongMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); - ret = callFloatMethod(0, methodID, vaargs, 'F'); + ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_FLOAT); va_end(vaargs); return ret; @@ -2068,30 +2705,32 @@ jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { + STATISTICS(jniinvokation()); - return callFloatMethod(0, methodID, args, 'F'); + return callFloatMethod(0, methodID, args, PRIMITIVETYPE_FLOAT); } jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticFloatMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!"); return 0; } - jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jdouble ret; va_list vaargs; + jdouble ret; - /* log_text("JNI-Call: CallStaticDoubleMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs,methodID); - ret = callFloatMethod(0, methodID, vaargs, 'D'); + ret = callFloatMethod(0, methodID, vaargs, PRIMITIVETYPE_DOUBLE); va_end(vaargs); return ret; @@ -2100,15 +2739,17 @@ jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, .. jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallStaticDoubleMethodV"); + STATISTICS(jniinvokation()); - return callFloatMethod(0, methodID, args, 'D'); + return callFloatMethod(0, methodID, args, PRIMITIVETYPE_DOUBLE); } jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallStaticDoubleMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!"); return 0; } @@ -2118,833 +2759,1705 @@ void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...) { va_list vaargs; -/* log_text("JNI-Call: CallStaticVoidMethod");*/ + STATISTICS(jniinvokation()); va_start(vaargs, methodID); - (void) callIntegerMethod(0, methodID, 'V', vaargs); + (void) callIntegerMethod(0, methodID, TYPE_VOID, vaargs); va_end(vaargs); } void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallStaticVoidMethodV"); - (void)callIntegerMethod(0, methodID, 'V', args); + STATISTICS(jniinvokation()); + + (void) callIntegerMethod(0, methodID, TYPE_VOID, args); } void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args) { - log_text("JNI-Call: CallStaticVoidMethodA"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: CallStaticVoidMethodA: IMPLEMENT ME!"); } -/****************** JNI-functions for accessing static fields ********************/ +/* Accessing Static Fields ****************************************************/ + +/* GetStaticFieldID ************************************************************ + + Returns the field ID for a static field of a class. The field is + specified by its name and signature. The GetStaticField and + SetStaticField families of accessor functions use field IDs + to retrieve static fields. -jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) +*******************************************************************************/ + +jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { jfieldID f; - f = jclass_findfield(clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); + STATISTICS(jniinvokation()); + + f = class_findfield(clazz, + utf_new_char((char *) name), + utf_new_char((char *) sig)); - if (!f) *exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldError); + if (!f) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); return f; } -jobject GetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID) +/* GetStaticField ******************************************************** + + This family of accessor routines returns the value of a static + field of an object. + +*******************************************************************************/ + +jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); - return fieldID->value.a; + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return NULL; + + return NewLocalRef(env, fieldID->value.a); } -jboolean GetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return false; + return fieldID->value.i; } -jbyte GetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0; + return fieldID->value.i; } -jchar GetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0; + return fieldID->value.i; } -jshort GetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0; + return fieldID->value.i; } -jint GetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0; + return fieldID->value.i; } -jlong GetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0; + return fieldID->value.l; } -jfloat GetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0.0; + return fieldID->value.f; } -jdouble GetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return 0.0; + return fieldID->value.d; } +/* SetStaticField ******************************************************* + + This family of accessor routines sets the value of a static field + of an object. -void SetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) +*******************************************************************************/ + +void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.a = value; } -void SetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) +void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.i = value; } -void SetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) +void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.i = value; } -void SetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) +void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.i = value; } -void SetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) +void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.i = value; } -void SetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) +void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.i = value; } -void SetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) +void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.l = value; } -void SetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) +void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.f = value; } -void SetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) +void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) { - class_init(clazz); + STATISTICS(jniinvokation()); + + if (!(clazz->state & CLASS_INITIALIZED)) + if (!initialize_class(clazz)) + return; + fieldID->value.d = value; } -/***** create new java.lang.String object from an array of Unicode characters ****/ +/* String Operations **********************************************************/ + +/* NewString ******************************************************************* -jstring NewString (JNIEnv *env, const jchar *buf, jsize len) + Create new java.lang.String object from an array of Unicode + characters. + +*******************************************************************************/ + +jstring NewString(JNIEnv *env, const jchar *buf, jsize len) { - u4 i; java_lang_String *s; - java_chararray *a; + java_chararray *a; + u4 i; + + STATISTICS(jniinvokation()); - s = (java_lang_String*) builtin_new (class_java_lang_String); - a = builtin_newarray_char (len); + s = (java_lang_String *) builtin_new(class_java_lang_String); + a = builtin_newarray_char(len); /* javastring or characterarray could not be created */ - if ( (!a) || (!s) ) return NULL; + if (!a || !s) + return NULL; /* copy text */ - for (i=0; idata[i] = buf[i]; - s -> value = a; - s -> offset = 0; - s -> count = len; + for (i = 0; i < len; i++) + a->data[i] = buf[i]; - return (jstring) s; + s->value = a; + s->offset = 0; + s->count = len; + + return (jstring) NewLocalRef(env, (jobject) s); } -static char emptyString[]=""; static jchar emptyStringJ[]={0,0}; -/******************* returns the length of a Java string ***************************/ +/* GetStringLength ************************************************************* + + Returns the length (the count of Unicode characters) of a Java + string. -jsize GetStringLength (JNIEnv *env, jstring str) +*******************************************************************************/ + +jsize GetStringLength(JNIEnv *env, jstring str) { - return ((java_lang_String*) str)->count; + return ((java_lang_String *) str)->count; } /******************** convertes javastring to u2-array ****************************/ -u2 *javastring_tou2 (jstring so) +u2 *javastring_tou2(jstring so) { - java_lang_String *s = (java_lang_String*) so; - java_chararray *a; - u4 i; - u2 *stringbuffer; + java_lang_String *s; + java_chararray *a; + u2 *stringbuffer; + u4 i; + + STATISTICS(jniinvokation()); - if (!s) return NULL; + s = (java_lang_String *) so; + + if (!s) + return NULL; a = s->value; - if (!a) return NULL; + + if (!a) + return NULL; /* allocate memory */ - stringbuffer = MNEW( u2 , s->count + 1 ); + + stringbuffer = MNEW(u2, s->count + 1); /* copy text */ - for (i=0; icount; i++) stringbuffer[i] = a->data[s->offset+i]; + + for (i = 0; i < s->count; i++) + stringbuffer[i] = a->data[s->offset + i]; /* terminate string */ + stringbuffer[i] = '\0'; return stringbuffer; } -/********* returns a pointer to an array of Unicode characters of the string *******/ -const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy) +/* GetStringChars ************************************************************** + + Returns a pointer to the array of Unicode characters of the + string. This pointer is valid until ReleaseStringchars() is called. + +*******************************************************************************/ + +const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) { - jchar *jc=javastring_tou2(str); + jchar *jc; + + STATISTICS(jniinvokation()); + + jc = javastring_tou2(str); if (jc) { - if (isCopy) *isCopy=JNI_TRUE; + if (isCopy) + *isCopy = JNI_TRUE; + return jc; } - if (isCopy) *isCopy=JNI_TRUE; + + if (isCopy) + *isCopy = JNI_TRUE; + return emptyStringJ; } -/**************** native code no longer needs access to chars **********************/ -void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars) +/* ReleaseStringChars ********************************************************** + + Informs the VM that the native code no longer needs access to + chars. The chars argument is a pointer obtained from string using + GetStringChars(). + +*******************************************************************************/ + +void ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars) { - if (chars==emptyStringJ) return; - MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1); + STATISTICS(jniinvokation()); + + if (chars == emptyStringJ) + return; + + MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1); } -/************ create new java.lang.String object from utf8-characterarray **********/ -jstring NewStringUTF (JNIEnv *env, const char *utf) +/* NewStringUTF **************************************************************** + + Constructs a new java.lang.String object from an array of UTF-8 characters. + +*******************************************************************************/ + +jstring NewStringUTF(JNIEnv *env, const char *bytes) { -/* log_text("NewStringUTF called");*/ - return (jstring) javastring_new(utf_new_char((char *) utf)); + java_lang_String *s; + + STATISTICS(jniinvokation()); + + s = javastring_new(utf_new_char(bytes)); + + return (jstring) NewLocalRef(env, (jobject) s); } + /****************** returns the utf8 length in bytes of a string *******************/ jsize GetStringUTFLength (JNIEnv *env, jstring string) { java_lang_String *s = (java_lang_String*) string; + STATISTICS(jniinvokation()); + return (jsize) u2_utflength(s->value->data, s->count); } -/************ converts a Javastring to an array of UTF-8 characters ****************/ -const char* GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy) +/* GetStringUTFChars *********************************************************** + + Returns a pointer to an array of UTF-8 characters of the + string. This array is valid until it is released by + ReleaseStringUTFChars(). + +*******************************************************************************/ + +const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) { - utf *u; - if (verbose) log_text("GetStringUTFChars:"); + utf *u; + + STATISTICS(jniinvokation()); - u=javastring_toutf((java_lang_String*) string,false); - if (isCopy) *isCopy=JNI_FALSE; - if (u) { - return u->text; - } - return emptyString; + if (!string) + return ""; + + if (isCopy) + *isCopy = JNI_TRUE; -} + u = javastring_toutf((java_lang_String *) string, false); -/***************** native code no longer needs access to utf ***********************/ + if (u) + return u->text; -void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars) -{ - /*we don't release utf chars right now, perhaps that should be done later. Since there is always one reference - the garbage collector will never get them*/ - /* - log_text("JNI-Call: ReleaseStringUTFChars"); - utf_display(utf_new_char(chars)); - */ + return ""; } -/************************** array operations ***************************************/ -jsize GetArrayLength (JNIEnv *env, jarray array) -{ - return array->size; -} +/* ReleaseStringUTFChars ******************************************************* -jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init) -{ - java_objectarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_anewarray (len, clazz); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + Informs the VM that the native code no longer needs access to + utf. The utf argument is a pointer derived from string using + GetStringUTFChars(). -jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index) +*******************************************************************************/ + +void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) { - jobject j = NULL; + STATISTICS(jniinvokation()); - if (indexheader.size) - j = array->data[index]; - else - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - - return j; + /* XXX we don't release utf chars right now, perhaps that should be done + later. Since there is always one reference the garbage collector will + never get them */ } -void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject val) -{ - if (index>=array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else { - /* check if the class of value is a subclass of the element class of the array */ +/* Array Operations ***********************************************************/ - if (!builtin_canstore((java_objectarray*)array,(java_objectheader*)val)) - *exceptionptr = proto_java_lang_ArrayStoreException; - else - array->data[index] = val; - } -} +/* GetArrayLength ************************************************************** + Returns the number of elements in the array. +*******************************************************************************/ -jbooleanArray NewBooleanArray (JNIEnv *env, jsize len) +jsize GetArrayLength(JNIEnv *env, jarray array) { - java_booleanarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_boolean(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; + STATISTICS(jniinvokation()); + + return array->size; } -jbyteArray NewByteArray (JNIEnv *env, jsize len) -{ - java_bytearray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_byte(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} +/* NewObjectArray ************************************************************** + Constructs a new array holding objects in class elementClass. All + elements are initially set to initialElement. -jcharArray NewCharArray (JNIEnv *env, jsize len) +*******************************************************************************/ + +jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) { - java_chararray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_char(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + java_objectarray *oa; + s4 i; + STATISTICS(jniinvokation()); -jshortArray NewShortArray (JNIEnv *env, jsize len) -{ - java_shortarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; + if (length < 0) { + exceptions_throw_negativearraysizeexception(); return NULL; - } - j = builtin_newarray_short(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + } + oa = builtin_anewarray(length, elementClass); -jintArray NewIntArray (JNIEnv *env, jsize len) -{ - java_intarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; + if (!oa) return NULL; - } - j = builtin_newarray_int(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + /* set all elements to initialElement */ -jlongArray NewLongArray (JNIEnv *env, jsize len) -{ - java_longarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_long(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; + for (i = 0; i < length; i++) + oa->data[i] = initialElement; + + return (jobjectArray) NewLocalRef(env, (jobject) oa); } -jfloatArray NewFloatArray (JNIEnv *env, jsize len) +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { - java_floatarray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_float(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + jobject o; + STATISTICS(jniinvokation()); -jdoubleArray NewDoubleArray (JNIEnv *env, jsize len) -{ - java_doublearray *j; - if (len<0) { - *exceptionptr=proto_java_lang_NegativeArraySizeException; + if (index >= array->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); return NULL; - } - j = builtin_newarray_double(len); - if (!j) *exceptionptr = proto_java_lang_OutOfMemoryError; - return j; + } + + o = array->data[index]; + + return NewLocalRef(env, o); } -jboolean * GetBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *isCopy) +void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + java_objectarray *oa; + java_objectheader *o; + STATISTICS(jniinvokation()); -jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + oa = (java_objectarray *) array; + o = (java_objectheader *) val; + if (index >= array->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } -jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + /* check if the class of value is a subclass of the element class + of the array */ + if (!builtin_canstore(oa, o)) { + *exceptionptr = new_exception(string_java_lang_ArrayStoreException); + + return; + } + + array->data[index] = val; +} + + +jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) +{ + java_booleanarray *ba; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + ba = builtin_newarray_boolean(len); + + return (jbooleanArray) NewLocalRef(env, (jobject) ba); +} + + +jbyteArray NewByteArray(JNIEnv *env, jsize len) +{ + java_bytearray *ba; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + ba = builtin_newarray_byte(len); + + return (jbyteArray) NewLocalRef(env, (jobject) ba); +} + + +jcharArray NewCharArray(JNIEnv *env, jsize len) +{ + java_chararray *ca; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + ca = builtin_newarray_char(len); + + return (jcharArray) NewLocalRef(env, (jobject) ca); +} + + +jshortArray NewShortArray(JNIEnv *env, jsize len) +{ + java_shortarray *sa; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + sa = builtin_newarray_short(len); + + return (jshortArray) NewLocalRef(env, (jobject) sa); +} + + +jintArray NewIntArray(JNIEnv *env, jsize len) +{ + java_intarray *ia; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + ia = builtin_newarray_int(len); + + return (jintArray) NewLocalRef(env, (jobject) ia); +} + + +jlongArray NewLongArray(JNIEnv *env, jsize len) +{ + java_longarray *la; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + la = builtin_newarray_long(len); + + return (jlongArray) NewLocalRef(env, (jobject) la); +} + + +jfloatArray NewFloatArray(JNIEnv *env, jsize len) +{ + java_floatarray *fa; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + fa = builtin_newarray_float(len); + + return (jfloatArray) NewLocalRef(env, (jobject) fa); +} + + +jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) +{ + java_doublearray *da; + + STATISTICS(jniinvokation()); + + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + da = builtin_newarray_double(len); + + return (jdoubleArray) NewLocalRef(env, (jobject) da); +} + + +/* GetArrayElements ********************************************* + + A family of functions that returns the body of the primitive array. + +*******************************************************************************/ + +jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *isCopy) +{ + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + + return array->data; +} + + +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) +{ + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + + return array->data; +} + + +jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) +{ + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + + return array->data; +} + + +jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) +{ + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; -jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; return array->data; } -jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy) +jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) { - if (isCopy) *isCopy = JNI_FALSE; + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + return array->data; } -jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy) +jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) { - if (isCopy) *isCopy = JNI_FALSE; + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + return array->data; } -jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy) +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { - if (isCopy) *isCopy = JNI_FALSE; + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + return array->data; } -jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy) +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jboolean *isCopy) { - if (isCopy) *isCopy = JNI_FALSE; + STATISTICS(jniinvokation()); + + if (isCopy) + *isCopy = JNI_FALSE; + return array->data; } +/* ReleaseArrayElements ***************************************** + + A family of functions that informs the VM that the native code no + longer needs access to elems. The elems argument is a pointer + derived from array using the corresponding + GetArrayElements() function. If necessary, this + function copies back all changes made to elems to the original + array. -void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode) +*******************************************************************************/ + +void ReleaseBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *elems, jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseCharArrayElements (JNIEnv *env, jcharArray array, jchar *elems, jint mode) +void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseShortArrayElements (JNIEnv *env, jshortArray array, jshort *elems, jint mode) +void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode) +void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode) +void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, + jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode) +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jdouble *elems, jint mode) { - /* empty */ + STATISTICS(jniinvokation()); + + if (elems != array->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(array->data, elems, jboolean, array->header.size); + break; + case 0: + MCOPY(array->data, elems, jboolean, array->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -void GetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) + +/* GetArrayRegion ********************************************** + + A family of functions that copies a region of a primitive array + into a buffer. + +*******************************************************************************/ + +void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jboolean, len); } -void GetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) +void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jbyte, len); } -void GetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) +void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jchar, len); } -void GetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) +void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jshort, len); } -void GetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) +void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jint, len); } -void GetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) +void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + jlong *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jlong, len); } -void GetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) +void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jfloat, len); } -void GetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) +void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start+len>array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + MCOPY(buf, &array->data[start], jdouble, len); } -void SetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) +/* SetArrayRegion ********************************************** + + A family of functions that copies back a region of a primitive + array from a buffer. + +*******************************************************************************/ + +void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + MCOPY(&array->data[start], buf, jboolean, len); } -void SetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) +void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + MCOPY(&array->data[start], buf, jbyte, len); } -void SetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) +void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&array->data[start], buf, jchar, len); } -void SetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) +void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + MCOPY(&array->data[start], buf, jshort, len); } -void SetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) +void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&array->data[start], buf, jint, len); } -void SetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) + +void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, + jlong *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&array->data[start], buf, jlong, len); } -void SetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) + +void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&array->data[start], buf, jfloat, len); } -void SetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) + +void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - if (start<0 || len<0 || start+len>array->header.size) - *exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; + STATISTICS(jniinvokation()); + + if (start < 0 || len < 0 || start + len > array->header.size) + exceptions_throw_arrayindexoutofboundsexception(); else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + MCOPY(&array->data[start], buf, jdouble, len); } -jint RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods) + +/* Registering Native Methods *************************************************/ + +/* RegisterNatives ************************************************************* + + Registers native methods with the class specified by the clazz + argument. The methods parameter specifies an array of + JNINativeMethod structures that contain the names, signatures, and + function pointers of the native methods. The nMethods parameter + specifies the number of native methods in the array. + +*******************************************************************************/ + +jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods) { - log_text("JNI-Call: RegisterNatives"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!"); + return 0; } -jint UnregisterNatives (JNIEnv* env, jclass clazz) +/* UnregisterNatives *********************************************************** + + Unregisters native methods of a class. The class goes back to the + state before it was linked or registered with its native method + functions. + + This function should not be used in normal native code. Instead, it + provides special programs a way to reload and relink native + libraries. + +*******************************************************************************/ + +jint UnregisterNatives(JNIEnv *env, jclass clazz) { - log_text("JNI-Call: UnregisterNatives"); + STATISTICS(jniinvokation()); + + /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */ + + log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!"); + return 0; } -/******************************* monitor operations ********************************/ -jint MonitorEnter (JNIEnv* env, jobject obj) +/* Monitor Operations *********************************************************/ + +/* MonitorEnter **************************************************************** + + Enters the monitor associated with the underlying Java object + referred to by obj. + +*******************************************************************************/ + +jint MonitorEnter(JNIEnv *env, jobject obj) { - builtin_monitorenter(obj); - return 0; + STATISTICS(jniinvokation()); + + if (!obj) { + exceptions_throw_nullpointerexception(); + return JNI_ERR; + } + +#if defined(USE_THREADS) + builtin_monitorenter(obj); +#endif + + return JNI_OK; } -jint MonitorExit (JNIEnv* env, jobject obj) +/* MonitorExit ***************************************************************** + + The current thread must be the owner of the monitor associated with + the underlying Java object referred to by obj. The thread + decrements the counter indicating the number of times it has + entered this monitor. If the value of the counter becomes zero, the + current thread releases the monitor. + +*******************************************************************************/ + +jint MonitorExit(JNIEnv *env, jobject obj) { - builtin_monitorexit(obj); - return 0; + STATISTICS(jniinvokation()); + + if (!obj) { + exceptions_throw_nullpointerexception(); + return JNI_ERR; + } + +#if defined(USE_THREADS) + builtin_monitorexit(obj); +#endif + + return JNI_OK; } -/************************************* JavaVM interface ****************************/ -#ifdef __cplusplus -#error CPP mode not supported yet -#else -jint GetJavaVM (JNIEnv* env, JavaVM **vm) +/* JavaVM Interface ***********************************************************/ + +/* GetJavaVM ******************************************************************* + + Returns the Java VM interface (used in the Invocation API) + associated with the current thread. The result is placed at the + location pointed to by the second argument, vm. + +*******************************************************************************/ + +jint GetJavaVM(JNIEnv *env, JavaVM **vm) { - log_text("JNI-Call: GetJavaVM"); - *vm=&javaVM; - return 0; + STATISTICS(jniinvokation()); + + *vm = &ptr_jvm; + + return 0; } -#endif /*__cplusplus*/ -void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) + +void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) { - log_text("JNI-Call: GetStringRegion"); + STATISTICS(jniinvokation()); + log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!"); } + void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf) { - log_text("JNI-Call: GetStringUTFRegion"); + STATISTICS(jniinvokation()); + log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!"); } -/****************** obtain direct pointer to array elements ***********************/ -void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy) +/* GetPrimitiveArrayCritical *************************************************** + + Obtain a direct pointer to array elements. + +*******************************************************************************/ + +void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) { - java_objectheader *s = (java_objectheader*) array; - arraydescriptor *desc = s->vftbl->arraydesc; + java_bytearray *ba; + jbyte *bp; + + ba = (java_bytearray *) array; + + /* do the same as Kaffe does */ - if (!desc) return NULL; + bp = GetByteArrayElements(env, ba, isCopy); - return ((u1*)s) + desc->dataoffset; + return (void *) bp; } -void ReleasePrimitiveArrayCritical (JNIEnv* env, jarray array, void *carray, jint mode) +/* ReleasePrimitiveArrayCritical *********************************************** + + No specific documentation. + +*******************************************************************************/ + +void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, + jint mode) { - log_text("JNI-Call: ReleasePrimitiveArrayCritical"); + STATISTICS(jniinvokation()); - /* empty */ + /* do the same as Kaffe does */ + + ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray, mode); } -/********* returns a pointer to an array of Unicode characters of the string *******/ -const jchar * GetStringCritical (JNIEnv* env, jstring string, jboolean *isCopy) +/* GetStringCritical *********************************************************** + + The semantics of these two functions are similar to the existing + Get/ReleaseStringChars functions. + +*******************************************************************************/ + +const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) { - log_text("JNI-Call: GetStringCritical"); + STATISTICS(jniinvokation()); - return GetStringChars(env,string,isCopy); + return GetStringChars(env, string, isCopy); } -/**************** native code no longer needs access to chars **********************/ -void ReleaseStringCritical (JNIEnv* env, jstring string, const jchar *cstring) +void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring) { - log_text("JNI-Call: ReleaseStringCritical"); + STATISTICS(jniinvokation()); - ReleaseStringChars(env,string,cstring); + ReleaseStringChars(env, string, cstring); } -jweak NewWeakGlobalRef (JNIEnv* env, jobject obj) +jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { - log_text("JNI-Call: NewWeakGlobalRef"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!"); return obj; } -void DeleteWeakGlobalRef (JNIEnv* env, jweak ref) +void DeleteWeakGlobalRef(JNIEnv* env, jweak ref) +{ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME"); +} + + +/* NewGlobalRef **************************************************************** + + Creates a new global reference to the object referred to by the obj + argument. + +*******************************************************************************/ + +jobject NewGlobalRef(JNIEnv* env, jobject lobj) { - log_text("JNI-Call: DeleteWeakGlobalRef"); + java_lang_Integer *refcount; + java_objectheader *newval; + + STATISTICS(jniinvokation()); + +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif + + refcount = (java_lang_Integer *) + asm_calljavafunction(getmid, *global_ref_table, lobj, NULL, NULL); + + if (refcount == NULL) { + newval = native_new_and_init_int(class_java_lang_Integer, 1); + + if (newval == NULL) { +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif + return NULL; + } - /* empty */ + asm_calljavafunction(putmid, *global_ref_table, lobj, newval, NULL); + + } else { + /* we can access the object itself, as we are in a + synchronized section */ + + refcount->value++; + } + +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif + + return lobj; } -/******************************* check for pending exception ***********************/ +/* DeleteGlobalRef ************************************************************* + + Deletes the global reference pointed to by globalRef. +*******************************************************************************/ -jboolean ExceptionCheck(JNIEnv* env) +void DeleteGlobalRef(JNIEnv* env, jobject globalRef) { - log_text("JNI-Call: ExceptionCheck"); + java_lang_Integer *refcount; + s4 val; + + STATISTICS(jniinvokation()); + +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif + + refcount = (java_lang_Integer *) + asm_calljavafunction(getmid, *global_ref_table, globalRef, NULL, NULL); + + if (refcount == NULL) { + log_text("JNI-DeleteGlobalRef: unable to find global reference"); + return; + } + + /* we can access the object itself, as we are in a synchronized + section */ + + val = refcount->value - 1; + + if (val == 0) { + asm_calljavafunction(removemid, *global_ref_table, refcount, NULL, + NULL); + + } else { + /* we do not create a new object, but set the new value into + the old one */ + + refcount->value = val; + } + +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif +} + + +/* ExceptionCheck ************************************************************** + + Returns JNI_TRUE when there is a pending exception; otherwise, + returns JNI_FALSE. + +*******************************************************************************/ + +jboolean ExceptionCheck(JNIEnv *env) +{ + STATISTICS(jniinvokation()); return *exceptionptr ? JNI_TRUE : JNI_FALSE; } +/* New JNI 1.4 functions ******************************************************/ + +/* NewDirectByteBuffer ********************************************************* + + Allocates and returns a direct java.nio.ByteBuffer referring to the + block of memory starting at the memory address address and + extending capacity bytes. + +*******************************************************************************/ + +jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) +{ + java_objectheader *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *paddress; +#else + gnu_classpath_Pointer32 *paddress; +#endif + + STATISTICS(jniinvokation()); + + log_text("JNI-NewDirectByteBuffer: called"); +#if 0 + /* allocate a java.nio.DirectByteBufferImpl$ReadWrite object */ + + if (!(nbuf = (java_nio_DirectByteBufferImpl$ReadWrite *) + builtin_new(class_java_nio_DirectByteBufferImpl_ReadWrite))) + return NULL; +#endif + /* alocate a gnu.classpath.Pointer{32,64} object */ + +#if SIZEOF_VOID_P == 8 + if (!(paddress = (gnu_classpath_Pointer64 *) + builtin_new(class_gnu_classpath_Pointer64))) +#else + if (!(paddress = (gnu_classpath_Pointer32 *) + builtin_new(class_gnu_classpath_Pointer32))) +#endif + return NULL; + + /* fill gnu.classpath.Pointer{32,64} with address */ + + paddress->data = (ptrint) address; + +#if 0 + /* fill java.nio.Buffer object */ + + nbuf->cap = (s4) capacity; + nbuf->limit = (s4) capacity; + nbuf->pos = 0; + nbuf->address = (gnu_classpath_Pointer *) paddress; +#endif + + nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite, + dbbirw_init, NULL, paddress, + (jint) capacity, (jint) capacity, (jint) 0); + + /* add local reference and return the value */ + + return NewLocalRef(env, nbuf); +} + + +/* GetDirectBufferAddress ****************************************************** + + Fetches and returns the starting address of the memory region + referenced by the given direct java.nio.Buffer. + +*******************************************************************************/ + +void *GetDirectBufferAddress(JNIEnv *env, jobject buf) +{ + java_nio_DirectByteBufferImpl *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *address; +#else + gnu_classpath_Pointer32 *address; +#endif + + STATISTICS(jniinvokation()); + +#if 0 + if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl)) + return NULL; +#endif + + nbuf = (java_nio_DirectByteBufferImpl *) buf; + +#if SIZEOF_VOID_P == 8 + address = (gnu_classpath_Pointer64 *) nbuf->address; +#else + address = (gnu_classpath_Pointer32 *) nbuf->address; +#endif + + return (void *) address->data; +} + + +/* GetDirectBufferCapacity ***************************************************** + + Fetches and returns the capacity in bytes of the memory region + referenced by the given direct java.nio.Buffer. + +*******************************************************************************/ + +jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) +{ + java_nio_Buffer *nbuf; + + STATISTICS(jniinvokation()); + + if (buf == NULL) + return -1; + + nbuf = (java_nio_Buffer *) buf; + + return (jlong) nbuf->cap; +} jint DestroyJavaVM(JavaVM *vm) { - log_text("DestroyJavaVM called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DestroyJavaVM: IMPLEMENT ME!"); return 0; } -jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2) +/* AttachCurrentThread ********************************************************* + + Attaches the current thread to a Java VM. Returns a JNI interface + pointer in the JNIEnv argument. + + Trying to attach a thread that is already attached is a no-op. + + A native thread cannot be attached simultaneously to two Java VMs. + + When a thread is attached to the VM, the context class loader is + the bootstrap loader. + +*******************************************************************************/ + +jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args) { - log_text("AttachCurrentThread called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!"); + +#if !defined(HAVE___THREAD) +/* cacao_thread_attach();*/ +#else + #error "No idea how to implement that. Perhaps Stefan knows" +#endif + + *env = &ptr_env; return 0; } @@ -2952,509 +4465,640 @@ jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2) jint DetachCurrentThread(JavaVM *vm) { - log_text("DetachCurrentThread called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!"); return 0; } -jint GetEnv(JavaVM *vm, void **environment, jint jniversion) +/* GetEnv ********************************************************************** + + If the current thread is not attached to the VM, sets *env to NULL, + and returns JNI_EDETACHED. If the specified version is not + supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise, + sets *env to the appropriate interface, and returns JNI_OK. + +*******************************************************************************/ + +jint GetEnv(JavaVM *vm, void **env, jint version) { - *environment = &env; + STATISTICS(jniinvokation()); - return 0; +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + if (thread_getself() == NULL) { + *env = NULL; + + return JNI_EDETACHED; + } +#endif + + if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) || + (version == JNI_VERSION_1_4)) { + *env = &ptr_env; + + return JNI_OK; + } + +#if defined(ENABLE_JVMTI) + if (version == JVMTI_VERSION_1_0) { + *env = (void *) new_jvmtienv(); + + if (env != NULL) + return JNI_OK; + } +#endif + + *env = NULL; + + return JNI_EVERSION; } + jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2) { - log_text("AttachCurrentThreadAsDaemon called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!"); return 0; } -/********************************* JNI invocation table ******************************/ +/* JNI invocation table *******************************************************/ -struct _JavaVM javaVMTable={ - NULL, - NULL, - NULL, - &DestroyJavaVM, - &AttachCurrentThread, - &DetachCurrentThread, - &GetEnv, - &AttachCurrentThreadAsDaemon +const struct JNIInvokeInterface JNI_JavaVMTable = { + NULL, + NULL, + NULL, + + DestroyJavaVM, + AttachCurrentThread, + DetachCurrentThread, + GetEnv, + AttachCurrentThreadAsDaemon }; -JavaVM javaVM = &javaVMTable; - - -/********************************* JNI function table ******************************/ - -struct JNI_Table envTable = { - NULL, - NULL, - NULL, - NULL, - &GetVersion, - &DefineClass, - &FindClass, - &FromReflectedMethod, - &FromReflectedField, - &ToReflectedMethod, - &GetSuperclass, - &IsAssignableForm, - &ToReflectedField, - &Throw, - &ThrowNew, - &ExceptionOccurred, - &ExceptionDescribe, - &ExceptionClear, - &FatalError, - &PushLocalFrame, - &PopLocalFrame, - &NewGlobalRef, - &DeleteGlobalRef, - &DeleteLocalRef, - &IsSameObject, - &NewLocalRef, - &EnsureLocalCapacity, - &AllocObject, - &NewObject, - &NewObjectV, - &NewObjectA, - &GetObjectClass, - &IsInstanceOf, - &GetMethodID, - &CallObjectMethod, - &CallObjectMethodV, - &CallObjectMethodA, - &CallBooleanMethod, - &CallBooleanMethodV, - &CallBooleanMethodA, - &CallByteMethod, - &CallByteMethodV, - &CallByteMethodA, - &CallCharMethod, - &CallCharMethodV, - &CallCharMethodA, - &CallShortMethod, - &CallShortMethodV, - &CallShortMethodA, - &CallIntMethod, - &CallIntMethodV, - &CallIntMethodA, - &CallLongMethod, - &CallLongMethodV, - &CallLongMethodA, - &CallFloatMethod, - &CallFloatMethodV, - &CallFloatMethodA, - &CallDoubleMethod, - &CallDoubleMethodV, - &CallDoubleMethodA, - &CallVoidMethod, - &CallVoidMethodV, - &CallVoidMethodA, - &CallNonvirtualObjectMethod, - &CallNonvirtualObjectMethodV, - &CallNonvirtualObjectMethodA, - &CallNonvirtualBooleanMethod, - &CallNonvirtualBooleanMethodV, - &CallNonvirtualBooleanMethodA, - &CallNonvirtualByteMethod, - &CallNonvirtualByteMethodV, - &CallNonvirtualByteMethodA, - &CallNonvirtualCharMethod, - &CallNonvirtualCharMethodV, - &CallNonvirtualCharMethodA, - &CallNonvirtualShortMethod, - &CallNonvirtualShortMethodV, - &CallNonvirtualShortMethodA, - &CallNonvirtualIntMethod, - &CallNonvirtualIntMethodV, - &CallNonvirtualIntMethodA, - &CallNonvirtualLongMethod, - &CallNonvirtualLongMethodV, - &CallNonvirtualLongMethodA, - &CallNonvirtualFloatMethod, - &CallNonvirtualFloatMethodV, - &CallNonvirtualFloatMethodA, - &CallNonvirtualDoubleMethod, - &CallNonvirtualDoubleMethodV, - &CallNonvirtualDoubleMethodA, - &CallNonvirtualVoidMethod, - &CallNonvirtualVoidMethodV, - &CallNonvirtualVoidMethodA, - &GetFieldID, - &GetObjectField, - &GetBooleanField, - &GetByteField, - &GetCharField, - &GetShortField, - &GetIntField, - &GetLongField, - &GetFloatField, - &GetDoubleField, - &SetObjectField, - &SetBooleanField, - &SetByteField, - &SetCharField, - &SetShortField, - &SetIntField, - &SetLongField, - &SetFloatField, - &SetDoubleField, - &GetStaticMethodID, - &CallStaticObjectMethod, - &CallStaticObjectMethodV, - &CallStaticObjectMethodA, - &CallStaticBooleanMethod, - &CallStaticBooleanMethodV, - &CallStaticBooleanMethodA, - &CallStaticByteMethod, - &CallStaticByteMethodV, - &CallStaticByteMethodA, - &CallStaticCharMethod, - &CallStaticCharMethodV, - &CallStaticCharMethodA, - &CallStaticShortMethod, - &CallStaticShortMethodV, - &CallStaticShortMethodA, - &CallStaticIntMethod, - &CallStaticIntMethodV, - &CallStaticIntMethodA, - &CallStaticLongMethod, - &CallStaticLongMethodV, - &CallStaticLongMethodA, - &CallStaticFloatMethod, - &CallStaticFloatMethodV, - &CallStaticFloatMethodA, - &CallStaticDoubleMethod, - &CallStaticDoubleMethodV, - &CallStaticDoubleMethodA, - &CallStaticVoidMethod, - &CallStaticVoidMethodV, - &CallStaticVoidMethodA, - &GetStaticFieldID, - &GetStaticObjectField, - &GetStaticBooleanField, - &GetStaticByteField, - &GetStaticCharField, - &GetStaticShortField, - &GetStaticIntField, - &GetStaticLongField, - &GetStaticFloatField, - &GetStaticDoubleField, - &SetStaticObjectField, - &SetStaticBooleanField, - &SetStaticByteField, - &SetStaticCharField, - &SetStaticShortField, - &SetStaticIntField, - &SetStaticLongField, - &SetStaticFloatField, - &SetStaticDoubleField, - &NewString, - &GetStringLength, - &GetStringChars, - &ReleaseStringChars, - &NewStringUTF, - &GetStringUTFLength, - &GetStringUTFChars, - &ReleaseStringUTFChars, - &GetArrayLength, - &NewObjectArray, - &GetObjectArrayElement, - &SetObjectArrayElement, - &NewBooleanArray, - &NewByteArray, - &NewCharArray, - &NewShortArray, - &NewIntArray, - &NewLongArray, - &NewFloatArray, - &NewDoubleArray, - &GetBooleanArrayElements, - &GetByteArrayElements, - &GetCharArrayElements, - &GetShortArrayElements, - &GetIntArrayElements, - &GetLongArrayElements, - &GetFloatArrayElements, - &GetDoubleArrayElements, - &ReleaseBooleanArrayElements, - &ReleaseByteArrayElements, - &ReleaseCharArrayElements, - &ReleaseShortArrayElements, - &ReleaseIntArrayElements, - &ReleaseLongArrayElements, - &ReleaseFloatArrayElements, - &ReleaseDoubleArrayElements, - &GetBooleanArrayRegion, - &GetByteArrayRegion, - &GetCharArrayRegion, - &GetShortArrayRegion, - &GetIntArrayRegion, - &GetLongArrayRegion, - &GetFloatArrayRegion, - &GetDoubleArrayRegion, - &SetBooleanArrayRegion, - &SetByteArrayRegion, - &SetCharArrayRegion, - &SetShortArrayRegion, - &SetIntArrayRegion, - &SetLongArrayRegion, - &SetFloatArrayRegion, - &SetDoubleArrayRegion, - &RegisterNatives, - &UnregisterNatives, - &MonitorEnter, - &MonitorExit, - &GetJavaVM, - &GetStringRegion, - &GetStringUTFRegion, - &GetPrimitiveArrayCritical, - &ReleasePrimitiveArrayCritical, - &GetStringCritical, - &ReleaseStringCritical, - &NewWeakGlobalRef, - &DeleteWeakGlobalRef, - &ExceptionCheck + +/* JNI function table *********************************************************/ + +struct JNINativeInterface JNI_JNIEnvTable = { + NULL, + NULL, + NULL, + NULL, + &GetVersion, + + &DefineClass, + &FindClass, + &FromReflectedMethod, + &FromReflectedField, + &ToReflectedMethod, + &GetSuperclass, + &IsAssignableFrom, + &ToReflectedField, + + &Throw, + &ThrowNew, + &ExceptionOccurred, + &ExceptionDescribe, + &ExceptionClear, + &FatalError, + &PushLocalFrame, + &PopLocalFrame, + + &NewGlobalRef, + &DeleteGlobalRef, + &DeleteLocalRef, + &IsSameObject, + &NewLocalRef, + &EnsureLocalCapacity, + + &AllocObject, + &NewObject, + &NewObjectV, + &NewObjectA, + + &GetObjectClass, + &IsInstanceOf, + + &GetMethodID, + + &CallObjectMethod, + &CallObjectMethodV, + &CallObjectMethodA, + &CallBooleanMethod, + &CallBooleanMethodV, + &CallBooleanMethodA, + &CallByteMethod, + &CallByteMethodV, + &CallByteMethodA, + &CallCharMethod, + &CallCharMethodV, + &CallCharMethodA, + &CallShortMethod, + &CallShortMethodV, + &CallShortMethodA, + &CallIntMethod, + &CallIntMethodV, + &CallIntMethodA, + &CallLongMethod, + &CallLongMethodV, + &CallLongMethodA, + &CallFloatMethod, + &CallFloatMethodV, + &CallFloatMethodA, + &CallDoubleMethod, + &CallDoubleMethodV, + &CallDoubleMethodA, + &CallVoidMethod, + &CallVoidMethodV, + &CallVoidMethodA, + + &CallNonvirtualObjectMethod, + &CallNonvirtualObjectMethodV, + &CallNonvirtualObjectMethodA, + &CallNonvirtualBooleanMethod, + &CallNonvirtualBooleanMethodV, + &CallNonvirtualBooleanMethodA, + &CallNonvirtualByteMethod, + &CallNonvirtualByteMethodV, + &CallNonvirtualByteMethodA, + &CallNonvirtualCharMethod, + &CallNonvirtualCharMethodV, + &CallNonvirtualCharMethodA, + &CallNonvirtualShortMethod, + &CallNonvirtualShortMethodV, + &CallNonvirtualShortMethodA, + &CallNonvirtualIntMethod, + &CallNonvirtualIntMethodV, + &CallNonvirtualIntMethodA, + &CallNonvirtualLongMethod, + &CallNonvirtualLongMethodV, + &CallNonvirtualLongMethodA, + &CallNonvirtualFloatMethod, + &CallNonvirtualFloatMethodV, + &CallNonvirtualFloatMethodA, + &CallNonvirtualDoubleMethod, + &CallNonvirtualDoubleMethodV, + &CallNonvirtualDoubleMethodA, + &CallNonvirtualVoidMethod, + &CallNonvirtualVoidMethodV, + &CallNonvirtualVoidMethodA, + + &GetFieldID, + + &GetObjectField, + &GetBooleanField, + &GetByteField, + &GetCharField, + &GetShortField, + &GetIntField, + &GetLongField, + &GetFloatField, + &GetDoubleField, + &SetObjectField, + &SetBooleanField, + &SetByteField, + &SetCharField, + &SetShortField, + &SetIntField, + &SetLongField, + &SetFloatField, + &SetDoubleField, + + &GetStaticMethodID, + + &CallStaticObjectMethod, + &CallStaticObjectMethodV, + &CallStaticObjectMethodA, + &CallStaticBooleanMethod, + &CallStaticBooleanMethodV, + &CallStaticBooleanMethodA, + &CallStaticByteMethod, + &CallStaticByteMethodV, + &CallStaticByteMethodA, + &CallStaticCharMethod, + &CallStaticCharMethodV, + &CallStaticCharMethodA, + &CallStaticShortMethod, + &CallStaticShortMethodV, + &CallStaticShortMethodA, + &CallStaticIntMethod, + &CallStaticIntMethodV, + &CallStaticIntMethodA, + &CallStaticLongMethod, + &CallStaticLongMethodV, + &CallStaticLongMethodA, + &CallStaticFloatMethod, + &CallStaticFloatMethodV, + &CallStaticFloatMethodA, + &CallStaticDoubleMethod, + &CallStaticDoubleMethodV, + &CallStaticDoubleMethodA, + &CallStaticVoidMethod, + &CallStaticVoidMethodV, + &CallStaticVoidMethodA, + + &GetStaticFieldID, + + &GetStaticObjectField, + &GetStaticBooleanField, + &GetStaticByteField, + &GetStaticCharField, + &GetStaticShortField, + &GetStaticIntField, + &GetStaticLongField, + &GetStaticFloatField, + &GetStaticDoubleField, + &SetStaticObjectField, + &SetStaticBooleanField, + &SetStaticByteField, + &SetStaticCharField, + &SetStaticShortField, + &SetStaticIntField, + &SetStaticLongField, + &SetStaticFloatField, + &SetStaticDoubleField, + + &NewString, + &GetStringLength, + &GetStringChars, + &ReleaseStringChars, + + &NewStringUTF, + &GetStringUTFLength, + &GetStringUTFChars, + &ReleaseStringUTFChars, + + &GetArrayLength, + + &NewObjectArray, + &GetObjectArrayElement, + &SetObjectArrayElement, + + &NewBooleanArray, + &NewByteArray, + &NewCharArray, + &NewShortArray, + &NewIntArray, + &NewLongArray, + &NewFloatArray, + &NewDoubleArray, + + &GetBooleanArrayElements, + &GetByteArrayElements, + &GetCharArrayElements, + &GetShortArrayElements, + &GetIntArrayElements, + &GetLongArrayElements, + &GetFloatArrayElements, + &GetDoubleArrayElements, + + &ReleaseBooleanArrayElements, + &ReleaseByteArrayElements, + &ReleaseCharArrayElements, + &ReleaseShortArrayElements, + &ReleaseIntArrayElements, + &ReleaseLongArrayElements, + &ReleaseFloatArrayElements, + &ReleaseDoubleArrayElements, + + &GetBooleanArrayRegion, + &GetByteArrayRegion, + &GetCharArrayRegion, + &GetShortArrayRegion, + &GetIntArrayRegion, + &GetLongArrayRegion, + &GetFloatArrayRegion, + &GetDoubleArrayRegion, + &SetBooleanArrayRegion, + &SetByteArrayRegion, + &SetCharArrayRegion, + &SetShortArrayRegion, + &SetIntArrayRegion, + &SetLongArrayRegion, + &SetFloatArrayRegion, + &SetDoubleArrayRegion, + + &RegisterNatives, + &UnregisterNatives, + + &MonitorEnter, + &MonitorExit, + + &GetJavaVM, + + /* new JNI 1.2 functions */ + + &GetStringRegion, + &GetStringUTFRegion, + + &GetPrimitiveArrayCritical, + &ReleasePrimitiveArrayCritical, + + &GetStringCritical, + &ReleaseStringCritical, + + &NewWeakGlobalRef, + &DeleteWeakGlobalRef, + + &ExceptionCheck, + + /* new JNI 1.4 functions */ + + &NewDirectByteBuffer, + &GetDirectBufferAddress, + &GetDirectBufferCapacity }; -JNIEnv env = &envTable; +/* Invocation API Functions ***************************************************/ + +/* JNI_GetDefaultJavaVMInitArgs ************************************************ + + Returns a default configuration for the Java VM. + +*******************************************************************************/ -jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params) +jint JNI_GetDefaultJavaVMInitArgs(void *vm_args) +{ + JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) vm_args; + + /* GNU classpath currently supports JNI 1.2 */ + + _vm_args->version = JNI_VERSION_1_2; + + return 0; +} + + +/* JNI_GetCreatedJavaVMs ******************************************************* + + Returns all Java VMs that have been created. Pointers to VMs are written in + the buffer vmBuf in the order they are created. At most bufLen number of + entries will be written. The total number of created VMs is returned in + *nVMs. + +*******************************************************************************/ + +jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) +{ + log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!"); + + return 0; +} + + +/* JNI_CreateJavaVM ************************************************************ + + Loads and initializes a Java VM. The current thread becomes the main thread. + Sets the env argument to the JNI interface pointer of the main thread. + +*******************************************************************************/ + +jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args) +{ + const struct JNIInvokeInterface *vm; + struct JNINativeInterface *env; + + vm = &JNI_JavaVMTable; + env = &JNI_JNIEnvTable; + + *p_vm = (JavaVM *) vm; + *p_env = (JNIEnv *) env; + + return 0; +} + + +jobject *jni_method_invokeNativeHelper(JNIEnv *env, methodinfo *methodID, + jobject obj, java_objectarray *params) { - int argcount; jni_callblock *blk; - char retT; - jobject retVal; + jobject o; + s4 argcount; + s4 paramcount; if (methodID == 0) { - *exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; + *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); + return NULL; } - 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"); - return 0; - } + argcount = methodID->parseddesc->paramcount; + paramcount = argcount; + /* if method is non-static, remove the `this' pointer */ + if (!(methodID->flags & ACC_STATIC)) + paramcount--; - if (argcount > 3) { - *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. invokeNativeHelper does not support that"); - return 0; + /* the method is an instance method the obj has to be an instance of the + class the method belongs to. For static methods the obj parameter + is ignored. */ + + if (!(methodID->flags & ACC_STATIC) && obj && + (!builtin_instanceof((java_objectheader *) obj, methodID->class))) { + *exceptionptr = + new_exception_message(string_java_lang_IllegalArgumentException, + "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative"); + return NULL; } - if ( ((!params) && (argcount!=0)) || - (params && (params->header.size!=argcount)) - ) { - *exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; + if (((params == NULL) && (paramcount != 0)) || + (params && (params->header.size != paramcount))) { + *exceptionptr = + new_exception(string_java_lang_IllegalArgumentException); + return NULL; } - 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"); - return 0; + if (!(methodID->flags & ACC_STATIC) && !obj) { + *exceptionptr = + new_exception_message(string_java_lang_NullPointerException, + "Static mismatch in Java_java_lang_reflect_Method_invokeNative"); + return NULL; } - if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0; + if ((methodID->flags & ACC_STATIC) && (obj)) + obj = NULL; + + if (obj) { + if ((methodID->flags & ACC_ABSTRACT) || + (methodID->class->flags & ACC_INTERFACE)) { + methodID = get_virtual(obj, methodID); + } + } - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + blk = MNEW(jni_callblock, argcount); - retT = fill_callblock_objA(obj, methodID->descriptor, blk, params); + if (!fill_callblock_from_objectarray(obj, methodID->parseddesc, blk, + params)) + return NULL; - switch (retT) { - case 'V': - (void) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), + switch (methodID->parseddesc->returntype.decltype) { + case TYPE_VOID: + (void) asm_calljavafunction2(methodID, argcount, + argcount * sizeof(jni_callblock), blk); - retVal = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/ + o = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/ break; - case 'I': { - s4 intVal; - intVal = (s4) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Integer"))); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(I)V")), - intVal); + case PRIMITIVETYPE_INT: { + s4 i; + i = asm_calljavafunction2int(methodID, argcount, + argcount * sizeof(jni_callblock), + blk); + + o = native_new_and_init_int(class_java_lang_Integer, i); } break; - case 'B': { - s4 intVal; - intVal = (s4) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Byte"))); + case PRIMITIVETYPE_BYTE: { + s4 i; + i = asm_calljavafunction2int(methodID, argcount, + argcount * sizeof(jni_callblock), + blk); + +/* o = native_new_and_init_int(class_java_lang_Byte, i); */ + o = builtin_new(class_java_lang_Byte); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(B)V")), - intVal); + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_byte__void), + i); } break; - case 'C': { - s4 intVal; - intVal = (s4) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Character"))); + case PRIMITIVETYPE_CHAR: { + s4 intVal; + intVal = asm_calljavafunction2int(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Character); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(C)V")), + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_char__void), intVal); } break; - case 'S': { - s4 intVal; - intVal = (s4) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Short"))); + case PRIMITIVETYPE_SHORT: { + s4 intVal; + intVal = asm_calljavafunction2int(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Short); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(S)V")), + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_short__void), intVal); } break; - case 'Z': { - s4 intVal; - intVal = (s4) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Boolean"))); + case PRIMITIVETYPE_BOOLEAN: { + s4 intVal; + intVal = asm_calljavafunction2int(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Boolean); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(Z)V")), + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_boolean__void), intVal); } break; - case 'J': { - jlong intVal; - intVal = asm_calljavafunction2long(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Long"))); + case PRIMITIVETYPE_LONG: { + jlong longVal; + longVal = asm_calljavafunction2long(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Long); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(J)V")), - intVal); + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_long__void), + longVal); } break; - case 'F': { + case PRIMITIVETYPE_FLOAT: { jdouble floatVal; - floatVal = asm_calljavafunction2double(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Float"))); + floatVal = asm_calljavafunction2float(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Float); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(F)V")), + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_float__void), floatVal); } break; - case 'D': { - jdouble floatVal; - floatVal = asm_calljavafunction2double(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(loader_load_sysclass(NULL, - utf_new_char("java/lang/Double"))); + case PRIMITIVETYPE_DOUBLE: { + jdouble doubleVal; + doubleVal = asm_calljavafunction2double(methodID, + argcount, + argcount * sizeof(jni_callblock), + blk); + o = builtin_new(class_java_lang_Double); CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""), - utf_new_char("(D)V")), - floatVal); + o, + class_resolvemethod(o->vftbl->class, + utf_init, + utf_double__void), + doubleVal); } break; - case 'L': /* fall through */ - case '[': - retVal = asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + case TYPE_ADR: + o = asm_calljavafunction2(methodID, argcount, + argcount * sizeof(jni_callblock), blk); break; default: - /* if this happens the acception has already been set by fill_callblock_objA*/ - MFREE(blk, jni_callblock, 4 /*argcount+2*/); + /* if this happens the exception has already been set by */ + /* fill_callblock_from_objectarray */ + + MFREE(blk, jni_callblock, argcount); return (jobject *) 0; } - MFREE(blk, jni_callblock, 4 /*argcount+2*/); + MFREE(blk, jni_callblock, argcount); if (*exceptionptr) { - java_objectheader *exceptionToWrap=*exceptionptr; - classinfo *ivtec = loader_load_sysclass(NULL, - utf_new_char("java/lang/reflect/InvocationTargetException")); - java_objectheader* ivte = builtin_new(ivtec); - asm_calljavafunction(class_resolvemethod(ivtec, - utf_new_char(""), - utf_new_char("(Ljava/lang/Throwable;)V")), - ivte, - exceptionToWrap, - 0, - 0); + java_objectheader *cause; + + cause = *exceptionptr; + + /* clear exception pointer, we are calling JIT code again */ - if (*exceptionptr != NULL) - panic("jni.c: error while creating InvocationTargetException wrapper"); + *exceptionptr = NULL; - *exceptionptr = ivte; + *exceptionptr = + new_exception_throwable(string_java_lang_reflect_InvocationTargetException, + (java_lang_Throwable *) cause); } - return (jobject *) retVal; + return (jobject *) o; }