X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fnative%2Fjni.c;h=cf499c7942831336a1181c8287fd484eb0ff2b8e;hb=e9864e23dcee7bd5527e062608816841649bd3bb;hp=90b3674a477ea88c3df67c396593c9ef6262db9e;hpb=dc1f9b41cef4efcce5b63eea1a763c71ebfba23b;p=cacao.git diff --git a/src/native/jni.c b/src/native/jni.c index 90b3674a4..cf499c794 100644 --- a/src/native/jni.c +++ b/src/native/jni.c @@ -1,9 +1,9 @@ /* src/native/jni.c - implementation of the Java Native Interface functions - 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 + Copyright (C) 1996-2005, 2006 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. @@ -19,10 +19,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Rainhard Grafl Roman Obermaisser @@ -30,19 +30,34 @@ Changes: Joseph Wenninger Martin Platter Christian Thalinger + Edwin Steiner - $Id: jni.c 2146 2005-03-30 16:44:24Z twisti $ + $Id: jni.c 4567 2006-03-07 10:48:24Z twisti $ */ +#include "config.h" + +#include #include -#include "config.h" +#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" @@ -52,6 +67,19 @@ #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) @@ -65,886 +93,1101 @@ #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/tables.h" #include "vm/jit/asmpart.h" #include "vm/jit/jit.h" +#include "vm/statistics.h" +#include "vm/vm.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; +/* global variables ***********************************************************/ -/* pointers to VM and the environment needed by GetJavaVM and GetEnv */ -static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable; -static void* ptr_env = (void*) &JNI_JNIEnvTable; +/* global reference table *****************************************************/ +static java_objectheader **global_ref_table; -#define PTR_TO_ITEM(ptr) ((u8)(size_t)(ptr)) +/* 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; -/* global reference table */ -static jobject *global_ref_table; -static bool initrunning=false; -/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/ -static jmethodID getmid = NULL; -static jmethodID putmid = NULL; -static jclass intclass = NULL; -static jmethodID intvalue = NULL; -static jmethodID newint = NULL; -static jclass ihmclass = NULL; -static jmethodID removemid = NULL; +/* direct buffer stuff ********************************************************/ +static classinfo *class_java_nio_Buffer; +static classinfo *class_java_nio_DirectByteBufferImpl; +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 -/********************* accessing instance-fields **********************************/ +static methodinfo *dbbirw_init; -#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); +/* local reference table ******************************************************/ +#if !defined(USE_THREADS) +localref_table *_no_threads_localref_table; +#endif -u4 get_parametercount(methodinfo *m) -{ - 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 */ - u4 parametercount = 0; - /* skip '(' */ - utf_nextu2(&utf_ptr); +/* accessing instance fields macros *******************************************/ - /* determine number of parameters */ - while (*utf_ptr != ')') { - get_type(&utf_ptr, desc_end, true); - parametercount++; - } +#define SET_FIELD(o,type,f,value) \ + *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) = (type) (value) - return parametercount; -} +#define GET_FIELD(o,type,f) \ + *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) +/* some forward declarations **************************************************/ -void fill_callblock(void *obj, utf *descr, jni_callblock blk[], va_list data, char ret) -{ - 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 */ - int cnt; - u4 dummy; - char c; +jobject NewLocalRef(JNIEnv *env, jobject ref); - /* - log_text("fill_callblock"); - utf_display(descr); - log_text("===="); - */ - /* skip '(' */ - utf_nextu2(utf_ptr); - /* determine number of parameters */ - if (obj) { - blk[0].itemtype = TYPE_ADR; - blk[0].item = PTR_TO_ITEM(obj); - cnt = 1; - } else cnt = 0; +/* jni_init ******************************************************************** - while (**utf_ptr != ')') { - if (*utf_ptr >= desc_end) - panic("illegal method descriptor"); + Initialize the JNI subsystem. - 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; - break; +bool jni_init(void) +{ + /* initalize global reference table */ - case 'J': - blk[cnt].itemtype = TYPE_LNG; - blk[cnt].item = (u8) va_arg(data, jlong); - break; + if (!(ihmclass = + load_class_bootstrap(utf_new_char("java/util/IdentityHashMap")))) + return false; + + global_ref_table = GCNEW(jobject); + + 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 */ + + if (!(class_java_nio_Buffer = + load_class_bootstrap(utf_new_char("java/nio/Buffer"))) || + !link_class(class_java_nio_Buffer)) + return false; + + if (!(class_java_nio_DirectByteBufferImpl = + load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) || + !link_class(class_java_nio_DirectByteBufferImpl)) + return false; + + if (!(class_java_nio_DirectByteBufferImpl_ReadWrite = + load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) || + !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; + +#if SIZEOF_VOID_P == 8 + if (!(class_gnu_classpath_Pointer64 = + load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) || + !link_class(class_gnu_classpath_Pointer64)) + return false; +#else + if (!(class_gnu_classpath_Pointer32 = + load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) || + !link_class(class_gnu_classpath_Pointer32)) + return false; +#endif - case 'F': - blk[cnt].itemtype = TYPE_FLT; - *((jfloat *) (&blk[cnt].item)) = (jfloat) va_arg(data, jdouble); - break; + return true; +} - case 'D': - blk[cnt].itemtype = TYPE_DBL; - *((jdouble *) (&blk[cnt].item)) = (jdouble) va_arg(data, jdouble); - break; - case 'V': - panic ("V not allowed as function parameter"); - 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; - } - } - cnt++; - } +/* _Jv_jni_vmargs_from_objectarray ********************************************* - /*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===="); -} + XXX +*******************************************************************************/ -/* 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 _Jv_jni_vmargs_from_objectarray(java_objectheader *o, + methoddesc *descr, + vm_arg *vmargs, + 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 */ + java_objectheader *param; + s4 paramcount; + typedesc *paramtypes; + classinfo *c; + s4 i; + s4 j; - jobject param; - int cnt; - int cnts; - char c; + paramcount = descr->paramcount; + paramtypes = descr->paramtypes; - /* - 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 */ - /* determine number of parameters */ - if (obj) { - blk[0].itemtype = TYPE_ADR; - blk[0].item = PTR_TO_ITEM(obj); - cnt=1; + i = 0; - } else { - cnt = 0; - } + if (o != NULL) { + /* this pointer */ + vmargs[0].type = TYPE_ADR; + vmargs[0].data = (u8) (ptrint) o; - cnts = 0; - while (**utf_ptr != ')') { - if (*utf_ptr >= desc_end) - panic("illegal method descriptor"); + paramtypes++; + paramcount--; + i++; + } + 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 = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Byte) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Byte *) param)->value; + case TYPE_INT: + case TYPE_LONG: + case TYPE_FLOAT: + case TYPE_DOUBLE: + param = params->data[j]; - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - break; + if (param == NULL) + goto illegal_arg; - case 'C': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Character) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Character *) param)->value; + /* internally used data type */ + vmargs[i].type = paramtypes->type; - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - break; + /* convert the value according to its declared type */ - case 'S': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Short) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Short *) param)->value; - - } else { - if (param->vftbl->class->name == utf_java_lang_Byte) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Byte *) param)->value; - - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - } - break; + c = param->vftbl->class; - case 'Z': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Boolean) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Boolean *) param)->value; + switch (paramtypes->decltype) { + case PRIMITIVETYPE_BOOLEAN: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Boolean *) param)->value; + else + goto illegal_arg; + break; - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - break; + case PRIMITIVETYPE_BYTE: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; - case 'I': - /*log_text("fill_callblock_objA: param 'I'");*/ - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Integer) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Integer *) param)->value; - /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/ - } else { - if (param->vftbl->class->name == utf_java_lang_Short) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Short *) param)->value; - - } else { - if (param->vftbl->class->name == utf_java_lang_Byte) { - blk[cnt].itemtype = TYPE_INT; - blk[cnt].item = (u8) ((java_lang_Byte *) param)->value; - - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - } - } - break; + case PRIMITIVETYPE_CHAR: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Character *) param)->value; + else + goto illegal_arg; + break; + + case PRIMITIVETYPE_SHORT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + vmargs[i].data = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; + + case PRIMITIVETYPE_INT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Integer *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap) + vmargs[i].data = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + vmargs[i].data = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; + + case PRIMITIVETYPE_LONG: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Long *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_INT].class_wrap) + vmargs[i].data = (s8) ((java_lang_Integer *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_SHORT].class_wrap) + vmargs[i].data = (s8) ((java_lang_Short *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_BYTE].class_wrap) + vmargs[i].data = (s8) ((java_lang_Byte *) param)->value; + else + goto illegal_arg; + break; + + case PRIMITIVETYPE_FLOAT: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value; + else + goto illegal_arg; + break; + + case PRIMITIVETYPE_DOUBLE: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + *((jdouble *) (&vmargs[i].data)) = (jdouble) ((java_lang_Double *) param)->value; + else if (c == primitivetype_table[PRIMITIVETYPE_FLOAT].class_wrap) + *((jfloat *) (&vmargs[i].data)) = (jfloat) ((java_lang_Float *) param)->value; + else + goto illegal_arg; + break; - case 'J': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; + default: + goto illegal_arg; } - if (param->vftbl->class->name == utf_java_lang_Long) { - blk[cnt].itemtype = TYPE_LNG; - blk[cnt].item = (u8) ((java_lang_Long *) param)->value; - - } else { - if (param->vftbl->class->name == utf_java_lang_Integer) { - blk[cnt].itemtype = TYPE_LNG; - blk[cnt].item = (u8) ((java_lang_Integer *) param)->value; - - } else { - if (param->vftbl->class->name == utf_java_lang_Short) { - blk[cnt].itemtype = TYPE_LNG; - blk[cnt].item = (u8) ((java_lang_Short *) param)->value; - - } else { - if (param->vftbl->class->name == utf_java_lang_Byte) { - blk[cnt].itemtype = TYPE_LNG; - blk[cnt].item = (u8) ((java_lang_Byte *) param)->value; - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } + 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; } } + vmargs[i].type = TYPE_ADR; + vmargs[i].data = (u8) (ptrint) params->data[j]; + break; - } - break; + default: + goto illegal_arg; + } + } - case 'F': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } +/* if (rettype) */ +/* *rettype = descr->returntype.decltype; */ - if (param->vftbl->class->name == utf_java_lang_Float) { - blk[cnt].itemtype = TYPE_FLT; - *((jfloat *) (&blk[cnt].item)) = (jfloat) ((java_lang_Float *) param)->value; + return true; - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - break; +illegal_arg: + exceptions_throw_illegalargumentexception(); + return false; +} - case 'D': - param = params->data[cnts]; - if (param == 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - if (param->vftbl->class->name == utf_java_lang_Double) { - blk[cnt].itemtype = TYPE_DBL; - *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value; +/* _Jv_jni_CallObjectMethod **************************************************** - } else { - if (param->vftbl->class->name == utf_java_lang_Float) { - blk[cnt].itemtype = TYPE_DBL; - *((jdouble *) (&blk[cnt].item)) = (jdouble) ((java_lang_Float *) param)->value; + Internal function to call Java Object methods. - } else { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - } - break; +*******************************************************************************/ - case 'V': - panic("V not allowed as function parameter"); - break; +static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o, + vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + java_objectheader *ro; - case 'L': - { - char *start = (*utf_ptr) - 1; - /*char *end = NULL; + STATISTICS(jniinvokation()); - while (utf_nextu2(utf_ptr) != ';') - end = (*utf_ptr) + 1;*/ + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; + } - if (!builtin_instanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD))) { - if (params->data[cnts] != 0) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } - } - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item = PTR_TO_ITEM(params->data[cnts]); - break; - } + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - case '[': - { - char *start = (*utf_ptr) - 1; - /*char *end; - - char ch; - while ((ch = utf_nextu2(utf_ptr)) == '[') - if (ch == 'L') { - while (utf_nextu2(utf_ptr) != ';') {} - } + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - end = (*utf_ptr) - 1; - ch = utf_nextu2(utf_ptr); */ + if (o != NULL) + o = NULL; - if (!builtin_arrayinstanceof(params->data[cnts], class_from_descriptor(start, desc_end, utf_ptr, CLASSLOAD_LOAD)->vftbl)) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } + /* for convenience */ - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item = PTR_TO_ITEM(params->data[cnts]); - break; - } - } - cnt++; - cnts++; + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); } - c = utf_nextu2(utf_ptr); - c = utf_nextu2(utf_ptr); - return c; /*return type needed usage of the right lowlevel methods*/ -} + STATISTICS(jnicallXmethodnvokation()); + ro = vm_call_method_valist(resm, o, ap); -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); + return ro; } -jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) { - if (clazz==methodID->class) return methodID; -/*class_resolvemethod -> classfindmethod? (JOWENN)*/ - return class_resolvemethod (clazz, methodID->name, methodID->descriptor); -} +/* _Jv_jni_CallObjectMethodA *************************************************** + Internal function to call Java Object methods. -jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args) -{ - int argcount; - jni_callblock *blk; - jobject ret; +*******************************************************************************/ +static java_objectheader *_Jv_jni_CallObjectMethodA(java_objectheader *o, + vftbl_t *vftbl, + methodinfo *m, jvalue *args) +{ + methodinfo *resm; + java_objectheader *ro; + STATISTICS(jniinvokation()); - if (methodID == 0) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; } - argcount = get_parametercount(methodID); + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - if (obj && !builtin_instanceof(obj, methodID->class)) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + if (o != NULL) + o = NULL; -#ifdef arglimit + /* for convenience */ - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); } -#endif - blk = MNEW(jni_callblock, /*4 */argcount+2); + STATISTICS(jnicallXmethodnvokation()); - fill_callblock(obj, methodID->descriptor, blk, args, 'O'); - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + ro = vm_call_method_jvalue(resm, o, args); - return ret; + return ro; } -/* - 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) -{ - int argcount; - jni_callblock *blk; - jint ret; - -/* printf("%p, %c\n",retType,methodID,retType);*/ - - /* - log_text("JNI-Call: CallObjectMethodV"); - utf_display(methodID->name); - utf_display(methodID->descriptor); - printf("\nParmaeter count: %d\n",argcount); - utf_display(obj->vftbl->class->name); - printf("\n"); - */ - if (methodID == 0) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); +/* _Jv_jni_CallIntMethod ******************************************************* + + Internal function to call Java integer class methods (boolean, + byte, char, short, int). + +*******************************************************************************/ + +static jint _Jv_jni_CallIntMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + jint i; + + STATISTICS(jniinvokation()); + + if (m == NULL) { + exceptions_throw_nullpointerexception(); return 0; } - argcount = get_parametercount(methodID); + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - if (obj && !builtin_instanceof(obj, methodID->class)) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + if (o != NULL) + o = NULL; -#ifdef arglimit - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. CallIntegerMethod does not support that"); - return 0; - } -#endif + /* for convenience */ + + resm = m; - blk = MNEW(jni_callblock, /*4 */ argcount+2); + } else { + /* For instance methods we make a virtual function table lookup. */ - fill_callblock(obj, methodID->descriptor, blk, args, retType); + resm = method_vftbl_lookup(vftbl, m); + } - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + STATISTICS(jnicallXmethodnvokation()); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + i = vm_call_method_int_valist(resm, o, ap); - return ret; + return i; } -/*core function for long class functions*/ -jlong callLongMethod(jobject obj, jmethodID methodID, va_list args) +/* _Jv_jni_CallIntMethodA ****************************************************** + + Internal function to call Java integer class methods (boolean, + byte, char, short, int). + +*******************************************************************************/ + +static jint _Jv_jni_CallIntMethodA(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, jvalue *args) { - int argcount; - jni_callblock *blk; - jlong ret; + methodinfo *resm; + jint i; -/* - log_text("JNI-Call: CallObjectMethodV"); - utf_display(methodID->name); - utf_display(methodID->descriptor); - printf("\nParmaeter count: %d\n",argcount); - utf_display(obj->vftbl->class->name); - printf("\n"); -*/ - if (methodID == 0) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); + STATISTICS(jniinvokation()); + + if (m == NULL) { + exceptions_throw_nullpointerexception(); return 0; } + + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - argcount = get_parametercount(methodID); + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + if (o != NULL) + o = NULL; - if (obj && !builtin_instanceof(obj,methodID->class)) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return 0; - } + /* for convenience */ -#ifdef arglimit - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } -#endif + resm = m; - blk = MNEW(jni_callblock,/* 4 */argcount+2); + } else { + /* For instance methods we make a virtual function table lookup. */ - fill_callblock(obj, methodID->descriptor, blk, args, 'J'); + resm = method_vftbl_lookup(vftbl, m); + } - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2long(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + STATISTICS(jnicallXmethodnvokation()); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + i = vm_call_method_int_jvalue(resm, o, args); - return ret; + return i; } -/*core function for float class methods (float,double)*/ -jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType) +/* _Jv_jni_CallLongMethod ****************************************************** + + Internal function to call Java long methods. + +*******************************************************************************/ + +static jlong _Jv_jni_CallLongMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) { - int argcount = get_parametercount(methodID); - jni_callblock *blk; - jdouble ret; + methodinfo *resm; + jlong l; - /* - 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()); -#ifdef arglimit - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. CallObjectMethod does not support that"); + if (m == NULL) { + exceptions_throw_nullpointerexception(); return 0; } -#endif - blk = MNEW(jni_callblock, /*4 */ argcount+2); + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - fill_callblock(obj, methodID->descriptor, blk, args, retType); + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2double(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + if (o != NULL) + o = NULL; - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ - - return ret; -} + /* for convenience */ + resm = m; -/*************************** function: jclass_findfield **************************** - - searches for field with specified name and type in a 'classinfo'-structur - if no such field is found NULL is returned + } else { + /* For instance methods we make a virtual function table lookup. */ -************************************************************************************/ + resm = method_vftbl_lookup(vftbl, m); + } -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]); - } + STATISTICS(jnicallXmethodnvokation()); - if (c->super) return jclass_findfield(c->super,name,desc); + l = vm_call_method_long_valist(resm, o, ap); - return NULL; + return l; } -/* GetVersion ****************************************************************** +/* _Jv_jni_CallFloatMethod ***************************************************** - Returns the major version number in the higher 16 bits and the - minor version number in the lower 16 bits. + Internal function to call Java float methods. *******************************************************************************/ -jint GetVersion(JNIEnv *env) +static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) { - /* GNU classpath currently supports JNI 1.2 */ + methodinfo *resm; + jfloat f; - return JNI_VERSION_1_2; -} + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ -/* Class Operations ***********************************************************/ + if (o != NULL) + o = NULL; -/* DefineClass ***************************************************************** + /* for convenience */ - 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. + resm = m; -*******************************************************************************/ + } else { + /* For instance methods we make a virtual function table lookup. */ -jclass DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen) -{ - jclass c; - jclass r; - classbuffer *cb; + resm = method_vftbl_lookup(vftbl, m); + } - c = class_new(utf_new_char_classname((char *) name)); + STATISTICS(jnicallXmethodnvokation()); -#if defined(USE_THREADS) - /* enter a monitor on the class */ + f = vm_call_method_float_valist(resm, o, ap); - builtin_monitorenter((java_objectheader *) c); -#endif + return f; +} -#if defined(STATISTICS) - /* measure time */ - if (getloadingtime) - loadingtime_start(); -#endif +/* _Jv_jni_CallDoubleMethod **************************************************** + + Internal function to call Java double methods. + +*******************************************************************************/ - /* build a classbuffer with the given data */ +static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + jdouble d; - cb = NEW(classbuffer); - cb->class = c; - cb->size = bufLen; - cb->data = (u1 *) buf; - cb->pos = cb->data - 1; + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - /* load the class from this buffer */ + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - r = load_class_from_classbuffer(cb); + if (o != NULL) + o = NULL; - /* if return value is NULL, we had a problem and the class is not loaded */ + /* for convenience */ - if (!r) { - c->loaded = false; + resm = m; - /* now free the allocated memory, otherwise we could ran into a DOS */ + } else { + /* For instance methods we make a virtual function table lookup. */ - class_remove(c); + resm = method_vftbl_lookup(vftbl, m); } - /* free memory */ + d = vm_call_method_double_valist(resm, o, ap); - FREE(cb, classbuffer); + return d; +} -#if defined(STATISTICS) - /* measure time */ - if (getloadingtime) - loadingtime_stop(); -#endif +/* _Jv_jni_CallVoidMethod ****************************************************** -#if defined(USE_THREADS) - /* leave the monitor */ + Internal function to call Java void methods. - builtin_monitorexit((java_objectheader *) c); -#endif +*******************************************************************************/ - /* XXX link the class here? */ -/* if (class_link(c)) */ -/* return NULL; */ +static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; - if (r) { - c->classloader = loader; - use_class_as_object(r); + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return; } - return r; -} - + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ -/* FindClass ******************************************************************* + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - 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. + if (o != NULL) + o = NULL; -*******************************************************************************/ + /* for convenience */ -jclass FindClass(JNIEnv *env, const char *name) -{ - classinfo *c; - - c = class_new(utf_new_char_classname((char *) name)); + resm = m; - if (!load_class_bootstrap(c) || !link_class(c)) { - class_remove(c); + } else { + /* For instance methods we make a virtual function table lookup. */ - return NULL; + resm = method_vftbl_lookup(vftbl, m); } - use_class_as_object(c); - - return c; -} - - -/******************************************************************************* - - converts java.lang.reflect.Method or - java.lang.reflect.Constructor object to a method ID - -*******************************************************************************/ - -jmethodID FromReflectedMethod(JNIEnv* env, jobject method) -{ - log_text("JNI-Call: FromReflectedMethod: IMPLEMENT ME!!!"); + STATISTICS(jnicallXmethodnvokation()); - return 0; + (void) vm_call_method_valist(resm, o, ap); } -/* GetSuperclass *************************************************************** +/* _Jv_jni_CallVoidMethodA ***************************************************** - 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. + Internal function to call Java void methods. *******************************************************************************/ - -jclass GetSuperclass(JNIEnv *env, jclass sub) -{ - classinfo *c; - c = ((classinfo *) sub)->super; +static void _Jv_jni_CallVoidMethodA(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, jvalue *args) +{ + methodinfo *resm; - if (!c) - return NULL; + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return; + } - use_class_as_object(c); + /* Class initialization is done by the JIT compiler. This is ok + since a static method always belongs to the declaring class. */ - return c; -} - - -/* IsAssignableFrom ************************************************************ + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ - Determines whether an object of sub can be safely cast to sup. + if (o != NULL) + o = NULL; -*******************************************************************************/ + /* for convenience */ -jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) -{ - return builtin_isanysubclass(sub, sup); -} + resm = m; + } else { + /* For instance methods we make a virtual function table lookup. */ -/***** converts a field ID derived from cls to a java.lang.reflect.Field object ***/ + resm = method_vftbl_lookup(vftbl, m); + } -jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic) -{ - log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!!!"); + STATISTICS(jnicallXmethodnvokation()); - return NULL; + (void) vm_call_method_jvalue(resm, o, args); } -/* Throw *********************************************************************** +/* _Jv_jni_invokeNative ******************************************************** - Causes a java.lang.Throwable object to be thrown. + Invoke a method on the given object with the given arguments. + + For instance methods OBJ must be != NULL and the method is looked up + in the vftbl of the object. + + For static methods, OBJ is ignored. *******************************************************************************/ -jint Throw(JNIEnv *env, jthrowable obj) +java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o, + java_objectarray *params) { - *exceptionptr = (java_objectheader *) obj; + methodinfo *resm; + vm_arg *vmargs; + java_objectheader *ro; + s4 argcount; + s4 paramcount; - return JNI_OK; -} + if (!m) { + exceptions_throw_nullpointerexception(); + return NULL; + } + + argcount = m->parseddesc->paramcount; + paramcount = argcount; + + /* if method is non-static, remove the `this' pointer */ + + if (!(m->flags & ACC_STATIC)) + paramcount--; + + /* For instance methods the object has to be an instance of the + class the method belongs to. For static methods the obj + parameter is ignored. */ + + if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) { + *exceptionptr = + new_exception_message(string_java_lang_IllegalArgumentException, + "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative"); + return NULL; + } + + /* check if we got the right number of arguments */ + + if (((params == NULL) && (paramcount != 0)) || + (params && (params->header.size != paramcount))) + { + *exceptionptr = + new_exception(string_java_lang_IllegalArgumentException); + return NULL; + } + + /* for instance methods we need an object */ + + if (!(m->flags & ACC_STATIC) && (o == NULL)) { + *exceptionptr = + new_exception_message(string_java_lang_NullPointerException, + "Static mismatch in Java_java_lang_reflect_Method_invokeNative"); + return NULL; + } + + /* for static methods, zero object to make subsequent code simpler */ + if (m->flags & ACC_STATIC) + o = NULL; + + if (o != NULL) { + /* for instance methods we must do a vftbl lookup */ + resm = method_vftbl_lookup(o->vftbl, m); + + } else { + /* for static methods, just for convenience */ + resm = m; + } + + vmargs = MNEW(vm_arg, argcount); + + if (!_Jv_jni_vmargs_from_objectarray(o, resm->parseddesc, vmargs, params)) + return NULL; + + switch (resm->parseddesc->returntype.decltype) { + case TYPE_VOID: + (void) vm_call_method_vmarg(resm, argcount, vmargs); + + ro = NULL; + break; + + case PRIMITIVETYPE_BOOLEAN: { + s4 i; + java_lang_Boolean *bo; + + i = vm_call_method_int_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Boolean); + + /* setting the value of the object direct */ + + bo = (java_lang_Boolean *) ro; + bo->value = i; + } + break; + + case PRIMITIVETYPE_BYTE: { + s4 i; + java_lang_Byte *bo; + + i = vm_call_method_int_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Byte); + + /* setting the value of the object direct */ + + bo = (java_lang_Byte *) ro; + bo->value = i; + } + break; + + case PRIMITIVETYPE_CHAR: { + s4 i; + java_lang_Character *co; + + i = vm_call_method_int_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Character); + + /* setting the value of the object direct */ + + co = (java_lang_Character *) ro; + co->value = i; + } + break; + + case PRIMITIVETYPE_SHORT: { + s4 i; + java_lang_Short *so; + + i = vm_call_method_int_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Short); + + /* setting the value of the object direct */ + + so = (java_lang_Short *) ro; + so->value = i; + } + break; + + case PRIMITIVETYPE_INT: { + s4 i; + java_lang_Integer *io; + + i = vm_call_method_int_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Integer); + + /* setting the value of the object direct */ + + io = (java_lang_Integer *) ro; + io->value = i; + } + break; + + case PRIMITIVETYPE_LONG: { + s8 l; + java_lang_Long *lo; + + l = vm_call_method_long_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Long); + + /* setting the value of the object direct */ + + lo = (java_lang_Long *) ro; + lo->value = l; + } + break; + + case PRIMITIVETYPE_FLOAT: { + float f; + java_lang_Float *fo; + + f = vm_call_method_float_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Float); + + /* setting the value of the object direct */ + + fo = (java_lang_Float *) ro; + fo->value = f; + } + break; + + case PRIMITIVETYPE_DOUBLE: { + double d; + java_lang_Double *_do; + + d = vm_call_method_double_vmarg(resm, argcount, vmargs); + + ro = builtin_new(class_java_lang_Double); + + /* setting the value of the object direct */ + + _do = (java_lang_Double *) ro; + _do->value = d; + } + break; + + case TYPE_ADR: + ro = vm_call_method_vmarg(resm, argcount, vmargs); + break; + + default: + /* if this happens the exception has already been set by + fill_callblock_from_objectarray */ + + MFREE(vmargs, vm_arg, argcount); + + return NULL; + } + + MFREE(vmargs, vm_arg, argcount); + + if (*exceptionptr) { + java_objectheader *cause; + + cause = *exceptionptr; + + /* clear exception pointer, we are calling JIT code again */ + + *exceptionptr = NULL; + + *exceptionptr = + new_exception_throwable(string_java_lang_reflect_InvocationTargetException, + (java_lang_Throwable *) cause); + } + + return ro; +} + + +/* 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) +{ + STATISTICS(jniinvokation()); + + /* we support JNI 1.4 */ + + return JNI_VERSION_1_4; +} + + +/* 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) +{ + java_lang_ClassLoader *cl; + java_lang_String *s; + java_bytearray *ba; + jclass c; + + STATISTICS(jniinvokation()); + + cl = (java_lang_ClassLoader *) loader; + s = javastring_new_char(name); + ba = (java_bytearray *) buf; + + c = (jclass) Java_java_lang_VMClassLoader_defineClass(env, NULL, cl, s, ba, + 0, bufLen, NULL); + + return (jclass) NewLocalRef(env, (jobject) c); +} + + +/* 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) +{ + utf *u; + classinfo *cc; + classinfo *c; + + STATISTICS(jniinvokation()); + + u = utf_new_char_classname((char *) name); + + /* Check stacktrace for classloader, if one found use it, + otherwise use the system classloader. */ + + /* Quote from the JNI documentation: + + In the Java 2 Platform, FindClass locates the class loader + associated with the current native method. If the native code + belongs to a system class, no class loader will be + involved. Otherwise, the proper class loader will be invoked to + load and link the named class. When FindClass is called through + the Invocation Interface, there is no current native method or + its associated class loader. In that case, the result of + ClassLoader.getBaseClassLoader is used." */ + +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__X86_64__) + /* these JITs support stacktraces, and so does the interpreter */ + + cc = stacktrace_getCurrentClass(); +#else +# if defined(ENABLE_INTRP) + /* the interpreter supports stacktraces, even if the JIT does not */ + + if (opt_intrp) + cc = stacktrace_getCurrentClass(); + else +# endif + cc = NULL; +#endif + + /* if no Java method was found, use the system classloader */ + + if (cc == NULL) + c = load_class_from_sysloader(u); + else + c = load_class_from_classloader(u, cc->classloader); + + if (c == NULL) + return NULL; + + if (!link_class(c)) + return NULL; + + return (jclass) NewLocalRef(env, (jobject) c); +} + + +/* 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) +{ + classinfo *c; + + STATISTICS(jniinvokation()); + + c = ((classinfo *) sub)->super.cls; + + if (!c) + return NULL; + + return (jclass) NewLocalRef(env, (jobject) c); +} + + +/* IsAssignableFrom ************************************************************ + + Determines whether an object of sub can be safely cast to sup. + +*******************************************************************************/ + +jboolean IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup) +{ + STATISTICS(jniinvokation()); + + return Java_java_lang_VMClass_isAssignableFrom(env, + NULL, + (java_lang_Class *) sup, + (java_lang_Class *) sub); +} + + +/* Throw *********************************************************************** + + Causes a java.lang.Throwable object to be thrown. + +*******************************************************************************/ + +jint Throw(JNIEnv *env, jthrowable obj) +{ + STATISTICS(jniinvokation()); + + *exceptionptr = (java_objectheader *) obj; + + return JNI_OK; +} /* ThrowNew ******************************************************************** @@ -960,6 +1203,8 @@ 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 */ @@ -986,7 +1231,13 @@ jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) jthrowable ExceptionOccurred(JNIEnv *env) { - return (jthrowable) *exceptionptr; + java_objectheader *e; + + STATISTICS(jniinvokation()); + + e = *exceptionptr; + + return NewLocalRef(env, (jthrowable) e); } @@ -1003,6 +1254,8 @@ void ExceptionDescribe(JNIEnv *env) java_objectheader *e; methodinfo *m; + STATISTICS(jniinvokation()); + e = *exceptionptr; if (e) { @@ -1022,2094 +1275,3571 @@ void ExceptionDescribe(JNIEnv *env) /* XXX what should we do? */ return; - /* print the stacktrace */ + /* print the stacktrace */ + + (void) vm_call_method(m, e); + } +} + + +/* 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) +{ + STATISTICS(jniinvokation()); + + *exceptionptr = NULL; +} + + +/* 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) +{ + STATISTICS(jniinvokation()); + + throw_cacao_exception_exit(string_java_lang_InternalError, msg); +} + + +/* 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) +{ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: PushLocalFrame: IMPLEMENT ME!"); + + assert(0); + + return 0; +} + +/* 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) +{ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!"); + + assert(0); + + /* add local reference and return the value */ + + return NewLocalRef(env, NULL); +} + + +/* DeleteLocalRef ************************************************************** + + Deletes the local reference pointed to by localRef. + +*******************************************************************************/ + +void DeleteLocalRef(JNIEnv *env, jobject localRef) +{ + 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"); +} + + +/* IsSameObject **************************************************************** + + Tests whether two references refer to the same Java object. + +*******************************************************************************/ + +jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) +{ + STATISTICS(jniinvokation()); + + if (ref1 == ref2) + return JNI_TRUE; + else + return JNI_FALSE; +} + + +/* NewLocalRef ***************************************************************** + + Creates a new local reference that refers to the same object as ref. + +*******************************************************************************/ + +jobject NewLocalRef(JNIEnv *env, jobject 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"); */ + fprintf(stderr, "Too many local references"); + assert(0); + } + + /* 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; +} + + +/* EnsureLocalCapacity ********************************************************* + + Ensures that at least a given number of local references can be + created in the current thread + +*******************************************************************************/ + +jint EnsureLocalCapacity(JNIEnv* env, jint capacity) +{ + 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; +} + + +/* 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) +{ + classinfo *c; + java_objectheader *o; + + STATISTICS(jniinvokation()); + + c = (classinfo *) clazz; + + if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) { + *exceptionptr = + new_exception_utfmessage(string_java_lang_InstantiationException, + c->name); + return NULL; + } + + o = builtin_new(c); + + return NewLocalRef(env, o); +} + + +/* NewObject ******************************************************************* + + 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, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + + STATISTICS(jniinvokation()); + + m = (methodinfo *) methodID; + + /* create object */ + + o = builtin_new(clazz); + + if (o == NULL) + return NULL; + + /* call constructor */ + + va_start(ap, methodID); + _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap); + va_end(ap); + + return NewLocalRef(env, o); +} + + +/* NewObjectV ****************************************************************** + + Programmers place all arguments that are to be passed to the + constructor in an args argument of type va_list that immediately + follows the methodID argument. NewObjectV() accepts these + arguments, and, in turn, passes them to the Java method that the + programmer wishes to invoke. + +*******************************************************************************/ + +jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + + STATISTICS(jniinvokation()); + + m = (methodinfo *) methodID; + + /* create object */ + + o = builtin_new(clazz); + + if (o == NULL) + return NULL; + + /* call constructor */ + + _Jv_jni_CallVoidMethod(o, o->vftbl, m, args); + + return NewLocalRef(env, o); +} + + +/* NewObjectA ***************************************************************** + + Programmers place all arguments that are to be passed to the + constructor in an args array of jvalues that immediately follows + the methodID argument. NewObjectA() accepts the arguments in this + array, and, in turn, passes them to the Java method that the + programmer wishes to invoke. + +*******************************************************************************/ + +jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args) +{ + java_objectheader *o; + methodinfo *m; + + STATISTICS(jniinvokation()); + + m = (methodinfo *) methodID; + + /* create object */ + + o = builtin_new(clazz); + + if (o == NULL) + return NULL; + + /* call constructor */ + + _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args); + + return NewLocalRef(env, o); +} + + +/* GetObjectClass ************************************************************** + + Returns the class of an object. + +*******************************************************************************/ + +jclass GetObjectClass(JNIEnv *env, jobject obj) +{ + java_objectheader *o; + classinfo *c; + + STATISTICS(jniinvokation()); + + o = (java_objectheader *) obj; + + if ((o == NULL) || (o->vftbl == NULL)) + return NULL; + + c = o->vftbl->class; + + return (jclass) NewLocalRef(env, (jobject) c); +} + + +/* IsInstanceOf **************************************************************** + + Tests whether an object is an instance of a class. + +*******************************************************************************/ + +jboolean IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz) +{ + STATISTICS(jniinvokation()); + + return Java_java_lang_VMClass_isInstance(env, + NULL, + (java_lang_Class *) clazz, + (java_lang_Object *) obj); +} + + +/* Reflection Support *********************************************************/ + +/* FromReflectedMethod ********************************************************* + + Converts java.lang.reflect.Method or java.lang.reflect.Constructor + object to a method ID. + +*******************************************************************************/ + +jmethodID FromReflectedMethod(JNIEnv *env, jobject method) +{ + methodinfo *mi; + classinfo *c; + s4 slot; + + 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; + + mi = &(c->methods[slot]); + + return (jmethodID) mi; +} + + +/* FromReflectedField ********************************************************** + + Converts a java.lang.reflect.Field to a field ID. + +*******************************************************************************/ + +jfieldID FromReflectedField(JNIEnv* env, jobject field) +{ + java_lang_reflect_Field *rf; + classinfo *c; + fieldinfo *f; + + STATISTICS(jniinvokation()); + + rf = (java_lang_reflect_Field *) field; + + if (rf == NULL) + return NULL; + + c = (classinfo *) rf->declaringClass; + + f = &(c->fields[rf->slot]); + + return (jfieldID) f; +} + + +/* ToReflectedMethod *********************************************************** + + 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) +{ + 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; +} + + +/* Calling Instance Methods ***************************************************/ + +/* GetMethodID ***************************************************************** + + 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) +{ + 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 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 == NULL) || (m->flags & ACC_STATIC)) { + exceptions_throw_nosuchmethoderror(c, uname, udesc); + + return NULL; + } + + return (jmethodID) m; +} + + +/* JNI-functions for calling instance methods *********************************/ + +jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + java_objectheader *ret; + va_list ap; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, ap); + va_end(ap); + + return NewLocalRef(env, ret); +} + + +jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + java_objectheader *ret; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + ret = _Jv_jni_CallObjectMethod(o, o->vftbl, m, args); + + return NewLocalRef(env, ret); +} + + +jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + java_objectheader *o; + methodinfo *m; + java_objectheader *ret; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + ret = _Jv_jni_CallObjectMethodA(o, o->vftbl, m, args); + + return NewLocalRef(env, ret); +} + + +jboolean CallBooleanMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jboolean b; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap); + va_end(ap); + + return b; +} + + +jboolean CallBooleanMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jboolean b; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args); + + return b; +} + + +jboolean CallBooleanMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + java_objectheader *o; + methodinfo *m; + jboolean b; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethodA(o, o->vftbl, m, args); + + return b; +} + + +jbyte CallByteMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jbyte b; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap); + va_end(ap); + + return b; + +} + +jbyte CallByteMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jbyte b; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(o, o->vftbl, m, args); + + return b; +} + + +jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallByteMethodA: IMPLEMENT ME!"); + + return 0; +} + + +jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jchar c; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + c = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap); + va_end(ap); + + return c; +} + + +jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jchar c; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + c = _Jv_jni_CallIntMethod(o, o->vftbl, m, args); + + return c; +} + + +jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallCharMethodA: IMPLEMENT ME!"); + + return 0; +} + + +jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jshort s; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + s = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap); + va_end(ap); + + return s; +} + + +jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jshort s; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + s = _Jv_jni_CallIntMethod(o, o->vftbl, m, args); + + return s; +} + + +jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallShortMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jint i; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + i = _Jv_jni_CallIntMethod(o, o->vftbl, m, ap); + va_end(ap); + + return i; +} + + +jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jint i; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + i = _Jv_jni_CallIntMethod(o, o->vftbl, m, args); + + return i; +} + + +jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallIntMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jlong l; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + l = _Jv_jni_CallLongMethod(o, o->vftbl, m, ap); + va_end(ap); + + return l; +} + + +jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jlong l; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + l = _Jv_jni_CallLongMethod(o, o->vftbl, m, args); + + return l; +} + + +jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallLongMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jfloat f; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, ap); + va_end(ap); + + return f; +} + + +jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jfloat f; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + f = _Jv_jni_CallFloatMethod(o, o->vftbl, m, args); + + return f; +} + + +jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallFloatMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + jdouble d; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, ap); + va_end(ap); + + return d; +} + + +jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + jdouble d; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + d = _Jv_jni_CallDoubleMethod(o, o->vftbl, m, args); + + return d; +} + + +jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallDoubleMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +{ + java_objectheader *o; + methodinfo *m; + va_list ap; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + _Jv_jni_CallVoidMethod(o, o->vftbl, m, ap); + va_end(ap); +} + + +void CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +{ + java_objectheader *o; + methodinfo *m; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethod(o, o->vftbl, m, args); +} + + +void CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +{ + java_objectheader *o; + methodinfo *m; + + o = (java_objectheader *) obj; + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethodA(o, o->vftbl, m, args); +} + + + +jobject CallNonvirtualObjectMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + java_objectheader *r; + va_list ap; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap); + va_end(ap); + + return NewLocalRef(env, r); +} + + +jobject CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + java_objectheader *r; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args); + + return NewLocalRef(env, r); +} + + +jobject CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); +} + + + +jboolean CallNonvirtualBooleanMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jboolean b; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap); + va_end(ap); + + return b; +} + + +jboolean CallNonvirtualBooleanMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jboolean b; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); + + return b; +} + + +jboolean CallNonvirtualBooleanMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualBooleanMethodA: IMPLEMENT ME!"); + + return 0; +} + + +jbyte CallNonvirtualByteMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jbyte b; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap); + va_end(ap); + + return b; +} + + +jbyte CallNonvirtualByteMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jbyte b; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); + + return b; +} + + +jbyte CallNonvirtualByteMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualByteMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jchar CallNonvirtualCharMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jchar ch; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap); + va_end(ap); + + return ch; +} + + +jchar CallNonvirtualCharMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jchar ch; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + ch = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); + + return ch; +} + + +jchar CallNonvirtualCharMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualCharMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jshort CallNonvirtualShortMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jshort s; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + s = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap); + va_end(ap); + + return s; +} + + +jshort CallNonvirtualShortMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jshort s; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + s = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); + + return s; +} + + +jshort CallNonvirtualShortMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualShortMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jint CallNonvirtualIntMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jint i; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + i = _Jv_jni_CallIntMethod(o, c->vftbl, m, ap); + va_end(ap); + + return i; +} + + +jint CallNonvirtualIntMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jint i; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + i = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); + + return i; +} + + +jint CallNonvirtualIntMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualIntMethodA: IMPLEMENT ME!"); + + return 0; +} + + + +jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jlong l; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + + va_start(ap, methodID); + l = _Jv_jni_CallLongMethod(o, c->vftbl, m, ap); + va_end(ap); + + return l; +} + + +jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jlong l; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - asm_calljavafunction(m, e, NULL, NULL, NULL); - } + l = _Jv_jni_CallLongMethod(o, c->vftbl, m, args); + + return l; } -/* ExceptionClear ************************************************************** +jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!"); - Clears any exception that is currently being thrown. If no - exception is currently being thrown, this routine has no effect. + return 0; +} -*******************************************************************************/ -void ExceptionClear(JNIEnv *env) + +jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) { - *exceptionptr = NULL; -} + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jfloat f; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -/* FatalError ****************************************************************** + va_start(ap, methodID); + f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, ap); + va_end(ap); - Raises a fatal error and does not expect the VM to recover. This - function does not return. + return f; +} -*******************************************************************************/ -void FatalError(JNIEnv *env, const char *msg) +jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - throw_cacao_exception_exit(string_java_lang_InternalError, msg); -} + java_objectheader *o; + classinfo *c; + methodinfo *m; + jfloat f; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -/******************* creates a new local reference frame **************************/ + f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, args); -jint PushLocalFrame(JNIEnv* env, jint capacity) + return f; +} + + +jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - /* empty */ + log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!"); return 0; } -/**************** Pops off the current local reference frame **********************/ -jobject PopLocalFrame(JNIEnv* env, jobject result) -{ - log_text("JNI-Call: PopLocalFrame: IMPLEMENT ME!"); - return NULL; -} +jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jdouble d; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -/* DeleteLocalRef ************************************************************** + va_start(ap, methodID); + d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, ap); + va_end(ap); - Deletes the local reference pointed to by localRef. + return d; +} -*******************************************************************************/ -void DeleteLocalRef(JNIEnv *env, jobject localRef) +jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: DeleteLocalRef: IMPLEMENT ME!"); -} + java_objectheader *o; + classinfo *c; + methodinfo *m; + jdouble d; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -/* IsSameObject **************************************************************** + d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, args); - Tests whether two references refer to the same Java object. + return d; +} -*******************************************************************************/ -jboolean IsSameObject(JNIEnv *env, jobject ref1, jobject ref2) +jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) { - return (ref1 == ref2); + log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!"); + + return 0; } -/* NewLocalRef ***************************************************************** - Creates a new local reference that refers to the same object as ref. +void CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; -*******************************************************************************/ + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -jobject NewLocalRef(JNIEnv *env, jobject ref) + va_start(ap, methodID); + _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap); + va_end(ap); +} + + +void CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: NewLocalRef: IMPLEMENT ME!"); + java_objectheader *o; + classinfo *c; + methodinfo *m; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - return ref; + _Jv_jni_CallVoidMethod(o, c->vftbl, m, args); } -/*********************************************************************************** - Ensures that at least a given number of local references can - be created in the current thread +void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; - **********************************************************************************/ + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; -jint EnsureLocalCapacity (JNIEnv* env, jint capacity) -{ - return 0; /* return 0 on success */ + _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args); } -/* AllocObject ***************************************************************** +/* Accessing Fields of Objects ************************************************/ - Allocates a new Java object without invoking any of the - constructors for the object. Returns a reference to the object. +/* 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. *******************************************************************************/ -jobject AllocObject(JNIEnv *env, jclass clazz) +jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - java_objectheader *o; + fieldinfo *f; + utf *uname; + utf *udesc; - 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); + STATISTICS(jniinvokation()); + + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); + + f = class_findfield(clazz, uname, udesc); + + if (!f) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); - return o; + return (jfieldID) f; } -/* NewObject ******************************************************************* +/* GetField Routines ***************************************************** - Constructs a new Java object. The method ID indicates which - constructor method to invoke. This ID must be obtained by calling - GetMethodID() with as the method name and void (V) as the - return type. + 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(). *******************************************************************************/ -jobject NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) { java_objectheader *o; - void* args[3]; - int argcount=get_parametercount(methodID); - int i; - va_list vaargs; - -#ifdef arglimit - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. NewObject does not support that"); - return 0; - } -#endif - /* create object */ + STATISTICS(jniinvokation()); - o = builtin_new(clazz); - - if (!o) - return NULL; + o = GET_FIELD(obj, java_objectheader*, fieldID); - va_start(vaargs, methodID); - for (i = 0; i < argcount; i++) { - args[i] = va_arg(vaargs, void*); - } - va_end(vaargs); + return NewLocalRef(env, o); +} - /* call constructor */ - asm_calljavafunction(methodID, o, args[0], args[1], args[2]); +jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + s4 i; + + STATISTICS(jniinvokation()); - return o; + i = GET_FIELD(obj, s4, fieldID); + + return (jboolean) i; } -/*********************************************************************************** +jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + s4 i; - Constructs a new Java object - arguments that are to be passed to the constructor are placed in va_list args + STATISTICS(jniinvokation()); -***********************************************************************************/ + i = GET_FIELD(obj, s4, fieldID); -jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID, va_list args) + return (jbyte) i; +} + + +jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) { - log_text("JNI-Call: NewObjectV"); + s4 i; - return NULL; + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jchar) i; } -/*********************************************************************************** +jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + s4 i; + + STATISTICS(jniinvokation()); - Constructs a new Java object - arguments that are to be passed to the constructor are placed in - args array of jvalues + i = GET_FIELD(obj, s4, fieldID); -***********************************************************************************/ + return (jshort) i; +} -jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID, jvalue *args) + +jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) { - log_text("JNI-Call: NewObjectA"); + java_objectheader *o; + fieldinfo *f; + s4 i; - return NULL; -} + STATISTICS(jniinvokation()); + o = (java_objectheader *) obj; + f = (fieldinfo *) fieldID; -/* GetObjectClass ************************************************************** + i = GET_FIELD(o, s4, f); - Returns the class of an object. + return i; +} -*******************************************************************************/ -jclass GetObjectClass(JNIEnv *env, jobject obj) +jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) { - classinfo *c = obj->vftbl->class; + s8 l; - use_class_as_object(c); + STATISTICS(jniinvokation()); - return c; -} + l = GET_FIELD(obj, s8, fieldID); + return l; +} -/************* tests whether an object is an instance of a class ******************/ -jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) +jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return builtin_instanceof(obj,clazz); -} + float f; + STATISTICS(jniinvokation()); -/***************** converts a java.lang.reflect.Field to a field ID ***************/ - -jfieldID FromReflectedField(JNIEnv* env, jobject field) -{ - log_text("JNI-Call: FromReflectedField"); + f = GET_FIELD(obj, float, fieldID); - return 0; + return f; } -/********************************************************************************** - - converts a method ID to a java.lang.reflect.Method or - java.lang.reflect.Constructor object +jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + double d; -**********************************************************************************/ + STATISTICS(jniinvokation()); -jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic) -{ - log_text("JNI-Call: ToReflectedMethod"); + d = GET_FIELD(obj, double, fieldID); - return NULL; + return d; } -/* GetMethodID ***************************************************************** +/* SetField Routines ***************************************************** - returns the method ID for an instance method + 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(). *******************************************************************************/ -jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig) +void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) { - jmethodID m; + STATISTICS(jniinvokation()); - m = class_resolvemethod(clazz, - utf_new_char((char *) name), - utf_new_char((char *) sig)); + SET_FIELD(obj, java_objectheader*, fieldID, value); +} - if (!m || (m->flags & ACC_STATIC)) { - *exceptionptr = - new_exception_message(string_java_lang_NoSuchMethodError, name); - return 0; - } +void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value) +{ + STATISTICS(jniinvokation()); - return m; + SET_FIELD(obj, s4, fieldID, value); } -/******************** JNI-functions for calling instance methods ******************/ - -jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value) { - jobject 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; + SET_FIELD(obj, s4, fieldID, value); } -jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value) { - return callObjectMethod(obj,methodID,args); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } -jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) +void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value) { - log_text("JNI-Call: CallObjectMethodA"); + STATISTICS(jniinvokation()); - return NULL; + SET_FIELD(obj, s4, fieldID, value); } - - -jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) +void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value) { - jboolean ret; - va_list vaargs; + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); +} -/* log_text("JNI-Call: CallBooleanMethod");*/ - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs); - va_end(vaargs); - return ret; +void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value) +{ + STATISTICS(jniinvokation()); + SET_FIELD(obj, s8, fieldID, value); } -jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) + +void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value) { - return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args); + STATISTICS(jniinvokation()); + SET_FIELD(obj, float, fieldID, value); } -jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) + +void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value) { - log_text("JNI-Call: CallBooleanMethodA"); + STATISTICS(jniinvokation()); - return 0; + SET_FIELD(obj, double, fieldID, value); } -jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) -{ - jbyte ret; - va_list vaargs; -/* log_text("JNI-Call: CallVyteMethod");*/ +/* Calling Static Methods *****************************************************/ - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs); - va_end(vaargs); - return ret; +/* GetStaticMethodID *********************************************************** -} + Returns the method ID for a static method of a class. The method is + specified by its name and signature. -jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ -/* log_text("JNI-Call: CallByteMethodV");*/ - return callIntegerMethod(obj,methodID,'B',args); -} + GetStaticMethodID() causes an uninitialized class to be + initialized. +*******************************************************************************/ -jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - log_text("JNI-Call: CallByteMethodA"); - - return 0; -} + classinfo *c; + utf *uname; + utf *udesc; + methodinfo *m; + STATISTICS(jniinvokation()); -jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) -{ - jchar ret; - va_list vaargs; + c = (classinfo *) clazz; -/* log_text("JNI-Call: CallCharMethod");*/ + if (!c) + return NULL; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs); - va_end(vaargs); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; - return ret; -} + /* try to get the static method of the class */ + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); -jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ -/* log_text("JNI-Call: CallCharMethodV");*/ - return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args); -} + m = class_resolvemethod(c, uname, udesc); + if ((m == NULL) || !(m->flags & ACC_STATIC)) { + exceptions_throw_nosuchmethoderror(c, uname, udesc); -jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallCharMethodA"); + return NULL; + } - return 0; + return (jmethodID) m; } -jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jshort ret; - va_list vaargs; + methodinfo *m; + java_objectheader *o; + va_list ap; -/* log_text("JNI-Call: CallShortMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs, methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs); - va_end(vaargs); + va_start(ap, methodID); + o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap); + va_end(ap); - return ret; + return NewLocalRef(env, o); } -jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args); -} + methodinfo *m; + java_objectheader *o; + m = (methodinfo *) methodID; -jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallShortMethodA"); + o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args); - return 0; + return NewLocalRef(env, o); } - -jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - jint ret; - va_list vaargs; + methodinfo *m; + java_objectheader *o; + + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs); - va_end(vaargs); + o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args); - return ret; + return NewLocalRef(env, o); } -jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args); -} + methodinfo *m; + va_list ap; + jboolean b; + m = (methodinfo *) methodID; -jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallIntMethodA"); + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); - return 0; + return b; } - -jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - jlong ret; - va_list vaargs; - - va_start(vaargs,methodID); - ret = callLongMethod(obj,get_virtual(obj, methodID),vaargs); - va_end(vaargs); + methodinfo *m; + jboolean b; - return ret; -} + m = (methodinfo *) methodID; + b = _Jv_jni_CallIntMethod(NULL, NULL, m, args); -jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ - return callLongMethod(obj,get_virtual(obj, methodID),args); + return b; } -jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallLongMethodA"); + log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!"); return 0; } - -jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jfloat ret; - va_list vaargs; + methodinfo *m; + va_list ap; + jbyte b; -/* log_text("JNI-Call: CallFloatMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F'); - va_end(vaargs); + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); - return ret; + return b; } -jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallFloatMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F'); + methodinfo *m; + jbyte b; + + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return b; } -jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallFloatMethodA"); + log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!"); return 0; } - -jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jdouble ret; - va_list vaargs; + methodinfo *m; + va_list ap; + jchar c; -/* log_text("JNI-Call: CallDoubleMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D'); - va_end(vaargs); + va_start(ap, methodID); + c = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); - return ret; + return c; } -jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallDoubleMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D'); + methodinfo *m; + jchar c; + + m = (methodinfo *) methodID; + + c = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return c; } -jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallDoubleMethodA"); + log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!"); + return 0; } +jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; + jshort s; + + m = (methodinfo *) methodID; + + va_start(ap, methodID); + s = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); -void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) + return s; +} + + +jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - va_list vaargs; + methodinfo *m; + jshort s; + + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs); - va_end(vaargs); + s = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return s; } -void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallVoidMethodV"); - (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args); + log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!"); + + return 0; } -void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) +jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - log_text("JNI-Call: CallVoidMethodA"); -} + methodinfo *m; + va_list ap; + jint i; + m = (methodinfo *) methodID; + va_start(ap, methodID); + i = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); -jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - log_text("JNI-Call: CallNonvirtualObjectMethod"); - - return NULL; + return i; } -jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - log_text("JNI-Call: CallNonvirtualObjectMethodV"); + methodinfo *m; + jint i; - return NULL; + m = (methodinfo *) methodID; + + i = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return i; } -jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualObjectMethodA"); + log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!"); - return NULL; + return 0; } - -jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jboolean ret; - va_list vaargs; + methodinfo *m; + va_list ap; + jlong l; -/* log_text("JNI-Call: CallNonvirtualBooleanMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs); - va_end(vaargs); - return ret; + va_start(ap, methodID); + l = _Jv_jni_CallLongMethod(NULL, NULL, m, ap); + va_end(ap); + return l; } -jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, + va_list args) { -/* log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/ - return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args); + methodinfo *m; + jlong l; + + m = (methodinfo *) methodID; + + l = _Jv_jni_CallLongMethod(NULL, NULL, m, args); + + return l; } -jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualBooleanMethodA"); + log_text("JNI-Call: CallStaticLongMethodA: IMPLEMENT ME!"); return 0; } -jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jbyte ret; - va_list vaargs; + methodinfo *m; + va_list ap; + jfloat f; + + m = (methodinfo *) methodID; -/* log_text("JNI-Call: CallNonvirutalByteMethod");*/ + va_start(ap, methodID); + f = _Jv_jni_CallFloatMethod(NULL, NULL, m, ap); + va_end(ap); - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs); - va_end(vaargs); - return ret; + return f; } -jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',args); + methodinfo *m; + jfloat f; + + m = (methodinfo *) methodID; + + f = _Jv_jni_CallFloatMethod(NULL, NULL, m, args); + return f; } -jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualByteMethodA"); + log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!"); return 0; } - -jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jchar ret; - va_list vaargs; + methodinfo *m; + va_list ap; + jdouble d; -/* log_text("JNI-Call: CallNonVirtualCharMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs); - va_end(vaargs); - return ret; + va_start(ap, methodID); + d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, ap); + va_end(ap); + + return d; } -jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args); + methodinfo *m; + jdouble d; + + m = (methodinfo *) methodID; + + d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, args); + + return d; } -jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: CallNonvirtualCharMethodA"); + log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!"); return 0; } - -jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - jshort ret; - va_list vaargs; + methodinfo *m; + va_list ap; - /*log_text("JNI-Call: CallNonvirtualShortMethod");*/ + m = (methodinfo *) methodID; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs); - va_end(vaargs); - return ret; + va_start(ap, methodID); + _Jv_jni_CallVoidMethod(NULL, NULL, m, ap); + va_end(ap); } -jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args); + methodinfo *m; + + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethod(NULL, NULL, m, args); } -jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args) { - log_text("JNI-Call: CallNonvirtualShortMethodA"); + methodinfo *m; - return 0; + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethodA(NULL, NULL, m, args); } +/* Accessing Static Fields ****************************************************/ + +/* GetStaticFieldID ************************************************************ -jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) + 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) { + fieldinfo *f; - jint ret; - va_list vaargs; + STATISTICS(jniinvokation()); - /*log_text("JNI-Call: CallNonvirtualIntMethod");*/ + f = class_findfield(clazz, + utf_new_char((char *) name), + utf_new_char((char *) sig)); + + if (f == NULL) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs); - va_end(vaargs); - return ret; + return (jfieldID) f; } -jint CallNonvirtualIntMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ - /*log_text("JNI-Call: CallNonvirtualIntMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',args); -} +/* GetStaticField ******************************************************** + This family of accessor routines returns the value of a static + field of an object. -jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualIntMethodA"); +*******************************************************************************/ - return 0; -} +jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) +{ + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - log_text("JNI-Call: CallNonvirtualLongMethod"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; - return 0; + return NewLocalRef(env, f->value.a); } -jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallNonvirtualLongMethodV"); + classinfo *c; + fieldinfo *f; - return 0; -} + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualLongMethodA"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return false; - return 0; + return f->value.i; } - -jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jfloat ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; - /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/ + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F'); - va_end(vaargs); - return ret; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + return f->value.i; } -jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallNonvirtualFloatMethodV"); - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F'); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualFloatMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return 0; -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + return f->value.i; +} -jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jdouble ret; - va_list vaargs; - log_text("JNI-Call: CallNonvirtualDoubleMethod"); + classinfo *c; + fieldinfo *f; - va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D'); - va_end(vaargs); - return ret; + STATISTICS(jniinvokation()); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; -jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ -/* log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/ - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D'); + return f->value.i; } -jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallNonvirtualDoubleMethodA"); + classinfo *c; + fieldinfo *f; - return 0; -} + STATISTICS(jniinvokation()); + + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + + return f->value.i; +} -void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - va_list vaargs; + classinfo *c; + fieldinfo *f; + + STATISTICS(jniinvokation()); -/* log_text("JNI-Call: CallNonvirtualVoidMethod");*/ + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - va_start(vaargs,methodID); - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs); - va_end(vaargs); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + return f->value.l; } -void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) { -/* log_text("JNI-Call: CallNonvirtualVoidMethodV");*/ + classinfo *c; + fieldinfo *f; - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args); + STATISTICS(jniinvokation()); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0.0; -void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) -{ - log_text("JNI-Call: CallNonvirtualVoidMethodA"); + return f->value.f; } -/************************* JNI-functions for accessing fields ************************/ -jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) +jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jfieldID f; - -/* log_text("========================= searching for:"); - log_text(name); - log_text(sig);*/ - f = jclass_findfield(clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); - - if (!f) { - /*utf_display(clazz->name); - log_text(name); - log_text(sig);*/ - *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); - } - return f; -} + classinfo *c; + fieldinfo *f; -/*************************** retrieve fieldid, abort on error ************************/ + STATISTICS(jniinvokation()); -jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig) -{ - jfieldID id = GetFieldID(env, clazz, name, sig); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - if (!id) { - log_text("class:"); - utf_display(clazz->name); - log_text("\nfield:"); - log_text(name); - log_text("sig:"); - log_text(sig); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0.0; - panic("setfield_critical failed"); - } - return id; + return f->value.d; } -jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - /* - jobject dbg,dretval,*dpretval; - long int dli1, dli2, dli3; - printf("GetObjectField(1): thread: %s obj: %p name: %s desc: %s \n",GetStringUTFChars(env, - ((threadobject *) THREADOBJECT)->o - .thread->name,NULL) - ,obj,((fieldinfo*)fieldID)->name->text,(fieldID->descriptor)->text); +/* SetStaticField ******************************************************* - dbg = getField(obj,jobject,fieldID); - dli1 = (long int) obj; - dli2 = (long int) fieldID->offset; - dli3 = dli1+dli2; - dpretval = (jobject*) dli3; - dretval = *dpretval; - jclass tmp; - jmethodID mid; - jstring jstr; + This family of accessor routines sets the value of a static field + of an object. - tmp = FindClass(env, "java/lang/Object"); - mid = GetMethodID(env,tmp,"toString","()Ljava/lang/String;"); - jstr = CallObjectMethod(env,dbg,mid);*/ +*******************************************************************************/ -/* printf("GetObjectField(2): retval %p (obj: %#lx + offset: %#lx = %#lx (jobject*) %p (jobject) %p\n" - ,dbg, dli1, dli2, dli3,dpretval, dretval);*/ +void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) +{ + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -/* return dbg;*/ + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return getField(obj,jobject,fieldID); -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jboolean,fieldID); + f->value.a = value; } -jbyte GetByteField (JNIEnv *env, jobject obj, jfieldID fieldID) +void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) { - return getField(obj,jbyte,fieldID); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jchar GetCharField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jchar,fieldID); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -jshort GetShortField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jshort,fieldID); + f->value.i = value; } -jint GetIntField (JNIEnv *env, jobject obj, jfieldID fieldID) +void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) { - return getField(obj,jint,fieldID); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jlong GetLongField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jlong,fieldID); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -jfloat GetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jfloat,fieldID); + f->value.i = value; } -jdouble GetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID) +void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) { - return getField(obj,jdouble,fieldID); -} - -void SetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val) -{ - setField(obj,jobject,fieldID,val); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -void SetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val) -{ - setField(obj,jboolean,fieldID,val); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -void SetByteField (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val) -{ - setField(obj,jbyte,fieldID,val); + f->value.i = value; } -void SetCharField (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val) +void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) { - setField(obj,jchar,fieldID,val); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -void SetShortField (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val) -{ - setField(obj,jshort,fieldID,val); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -void SetIntField (JNIEnv *env, jobject obj, jfieldID fieldID, jint val) -{ - setField(obj,jint,fieldID,val); + f->value.i = value; } -void SetLongField (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val) +void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) { - setField(obj,jlong,fieldID,val); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -void SetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val) -{ - setField(obj,jfloat,fieldID,val); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val) -{ - setField(obj,jdouble,fieldID,val); + f->value.i = value; } -/**************** JNI-functions for calling static methods **********************/ - -jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig) +void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) { - jmethodID m; + classinfo *c; + fieldinfo *f; - m = class_resolvemethod(clazz, - utf_new_char((char *) name), - utf_new_char((char *) sig)); + STATISTICS(jniinvokation()); - if (!m || !(m->flags & ACC_STATIC)) { - *exceptionptr = - new_exception_message(string_java_lang_NoSuchMethodError, name); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return NULL; - } + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; - return m; + f->value.l = value; } -jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) { - jobject ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; + + STATISTICS(jniinvokation()); - /* log_text("JNI-Call: CallStaticObjectMethod");*/ + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - va_start(vaargs, methodID); - ret = callObjectMethod(0, methodID, vaargs); - va_end(vaargs); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; - return ret; + f->value.f = value; } -jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) { - /* log_text("JNI-Call: CallStaticObjectMethodV"); */ - - return callObjectMethod(0,methodID,args); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticObjectMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return NULL; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + + f->value.d = value; } -jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - jboolean ret; - va_list vaargs; +/* String Operations **********************************************************/ - va_start(vaargs, methodID); - ret = (jboolean) callIntegerMethod(0, methodID, 'Z', vaargs); - va_end(vaargs); +/* NewString ******************************************************************* - return ret; -} + Create new java.lang.String object from an array of Unicode + characters. +*******************************************************************************/ -jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jstring NewString(JNIEnv *env, const jchar *buf, jsize len) { - return (jboolean) callIntegerMethod(0, methodID, 'Z', args); -} + java_lang_String *s; + java_chararray *a; + u4 i; + STATISTICS(jniinvokation()); + + s = (java_lang_String *) builtin_new(class_java_lang_String); + a = builtin_newarray_char(len); -jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticBooleanMethodA"); + /* javastring or characterarray could not be created */ + if (!a || !s) + return NULL; - return 0; -} + /* copy text */ + for (i = 0; i < len; i++) + a->data[i] = buf[i]; + s->value = a; + s->offset = 0; + s->count = len; -jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - jbyte ret; - va_list vaargs; + return (jstring) NewLocalRef(env, (jobject) s); +} - /* log_text("JNI-Call: CallStaticByteMethod");*/ - va_start(vaargs, methodID); - ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs); - va_end(vaargs); +static jchar emptyStringJ[]={0,0}; - return ret; -} +/* GetStringLength ************************************************************* + Returns the length (the count of Unicode characters) of a Java + string. -jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +*******************************************************************************/ + +jsize GetStringLength(JNIEnv *env, jstring str) { - return (jbyte) callIntegerMethod(0, methodID, 'B', args); + return ((java_lang_String *) str)->count; } -jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) +/******************** convertes javastring to u2-array ****************************/ + +u2 *javastring_tou2(jstring so) { - log_text("JNI-Call: CallStaticByteMethodA"); + java_lang_String *s; + java_chararray *a; + u2 *stringbuffer; + u4 i; - return 0; -} + STATISTICS(jniinvokation()); + + s = (java_lang_String *) so; + if (!s) + return NULL; -jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - jchar ret; - va_list vaargs; + a = s->value; + + if (!a) + return NULL; - /* log_text("JNI-Call: CallStaticByteMethod");*/ + /* allocate memory */ - va_start(vaargs, methodID); - ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs); - va_end(vaargs); + stringbuffer = MNEW(u2, s->count + 1); - return ret; -} + /* copy text */ + for (i = 0; i < s->count; i++) + stringbuffer[i] = a->data[s->offset + i]; + + /* terminate string */ -jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - return (jchar) callIntegerMethod(0, methodID, 'C', args); + stringbuffer[i] = '\0'; + + return stringbuffer; } -jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticCharMethodA"); +/* GetStringChars ************************************************************** - return 0; -} + 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; -jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - jshort ret; - va_list vaargs; + STATISTICS(jniinvokation()); - /* log_text("JNI-Call: CallStaticByteMethod");*/ + jc = javastring_tou2(str); - va_start(vaargs, methodID); - ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs); - va_end(vaargs); + if (jc) { + if (isCopy) + *isCopy = JNI_TRUE; - return ret; -} + return jc; + } + if (isCopy) + *isCopy = JNI_TRUE; -jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - /*log_text("JNI-Call: CallStaticShortMethodV");*/ - return (jshort) callIntegerMethod(0, methodID, 'S', args); + return emptyStringJ; } -jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) +/* 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) { - log_text("JNI-Call: CallStaticShortMethodA"); + STATISTICS(jniinvokation()); - return 0; + if (chars == emptyStringJ) + return; + + MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1); } +/* NewStringUTF **************************************************************** -jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) + Constructs a new java.lang.String object from an array of UTF-8 characters. + +*******************************************************************************/ + +jstring NewStringUTF(JNIEnv *env, const char *bytes) { - jint ret; - va_list vaargs; + java_lang_String *s; - /* log_text("JNI-Call: CallStaticIntMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs, methodID); - ret = callIntegerMethod(0, methodID, 'I', vaargs); - va_end(vaargs); + s = javastring_new(utf_new_char(bytes)); - return ret; + return (jstring) NewLocalRef(env, (jobject) s); } -jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallStaticIntMethodV"); - - return callIntegerMethod(0, methodID, 'I', args); -} +/****************** returns the utf8 length in bytes of a string *******************/ +jsize GetStringUTFLength (JNIEnv *env, jstring string) +{ + java_lang_String *s = (java_lang_String*) string; -jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticIntMethodA"); + STATISTICS(jniinvokation()); - return 0; + return (jsize) u2_utflength(s->value->data, s->count); } +/* GetStringUTFChars *********************************************************** -jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - jlong ret; - va_list vaargs; + Returns a pointer to an array of UTF-8 characters of the + string. This array is valid until it is released by + ReleaseStringUTFChars(). - /* log_text("JNI-Call: CallStaticLongMethod");*/ +*******************************************************************************/ - va_start(vaargs, methodID); - ret = callLongMethod(0, methodID, vaargs); - va_end(vaargs); +const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) +{ + utf *u; - return ret; -} + STATISTICS(jniinvokation()); + if (!string) + return ""; -jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallStaticLongMethodV"); + if (isCopy) + *isCopy = JNI_TRUE; - return callLongMethod(0,methodID,args); -} + u = javastring_toutf((java_lang_String *) string, false); + if (u) + return u->text; -jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticLongMethodA"); - - return 0; + return ""; } +/* ReleaseStringUTFChars ******************************************************* -jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) + Informs the VM that the native code no longer needs access to + utf. The utf argument is a pointer derived from string using + GetStringUTFChars(). + +*******************************************************************************/ + +void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) { - jfloat ret; - va_list vaargs; + STATISTICS(jniinvokation()); + + /* 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 */ +} + - /* log_text("JNI-Call: CallStaticLongMethod");*/ +/* Array Operations ***********************************************************/ - va_start(vaargs, methodID); - ret = callFloatMethod(0, methodID, vaargs, 'F'); - va_end(vaargs); +/* GetArrayLength ************************************************************** - return ret; -} + Returns the number of elements in the array. +*******************************************************************************/ -jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jsize GetArrayLength(JNIEnv *env, jarray array) { + java_arrayheader *a; - return callFloatMethod(0, methodID, args, 'F'); + STATISTICS(jniinvokation()); -} + a = (java_arrayheader *) array; + return a->size; +} -jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticFloatMethodA"); - return 0; -} +/* NewObjectArray ************************************************************** + Constructs a new array holding objects in class elementClass. All + elements are initially set to initialElement. +*******************************************************************************/ -jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) { - jdouble ret; - va_list vaargs; + java_objectarray *oa; + s4 i; - /* log_text("JNI-Call: CallStaticDoubleMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = callFloatMethod(0, methodID, vaargs, 'D'); - va_end(vaargs); + if (length < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } - return ret; -} + oa = builtin_anewarray(length, elementClass); + + if (!oa) + return NULL; + /* set all elements to initialElement */ -jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallStaticDoubleMethodV"); + for (i = 0; i < length; i++) + oa->data[i] = initialElement; - return callFloatMethod(0, methodID, args, 'D'); + return (jobjectArray) NewLocalRef(env, (jobject) oa); } -jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { - log_text("JNI-Call: CallStaticDoubleMethodA"); + java_objectarray *oa; + jobject o; - return 0; -} + STATISTICS(jniinvokation()); + oa = (java_objectarray *) array; -void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...) -{ - va_list vaargs; + if (index >= oa->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); + return NULL; + } - va_start(vaargs, methodID); - (void) callIntegerMethod(0, methodID, 'V', vaargs); - va_end(vaargs); + o = oa->data[index]; + + return NewLocalRef(env, o); } -void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args) +void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val) { - log_text("JNI-Call: CallStaticVoidMethodV"); - (void)callIntegerMethod(0, methodID, 'V', args); -} + java_objectarray *oa; + java_objectheader *o; + STATISTICS(jniinvokation()); -void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args) -{ - log_text("JNI-Call: CallStaticVoidMethodA"); -} + oa = (java_objectarray *) array; + o = (java_objectheader *) val; + if (index >= oa->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } -/****************** JNI-functions for accessing static fields ********************/ + /* check if the class of value is a subclass of the element class + of the array */ -jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) -{ - jfieldID f; + if (!builtin_canstore(oa, o)) { + *exceptionptr = new_exception(string_java_lang_ArrayStoreException); - f = jclass_findfield(clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); - - if (!f) *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); + return; + } - return f; + oa->data[index] = val; } -jobject GetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) { - class_init(clazz); - return fieldID->value.a; -} + java_booleanarray *ba; + STATISTICS(jniinvokation()); -jboolean GetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ba = builtin_newarray_boolean(len); -jbyte GetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; + return (jbooleanArray) NewLocalRef(env, (jobject) ba); } -jchar GetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jbyteArray NewByteArray(JNIEnv *env, jsize len) { - class_init(clazz); - return fieldID->value.i; -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jshort GetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ba = builtin_newarray_byte(len); -jint GetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; + return (jbyteArray) NewLocalRef(env, (jobject) ba); } -jlong GetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID) +jcharArray NewCharArray(JNIEnv *env, jsize len) { - class_init(clazz); - return fieldID->value.l; -} + java_chararray *ca; + STATISTICS(jniinvokation()); -jfloat GetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.f; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ca = builtin_newarray_char(len); -jdouble GetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.d; + return (jcharArray) NewLocalRef(env, (jobject) ca); } - -void SetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) +jshortArray NewShortArray(JNIEnv *env, jsize len) { - class_init(clazz); - fieldID->value.a = value; -} + java_shortarray *sa; + STATISTICS(jniinvokation()); -void SetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) -{ - class_init(clazz); - fieldID->value.i = value; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + sa = builtin_newarray_short(len); -void SetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) -{ - class_init(clazz); - fieldID->value.i = value; + return (jshortArray) NewLocalRef(env, (jobject) sa); } -void SetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) +jintArray NewIntArray(JNIEnv *env, jsize len) { - class_init(clazz); - fieldID->value.i = value; -} + java_intarray *ia; + STATISTICS(jniinvokation()); -void SetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) -{ - class_init(clazz); - fieldID->value.i = value; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ia = builtin_newarray_int(len); -void SetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) -{ - class_init(clazz); - fieldID->value.i = value; + return (jintArray) NewLocalRef(env, (jobject) ia); } -void SetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) +jlongArray NewLongArray(JNIEnv *env, jsize len) { - class_init(clazz); - fieldID->value.l = value; -} + java_longarray *la; + STATISTICS(jniinvokation()); -void SetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) -{ - class_init(clazz); - fieldID->value.f = value; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + la = builtin_newarray_long(len); -void SetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) -{ - class_init(clazz); - fieldID->value.d = value; + return (jlongArray) NewLocalRef(env, (jobject) la); } -/***** create new java.lang.String object from an array of Unicode characters ****/ - -jstring NewString (JNIEnv *env, const jchar *buf, jsize len) +jfloatArray NewFloatArray(JNIEnv *env, jsize len) { - u4 i; - java_lang_String *s; - java_chararray *a; - - s = (java_lang_String*) builtin_new (class_java_lang_String); - a = builtin_newarray_char (len); + java_floatarray *fa; - /* javastring or characterarray could not be created */ - if ( (!a) || (!s) ) return NULL; + STATISTICS(jniinvokation()); - /* copy text */ - for (i=0; idata[i] = buf[i]; - s -> value = a; - s -> offset = 0; - s -> count = len; + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } - return (jstring) s; + fa = builtin_newarray_float(len); + + return (jfloatArray) NewLocalRef(env, (jobject) fa); } -static char emptyString[]=""; -static jchar emptyStringJ[]={0,0}; +jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) +{ + java_doublearray *da; -/******************* returns the length of a Java string ***************************/ + STATISTICS(jniinvokation()); -jsize GetStringLength (JNIEnv *env, jstring str) -{ - return ((java_lang_String*) str)->count; + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + + da = builtin_newarray_double(len); + + return (jdoubleArray) NewLocalRef(env, (jobject) da); } -/******************** convertes javastring to u2-array ****************************/ - -u2 *javastring_tou2 (jstring so) -{ - java_lang_String *s = (java_lang_String*) so; - java_chararray *a; - u4 i; - u2 *stringbuffer; - - if (!s) return NULL; +/* GetArrayElements ********************************************* - a = s->value; - if (!a) return NULL; + A family of functions that returns the body of the primitive array. - /* allocate memory */ - stringbuffer = MNEW( u2 , s->count + 1 ); +*******************************************************************************/ - /* copy text */ - for (i=0; icount; i++) stringbuffer[i] = a->data[s->offset+i]; - - /* terminate string */ - stringbuffer[i] = '\0'; +jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *isCopy) +{ + java_booleanarray *ba; - return stringbuffer; -} + STATISTICS(jniinvokation()); -/********* returns a pointer to an array of Unicode characters of the string *******/ + ba = (java_booleanarray *) array; -const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy) -{ - jchar *jc=javastring_tou2(str); + if (isCopy) + *isCopy = JNI_FALSE; - if (jc) { - if (isCopy) *isCopy=JNI_TRUE; - return jc; - } - if (isCopy) *isCopy=JNI_TRUE; - return emptyStringJ; + return ba->data; } -/**************** native code no longer needs access to chars **********************/ -void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars) +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { - if (chars==emptyStringJ) return; - MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1); -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -/* NewStringUTF **************************************************************** + ba = (java_bytearray *) array; - Constructs a new java.lang.String object from an array of UTF-8 characters. + if (isCopy) + *isCopy = JNI_FALSE; -*******************************************************************************/ + return ba->data; +} -jstring NewStringUTF(JNIEnv *env, const char *bytes) + +jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) { - return (jstring) javastring_new(utf_new_char(bytes)); -} + java_chararray *ca; + STATISTICS(jniinvokation()); -/****************** returns the utf8 length in bytes of a string *******************/ + ca = (java_chararray *) array; -jsize GetStringUTFLength (JNIEnv *env, jstring string) -{ - java_lang_String *s = (java_lang_String*) string; + if (isCopy) + *isCopy = JNI_FALSE; - return (jsize) u2_utflength(s->value->data, s->count); + return ca->data; } -/************ converts a Javastring to an array of UTF-8 characters ****************/ - -const char* GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) +jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) { - utf *u; + java_shortarray *sa; + + STATISTICS(jniinvokation()); - u = javastring_toutf((java_lang_String *) string, false); + sa = (java_shortarray *) array; - if (isCopy) + if (isCopy) *isCopy = JNI_FALSE; - - if (u) - return u->text; - return emptyString; - + return sa->data; } -/***************** native code no longer needs access to utf ***********************/ - -void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars) +jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) { - /*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)); - */ -} + java_intarray *ia; -/************************** array operations ***************************************/ + STATISTICS(jniinvokation()); -jsize GetArrayLength(JNIEnv *env, jarray array) -{ - return array->size; + ia = (java_intarray *) array; + + if (isCopy) + *isCopy = JNI_FALSE; + + return ia->data; } -jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init) +jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) { - java_objectarray *j; + java_longarray *la; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); + + la = (java_longarray *) array; - j = builtin_anewarray(len, clazz); + if (isCopy) + *isCopy = JNI_FALSE; + + /* We cast this one to prevent a compiler warning on 64-bit + systems since GNU Classpath typedef jlong to long long. */ - return j; + return (jlong *) la->data; } -jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { - jobject j = NULL; + java_floatarray *fa; - if (index < array->header.size) - j = array->data[index]; - else - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); - - return j; + STATISTICS(jniinvokation()); + + fa = (java_floatarray *) array; + + if (isCopy) + *isCopy = JNI_FALSE; + + return fa->data; } -void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val) +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jboolean *isCopy) { - if (index >= array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_doublearray *da; + + STATISTICS(jniinvokation()); + + da = (java_doublearray *) array; - else { - /* check if the class of value is a subclass of the element class of the array */ - if (!builtin_canstore((java_objectarray *) array, (java_objectheader *) val)) - *exceptionptr = new_exception(string_java_lang_ArrayStoreException); + if (isCopy) + *isCopy = JNI_FALSE; - else - array->data[index] = val; - } + return da->data; } +/* ReleaseArrayElements ***************************************** -jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) + 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) { - java_booleanarray *j; + java_booleanarray *ba; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_boolean(len); + ba = (java_booleanarray *) array; - return j; + if (elems != ba->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(ba->data, elems, u1, ba->header.size); + break; + case 0: + MCOPY(ba->data, elems, u1, ba->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jbyteArray NewByteArray(JNIEnv *env, jsize len) +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode) { - java_bytearray *j; + java_bytearray *ba; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_byte(len); + ba = (java_bytearray *) array; - return j; + if (elems != ba->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(ba->data, elems, s1, ba->header.size); + break; + case 0: + MCOPY(ba->data, elems, s1, ba->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jcharArray NewCharArray(JNIEnv *env, jsize len) +void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, + jint mode) { - java_chararray *j; + java_chararray *ca; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_char(len); + ca = (java_chararray *) array; - return j; + if (elems != ca->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(ca->data, elems, u2, ca->header.size); + break; + case 0: + MCOPY(ca->data, elems, u2, ca->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jshortArray NewShortArray(JNIEnv *env, jsize len) +void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, + jint mode) { - java_shortarray *j; + java_shortarray *sa; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_short(len); + sa = (java_shortarray *) array; - return j; + if (elems != sa->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(sa->data, elems, s2, sa->header.size); + break; + case 0: + MCOPY(sa->data, elems, s2, sa->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jintArray NewIntArray(JNIEnv *env, jsize len) +void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, + jint mode) { - java_intarray *j; + java_intarray *ia; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_int(len); + ia = (java_intarray *) array; - return j; + if (elems != ia->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(ia->data, elems, s4, ia->header.size); + break; + case 0: + MCOPY(ia->data, elems, s4, ia->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jlongArray NewLongArray(JNIEnv *env, jsize len) +void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, + jint mode) { - java_longarray *j; + java_longarray *la; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); + + la = (java_longarray *) array; - j = builtin_newarray_long(len); + /* We cast this one to prevent a compiler warning on 64-bit + systems since GNU Classpath typedef jlong to long long. */ - return j; + if ((s8 *) elems != la->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(la->data, elems, s8, la->header.size); + break; + case 0: + MCOPY(la->data, elems, s8, la->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jfloatArray NewFloatArray(JNIEnv *env, jsize len) +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, + jint mode) { - java_floatarray *j; + java_floatarray *fa; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_float(len); + fa = (java_floatarray *) array; - return j; + if (elems != fa->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(fa->data, elems, float, fa->header.size); + break; + case 0: + MCOPY(fa->data, elems, float, fa->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jdouble *elems, jint mode) { - java_doublearray *j; + java_doublearray *da; - if (len < 0) { - *exceptionptr = new_exception(string_java_lang_NegativeArraySizeException); - return NULL; - } + STATISTICS(jniinvokation()); - j = builtin_newarray_double(len); + da = (java_doublearray *) array; - return j; + if (elems != da->data) { + switch (mode) { + case JNI_COMMIT: + MCOPY(da->data, elems, double, da->header.size); + break; + case 0: + MCOPY(da->data, elems, double, da->header.size); + /* XXX TWISTI how should it be freed? */ + break; + case JNI_ABORT: + /* XXX TWISTI how should it be freed? */ + break; + } + } } -jboolean * GetBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} +/* GetArrayRegion ********************************************** + + A family of functions that copies a region of a primitive array + into a buffer. +*******************************************************************************/ -jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy) +void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + java_booleanarray *ba; + STATISTICS(jniinvokation()); -jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + ba = (java_booleanarray *) array; + + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &ba->data[start], u1, len); } -jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy) +void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + ba = (java_bytearray *) array; + + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &ba->data[start], s1, len); } -jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy) +void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + java_chararray *ca; + STATISTICS(jniinvokation()); -jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + ca = (java_chararray *) array; + + if ((start < 0) || (len < 0) || (start + len > ca->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &ca->data[start], u2, len); } -jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy) +void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + java_shortarray *sa; + STATISTICS(jniinvokation()); + sa = (java_shortarray *) array; -void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode) -{ - /* empty */ + if ((start < 0) || (len < 0) || (start + len > sa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &sa->data[start], s2, len); } -void ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) +void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { - /* empty */ -} + java_intarray *ia; + STATISTICS(jniinvokation()); -void ReleaseCharArrayElements (JNIEnv *env, jcharArray array, jchar *elems, jint mode) -{ - /* empty */ + ia = (java_intarray *) array; + + if ((start < 0) || (len < 0) || (start + len > ia->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &ia->data[start], s4, len); } -void ReleaseShortArrayElements (JNIEnv *env, jshortArray array, jshort *elems, jint mode) +void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + jlong *buf) { - /* empty */ -} + java_longarray *la; + STATISTICS(jniinvokation()); -void ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode) -{ - /* empty */ + la = (java_longarray *) array; + + if ((start < 0) || (len < 0) || (start + len > la->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &la->data[start], s8, len); } -void ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode) +void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - /* empty */ -} + java_floatarray *fa; + STATISTICS(jniinvokation()); -void ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) -{ - /* empty */ + fa = (java_floatarray *) array; + + if ((start < 0) || (len < 0) || (start + len > fa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &fa->data[start], float, len); } -void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode) +void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - /* empty */ -} + java_doublearray *da; + STATISTICS(jniinvokation()); -void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + da = (java_doublearray *) array; - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); + if ((start < 0) || (len < 0) || (start + len > da->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &da->data[start], double, len); } -void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); +/* SetArrayRegion ********************************************** - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); -} + A family of functions that copies back a region of a primitive + array from a buffer. +*******************************************************************************/ -void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) +void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); - - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); -} + java_booleanarray *ba; + STATISTICS(jniinvokation()); -void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + ba = (java_booleanarray *) array; - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ba->data[start], buf, u1, len); } -void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) +void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); - - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + ba = (java_bytearray *) array; - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ba->data[start], buf, s1, len); } -void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) +void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); - - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); -} + java_chararray *ca; + STATISTICS(jniinvokation()); -void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) -{ - if (start < 0 || len < 0 || start+len>array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + ca = (java_chararray *) array; - else - memcpy(buf, &array->data[start], len * sizeof(array->data[0])); + if ((start < 0) || (len < 0) || (start + len > ca->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ca->data[start], buf, u2, len); } -void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) +void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_shortarray *sa; - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + sa = (java_shortarray *) array; + + if ((start < 0) || (len < 0) || (start + len > sa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&sa->data[start], buf, s2, len); } -void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) +void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_intarray *ia; - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + ia = (java_intarray *) array; + + if ((start < 0) || (len < 0) || (start + len > ia->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ia->data[start], buf, s4, len); } -void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) +void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, + jlong *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_longarray *la; - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + STATISTICS(jniinvokation()); + la = (java_longarray *) array; + + if ((start < 0) || (len < 0) || (start + len > la->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&la->data[start], buf, s8, len); } -void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) +void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_floatarray *fa; - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + fa = (java_floatarray *) array; + + if ((start < 0) || (len < 0) || (start + len > fa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&fa->data[start], buf, float, len); } -void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) +void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + java_doublearray *da; - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + da = (java_doublearray *) array; + if ((start < 0) || (len < 0) || (start + len > da->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&da->data[start], buf, double, len); } -void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); +/* Registering Native Methods *************************************************/ - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); +/* 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. +*******************************************************************************/ -void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) +jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods) { - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); + STATISTICS(jniinvokation()); - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); + log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!"); + return 0; } -void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) -{ - if (start < 0 || len < 0 || start + len > array->header.size) - *exceptionptr = new_exception(string_java_lang_ArrayIndexOutOfBoundsException); +/* UnregisterNatives *********************************************************** - else - memcpy(&array->data[start], buf, len * sizeof(array->data[0])); -} + 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 RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods) +jint UnregisterNatives(JNIEnv *env, jclass clazz) { - log_text("JNI-Call: RegisterNatives"); - return 0; -} + STATISTICS(jniinvokation()); + /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */ + + log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!"); -jint UnregisterNatives (JNIEnv* env, jclass clazz) -{ - log_text("JNI-Call: UnregisterNatives"); return 0; } @@ -3125,8 +4855,10 @@ jint UnregisterNatives (JNIEnv* env, jclass clazz) jint MonitorEnter(JNIEnv *env, jobject obj) { + STATISTICS(jniinvokation()); + if (!obj) { - *exceptionptr = new_nullpointerexception(); + exceptions_throw_nullpointerexception(); return JNI_ERR; } @@ -3150,8 +4882,10 @@ jint MonitorEnter(JNIEnv *env, jobject obj) jint MonitorExit(JNIEnv *env, jobject obj) { + STATISTICS(jniinvokation()); + if (!obj) { - *exceptionptr = new_nullpointerexception(); + exceptions_throw_nullpointerexception(); return JNI_ERR; } @@ -3175,138 +4909,225 @@ jint MonitorExit(JNIEnv *env, jobject obj) jint GetJavaVM(JNIEnv *env, JavaVM **vm) { - *vm = &ptr_jvm; + STATISTICS(jniinvokation()); + + *vm = (JavaVM *) _Jv_jvm; return 0; } -void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) +/* GetStringRegion ************************************************************* + + Copies len number of Unicode characters beginning at offset start + to the given buffer buf. + + Throws StringIndexOutOfBoundsException on index overflow. + +*******************************************************************************/ + +void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) { - log_text("JNI-Call: GetStringRegion"); + java_lang_String *s; + java_chararray *ca; + + STATISTICS(jniinvokation()); + + s = (java_lang_String *) str; + ca = s->value; + + if ((start < 0) || (len < 0) || (start > s->count) || + (start + len > s->count)) { + exceptions_throw_stringindexoutofboundsexception(); + return; + } + + MCOPY(buf, &ca->data[start], u2, len); } 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 ***********************/ +/* GetPrimitiveArrayCritical *************************************************** + + Obtain a direct pointer to array elements. -void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy) +*******************************************************************************/ + +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) { - log_text("JNI-Call: DeleteWeakGlobalRef"); + STATISTICS(jniinvokation()); - /* empty */ + log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME"); } -/** Creates a new global reference to the object referred to by the obj argument **/ +/* NewGlobalRef **************************************************************** + + Creates a new global reference to the object referred to by the obj + argument. + +*******************************************************************************/ jobject NewGlobalRef(JNIEnv* env, jobject lobj) { - jobject refcount; - jint val; - jobject newval; + java_objectheader *o; + java_lang_Integer *refcount; + java_objectheader *newval; - MonitorEnter(env, *global_ref_table); + STATISTICS(jniinvokation()); + +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif - refcount = CallObjectMethod(env, *global_ref_table, getmid, lobj); - val = (refcount == NULL) ? 0 : CallIntMethod(env, refcount, intvalue); - newval = NewObject(env, intclass, newint, val + 1); + o = vm_call_method(getmid, *global_ref_table, lobj); + + refcount = (java_lang_Integer *) o; + + if (refcount == NULL) { + newval = native_new_and_init_int(class_java_lang_Integer, 1); - if (newval != NULL) { - CallObjectMethod(env, *global_ref_table, putmid, lobj, newval); - MonitorExit(env, *global_ref_table); - return lobj; + if (newval == NULL) { +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif + return NULL; + } + + (void) vm_call_method(putmid, *global_ref_table, lobj, newval); } else { - log_text("JNI-NewGlobalRef: unable to create new java.lang.Integer"); - MonitorExit(env, *global_ref_table); - return NULL; + /* 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; } -/************* Deletes the global reference pointed to by globalRef **************/ -void DeleteGlobalRef(JNIEnv* env, jobject gref) +/* DeleteGlobalRef ************************************************************* + + Deletes the global reference pointed to by globalRef. + +*******************************************************************************/ + +void DeleteGlobalRef(JNIEnv* env, jobject globalRef) { - jobject refcount; - jint val; + java_objectheader *o; + java_lang_Integer *refcount; + s4 val; + + STATISTICS(jniinvokation()); - MonitorEnter(env, *global_ref_table); - refcount = CallObjectMethod(env, *global_ref_table, getmid, gref); +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif + + o = vm_call_method(getmid, *global_ref_table, globalRef); + + refcount = (java_lang_Integer *) o; if (refcount == NULL) { log_text("JNI-DeleteGlobalRef: unable to find global reference"); return; } - val = CallIntMethod(env, refcount, intvalue); - val--; + /* we can access the object itself, as we are in a synchronized + section */ + + val = refcount->value - 1; if (val == 0) { - CallObjectMethod(env, *global_ref_table, removemid,refcount); + (void) vm_call_method(removemid, *global_ref_table, refcount); } else { - jobject newval = NewObject(env, intclass, newint, val); - - if (newval != NULL) { - CallObjectMethod(env,*global_ref_table, putmid,newval); + /* we do not create a new object, but set the new value into + the old one */ - } else { - log_text("JNI-DeleteGlobalRef: unable to create new java.lang.Integer"); - } + refcount->value = val; } - MonitorExit(env,*global_ref_table); +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif } @@ -3319,6 +5140,8 @@ void DeleteGlobalRef(JNIEnv* env, jobject gref) jboolean ExceptionCheck(JNIEnv *env) { + STATISTICS(jniinvokation()); + return *exceptionptr ? JNI_TRUE : JNI_FALSE; } @@ -3327,210 +5150,224 @@ jboolean ExceptionCheck(JNIEnv *env) /* 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. + 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) { - log_text("NewDirectByteBuffer: IMPLEMENT ME!"); + java_objectheader *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *paddress; +#else + gnu_classpath_Pointer32 *paddress; +#endif - return NULL; + STATISTICS(jniinvokation()); + + /* 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; + + /* create a java.nio.DirectByteBufferImpl$ReadWrite object */ + + nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite, + (jmethodID) 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. + Fetches and returns the starting address of the memory region + referenced by the given direct java.nio.Buffer. *******************************************************************************/ void *GetDirectBufferAddress(JNIEnv *env, jobject buf) { - log_text("GetDirectBufferAddress: IMPLEMENT ME!"); + java_nio_DirectByteBufferImpl *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *address; +#else + gnu_classpath_Pointer32 *address; +#endif - return NULL; + STATISTICS(jniinvokation()); + + if (!builtin_instanceof(buf, class_java_nio_Buffer)) + return NULL; + + 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. + 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) { - log_text("GetDirectBufferCapacity: IMPLEMENT ME!"); + java_nio_Buffer *nbuf; - return 0; + STATISTICS(jniinvokation()); + + if (!builtin_instanceof(buf, class_java_nio_DirectByteBufferImpl)) + return -1; + + nbuf = (java_nio_Buffer *) buf; + + return (jlong) nbuf->cap; } +/* DestroyJavaVM *************************************************************** + + Unloads a Java VM and reclaims its resources. Only the main thread + can unload the VM. The system waits until the main thread is only + remaining user thread before it destroys the VM. + +*******************************************************************************/ + jint DestroyJavaVM(JavaVM *vm) { - log_text("DestroyJavaVM called"); + s4 status; - return 0; + STATISTICS(jniinvokation()); + + status = vm_destroy(vm); + + return status; } -jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2) -{ - log_text("AttachCurrentThread called"); +/* AttachCurrentThread ********************************************************* - return 0; -} + 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. -jint DetachCurrentThread(JavaVM *vm) -{ - log_text("DetachCurrentThread called"); + A native thread cannot be attached simultaneously to two Java VMs. - return 0; -} + When a thread is attached to the VM, the context class loader is + the bootstrap loader. +*******************************************************************************/ -jint GetEnv(JavaVM *vm, void **env, jint version) +jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args) { - if ((version != JNI_VERSION_1_1) && (version != JNI_VERSION_1_2) && - (version != JNI_VERSION_1_4)) { - *env = NULL; - return JNI_EVERSION; - } + STATISTICS(jniinvokation()); - /* - TODO: If the current thread is not attached to the VM... - if (0) { - *env = NULL; - return JNI_EDETACHED; - } - */ + log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!"); - *env = &ptr_env; +#if !defined(HAVE___THREAD) +/* cacao_thread_attach();*/ +#else + #error "No idea how to implement that. Perhaps Stefan knows" +#endif - return JNI_OK; + *env = _Jv_env; + + return 0; } -jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2) +jint DetachCurrentThread(JavaVM *vm) { - log_text("AttachCurrentThreadAsDaemon called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!"); return 0; } -/************* JNI Initialization ****************************************************/ -jobject jni_init1(JNIEnv* env, jobject lobj) { -#if defined(USE_THREADS) - while (initrunning) {yieldThread();} /* wait until init is done */ -#endif - if (global_ref_table == NULL) { - jni_init(); - } -#if defined(USE_THREADS) - else { - /* wait until jni_init is done */ - MonitorEnter(env, *global_ref_table) ; - MonitorExit(env, *global_ref_table); - } -#endif - return NewGlobalRef(env, lobj); -} -void jni_init2(JNIEnv* env, jobject gref) { - log_text("DeleteGlobalref called before NewGlobalref"); -#if defined(USE_THREADS) - while (initrunning) {yieldThread();} /* wait until init is done */ -#endif - if (global_ref_table == NULL) { - jni_init(); - } -#if defined(USE_THREADS) - else { - /* wait until jni_init is done */ - MonitorEnter(env, *global_ref_table) ; - MonitorExit(env, *global_ref_table); - } -#endif - DeleteGlobalRef(env, gref); -} +/* GetEnv ********************************************************************** -void jni_init(){ - jmethodID mid; + 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. - initrunning = true; - log_text("JNI-Init: initialize global_ref_table"); - /* initalize global reference table */ - ihmclass = FindClass(NULL, "java/util/IdentityHashMap"); - - if (ihmclass == NULL) { - log_text("JNI-Init: unable to find java.util.IdentityHashMap"); - } +*******************************************************************************/ - mid = GetMethodID(NULL, ihmclass, "","()V"); - if (mid == NULL) { - log_text("JNI-Init: unable to find constructor in java.util.IdentityHashMap"); - } - - global_ref_table = (jobject*)heap_allocate(sizeof(jobject),true,NULL); +jint GetEnv(JavaVM *vm, void **env, jint version) +{ + STATISTICS(jniinvokation()); - *global_ref_table = NewObject(NULL,ihmclass,mid); +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + if (thread_getself() == NULL) { + *env = NULL; - if (*global_ref_table == NULL) { - log_text("JNI-Init: unable to create new global_ref_table"); + return JNI_EDETACHED; } +#endif - initrunning = false; + if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) || + (version == JNI_VERSION_1_4)) { + *env = _Jv_env; - getmid = GetMethodID(NULL, ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;"); - if (mid == NULL) { - log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap"); + return JNI_OK; } - getmid = GetMethodID(NULL ,ihmclass, "get","(Ljava/lang/Object;)Ljava/lang/Object;"); - if (getmid == NULL) { - log_text("JNI-Init: unable to find method \"get\" in java.util.IdentityHashMap"); - } +#if defined(ENABLE_JVMTI) + if (version == JVMTI_VERSION_1_0) { + *env = (void *) new_jvmtienv(); - putmid = GetMethodID(NULL, ihmclass, "put","(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); - if (putmid == NULL) { - log_text("JNI-Init: unable to find method \"put\" in java.util.IdentityHashMap"); + if (env != NULL) + return JNI_OK; } +#endif + + *env = NULL; - intclass = FindClass(NULL, "java/lang/Integer"); - if (intclass == NULL) { - log_text("JNI-Init: unable to find java.lang.Integer"); - } + return JNI_EVERSION; +} - newint = GetMethodID(NULL, intclass, "","(I)V"); - if (newint == NULL) { - log_text("JNI-Init: unable to find constructor in java.lang.Integer"); - } - intvalue = GetMethodID(NULL, intclass, "intValue","()I"); - if (intvalue == NULL) { - log_text("JNI-Init: unable to find method \"intValue\" in java.lang.Integer"); - } - removemid = GetMethodID(NULL, ihmclass, "remove","(Ljava/lang/Object;)Ljava/lang/Object;"); - if (removemid == NULL) { - log_text("JNI-DeleteGlobalRef: unable to find method \"remove\" in java.lang.Object"); - } - - /* set NewGlobalRef, DeleteGlobalRef envTable entry to real implementation */ +jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2) +{ + STATISTICS(jniinvokation()); + + log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!"); - JNI_JNIEnvTable.NewGlobalRef = &NewGlobalRef; - JNI_JNIEnvTable.DeleteGlobalRef = &DeleteGlobalRef; + return 0; } /* JNI invocation table *******************************************************/ -const struct JNIInvokeInterface JNI_JavaVMTable = { +const struct JNIInvokeInterface _Jv_JNIInvokeInterface = { NULL, NULL, NULL, @@ -3545,274 +5382,274 @@ const struct JNIInvokeInterface JNI_JavaVMTable = { /* JNI function table *********************************************************/ -struct JNINativeInterface JNI_JNIEnvTable = { +struct JNINativeInterface _Jv_JNINativeInterface = { NULL, NULL, NULL, NULL, - &GetVersion, - - &DefineClass, - &FindClass, - &FromReflectedMethod, - &FromReflectedField, - &ToReflectedMethod, - &GetSuperclass, - &IsAssignableFrom, - &ToReflectedField, - - &Throw, - &ThrowNew, - &ExceptionOccurred, - &ExceptionDescribe, - &ExceptionClear, - &FatalError, - &PushLocalFrame, - &PopLocalFrame, - - &jni_init1, /* &NewGlobalRef, initialize Global_Ref_Table*/ - &jni_init2, /* &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, + 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, + GetStringRegion, + GetStringUTFRegion, - &GetPrimitiveArrayCritical, - &ReleasePrimitiveArrayCritical, + GetPrimitiveArrayCritical, + ReleasePrimitiveArrayCritical, - &GetStringCritical, - &ReleaseStringCritical, + GetStringCritical, + ReleaseStringCritical, - &NewWeakGlobalRef, - &DeleteWeakGlobalRef, + NewWeakGlobalRef, + DeleteWeakGlobalRef, - &ExceptionCheck, + ExceptionCheck, /* new JNI 1.4 functions */ - &NewDirectByteBuffer, - &GetDirectBufferAddress, - &GetDirectBufferCapacity + NewDirectByteBuffer, + GetDirectBufferAddress, + GetDirectBufferCapacity }; @@ -3826,12 +5663,28 @@ struct JNINativeInterface JNI_JNIEnvTable = { jint JNI_GetDefaultJavaVMInitArgs(void *vm_args) { - JDK1_1InitArgs *_vm_args = (JDK1_1InitArgs *) vm_args; + JavaVMInitArgs *_vm_args; + + _vm_args = (JavaVMInitArgs *) vm_args; /* GNU classpath currently supports JNI 1.2 */ - _vm_args->version = JNI_VERSION_1_2; + switch (_vm_args->version) { + case JNI_VERSION_1_1: + _vm_args->version = JNI_VERSION_1_1; + break; + + case JNI_VERSION_1_2: + case JNI_VERSION_1_4: + _vm_args->ignoreUnrecognized = JNI_FALSE; + _vm_args->options = NULL; + _vm_args->nOptions = 0; + break; + default: + return -1; + } + return 0; } @@ -3860,253 +5713,64 @@ jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) *******************************************************************************/ -jint JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args) -{ - *p_vm = (JavaVM *) &JNI_JavaVMTable; - *p_env = (JNIEnv *) &JNI_JNIEnvTable; - - return 0; -} - - -jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, jobject obj, java_objectarray *params) +jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args) { - int argcount; - jni_callblock *blk; - char retT; - jobject retVal; - - if (methodID == 0) { - *exceptionptr = new_exception(string_java_lang_NoSuchMethodError); - return NULL; - } - - argcount = get_parametercount(methodID); - - /* 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 0; - } - - -#ifdef arglimit - if (argcount > 3) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - log_text("Too many arguments. invokeNativeHelper does not support that"); - return 0; - } -#endif - if (((params==0) && (argcount != 0)) || (params && (params->header.size != argcount))) { - *exceptionptr = new_exception(string_java_lang_IllegalArgumentException); - return 0; - } + JavaVMInitArgs *_vm_args; + _Jv_JNIEnv *env; + _Jv_JavaVM *jvm; + localref_table *lrt; + /* get the arguments for the new JVM */ - if (((methodID->flags & ACC_STATIC)==0) && (0==obj)) { - *exceptionptr = - new_exception_message(string_java_lang_NullPointerException, - "Static mismatch in Java_java_lang_reflect_Method_invokeNative"); - return 0; - } + _vm_args = (JavaVMInitArgs *) vm_args; - if ((methodID->flags & ACC_STATIC) && (obj)) obj = 0; + /* get the VM and Env tables (must be set before vm_create) */ - if (obj) { - if ( (methodID->flags & ACC_ABSTRACT) || (methodID->class->flags & ACC_INTERFACE) ) { - methodID=get_virtual(obj,methodID); - } - } + env = NEW(_Jv_JNIEnv); + env->env = &_Jv_JNINativeInterface; - blk = MNEW(jni_callblock, /*4 */argcount+2); + /* XXX Set the global variable. Maybe we should do that differently. */ - retT = fill_callblock_objA(obj, methodID->descriptor, blk, params); + _Jv_env = env; - switch (retT) { - case 'V': - (void) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = NULL; /*native_new_and_init(loader_load(utf_new_char("java/lang/Void")));*/ - break; + /* actually create the JVM */ - case 'I': { - s4 intVal; - intVal = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Integer); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_int__void), - intVal); - } - break; + if (!vm_create(_vm_args)) + return -1; - case 'B': { - s4 intVal; - intVal = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Byte); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_byte__void), - intVal); - } - break; + /* create and fill a JavaVM structure */ - case 'C': { - s4 intVal; - intVal = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Character); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_char__void), - intVal); - } - break; + jvm = NEW(_Jv_JavaVM); + jvm->functions = &_Jv_JNIInvokeInterface; - case 'S': { - s4 intVal; - intVal = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Short); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_short__void), - intVal); - } - break; + /* XXX Set the global variable. Maybe we should do that differently. */ - case 'Z': { - s4 intVal; - intVal = asm_calljavafunction2int(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Boolean); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_boolean__void), - intVal); - } - break; + _Jv_jvm = jvm; - case 'J': { - jlong longVal; - longVal = asm_calljavafunction2long(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Long); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_long__void), - longVal); - } - break; + /* setup the local ref table (must be created after vm_create) */ - case 'F': { - jdouble floatVal; - floatVal = asm_calljavafunction2float(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Float); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_float__void), - floatVal); - } - break; + lrt = GCNEW(localref_table); - case 'D': { - jdouble doubleVal; - doubleVal = asm_calljavafunction2double(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - retVal = builtin_new(class_java_lang_Double); - CallVoidMethod(env, - retVal, - class_resolvemethod(retVal->vftbl->class, - utf_init, - utf_double__void), - doubleVal); - } - break; + lrt->capacity = LOCALREFTABLE_CAPACITY; + lrt->used = 0; + lrt->localframes = 1; + lrt->prev = LOCALREFTABLE; - case 'L': /* fall through */ - case '[': - retVal = asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); - break; + /* clear the references array (memset is faster then a for-loop) */ - default: - /* if this happens the acception has already been set by fill_callblock_objA*/ - MFREE(blk, jni_callblock, /*4 */ argcount+2); - return (jobject *) 0; - } + MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY); - MFREE(blk, jni_callblock, /* 4 */ argcount+2); + LOCALREFTABLE = lrt; - if (*exceptionptr) { - java_objectheader *exceptionToWrap = *exceptionptr; - classinfo *ivtec; - java_objectheader *ivte; + /* now return the values */ - *exceptionptr = NULL; - ivtec = class_new(utf_new_char("java/lang/reflect/InvocationTargetException")); - ivte = builtin_new(ivtec); - asm_calljavafunction(class_resolvemethod(ivtec, - utf_new_char(""), - utf_new_char("(Ljava/lang/Throwable;)V")), - ivte, - exceptionToWrap, - 0, - 0); - - if (*exceptionptr != NULL) - panic("jni.c: error while creating InvocationTargetException wrapper"); - - *exceptionptr = ivte; - } + *p_vm = (JavaVM *) jvm; + *p_env = (void *) env; - return (jobject *) retVal; + return 0; } - - /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where @@ -4118,4 +5782,5 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env, struct methodinfo *methodID, * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */