X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fnative%2Fjni.c;h=d3e435b243632eec0a5cd75f66cc0b7c49ae482f;hb=7eb9565b4da854fc6ced7220cb19040df0033573;hp=9d57fd2a57d8bbaaa96a713ea1e6a24845a98aa7;hpb=7b521f6123e9529b9f1be52d956b09fec3f6ad98;p=cacao.git diff --git a/src/native/jni.c b/src/native/jni.c index 9d57fd2a5..0e58a9a61 100644 --- a/src/native/jni.c +++ b/src/native/jni.c @@ -1,9 +1,9 @@ -/* jni.c - implementation of the Java Native Interface functions +/* src/native/jni.c - implementation of the Java Native Interface functions - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 - R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser, - M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck, - P. Tomsich, J. Wenninger + Copyright (C) 1996-2005, 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,2925 +19,5209 @@ 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: ? + Authors: Rainhard Grafl + Roman Obermaisser Changes: Joseph Wenninger + Martin Platter + Christian Thalinger + Edwin Steiner - $Id: jni.c 709 2003-12-07 17:32:46Z twisti $ + $Id: jni.c 4559 2006-03-05 23:24:50Z twisti $ */ +#include "config.h" + +#include #include -#include "jni.h" -#include "global.h" -#include "loader.h" -#include "tables.h" -#include "native.h" -#include "builtin.h" -#include "threads/thread.h" -#include "toolbox/loging.h" -#include "toolbox/memory.h" -#include "nat/java_lang_Byte.h" -#include "nat/java_lang_Character.h" -#include "nat/java_lang_Short.h" -#include "nat/java_lang_Integer.h" -#include "nat/java_lang_Boolean.h" -#include "nat/java_lang_Long.h" -#include "nat/java_lang_Float.h" -#include "nat/java_lang_Double.h" -#include "nat/java_lang_Throwable.h" -#include "jit/jit.h" -#include "asmpart.h" -#define JNI_VERSION 0x00010002 - - -static utf* utf_char = 0; -static utf* utf_bool = 0; -static utf* utf_byte =0; -static utf* utf_short = 0; -static utf* utf_int = 0; -static utf* utf_long = 0; -static utf* utf_float = 0; -static utf* utf_double = 0; - - -/********************* accessing instance-fields **********************************/ - -#define setField(obj,typ,var,val) *((typ*) ((long int) obj + (long int) var->offset))=val; -#define getField(obj,typ,var) *((typ*) ((long int) obj + (long int) var->offset)) -#define setfield_critical(clazz,obj,name,sig,jdatatype,val) setField(obj,jdatatype,getFieldID_critical(env,clazz,name,sig),val); - - - -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 */ - java_objectarray* result; - int parametercount = 0; - int i; - - /* skip '(' */ - utf_nextu2(&utf_ptr); - - /* determine number of parameters */ - while ( *utf_ptr != ')' ) { - get_type(&utf_ptr,desc_end,true); - parametercount++; - } - - return parametercount; -} - - - -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; - - jdouble d; - jlong l; - u4 dummy; - char c; - /* - 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=(u8)(u4)obj; - cnt=1; - } else cnt=0; - while ( **utf_ptr != ')' ) { - if (*utf_ptr>=desc_end) - panic("illegal method descriptor"); - - switch (utf_nextu2(utf_ptr)) { - /* primitive types */ - case 'B' : - case 'C' : - case 'S' : - case 'Z' : - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item=(u8) va_arg(data,int); - break; - case 'I' : - blk[cnt].itemtype=TYPE_INT; - dummy=va_arg(data,u4); - /*printf("fill_callblock: pos:%d, value:%d\n",cnt,dummy);*/ - blk[cnt].item=(u8)dummy; - - break; - - case 'J' : - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item=(u8)va_arg(data,jlong); - break; - case 'F' : - blk[cnt].itemtype=TYPE_FLT; - *((jfloat*)(&blk[cnt].item))=((jfloat)va_arg(data,jdouble)); - break; - - 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=(u8)(u4)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=(u8)(u4)va_arg(data,void*); - break; - } - } - cnt++; - } - - /*the standard doesn't say anything about return value checking, but it appears to be usefull*/ - c=utf_nextu2(utf_ptr); - c=utf_nextu2(utf_ptr); - /*printf("%c %c\n",ret,c);*/ - if (ret=='O') { - if (!((c=='L') || (c=='['))) log_text("\n====\nWarning call*Method called for function with wrong return type\n===="); - } else if (ret != c) log_text("\n====\nWarning call*Method called for function with wrong return type\n===="); - -} - -/* 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) -{ - char *utf__ptr = descr->text; /* current position in utf-text */ - char **utf_ptr = &utf__ptr; - char *desc_end = utf_end(descr); /* points behind utf string */ - - jobject param; - int cnt; - int cnts; - - u4 dummy; - char c; - char *cp; - intsDisable(); - if (utf_char==0) { - utf_char=utf_new_char("java/lang/Character"); - utf_bool=utf_new_char("java/lang/Boolean"); - utf_byte=utf_new_char("java/lang/Byte"); - utf_short=utf_new_char("java/lang/Short"); - utf_int=utf_new_char("java/lang/Integer"); - utf_long=utf_new_char("java/lang/Long"); - utf_float=utf_new_char("java/lang/Float"); - utf_double=utf_new_char("java/lang/Double"); - } - intsRestore(); - - /* - 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 = (u8)(u4)obj; - cnt=1; - } else { - cnt = 0; - } +#include "vm/types.h" + +#include "mm/boehm.h" +#include "mm/memory.h" +#include "native/jni.h" +#include "native/native.h" + +#include "native/include/gnu_classpath_Pointer.h" + +#if SIZEOF_VOID_P == 8 +# include "native/include/gnu_classpath_Pointer64.h" +#else +# include "native/include/gnu_classpath_Pointer32.h" +#endif + +#include "native/include/java_lang_Object.h" +#include "native/include/java_lang_Byte.h" +#include "native/include/java_lang_Character.h" +#include "native/include/java_lang_Short.h" +#include "native/include/java_lang_Integer.h" +#include "native/include/java_lang_Boolean.h" +#include "native/include/java_lang_Long.h" +#include "native/include/java_lang_Float.h" +#include "native/include/java_lang_Double.h" +#include "native/include/java_lang_Throwable.h" +#include "native/include/java_lang_reflect_Method.h" +#include "native/include/java_lang_reflect_Constructor.h" +#include "native/include/java_lang_reflect_Field.h" + +#include "native/include/java_lang_Class.h" /* for java_lang_VMClass.h */ +#include "native/include/java_lang_VMClass.h" +#include "native/include/java_lang_VMClassLoader.h" +#include "native/include/java_nio_Buffer.h" +#include "native/include/java_nio_DirectByteBufferImpl.h" + +#if defined(ENABLE_JVMTI) +# include "native/jvmti/jvmti.h" +#endif + +#if defined(USE_THREADS) +# if defined(NATIVE_THREADS) +# include "threads/native/threads.h" +# else +# include "threads/green/threads.h" +# endif +#endif + +#include "toolbox/logging.h" +#include "vm/builtin.h" +#include "vm/exceptions.h" +#include "vm/global.h" +#include "vm/initialize.h" +#include "vm/loader.h" +#include "vm/options.h" +#include "vm/resolve.h" +#include "vm/statistics.h" +#include "vm/stringlocal.h" +#include "vm/jit/asmpart.h" +#include "vm/jit/jit.h" +#include "vm/statistics.h" +#include "vm/vm.h" + + +/* pointers to VM and the environment needed by GetJavaVM and GetEnv */ + +static JavaVM ptr_jvm = (JavaVM) &JNI_JavaVMTable; +void *ptr_env = (void*) &JNI_JNIEnvTable; + + +/* global variables ***********************************************************/ + +/* global reference table *****************************************************/ + +static java_objectheader **global_ref_table; + +/* jmethodID and jclass caching variables for NewGlobalRef and DeleteGlobalRef*/ +static classinfo *ihmclass = NULL; +static methodinfo *putmid = NULL; +static methodinfo *getmid = NULL; +static methodinfo *removemid = NULL; + + +/* direct buffer stuff ********************************************************/ + +static 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 + +static methodinfo *dbbirw_init; + + +/* local reference table ******************************************************/ + +#if !defined(USE_THREADS) +localref_table *_no_threads_localref_table; +#endif + + +/* accessing instance fields macros *******************************************/ + +#define SET_FIELD(o,type,f,value) \ + *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) = (type) (value) + +#define GET_FIELD(o,type,f) \ + *((type *) ((ptrint) (o) + (ptrint) ((fieldinfo *) (f))->offset)) + + +/* some forward declarations **************************************************/ + +jobject NewLocalRef(JNIEnv *env, jobject ref); + + +/* jni_init ******************************************************************** + + Initialize the JNI subsystem. + +*******************************************************************************/ + +bool jni_init(void) +{ + /* initalize global reference table */ + + 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 + + return true; +} + + +/* _Jv_jni_vmargs_from_objectarray ********************************************* + + XXX + +*******************************************************************************/ + +static bool _Jv_jni_vmargs_from_objectarray(java_objectheader *o, + methoddesc *descr, + vm_arg *vmargs, + java_objectarray *params) +{ + java_objectheader *param; + s4 paramcount; + typedesc *paramtypes; + classinfo *c; + s4 i; + s4 j; + + paramcount = descr->paramcount; + paramtypes = descr->paramtypes; + + /* if method is non-static fill first block and skip `this' pointer */ + + i = 0; + + if (o != NULL) { + /* this pointer */ + vmargs[0].type = TYPE_ADR; + vmargs[0].data = (u8) (ptrint) o; + + paramtypes++; + paramcount--; + i++; + } + + for (j = 0; j < paramcount; i++, j++, paramtypes++) { + switch (paramtypes->type) { + /* primitive types */ + case TYPE_INT: + case TYPE_LONG: + case TYPE_FLOAT: + case TYPE_DOUBLE: + param = params->data[j]; + + if (param == NULL) + goto illegal_arg; + + /* internally used data type */ + vmargs[i].type = paramtypes->type; + + /* convert the value according to its declared type */ + + c = param->vftbl->class; + + switch (paramtypes->decltype) { + case PRIMITIVETYPE_BOOLEAN: + if (c == primitivetype_table[paramtypes->decltype].class_wrap) + vmargs[i].data = (s8) ((java_lang_Boolean *) param)->value; + else + goto illegal_arg; + 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 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; + + default: + goto illegal_arg; + } + 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; + + default: + goto illegal_arg; + } + } + +/* if (rettype) */ +/* *rettype = descr->returntype.decltype; */ + + return true; + +illegal_arg: + exceptions_throw_illegalargumentexception(); + return false; +} + + +/* _Jv_jni_CallObjectMethod **************************************************** + + Internal function to call Java Object methods. + +*******************************************************************************/ + +static java_objectheader *_Jv_jni_CallObjectMethod(java_objectheader *o, + vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + java_objectheader *ro; + + STATISTICS(jniinvokation()); + + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; + } + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + ro = vm_call_method_valist(resm, o, ap); + + return ro; +} + + +/* _Jv_jni_CallObjectMethodA *************************************************** + + Internal function to call Java Object methods. + +*******************************************************************************/ + +static java_objectheader *_Jv_jni_CallObjectMethodA(java_objectheader *o, + vftbl_t *vftbl, + methodinfo *m, jvalue *args) +{ + methodinfo *resm; + java_objectheader *ro; + + STATISTICS(jniinvokation()); + + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return NULL; + } + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + ro = vm_call_method_jvalue(resm, o, args); + + return ro; +} + + +/* _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; + } + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + i = vm_call_method_int_valist(resm, o, ap); + + return i; +} + + +/* _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) +{ + methodinfo *resm; + jlong l; + + 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. */ + + if (m->flags & ACC_STATIC) { + /* For static methods we reset the object. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + l = vm_call_method_long_valist(resm, o, ap); + + return l; +} + + +/* _Jv_jni_CallFloatMethod ***************************************************** + + Internal function to call Java float methods. + +*******************************************************************************/ + +static jfloat _Jv_jni_CallFloatMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + jfloat f; + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + f = vm_call_method_float_valist(resm, o, ap); + + return f; +} + + +/* _Jv_jni_CallDoubleMethod **************************************************** + + Internal function to call Java double methods. + +*******************************************************************************/ + +static jdouble _Jv_jni_CallDoubleMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + jdouble d; + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + d = vm_call_method_double_valist(resm, o, ap); + + return d; +} + + +/* _Jv_jni_CallVoidMethod ****************************************************** + + Internal function to call Java void methods. + +*******************************************************************************/ + +static void _Jv_jni_CallVoidMethod(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, va_list ap) +{ + methodinfo *resm; + + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return; + } + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + (void) vm_call_method_valist(resm, o, ap); +} + + +/* _Jv_jni_CallVoidMethodA ***************************************************** + + Internal function to call Java void methods. + +*******************************************************************************/ + +static void _Jv_jni_CallVoidMethodA(java_objectheader *o, vftbl_t *vftbl, + methodinfo *m, jvalue *args) +{ + methodinfo *resm; + + if (m == NULL) { + exceptions_throw_nullpointerexception(); + return; + } + + /* 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. */ + + if (o != NULL) + o = NULL; + + /* for convenience */ + + resm = m; + + } else { + /* For instance methods we make a virtual function table lookup. */ + + resm = method_vftbl_lookup(vftbl, m); + } + + STATISTICS(jnicallXmethodnvokation()); + + (void) vm_call_method_jvalue(resm, o, args); +} + + +/* _Jv_jni_invokeNative ******************************************************** + + 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. + +*******************************************************************************/ + +java_objectheader *_Jv_jni_invokeNative(methodinfo *m, java_objectheader *o, + java_objectarray *params) +{ + methodinfo *resm; + vm_arg *vmargs; + java_objectheader *ro; + s4 argcount; + s4 paramcount; + + 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 ******************************************************************** + + Constructs an exception object from the specified class with the + message specified by message and causes that exception to be + thrown. + +*******************************************************************************/ + +jint ThrowNew(JNIEnv* env, jclass clazz, const char *msg) +{ + java_lang_Throwable *o; + java_lang_String *s; + + STATISTICS(jniinvokation()); + + s = (java_lang_String *) javastring_new_char(msg); + + /* instantiate exception object */ + + o = (java_lang_Throwable *) native_new_and_init_string((classinfo *) clazz, + s); + + if (!o) + return -1; + + *exceptionptr = (java_objectheader *) o; + + return 0; +} + + +/* ExceptionOccurred *********************************************************** + + Determines if an exception is being thrown. The exception stays + being thrown until either the native code calls ExceptionClear(), + or the Java code handles the exception. + +*******************************************************************************/ + +jthrowable ExceptionOccurred(JNIEnv *env) +{ + java_objectheader *e; + + STATISTICS(jniinvokation()); + + e = *exceptionptr; + + return NewLocalRef(env, (jthrowable) e); +} + + +/* ExceptionDescribe *********************************************************** + + Prints an exception and a backtrace of the stack to a system + error-reporting channel, such as stderr. This is a convenience + routine provided for debugging. + +*******************************************************************************/ + +void ExceptionDescribe(JNIEnv *env) +{ + java_objectheader *e; + methodinfo *m; + + STATISTICS(jniinvokation()); + + e = *exceptionptr; + + if (e) { + /* clear exception, because we are calling jit code again */ + + *exceptionptr = NULL; + + /* get printStackTrace method from exception class */ + + m = class_resolveclassmethod(e->vftbl->class, + utf_printStackTrace, + utf_void__void, + NULL, + true); + + if (!m) + /* XXX what should we do? */ + return; + + /* print the stacktrace */ + + (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) +{ + log_text("JNI-Call: CallBooleanMethodA"); + + return 0; +} + + +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; +} + - cnts=0; - while (**utf_ptr != ')') { - if (*utf_ptr >= desc_end) - panic("illegal method descriptor"); - /* primitive types */ - switch (utf_nextu2(utf_ptr)) { - case 'B': - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - case 'C': - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_char) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Character * )param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; +jlong CallNonvirtualLongMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jlong l; - case 'S': - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - break; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - case 'Z': - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_bool) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Boolean * )param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - - case 'I': - log_text("fill_callblock_objA: param 'I'"); - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_int) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Integer * )param)->value; - /*printf("INT VALUE :%d\n",((struct java_lang_Integer * )param)->value);*/ - } else { - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_INT; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - } - break; - case 'J': - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_long) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Long * )param)->value; - } else { - if (param->vftbl->class->name==utf_int) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Integer * )param)->value; - } else { - if (param->vftbl->class->name==utf_short) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Short* )param)->value; - } else { - if (param->vftbl->class->name==utf_byte) { - blk[cnt].itemtype=TYPE_LNG; - blk[cnt].item = (u8) ((struct java_lang_Byte * )param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - } + va_start(ap, methodID); + l = _Jv_jni_CallLongMethod(o, c->vftbl, m, ap); + va_end(ap); - } - break; + return l; +} - case 'F' : - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - if (param->vftbl->class->name==utf_float) { - blk[cnt].itemtype=TYPE_FLT; - *((jfloat*)(&blk[cnt].item))=(jfloat) ((struct java_lang_Float*)param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - break; - case 'D' : - param=params->data[cnts]; - if (param==0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } +jlong CallNonvirtualLongMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jlong l; - if (param->vftbl->class->name==utf_double) { - blk[cnt].itemtype=TYPE_DBL; - *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value; - } else { - if (param->vftbl->class->name==utf_float) { - blk[cnt].itemtype=TYPE_DBL; - *((jdouble*)(&blk[cnt].item))=(jdouble) ((struct java_lang_Float*)param)->value; - } else { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - break; - case 'V': - panic("V not allowed as function parameter"); - break; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - case 'L': { - char *start=(*utf_ptr)-1; - char *end; - - while (utf_nextu2(utf_ptr) != ';') - end=(*utf_ptr)+1; - if (!builtin_instanceof(params->data[cnts],class_from_descriptor(start,end,0,CLASSLOAD_LOAD))) { - if (params->data[cnts]!=0) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } - } - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item= (u8)(u4) (params->data[cnts]); - break; - - } - case '[' : - { - char *start=(*utf_ptr)-1; - char *end; - - char ch; - while ((ch = utf_nextu2(utf_ptr)) == '[') - if (ch == 'L') { - while (utf_nextu2(utf_ptr) != ';') {} - } - end=(*utf_ptr)-1; - ch = utf_nextu2(utf_ptr); - if (!builtin_arrayinstanceof(params->data[cnts],class_from_descriptor(start,end,0,CLASSLOAD_LOAD))) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - - } - - blk[cnt].itemtype = TYPE_ADR; - blk[cnt].item = (u8)(u4) (params->data[cnts]); - break; - } - } - cnt++; - cnts++; - } + l = _Jv_jni_CallLongMethod(o, c->vftbl, m, args); - c = utf_nextu2(utf_ptr); - c = utf_nextu2(utf_ptr); - return c; /*return type needed usage of the right lowlevel methods*/ + return l; } +jlong CallNonvirtualLongMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualLongMethodA: IMPLEMENT ME!"); + return 0; +} +jfloat CallNonvirtualFloatMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jfloat f; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + va_start(ap, methodID); + f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, ap); + va_end(ap); + return f; +} +jfloat CallNonvirtualFloatMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jfloat f; + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; + f = _Jv_jni_CallFloatMethod(o, c->vftbl, m, args); - -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 f; } -jmethodID get_nonvirtual(jclass clazz,jmethodID methodID) { - if (clazz==methodID->class) return methodID; - return class_resolvemethod (clazz, methodID->name, methodID->descriptor); + +jfloat CallNonvirtualFloatMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualFloatMethodA: IMPLEMENT ME!"); + + return 0; } -jobject callObjectMethod (jobject obj, jmethodID methodID, va_list args) -{ - int argcount; - jni_callblock *blk; - jobject ret; - - /* - log_text("JNI-Call: CallObjectMethodV"); - utf_display(methodID->name); - utf_display(methodID->descriptor); - printf("\nParmaeter count: %d\n",argcount); - utf_display(obj->vftbl->class->name); - printf("\n"); - */ - - if (methodID == 0) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } +jdouble CallNonvirtualDoubleMethod(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + va_list ap; + jdouble d; - argcount = get_parametercount(methodID); + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } - - if (obj && !builtin_instanceof(obj, methodID->class)) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } + va_start(ap, methodID); + d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, ap); + va_end(ap); + + return d; +} - if (argcount > 3) { - exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } - blk = MNEW(jni_callblock, 4 /*argcount+2*/); +jdouble CallNonvirtualDoubleMethodV(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + jdouble d; - fill_callblock(obj, methodID->descriptor, blk, args, 'O'); + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + d = _Jv_jni_CallDoubleMethod(o, c->vftbl, m, args); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ - return ret; + return d; } -/* - 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 = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } - - argcount = get_parametercount(methodID); +jdouble CallNonvirtualDoubleMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallNonvirtualDoubleMethodA: IMPLEMENT ME!"); - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj != 0)) )) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } + return 0; +} - if (obj && !builtin_instanceof(obj, methodID->class)) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } - if (argcount > 3) { - exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } +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; + + 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) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; + + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + _Jv_jni_CallVoidMethod(o, c->vftbl, m, args); +} - fill_callblock(obj, methodID->descriptor, blk, args, retType); - /* printf("parameter: obj: %p",blk[0].item); */ - ret = (jint) asm_calljavafunction2(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); +void CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +{ + java_objectheader *o; + classinfo *c; + methodinfo *m; - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + o = (java_objectheader *) obj; + c = (classinfo *) clazz; + m = (methodinfo *) methodID; - return ret; + _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args); } -/*core function for long class functions*/ -jlong callLongMethod(jobject obj, jmethodID methodID, va_list args) +/* Accessing Fields of Objects ************************************************/ + +/* GetFieldID ****************************************************************** + + Returns the field ID for an instance (nonstatic) field of a + class. The field is specified by its name and signature. The + GetField and SetField families of accessor functions + use field IDs to retrieve object fields. + +*******************************************************************************/ + +jfieldID GetFieldID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - int argcount; - jni_callblock *blk; - jlong ret; + fieldinfo *f; + utf *uname; + utf *udesc; - /* - log_text("JNI-Call: CallObjectMethodV"); - utf_display(methodID->name); - utf_display(methodID->descriptor); - printf("\nParmaeter count: %d\n",argcount); - utf_display(obj->vftbl->class->name); - printf("\n"); - */ - if (methodID == 0) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } + STATISTICS(jniinvokation()); - argcount = get_parametercount(methodID); + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); - if (!( ((methodID->flags & ACC_STATIC) && (obj == 0)) || - ((!(methodID->flags & ACC_STATIC)) && (obj!=0)) )) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } + f = class_findfield(clazz, uname, udesc); + + if (!f) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); - if (obj && !builtin_instanceof(obj,methodID->class)) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } + return (jfieldID) f; +} - if (argcount > 3) { - exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } +/* GetField Routines ***************************************************** + + 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(). - blk = MNEW(jni_callblock, 4 /*argcount+2*/); +*******************************************************************************/ - fill_callblock(obj, methodID->descriptor, blk, args, 'L'); +jobject GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + java_objectheader *o; - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2long(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + STATISTICS(jniinvokation()); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + o = GET_FIELD(obj, java_objectheader*, fieldID); - return ret; + return NewLocalRef(env, o); } -/*core function for float class methods (float,double)*/ -jdouble callFloatMethod(jobject obj, jmethodID methodID, va_list args,char retType) +jboolean GetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID) { - int argcount = get_parametercount(methodID); - jni_callblock *blk; - jdouble ret; + s4 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"); - */ + STATISTICS(jniinvokation()); - if (argcount > 3) { - exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. CallObjectMethod does not support that"); - return 0; - } + i = GET_FIELD(obj, s4, fieldID); + + return (jboolean) i; +} - blk = MNEW(jni_callblock, 4 /*argcount+2*/); - fill_callblock(obj, methodID->descriptor, blk, args, retType); +jbyte GetByteField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + s4 i; - /* printf("parameter: obj: %p",blk[0].item); */ - ret = asm_calljavafunction2double(methodID, - argcount + 1, - (argcount + 1) * sizeof(jni_callblock), - blk); + STATISTICS(jniinvokation()); - MFREE(blk, jni_callblock, argcount + 1); - /* printf("(CallObjectMethodV)-->%p\n",ret); */ + i = GET_FIELD(obj, s4, fieldID); - return ret; + return (jbyte) i; } -/*************************** function: jclass_findfield **************************** - - searches for field with specified name and type in a 'classinfo'-structur - if no such field is found NULL is returned +jchar GetCharField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + s4 i; + + STATISTICS(jniinvokation()); + + i = GET_FIELD(obj, s4, fieldID); + + return (jchar) i; +} -************************************************************************************/ -fieldinfo *jclass_findfield (classinfo *c, utf *name, utf *desc) +jshort GetShortField(JNIEnv *env, jobject obj, jfieldID fieldID) { s4 i; -/* printf(" FieldCount: %d\n",c->fieldscount); - utf_display(c->name); */ - for (i = 0; i < c->fieldscount; i++) { -/* utf_display(c->fields[i].name); - printf("\n"); - utf_display(c->fields[i].descriptor); - printf("\n");*/ - if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) - return &(c->fields[i]); - } - if (c->super) return jclass_findfield(c->super,name,desc); + STATISTICS(jniinvokation()); - return NULL; + i = GET_FIELD(obj, s4, fieldID); + + return (jshort) i; +} + + +jint GetIntField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + java_objectheader *o; + fieldinfo *f; + s4 i; + + STATISTICS(jniinvokation()); + + o = (java_objectheader *) obj; + f = (fieldinfo *) fieldID; + + i = GET_FIELD(o, s4, f); + + return i; } -/********************* returns version of native method interface *****************/ -jint GetVersion (JNIEnv* env) +jlong GetLongField(JNIEnv *env, jobject obj, jfieldID fieldID) { - return JNI_VERSION; + s8 l; + + STATISTICS(jniinvokation()); + + l = GET_FIELD(obj, s8, fieldID); + + return l; } -/****************** loads a class from a buffer of raw class data *****************/ -jclass DefineClass(JNIEnv* env, const char *name, jobject loader, const jbyte *buf, jsize len) +jfloat GetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID) { - jclass clazz; + float f; + + STATISTICS(jniinvokation()); - /* change suck-mode, so subsequent class_load will read from memory-buffer */ - classload_buffer( (u1*) buf,len); + f = GET_FIELD(obj, float, fieldID); - clazz = loader_load(utf_new_char ((char *) name)); + return f; +} + + +jdouble GetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID) +{ + double d; + + STATISTICS(jniinvokation()); - /* restore old suck-mode */ - classload_buffer(NULL,0); + d = GET_FIELD(obj, double, fieldID); - return clazz; + return d; } -/*************** loads locally defined class with the specified name **************/ +/* SetField Routines ***************************************************** + + This family of accessor routines sets the value of an instance + (nonstatic) field of an object. The field to access is specified by + a field ID obtained by calling GetFieldID(). + +*******************************************************************************/ -jclass FindClass (JNIEnv* env, const char *name) +void SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value) { - classinfo *c; - -/* if (strcmp(name,"[B")==0) { - c = loader_load(utf_new_char("The_Array_Class")); - } - else*/ - c = loader_load(utf_new_char_classname ((char *) name)); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, java_objectheader*, fieldID, value); +} - if (!c) exceptionptr = native_new_and_init(class_java_lang_ClassFormatError); - return c; +void SetBooleanField(JNIEnv *env, jobject obj, jfieldID fieldID, jboolean value) +{ + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); } - -/*********************************************************************************** - converts java.lang.reflect.Method or - java.lang.reflect.Constructor object to a method ID - - **********************************************************************************/ - -jmethodID FromReflectedMethod(JNIEnv* env, jobject method) +void SetByteField(JNIEnv *env, jobject obj, jfieldID fieldID, jbyte value) { - /* log_text("JNI-Call: FromReflectedMethod"); */ + STATISTICS(jniinvokation()); - return 0; + SET_FIELD(obj, s4, fieldID, value); } -/*************** return superclass of the class represented by sub ****************/ - -jclass GetSuperclass(JNIEnv* env, jclass sub) +void SetCharField(JNIEnv *env, jobject obj, jfieldID fieldID, jchar value) { - classinfo *c; + STATISTICS(jniinvokation()); - c = ((classinfo*) sub)->super; + SET_FIELD(obj, s4, fieldID, value); +} - if (!c) return NULL; - use_class_as_object(c); +void SetShortField(JNIEnv *env, jobject obj, jfieldID fieldID, jshort value) +{ + STATISTICS(jniinvokation()); - return c; + SET_FIELD(obj, s4, fieldID, value); } - - -/*********************** check whether sub can be cast to sup ********************/ - -jboolean IsAssignableForm(JNIEnv* env, jclass sub, jclass sup) + + +void SetIntField(JNIEnv *env, jobject obj, jfieldID fieldID, jint value) +{ + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s4, fieldID, value); +} + + +void SetLongField(JNIEnv *env, jobject obj, jfieldID fieldID, jlong value) { - return builtin_isanysubclass(sub, sup); + STATISTICS(jniinvokation()); + + SET_FIELD(obj, s8, fieldID, value); } -/***** converts a field ID derived from cls to a java.lang.reflect.Field object ***/ +void SetFloatField(JNIEnv *env, jobject obj, jfieldID fieldID, jfloat value) +{ + STATISTICS(jniinvokation()); + + SET_FIELD(obj, float, fieldID, value); +} + -jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID, jboolean isStatic) +void SetDoubleField(JNIEnv *env, jobject obj, jfieldID fieldID, jdouble value) { - /* log_text("JNI-Call: ToReflectedField"); */ + STATISTICS(jniinvokation()); - return NULL; + SET_FIELD(obj, double, fieldID, value); } -/***************** throw java.lang.Throwable object ******************************/ +/* Calling Static Methods *****************************************************/ + +/* GetStaticMethodID *********************************************************** + + Returns the method ID for a static method of a class. The method is + specified by its name and signature. -jint Throw(JNIEnv* env, jthrowable obj) + GetStaticMethodID() causes an uninitialized class to be + initialized. + +*******************************************************************************/ + +jmethodID GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name, + const char *sig) { - exceptionptr = (java_objectheader*) obj; + classinfo *c; + utf *uname; + utf *udesc; + methodinfo *m; - return 0; + STATISTICS(jniinvokation()); + + c = (classinfo *) clazz; + + if (!c) + return NULL; + + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; + + /* try to get the static method of the class */ + + uname = utf_new_char((char *) name); + udesc = utf_new_char((char *) sig); + + m = class_resolvemethod(c, uname, udesc); + + if ((m == NULL) || !(m->flags & ACC_STATIC)) { + exceptions_throw_nosuchmethoderror(c, uname, udesc); + + return NULL; + } + + return (jmethodID) m; } -/*********************************************************************************** +jobject CallStaticObjectMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + java_objectheader *o; + va_list ap; + + m = (methodinfo *) methodID; - create exception object from the class clazz with the - specified message and cause it to be thrown + va_start(ap, methodID); + o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap); + va_end(ap); - **********************************************************************************/ + return NewLocalRef(env, o); +} -jint ThrowNew (JNIEnv* env, jclass clazz, const char *msg) +jobject CallStaticObjectMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - java_lang_Throwable *o; + methodinfo *m; + java_objectheader *o; - /* instantiate exception object */ - o = (java_lang_Throwable *) native_new_and_init ((classinfo*) clazz); + m = (methodinfo *) methodID; - if (!o) return (-1); + o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args); - o->detailMessage = (java_lang_String*) javastring_new_char((char *) msg); + return NewLocalRef(env, o); +} - exceptionptr = (java_objectheader*) o; - return 0; + +jobject CallStaticObjectMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) +{ + log_text("JNI-Call: CallStaticObjectMethodA: IMPLEMENT ME!"); + + return NewLocalRef(env, NULL); +} + + +jboolean CallStaticBooleanMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; + jboolean b; + + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); + + return b; +} + + +jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +{ + methodinfo *m; + jboolean b; + + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return b; } -/************************* check if exception occured *****************************/ -jthrowable ExceptionOccurred (JNIEnv* env) +jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - return (jthrowable) exceptionptr; + log_text("JNI-Call: CallStaticBooleanMethodA: IMPLEMENT ME!"); + + return 0; } -/********** print exception and a backtrace of the stack (for debugging) **********/ -void ExceptionDescribe (JNIEnv* env) +jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - utf_display(exceptionptr->vftbl->class->name); - printf ("\n"); - fflush (stdout); + methodinfo *m; + va_list ap; + jbyte b; + + m = (methodinfo *) methodID; + + va_start(ap, methodID); + b = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); + + return b; } -/******************* clear any exception currently being thrown *******************/ +jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +{ + methodinfo *m; + jbyte b; + + m = (methodinfo *) methodID; + + b = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return b; +} + -void ExceptionClear (JNIEnv* env) +jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - exceptionptr = NULL; + log_text("JNI-Call: CallStaticByteMethodA: IMPLEMENT ME!"); + + return 0; } -/********** raises a fatal error and does not expect the VM to recover ************/ +jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; + jchar c; + + m = (methodinfo *) methodID; + + va_start(ap, methodID); + c = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); + + return c; +} -void FatalError (JNIEnv* env, const char *msg) + +jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - panic((char *) msg); + methodinfo *m; + jchar c; + + m = (methodinfo *) methodID; + + c = _Jv_jni_CallIntMethod(NULL, NULL, m, args); + + return c; } -/******************* creates a new local reference frame **************************/ -jint PushLocalFrame(JNIEnv* env, jint capacity) +jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - /* empty */ + log_text("JNI-Call: CallStaticCharMethodA: IMPLEMENT ME!"); return 0; } -/**************** Pops off the current local reference frame **********************/ -jobject PopLocalFrame(JNIEnv* env, jobject result) +jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - /* empty */ + methodinfo *m; + va_list ap; + jshort s; - return NULL; -} - + m = (methodinfo *) methodID; -/** Creates a new global reference to the object referred to by the obj argument **/ - -jobject NewGlobalRef(JNIEnv* env, jobject lobj) -{ - heap_addreference((void**) &lobj); + va_start(ap, methodID); + s = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); - return lobj; + return s; } -/************* Deletes the global reference pointed to by globalRef **************/ -void DeleteGlobalRef (JNIEnv* env, jobject gref) +jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - /* empty */ -} + methodinfo *m; + jshort s; + m = (methodinfo *) methodID; -/*************** Deletes the local reference pointed to by localRef ***************/ + s = _Jv_jni_CallIntMethod(NULL, NULL, m, args); -void DeleteLocalRef (JNIEnv* env, jobject localRef) -{ - /* empty */ + return s; } -/********** Tests whether two references refer to the same Java object ************/ -jboolean IsSameObject (JNIEnv* env, jobject obj1, jobject obj2) +jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - return (obj1==obj2); + log_text("JNI-Call: CallStaticShortMethodA: IMPLEMENT ME!"); + + return 0; } -/***** Creates a new local reference that refers to the same object as ref *******/ -jobject NewLocalRef (JNIEnv* env, jobject ref) +jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) { - return ref; -} - -/*********************************************************************************** + methodinfo *m; + va_list ap; + jint i; - Ensures that at least a given number of local references can - be created in the current thread + m = (methodinfo *) methodID; - **********************************************************************************/ + va_start(ap, methodID); + i = _Jv_jni_CallIntMethod(NULL, NULL, m, ap); + va_end(ap); -jint EnsureLocalCapacity (JNIEnv* env, jint capacity) -{ - return 0; /* return 0 on success */ + return i; } -/********* Allocates a new Java object without invoking a constructor *************/ - -jobject AllocObject (JNIEnv* env, jclass clazz) +jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - java_objectheader *o = builtin_new(clazz); - return o; -} + methodinfo *m; + jint i; + m = (methodinfo *) methodID; -/*********************************************************************************** + i = _Jv_jni_CallIntMethod(NULL, NULL, m, args); - Constructs a new Java object - arguments that are to be passed to the constructor are placed after methodID + return i; +} -***********************************************************************************/ -jobject NewObject (JNIEnv* env, jclass clazz, jmethodID methodID, ...) +jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - java_objectheader *o; - void* args[3]; - int argcount=get_parametercount(methodID); - int i; - va_list vaargs; + log_text("JNI-Call: CallStaticIntMethodA: IMPLEMENT ME!"); - /* log_text("JNI-Call: NewObject"); */ + return 0; +} - if (argcount>3) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. NewObject does not support that"); - return 0; - } - - o = builtin_new (clazz); /* create object */ - - if (!o) return NULL; +jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; + jlong l; - va_start(vaargs,methodID); - for (i=0;ivftbl->class; -/* log_text("GetObjectClass"); - utf_display(obj->vftbl->class->name);*/ - use_class_as_object(c); - - /*printf("\nPointer: %p\n",c);*/ - return c; -} + methodinfo *m; + jfloat f; + m = (methodinfo *) methodID; -/************* tests whether an object is an instance of a class ******************/ + f = _Jv_jni_CallFloatMethod(NULL, NULL, m, args); -jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) -{ - return builtin_instanceof(obj,clazz); + return f; } -/***************** converts a java.lang.reflect.Field to a field ID ***************/ - -jfieldID FromReflectedField(JNIEnv* env, jobject field) +jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - log_text("JNI-Call: FromReflectedField"); + log_text("JNI-Call: CallStaticFloatMethodA: IMPLEMENT ME!"); return 0; } -/********************************************************************************** - - converts a method ID to a java.lang.reflect.Method or - java.lang.reflect.Constructor object +jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; + jdouble d; -**********************************************************************************/ + m = (methodinfo *) methodID; -jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic) -{ - log_text("JNI-Call: ToReflectedMethod"); + va_start(ap, methodID); + d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, ap); + va_end(ap); - return NULL; + return d; } -/**************** returns the method ID for an instance method ********************/ - -jmethodID GetMethodID(JNIEnv* env, jclass clazz, const char *name, const char *sig) +jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - jmethodID m; + methodinfo *m; + jdouble d; - m = class_resolvemethod ( - clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); + m = (methodinfo *) methodID; - if (!m) exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + d = _Jv_jni_CallDoubleMethod(NULL, NULL, m, args); - return m; + return d; } -/******************** JNI-functions for calling instance methods ******************/ - -jobject CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) { - jobject ret; - va_list vaargs; + log_text("JNI-Call: CallStaticDoubleMethodA: IMPLEMENT ME!"); -/* log_text("JNI-Call: CallObjectMethod");*/ + return 0; +} + + +void CallStaticVoidMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +{ + methodinfo *m; + va_list ap; - va_start(vaargs, methodID); - ret = callObjectMethod(obj, methodID, vaargs); - va_end(vaargs); + m = (methodinfo *) methodID; - return ret; + va_start(ap, methodID); + _Jv_jni_CallVoidMethod(NULL, NULL, m, ap); + va_end(ap); } -jobject CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void CallStaticVoidMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) { - return callObjectMethod(obj,methodID,args); + methodinfo *m; + + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethod(NULL, NULL, m, args); } -jobject CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) +void CallStaticVoidMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue * args) { - log_text("JNI-Call: CallObjectMethodA"); + methodinfo *m; - return NULL; + m = (methodinfo *) methodID; + + _Jv_jni_CallVoidMethodA(NULL, NULL, m, args); } +/* Accessing Static Fields ****************************************************/ + +/* GetStaticFieldID ************************************************************ + + Returns the field ID for a static field of a class. The field is + specified by its name and signature. The GetStaticField and + SetStaticField families of accessor functions use field IDs + to retrieve static fields. +*******************************************************************************/ -jboolean CallBooleanMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) +jfieldID GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name, const char *sig) { - jboolean ret; - va_list vaargs; + fieldinfo *f; -/* log_text("JNI-Call: CallBooleanMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',vaargs); - va_end(vaargs); - return ret; + f = class_findfield(clazz, + utf_new_char((char *) name), + utf_new_char((char *) sig)); + + if (f == NULL) + *exceptionptr = new_exception(string_java_lang_NoSuchFieldError); + return (jfieldID) f; } -jboolean CallBooleanMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ - return (jboolean)callIntegerMethod(obj,get_virtual(obj,methodID),'Z',args); -} +/* GetStaticField ******************************************************** -jboolean CallBooleanMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) -{ - log_text("JNI-Call: CallBooleanMethodA"); + This family of accessor routines returns the value of a static + field of an object. - return 0; -} +*******************************************************************************/ -jbyte CallByteMethod (JNIEnv *env, jobject obj, jmethodID methodID, ...) +jobject GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jbyte ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; -/* log_text("JNI-Call: CallVyteMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_virtual(obj,methodID),'B',vaargs); - va_end(vaargs); - return ret; + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return NULL; -jbyte CallByteMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ -/* log_text("JNI-Call: CallByteMethodV");*/ - return callIntegerMethod(obj,methodID,'B',args); + return NewLocalRef(env, f->value.a); } -jbyte CallByteMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jboolean GetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallByteMethodA"); + classinfo *c; + fieldinfo *f; - return 0; + STATISTICS(jniinvokation()); + + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return false; + + return f->value.i; } -jchar CallCharMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jbyte GetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jchar ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; -/* log_text("JNI-Call: CallCharMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'C', vaargs); - va_end(vaargs); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return ret; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + + return f->value.i; } -jchar CallCharMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jchar GetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID) { -/* log_text("JNI-Call: CallCharMethodV");*/ - return callIntegerMethod(obj,get_virtual(obj,methodID),'C',args); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jchar CallCharMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallCharMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return 0; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + + return f->value.i; } -jshort CallShortMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jshort GetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jshort ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; -/* log_text("JNI-Call: CallShortMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs, methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'S', vaargs); - va_end(vaargs); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return ret; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + + return f->value.i; } -jshort CallShortMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jint GetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - return callIntegerMethod(obj, get_virtual(obj, methodID), 'S', args); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jshort CallShortMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallShortMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return 0; -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; + return f->value.i; +} -jint CallIntMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +jlong GetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - jint ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj, get_virtual(obj, methodID), 'I', vaargs); - va_end(vaargs); + STATISTICS(jniinvokation()); - return ret; -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0; -jint CallIntMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ - return callIntegerMethod(obj, get_virtual(obj, methodID), 'I', args); + return f->value.l; } -jint CallIntMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) +jfloat GetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallIntMethodA"); - - return 0; -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jlong CallLongMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) -{ - log_text("JNI-Call: CallLongMethod"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0.0; - return 0; + return f->value.f; } -jlong CallLongMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +jdouble GetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID) { - log_text("JNI-Call: CallLongMethodV"); + classinfo *c; + fieldinfo *f; - return 0; -} + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jlong CallLongMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallLongMethodA"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return 0.0; - return 0; + return f->value.d; } +/* SetStaticField ******************************************************* -jfloat CallFloatMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) + This family of accessor routines sets the value of a static field + of an object. + +*******************************************************************************/ + +void SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) { - jfloat ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; + + STATISTICS(jniinvokation()); -/* log_text("JNI-Call: CallFloatMethod");*/ + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'F'); - va_end(vaargs); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; - return ret; + f->value.a = value; } -jfloat CallFloatMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void SetStaticBooleanField(JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) { - log_text("JNI-Call: CallFloatMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'F'); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jfloat CallFloatMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallFloatMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return 0; -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + f->value.i = value; +} -jdouble CallDoubleMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) +void SetStaticByteField(JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) { - jdouble ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; -/* log_text("JNI-Call: CallDoubleMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = callFloatMethod(obj, get_virtual(obj, methodID), vaargs, 'D'); - va_end(vaargs); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return ret; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + + f->value.i = value; } -jdouble CallDoubleMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args) +void SetStaticCharField(JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) { - log_text("JNI-Call: CallDoubleMethodV"); - return callFloatMethod(obj, get_virtual(obj, methodID), args, 'D'); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jdouble CallDoubleMethodA(JNIEnv *env, jobject obj, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallDoubleMethodA"); - return 0; -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + f->value.i = value; +} -void CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...) + +void SetStaticShortField(JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) { - va_list vaargs; + classinfo *c; + fieldinfo *f; -/* log_text("JNI-Call: CallVoidMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - (void) callIntegerMethod(obj, get_virtual(obj, methodID), 'V', vaargs); - va_end(vaargs); -} + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; -void CallVoidMethodV (JNIEnv *env, jobject obj, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallVoidMethodV"); - (void)callIntegerMethod(obj,get_virtual(obj,methodID),'V',args); + f->value.i = value; } -void CallVoidMethodA (JNIEnv *env, jobject obj, jmethodID methodID, jvalue * args) +void SetStaticIntField(JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) { - log_text("JNI-Call: CallVoidMethodA"); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jobject CallNonvirtualObjectMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - log_text("JNI-Call: CallNonvirtualObjectMethod"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; - return NULL; + f->value.i = value; } -jobject CallNonvirtualObjectMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +void SetStaticLongField(JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) { - log_text("JNI-Call: CallNonvirtualObjectMethodV"); + classinfo *c; + fieldinfo *f; - return NULL; -} + STATISTICS(jniinvokation()); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; -jobject CallNonvirtualObjectMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) -{ - log_text("JNI-Call: CallNonvirtualObjectMethodA"); + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; - return NULL; + f->value.l = value; } - -jboolean CallNonvirtualBooleanMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +void SetStaticFloatField(JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) { - jboolean ret; - va_list vaargs; + classinfo *c; + fieldinfo *f; + + STATISTICS(jniinvokation()); -/* log_text("JNI-Call: CallNonvirtualBooleanMethod");*/ + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',vaargs); - va_end(vaargs); - return ret; + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + f->value.f = value; } -jboolean CallNonvirtualBooleanMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +void SetStaticDoubleField(JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) { -/* log_text("JNI-Call: CallNonvirtualBooleanMethodV");*/ - return (jboolean)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'Z',args); -} + classinfo *c; + fieldinfo *f; + STATISTICS(jniinvokation()); -jboolean CallNonvirtualBooleanMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) -{ - log_text("JNI-Call: CallNonvirtualBooleanMethodA"); + c = (classinfo *) clazz; + f = (fieldinfo *) fieldID; - return 0; -} + if (!(c->state & CLASS_INITIALIZED)) + if (!initialize_class(c)) + return; + f->value.d = value; +} -jbyte CallNonvirtualByteMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - jbyte ret; - va_list vaargs; +/* String Operations **********************************************************/ -/* log_text("JNI-Call: CallNonvirutalByteMethod");*/ +/* NewString ******************************************************************* - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',vaargs); - va_end(vaargs); - return ret; -} + Create new java.lang.String object from an array of Unicode + characters. +*******************************************************************************/ -jbyte CallNonvirtualByteMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jstring NewString(JNIEnv *env, const jchar *buf, jsize len) { - /*log_text("JNI-Call: CallNonvirtualByteMethodV"); */ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'B',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); + /* javastring or characterarray could not be created */ + if (!a || !s) + return NULL; -jbyte CallNonvirtualByteMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualByteMethodA"); + /* copy text */ + for (i = 0; i < len; i++) + a->data[i] = buf[i]; - return 0; -} + s->value = a; + s->offset = 0; + s->count = len; + return (jstring) NewLocalRef(env, (jobject) s); +} -jchar CallNonvirtualCharMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - jchar ret; - va_list vaargs; +static jchar emptyStringJ[]={0,0}; -/* log_text("JNI-Call: CallNonVirtualCharMethod");*/ +/* GetStringLength ************************************************************* - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',vaargs); - va_end(vaargs); - return ret; -} + Returns the length (the count of Unicode characters) of a Java + string. +*******************************************************************************/ -jchar CallNonvirtualCharMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jsize GetStringLength(JNIEnv *env, jstring str) { - /*log_text("JNI-Call: CallNonvirtualCharMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'C',args); + return ((java_lang_String *) str)->count; } -jchar CallNonvirtualCharMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +/******************** convertes javastring to u2-array ****************************/ + +u2 *javastring_tou2(jstring so) { - log_text("JNI-Call: CallNonvirtualCharMethodA"); - - return 0; -} + java_lang_String *s; + java_chararray *a; + u2 *stringbuffer; + u4 i; + STATISTICS(jniinvokation()); + + s = (java_lang_String *) so; + if (!s) + return NULL; -jshort CallNonvirtualShortMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - jshort ret; - va_list vaargs; + a = s->value; - /*log_text("JNI-Call: CallNonvirtualShortMethod");*/ + if (!a) + return NULL; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',vaargs); - va_end(vaargs); - return ret; -} + /* allocate memory */ + stringbuffer = MNEW(u2, s->count + 1); -jshort CallNonvirtualShortMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ - /*log_text("JNI-Call: CallNonvirtualShortMethodV");*/ - return callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'S',args); -} + /* copy text */ + for (i = 0; i < s->count; i++) + stringbuffer[i] = a->data[s->offset + i]; + + /* terminate string */ -jshort CallNonvirtualShortMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualShortMethodA"); + stringbuffer[i] = '\0'; - return 0; + return stringbuffer; } +/* GetStringChars ************************************************************** -jint CallNonvirtualIntMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ + Returns a pointer to the array of Unicode characters of the + string. This pointer is valid until ReleaseStringchars() is called. - jint ret; - va_list vaargs; +*******************************************************************************/ - /*log_text("JNI-Call: CallNonvirtualIntMethod");*/ +const jchar *GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy) +{ + jchar *jc; - va_start(vaargs,methodID); - ret = callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'I',vaargs); - va_end(vaargs); - return ret; -} + STATISTICS(jniinvokation()); + jc = javastring_tou2(str); -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); -} + if (jc) { + if (isCopy) + *isCopy = JNI_TRUE; + return jc; + } -jint CallNonvirtualIntMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualIntMethodA"); + if (isCopy) + *isCopy = JNI_TRUE; - return 0; + return emptyStringJ; } +/* ReleaseStringChars ********************************************************** -jlong CallNonvirtualLongMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) + 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: CallNonvirtualLongMethod"); + STATISTICS(jniinvokation()); - return 0; + if (chars == emptyStringJ) + return; + + MFREE(((jchar *) chars), jchar, ((java_lang_String *) str)->count + 1); } -jlong CallNonvirtualLongMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +/* NewStringUTF **************************************************************** + + Constructs a new java.lang.String object from an array of UTF-8 characters. + +*******************************************************************************/ + +jstring NewStringUTF(JNIEnv *env, const char *bytes) { - log_text("JNI-Call: CallNonvirtualLongMethodV"); + java_lang_String *s; - return 0; + STATISTICS(jniinvokation()); + + s = javastring_new(utf_new_char(bytes)); + + return (jstring) NewLocalRef(env, (jobject) s); } -jlong CallNonvirtualLongMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualLongMethodA"); +/****************** returns the utf8 length in bytes of a string *******************/ - return 0; +jsize GetStringUTFLength (JNIEnv *env, jstring string) +{ + java_lang_String *s = (java_lang_String*) string; + + STATISTICS(jniinvokation()); + + return (jsize) u2_utflength(s->value->data, s->count); } +/* GetStringUTFChars *********************************************************** -jfloat CallNonvirtualFloatMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) + Returns a pointer to an array of UTF-8 characters of the + string. This array is valid until it is released by + ReleaseStringUTFChars(). + +*******************************************************************************/ + +const char *GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy) { - jfloat ret; - va_list vaargs; + utf *u; - /*log_text("JNI-Call: CallNonvirtualFloatMethod");*/ + STATISTICS(jniinvokation()); + if (!string) + return ""; + + if (isCopy) + *isCopy = JNI_TRUE; + + u = javastring_toutf((java_lang_String *) string, false); - va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'F'); - va_end(vaargs); - return ret; + if (u) + return u->text; + return ""; } -jfloat CallNonvirtualFloatMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallNonvirtualFloatMethodV"); - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'F'); -} +/* ReleaseStringUTFChars ******************************************************* + Informs the VM that the native code no longer needs access to + utf. The utf argument is a pointer derived from string using + GetStringUTFChars(). -jfloat CallNonvirtualFloatMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) +*******************************************************************************/ + +void ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf) { - log_text("JNI-Call: CallNonvirtualFloatMethodA"); + STATISTICS(jniinvokation()); - return 0; + /* 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 */ } +/* Array Operations ***********************************************************/ -jdouble CallNonvirtualDoubleMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) -{ - jdouble ret; - va_list vaargs; - log_text("JNI-Call: CallNonvirtualDoubleMethod"); - - va_start(vaargs,methodID); - ret = callFloatMethod(obj,get_nonvirtual(clazz,methodID),vaargs,'D'); - va_end(vaargs); - return ret; +/* GetArrayLength ************************************************************** -} + Returns the number of elements in the array. +*******************************************************************************/ -jdouble CallNonvirtualDoubleMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) +jsize GetArrayLength(JNIEnv *env, jarray array) { -/* log_text("JNI-Call: CallNonvirtualDoubleMethodV");*/ - return callFloatMethod(obj,get_nonvirtual(clazz,methodID),args,'D'); -} + java_arrayheader *a; + STATISTICS(jniinvokation()); -jdouble CallNonvirtualDoubleMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallNonvirtualDoubleMethodA"); + a = (java_arrayheader *) array; - return 0; + return a->size; } +/* NewObjectArray ************************************************************** + + Constructs a new array holding objects in class elementClass. All + elements are initially set to initialElement. + +*******************************************************************************/ -void CallNonvirtualVoidMethod (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...) +jobjectArray NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement) { - va_list vaargs; + java_objectarray *oa; + s4 i; -/* log_text("JNI-Call: CallNonvirtualVoidMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',vaargs); - va_end(vaargs); + if (length < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } -} + oa = builtin_anewarray(length, elementClass); + if (!oa) + return NULL; -void CallNonvirtualVoidMethodV (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, va_list args) -{ -/* log_text("JNI-Call: CallNonvirtualVoidMethodV");*/ + /* set all elements to initialElement */ - (void)callIntegerMethod(obj,get_nonvirtual(clazz,methodID),'V',args); + for (i = 0; i < length; i++) + oa->data[i] = initialElement; + return (jobjectArray) NewLocalRef(env, (jobject) oa); } -void CallNonvirtualVoidMethodA (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, jvalue * args) +jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { - log_text("JNI-Call: CallNonvirtualVoidMethodA"); -} + java_objectarray *oa; + jobject o; -/************************* JNI-functions for accessing fields ************************/ + STATISTICS(jniinvokation()); -jfieldID GetFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) -{ - jfieldID f; + oa = (java_objectarray *) array; -/* 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 = native_new_and_init(class_java_lang_NoSuchFieldError); + if (index >= oa->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); + return NULL; } - return f; + + o = oa->data[index]; + + return NewLocalRef(env, o); } -/*************************** retrieve fieldid, abort on error ************************/ -jfieldID getFieldID_critical(JNIEnv *env, jclass clazz, char *name, char *sig) +void SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject val) { - jfieldID id = GetFieldID(env, clazz, name, sig); + java_objectarray *oa; + java_objectheader *o; - if (!id) { - log_text("class:"); - utf_display(clazz->name); - log_text("\nfield:"); - log_text(name); - log_text("sig:"); - log_text(sig); + STATISTICS(jniinvokation()); - panic("setfield_critical failed"); - } - return id; -} + oa = (java_objectarray *) array; + o = (java_objectheader *) val; -jobject GetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jobject,fieldID); -} + if (index >= oa->header.size) { + exceptions_throw_arrayindexoutofboundsexception(); + return; + } -jboolean GetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jboolean,fieldID); -} + /* check if the class of value is a subclass of the element class + of the array */ + if (!builtin_canstore(oa, o)) { + *exceptionptr = new_exception(string_java_lang_ArrayStoreException); -jbyte GetByteField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jbyte,fieldID); + return; + } + + oa->data[index] = val; } -jchar GetCharField (JNIEnv *env, jobject obj, jfieldID fieldID) +jbooleanArray NewBooleanArray(JNIEnv *env, jsize len) { - return getField(obj,jchar,fieldID); -} + java_booleanarray *ba; + STATISTICS(jniinvokation()); -jshort GetShortField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jshort,fieldID); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ba = builtin_newarray_boolean(len); -jint GetIntField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jint,fieldID); + return (jbooleanArray) NewLocalRef(env, (jobject) ba); } -jlong GetLongField (JNIEnv *env, jobject obj, jfieldID fieldID) +jbyteArray NewByteArray(JNIEnv *env, jsize len) { - return getField(obj,jlong,fieldID); -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jfloat GetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jfloat,fieldID); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ba = builtin_newarray_byte(len); -jdouble GetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID) -{ - return getField(obj,jdouble,fieldID); + return (jbyteArray) NewLocalRef(env, (jobject) ba); } -void SetObjectField (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val) + +jcharArray NewCharArray(JNIEnv *env, jsize len) { - setField(obj,jobject,fieldID,val); -} + java_chararray *ca; + STATISTICS(jniinvokation()); -void SetBooleanField (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val) -{ - setField(obj,jboolean,fieldID,val); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ca = builtin_newarray_char(len); -void SetByteField (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val) -{ - setField(obj,jbyte,fieldID,val); + return (jcharArray) NewLocalRef(env, (jobject) ca); } -void SetCharField (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val) +jshortArray NewShortArray(JNIEnv *env, jsize len) { - setField(obj,jchar,fieldID,val); -} + java_shortarray *sa; + STATISTICS(jniinvokation()); -void SetShortField (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val) -{ - setField(obj,jshort,fieldID,val); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + sa = builtin_newarray_short(len); -void SetIntField (JNIEnv *env, jobject obj, jfieldID fieldID, jint val) -{ - setField(obj,jint,fieldID,val); + return (jshortArray) NewLocalRef(env, (jobject) sa); } -void SetLongField (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val) +jintArray NewIntArray(JNIEnv *env, jsize len) { - setField(obj,jlong,fieldID,val); -} + java_intarray *ia; + STATISTICS(jniinvokation()); -void SetFloatField (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val) -{ - setField(obj,jfloat,fieldID,val); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + ia = builtin_newarray_int(len); -void SetDoubleField (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val) -{ - setField(obj,jdouble,fieldID,val); + return (jintArray) NewLocalRef(env, (jobject) ia); } -/**************** JNI-functions for calling static methods **********************/ -jmethodID GetStaticMethodID (JNIEnv *env, jclass clazz, const char *name, const char *sig) +jlongArray NewLongArray(JNIEnv *env, jsize len) { - jmethodID m; - - m = class_resolvemethod ( - clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); + java_longarray *la; - if (!m) exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); + STATISTICS(jniinvokation()); - return m; -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } -jobject CallStaticObjectMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...) -{ - log_text("JNI-Call: CallStaticObjectMethod"); + la = builtin_newarray_long(len); - return NULL; + return (jlongArray) NewLocalRef(env, (jobject) la); } -jobject CallStaticObjectMethodV (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jfloatArray NewFloatArray(JNIEnv *env, jsize len) { - log_text("JNI-Call: CallStaticObjectMethodV"); + java_floatarray *fa; - return NULL; -} + STATISTICS(jniinvokation()); + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } -jobject CallStaticObjectMethodA (JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticObjectMethodA"); + fa = builtin_newarray_float(len); - return NULL; + return (jfloatArray) NewLocalRef(env, (jobject) fa); } -jboolean CallStaticBooleanMethod (JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jdoubleArray NewDoubleArray(JNIEnv *env, jsize len) { - jboolean ret; - va_list vaargs; - -/* log_text("JNI-Call: CallStaticBooleanMethod");*/ + java_doublearray *da; - va_start(vaargs,methodID); - ret = (jboolean)callIntegerMethod(0,methodID,'Z',vaargs); - va_end(vaargs); - return ret; + STATISTICS(jniinvokation()); -} + if (len < 0) { + exceptions_throw_negativearraysizeexception(); + return NULL; + } + da = builtin_newarray_double(len); -jboolean CallStaticBooleanMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) -{ - return (jboolean) callIntegerMethod(0, methodID, 'Z', args); + return (jdoubleArray) NewLocalRef(env, (jobject) da); } -jboolean CallStaticBooleanMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticBooleanMethodA"); - return 0; -} +/* GetArrayElements ********************************************* + A family of functions that returns the body of the primitive array. -jbyte CallStaticByteMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +*******************************************************************************/ + +jboolean *GetBooleanArrayElements(JNIEnv *env, jbooleanArray array, + jboolean *isCopy) { - jbyte ret; - va_list vaargs; + java_booleanarray *ba; + + STATISTICS(jniinvokation()); - /* log_text("JNI-Call: CallStaticByteMethod");*/ + ba = (java_booleanarray *) array; - va_start(vaargs, methodID); - ret = (jbyte) callIntegerMethod(0, methodID, 'B', vaargs); - va_end(vaargs); + if (isCopy) + *isCopy = JNI_FALSE; - return ret; + return ba->data; } -jbyte CallStaticByteMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jbyte *GetByteArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) { - return (jbyte) callIntegerMethod(0, methodID, 'B', args); -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jbyte CallStaticByteMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticByteMethodA"); + ba = (java_bytearray *) array; - return 0; + if (isCopy) + *isCopy = JNI_FALSE; + + return ba->data; } -jchar CallStaticCharMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jchar *GetCharArrayElements(JNIEnv *env, jcharArray array, jboolean *isCopy) { - jchar ret; - va_list vaargs; + java_chararray *ca; + + STATISTICS(jniinvokation()); - /* log_text("JNI-Call: CallStaticByteMethod");*/ + ca = (java_chararray *) array; - va_start(vaargs, methodID); - ret = (jchar) callIntegerMethod(0, methodID, 'C', vaargs); - va_end(vaargs); + if (isCopy) + *isCopy = JNI_FALSE; - return ret; + return ca->data; } -jchar CallStaticCharMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jshort *GetShortArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) { - return (jchar) callIntegerMethod(0, methodID, 'C', args); -} + java_shortarray *sa; + STATISTICS(jniinvokation()); -jchar CallStaticCharMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticCharMethodA"); + sa = (java_shortarray *) array; - return 0; -} + if (isCopy) + *isCopy = JNI_FALSE; + return sa->data; +} -jshort CallStaticShortMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jint *GetIntArrayElements(JNIEnv *env, jintArray array, jboolean *isCopy) { - jshort ret; - va_list vaargs; + java_intarray *ia; - /* log_text("JNI-Call: CallStaticByteMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = (jshort) callIntegerMethod(0, methodID, 'S', vaargs); - va_end(vaargs); + ia = (java_intarray *) array; - return ret; + if (isCopy) + *isCopy = JNI_FALSE; + + return ia->data; } -jshort CallStaticShortMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jlong *GetLongArrayElements(JNIEnv *env, jlongArray array, jboolean *isCopy) { - /*log_text("JNI-Call: CallStaticShortMethodV");*/ - return (jshort) callIntegerMethod(0, methodID, 'S', args); -} + java_longarray *la; + STATISTICS(jniinvokation()); -jshort CallStaticShortMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticShortMethodA"); + la = (java_longarray *) array; - return 0; -} + 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 (jlong *) la->data; +} -jint CallStaticIntMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +jfloat *GetFloatArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) { - jint ret; - va_list vaargs; + java_floatarray *fa; - /* log_text("JNI-Call: CallStaticIntMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs, methodID); - ret = callIntegerMethod(0, methodID, 'I', vaargs); - va_end(vaargs); + fa = (java_floatarray *) array; - return ret; + if (isCopy) + *isCopy = JNI_FALSE; + + return fa->data; } -jint CallStaticIntMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +jdouble *GetDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jboolean *isCopy) { - log_text("JNI-Call: CallStaticIntMethodV"); + java_doublearray *da; - return callIntegerMethod(0, methodID, 'I', args); -} + STATISTICS(jniinvokation()); + da = (java_doublearray *) array; -jint CallStaticIntMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticIntMethodA"); + if (isCopy) + *isCopy = JNI_FALSE; - return 0; + return da->data; } +/* ReleaseArrayElements ***************************************** -jlong CallStaticLongMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) + 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) { - jlong ret; - va_list vaargs; + java_booleanarray *ba; - /* log_text("JNI-Call: CallStaticLongMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs, methodID); - ret = callLongMethod(0, methodID, vaargs); - va_end(vaargs); + ba = (java_booleanarray *) array; - return ret; + 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; + } + } } -jlong CallStaticLongMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +void ReleaseByteArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, + jint mode) { - log_text("JNI-Call: CallStaticLongMethodV"); - - return callLongMethod(0,methodID,args); -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jlong CallStaticLongMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticLongMethodA"); + ba = (java_bytearray *) array; - return 0; + 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; + } + } } - -jfloat CallStaticFloatMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +void ReleaseCharArrayElements(JNIEnv *env, jcharArray array, jchar *elems, + jint mode) { - jfloat ret; - va_list vaargs; + java_chararray *ca; - /* log_text("JNI-Call: CallStaticLongMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs, methodID); - ret = callFloatMethod(0, methodID, vaargs, 'F'); - va_end(vaargs); + ca = (java_chararray *) array; - return ret; + 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; + } + } } -jfloat CallStaticFloatMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +void ReleaseShortArrayElements(JNIEnv *env, jshortArray array, jshort *elems, + jint mode) { + java_shortarray *sa; - return callFloatMethod(0, methodID, args, 'F'); + STATISTICS(jniinvokation()); -} - - -jfloat CallStaticFloatMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticFloatMethodA"); + sa = (java_shortarray *) array; - return 0; + 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; + } + } } - -jdouble CallStaticDoubleMethod(JNIEnv *env, jclass clazz, jmethodID methodID, ...) +void ReleaseIntArrayElements(JNIEnv *env, jintArray array, jint *elems, + jint mode) { - jdouble ret; - va_list vaargs; + java_intarray *ia; - /* log_text("JNI-Call: CallStaticDoubleMethod");*/ + STATISTICS(jniinvokation()); - va_start(vaargs,methodID); - ret = callFloatMethod(0, methodID, vaargs, 'D'); - va_end(vaargs); + ia = (java_intarray *) array; - return ret; + 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; + } + } } -jdouble CallStaticDoubleMethodV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args) +void ReleaseLongArrayElements(JNIEnv *env, jlongArray array, jlong *elems, + jint mode) { - log_text("JNI-Call: CallStaticDoubleMethodV"); + java_longarray *la; - return callFloatMethod(0, methodID, args, 'D'); -} + STATISTICS(jniinvokation()); + la = (java_longarray *) array; -jdouble CallStaticDoubleMethodA(JNIEnv *env, jclass clazz, jmethodID methodID, jvalue *args) -{ - log_text("JNI-Call: CallStaticDoubleMethodA"); + /* We cast this one to prevent a compiler warning on 64-bit + systems since GNU Classpath typedef jlong to long long. */ - return 0; + 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; + } + } } -void CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...) +void ReleaseFloatArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, + jint mode) { - va_list vaargs; + java_floatarray *fa; -/* log_text("JNI-Call: CallStaticVoidMethod");*/ - - va_start(vaargs, methodID); - (void) callIntegerMethod(0, methodID, 'V', vaargs); - va_end(vaargs); -} + STATISTICS(jniinvokation()); + fa = (java_floatarray *) array; -void CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args) -{ - log_text("JNI-Call: CallStaticVoidMethodV"); - (void)callIntegerMethod(0, methodID, 'V', args); + 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; + } + } } -void CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, jvalue * args) +void ReleaseDoubleArrayElements(JNIEnv *env, jdoubleArray array, + jdouble *elems, jint mode) { - log_text("JNI-Call: CallStaticVoidMethodA"); -} + java_doublearray *da; + STATISTICS(jniinvokation()); -/****************** JNI-functions for accessing static fields ********************/ + da = (java_doublearray *) array; -jfieldID GetStaticFieldID (JNIEnv *env, jclass clazz, const char *name, const char *sig) -{ - jfieldID f; + 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; + } + } +} - f = jclass_findfield(clazz, - utf_new_char ((char*) name), - utf_new_char ((char*) sig) - ); - - if (!f) exceptionptr = native_new_and_init(class_java_lang_NoSuchFieldError); - return f; -} +/* GetArrayRegion ********************************************** + + A family of functions that copies a region of a primitive array + into a buffer. +*******************************************************************************/ -jobject GetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID) +void GetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - 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; + 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); } -jbyte GetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID) +void GetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - class_init(clazz); - return fieldID->value.i; -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -jchar GetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; + 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); } -jshort GetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID) +void GetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) { - class_init(clazz); - return fieldID->value.i; -} + java_chararray *ca; + STATISTICS(jniinvokation()); -jint GetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.i; + 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); } -jlong GetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID) +void GetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - class_init(clazz); - return fieldID->value.l; -} + java_shortarray *sa; + STATISTICS(jniinvokation()); -jfloat GetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID) -{ - class_init(clazz); - return fieldID->value.f; + sa = (java_shortarray *) array; + + if ((start < 0) || (len < 0) || (start + len > sa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &sa->data[start], s2, len); } -jdouble GetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID) +void GetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { - class_init(clazz); - return fieldID->value.d; -} + java_intarray *ia; + STATISTICS(jniinvokation()); + ia = (java_intarray *) array; -void SetStaticObjectField (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value) -{ - class_init(clazz); - fieldID->value.a = value; + if ((start < 0) || (len < 0) || (start + len > ia->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &ia->data[start], s4, len); } -void SetStaticBooleanField (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value) +void GetLongArrayRegion(JNIEnv *env, jlongArray array, jsize start, jsize len, + jlong *buf) { - class_init(clazz); - fieldID->value.i = value; -} + java_longarray *la; + STATISTICS(jniinvokation()); -void SetStaticByteField (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value) -{ - class_init(clazz); - fieldID->value.i = value; -} + la = (java_longarray *) array; - -void SetStaticCharField (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value) -{ - class_init(clazz); - fieldID->value.i = value; + if ((start < 0) || (len < 0) || (start + len > la->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &la->data[start], s8, len); } -void SetStaticShortField (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value) +void GetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - class_init(clazz); - fieldID->value.i = value; -} + java_floatarray *fa; + STATISTICS(jniinvokation()); -void SetStaticIntField (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value) -{ - class_init(clazz); - fieldID->value.i = value; + 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 SetStaticLongField (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value) +void GetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - class_init(clazz); - fieldID->value.l = value; -} + java_doublearray *da; + STATISTICS(jniinvokation()); -void SetStaticFloatField (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value) -{ - class_init(clazz); - fieldID->value.f = value; + da = (java_doublearray *) array; + + if ((start < 0) || (len < 0) || (start + len > da->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(buf, &da->data[start], double, len); } -void SetStaticDoubleField (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value) -{ - class_init(clazz); - fieldID->value.d = value; -} +/* SetArrayRegion ********************************************** + A family of functions that copies back a region of a primitive + array from a buffer. -/***** create new java.lang.String object from an array of Unicode characters ****/ +*******************************************************************************/ -jstring NewString (JNIEnv *env, const jchar *buf, jsize len) +void SetBooleanArrayRegion(JNIEnv *env, jbooleanArray array, jsize start, + jsize len, jboolean *buf) { - 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_booleanarray *ba; - /* 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; + ba = (java_booleanarray *) array; - return (jstring) s; + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ba->data[start], buf, u1, len); } -static char emptyString[]=""; -static jchar emptyStringJ[]={0,0}; - -/******************* returns the length of a Java string ***************************/ - -jsize GetStringLength (JNIEnv *env, jstring str) +void SetByteArrayRegion(JNIEnv *env, jbyteArray array, jsize start, jsize len, + jbyte *buf) { - return ((java_lang_String*) str)->count; -} + java_bytearray *ba; + STATISTICS(jniinvokation()); -/******************** 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; - - a = s->value; - if (!a) return NULL; + ba = (java_bytearray *) array; - /* allocate memory */ - stringbuffer = MNEW( u2 , s->count + 1 ); + if ((start < 0) || (len < 0) || (start + len > ba->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ba->data[start], buf, s1, len); +} - /* copy text */ - for (i=0; icount; i++) stringbuffer[i] = a->data[s->offset+i]; - - /* terminate string */ - stringbuffer[i] = '\0'; - return stringbuffer; -} +void SetCharArrayRegion(JNIEnv *env, jcharArray array, jsize start, jsize len, + jchar *buf) +{ + java_chararray *ca; -/********* returns a pointer to an array of Unicode characters of the string *******/ + STATISTICS(jniinvokation()); -const jchar *GetStringChars (JNIEnv *env, jstring str, jboolean *isCopy) -{ - jchar *jc=javastring_tou2(str); + ca = (java_chararray *) array; - if (jc) { - if (isCopy) *isCopy=JNI_TRUE; - return jc; - } - if (isCopy) *isCopy=JNI_TRUE; - return emptyStringJ; + if ((start < 0) || (len < 0) || (start + len > ca->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ca->data[start], buf, u2, len); } -/**************** native code no longer needs access to chars **********************/ -void ReleaseStringChars (JNIEnv *env, jstring str, const jchar *chars) +void SetShortArrayRegion(JNIEnv *env, jshortArray array, jsize start, + jsize len, jshort *buf) { - if (chars==emptyStringJ) return; - MFREE(((jchar*) chars),jchar,((java_lang_String*) str)->count+1); + java_shortarray *sa; + + 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); } -/************ create new java.lang.String object from utf8-characterarray **********/ -jstring NewStringUTF (JNIEnv *env, const char *utf) +void SetIntArrayRegion(JNIEnv *env, jintArray array, jsize start, jsize len, + jint *buf) { -/* log_text("NewStringUTF called");*/ - return javastring_new(utf_new_char(utf)); -} + java_intarray *ia; -/****************** returns the utf8 length in bytes of a string *******************/ + STATISTICS(jniinvokation()); -jsize GetStringUTFLength (JNIEnv *env, jstring string) -{ - java_lang_String *s = (java_lang_String*) string; + ia = (java_intarray *) array; - return (jsize) u2_utflength(s->value->data, s->count); + if ((start < 0) || (len < 0) || (start + len > ia->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&ia->data[start], buf, s4, len); } -/************ converts a Javastring to an array of UTF-8 characters ****************/ -const char* GetStringUTFChars (JNIEnv *env, jstring string, jboolean *isCopy) +void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize len, + jlong *buf) { - utf *u; - if (verbose) log_text("GetStringUTFChars:"); + java_longarray *la; - u=javastring_toutf((java_lang_String*) string,false); - if (isCopy) *isCopy=JNI_FALSE; - if (u) { - return u->text; - } - return emptyString; - -} + STATISTICS(jniinvokation()); -/***************** native code no longer needs access to utf ***********************/ + la = (java_longarray *) array; -void ReleaseStringUTFChars (JNIEnv *env, jstring str, const char* chars) -{ - /*we don't release utf chars right now, perhaps that should be done later. Since there is always one reference - the garbage collector will never get them*/ - /* - log_text("JNI-Call: ReleaseStringUTFChars"); - utf_display(utf_new_char(chars)); - */ + if ((start < 0) || (len < 0) || (start + len > la->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&la->data[start], buf, s8, len); } -/************************** array operations ***************************************/ -jsize GetArrayLength (JNIEnv *env, jarray array) +void SetFloatArrayRegion(JNIEnv *env, jfloatArray array, jsize start, + jsize len, jfloat *buf) { - return array->size; -} + java_floatarray *fa; -jobjectArray NewObjectArray (JNIEnv *env, jsize len, jclass clazz, jobject init) -{ - java_objectarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_anewarray (len, clazz); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + STATISTICS(jniinvokation()); -jobject GetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index) -{ - jobject j = NULL; + fa = (java_floatarray *) array; - if (indexheader.size) - j = array->data[index]; - else - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - - return j; + if ((start < 0) || (len < 0) || (start + len > fa->header.size)) + exceptions_throw_arrayindexoutofboundsexception(); + else + MCOPY(&fa->data[start], buf, float, len); } -void SetObjectArrayElement (JNIEnv *env, jobjectArray array, jsize index, jobject val) + +void SetDoubleArrayRegion(JNIEnv *env, jdoubleArray array, jsize start, + jsize len, jdouble *buf) { - if (index>=array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else { + java_doublearray *da; - /* check if the class of value is a subclass of the element class of the array */ + STATISTICS(jniinvokation()); - if (!builtin_canstore((java_objectarray*)array,(java_objectheader*)val)) - exceptionptr = proto_java_lang_ArrayStoreException; - else - array->data[index] = val; - } + 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); } +/* Registering Native Methods *************************************************/ -jbooleanArray NewBooleanArray (JNIEnv *env, jsize len) -{ - java_booleanarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_boolean(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} +/* 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. -jbyteArray NewByteArray (JNIEnv *env, jsize len) +*******************************************************************************/ + +jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods) { - java_bytearray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_byte(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + STATISTICS(jniinvokation()); + log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!"); -jcharArray NewCharArray (JNIEnv *env, jsize len) -{ - java_chararray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_char(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; + return 0; } -jshortArray NewShortArray (JNIEnv *env, jsize len) -{ - java_shortarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_short(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} +/* UnregisterNatives *********************************************************** + Unregisters native methods of a class. The class goes back to the + state before it was linked or registered with its native method + functions. -jintArray NewIntArray (JNIEnv *env, jsize len) -{ - java_intarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_int(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + This function should not be used in normal native code. Instead, it + provides special programs a way to reload and relink native + libraries. +*******************************************************************************/ -jlongArray NewLongArray (JNIEnv *env, jsize len) +jint UnregisterNatives(JNIEnv *env, jclass clazz) { - java_longarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_long(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} + STATISTICS(jniinvokation()); + /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */ -jfloatArray NewFloatArray (JNIEnv *env, jsize len) -{ - java_floatarray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_float(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; + log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!"); + + return 0; } -jdoubleArray NewDoubleArray (JNIEnv *env, jsize len) -{ - java_doublearray *j; - if (len<0) { - exceptionptr=proto_java_lang_NegativeArraySizeException; - return NULL; - } - j = builtin_newarray_double(len); - if (!j) exceptionptr = proto_java_lang_OutOfMemoryError; - return j; -} +/* Monitor Operations *********************************************************/ +/* MonitorEnter **************************************************************** -jboolean * GetBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + Enters the monitor associated with the underlying Java object + referred to by obj. +*******************************************************************************/ -jbyte * GetByteArrayElements (JNIEnv *env, jbyteArray array, jboolean *isCopy) +jint MonitorEnter(JNIEnv *env, jobject obj) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} + STATISTICS(jniinvokation()); + if (!obj) { + exceptions_throw_nullpointerexception(); + return JNI_ERR; + } -jchar * GetCharArrayElements (JNIEnv *env, jcharArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; +#if defined(USE_THREADS) + builtin_monitorenter(obj); +#endif + + return JNI_OK; } -jshort * GetShortArrayElements (JNIEnv *env, jshortArray array, jboolean *isCopy) -{ - if (isCopy) *isCopy = JNI_FALSE; - return array->data; -} +/* MonitorExit ***************************************************************** + + The current thread must be the owner of the monitor associated with + the underlying Java object referred to by obj. The thread + decrements the counter indicating the number of times it has + entered this monitor. If the value of the counter becomes zero, the + current thread releases the monitor. +*******************************************************************************/ -jint * GetIntArrayElements (JNIEnv *env, jintArray array, jboolean *isCopy) +jint MonitorExit(JNIEnv *env, jobject obj) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + STATISTICS(jniinvokation()); + + if (!obj) { + exceptions_throw_nullpointerexception(); + return JNI_ERR; + } + +#if defined(USE_THREADS) + builtin_monitorexit(obj); +#endif + + return JNI_OK; } -jlong * GetLongArrayElements (JNIEnv *env, jlongArray array, jboolean *isCopy) +/* JavaVM Interface ***********************************************************/ + +/* GetJavaVM ******************************************************************* + + Returns the Java VM interface (used in the Invocation API) + associated with the current thread. The result is placed at the + location pointed to by the second argument, vm. + +*******************************************************************************/ + +jint GetJavaVM(JNIEnv *env, JavaVM **vm) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + STATISTICS(jniinvokation()); + + *vm = &ptr_jvm; + + return 0; } -jfloat * GetFloatArrayElements (JNIEnv *env, jfloatArray array, jboolean *isCopy) +void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + STATISTICS(jniinvokation()); + + log_text("JNI-Call: GetStringRegion: IMPLEMENT ME!"); } -jdouble * GetDoubleArrayElements (JNIEnv *env, jdoubleArray array, jboolean *isCopy) +void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf) { - if (isCopy) *isCopy = JNI_FALSE; - return array->data; + STATISTICS(jniinvokation()); + + log_text("JNI-Call: GetStringUTFRegion: IMPLEMENT ME!"); } +/* GetPrimitiveArrayCritical *************************************************** -void ReleaseBooleanArrayElements (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode) -{ - /* empty */ -} + Obtain a direct pointer to array elements. +*******************************************************************************/ -void ReleaseByteArrayElements (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) +void *GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy) { - /* empty */ -} + java_bytearray *ba; + jbyte *bp; + ba = (java_bytearray *) array; -void ReleaseCharArrayElements (JNIEnv *env, jcharArray array, jchar *elems, jint mode) -{ - /* empty */ -} + /* do the same as Kaffe does */ + bp = GetByteArrayElements(env, ba, isCopy); -void ReleaseShortArrayElements (JNIEnv *env, jshortArray array, jshort *elems, jint mode) -{ - /* empty */ + return (void *) bp; } -void ReleaseIntArrayElements (JNIEnv *env, jintArray array, jint *elems, jint mode) -{ - /* empty */ -} +/* ReleasePrimitiveArrayCritical *********************************************** + No specific documentation. -void ReleaseLongArrayElements (JNIEnv *env, jlongArray array, jlong *elems, jint mode) +*******************************************************************************/ + +void ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, + jint mode) { - /* empty */ -} + STATISTICS(jniinvokation()); + /* do the same as Kaffe does */ -void ReleaseFloatArrayElements (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) -{ - /* empty */ + ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray, mode); } -void ReleaseDoubleArrayElements (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode) -{ - /* empty */ -} +/* GetStringCritical *********************************************************** -void GetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); -} + The semantics of these two functions are similar to the existing + Get/ReleaseStringChars functions. +*******************************************************************************/ -void GetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) +const jchar *GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + return GetStringChars(env, string, isCopy); } -void GetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) +void ReleaseStringCritical(JNIEnv *env, jstring string, const jchar *cstring) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + ReleaseStringChars(env, string, cstring); } -void GetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) +jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); -} + STATISTICS(jniinvokation()); + log_text("JNI-Call: NewWeakGlobalRef: IMPLEMENT ME!"); -void GetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + return obj; } -void GetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) +void DeleteWeakGlobalRef(JNIEnv* env, jweak ref) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DeleteWeakGlobalRef: IMPLEMENT ME"); } -void GetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); -} +/* NewGlobalRef **************************************************************** + Creates a new global reference to the object referred to by the obj + argument. -void GetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) +*******************************************************************************/ + +jobject NewGlobalRef(JNIEnv* env, jobject lobj) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(buf,&array->data[start],len*sizeof(array->data[0])); -} + java_objectheader *o; + java_lang_Integer *refcount; + java_objectheader *newval; + STATISTICS(jniinvokation()); -void SetBooleanArrayRegion (JNIEnv* env, jbooleanArray array, jsize start, jsize len, jboolean *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); -} +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif + + o = vm_call_method(getmid, *global_ref_table, lobj); + refcount = (java_lang_Integer *) o; -void SetByteArrayRegion (JNIEnv* env, jbyteArray array, jsize start, jsize len, jbyte *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); -} + if (refcount == NULL) { + newval = native_new_and_init_int(class_java_lang_Integer, 1); + if (newval == NULL) { +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif + return NULL; + } -void SetCharArrayRegion (JNIEnv* env, jcharArray array, jsize start, jsize len, jchar *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + (void) vm_call_method(putmid, *global_ref_table, lobj, newval); -} + } else { + /* we can access the object itself, as we are in a + synchronized section */ + refcount->value++; + } -void SetShortArrayRegion (JNIEnv* env, jshortArray array, jsize start, jsize len, jshort *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif + + return lobj; } -void SetIntArrayRegion (JNIEnv* env, jintArray array, jsize start, jsize len, jint *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); +/* DeleteGlobalRef ************************************************************* -} + Deletes the global reference pointed to by globalRef. -void SetLongArrayRegion (JNIEnv* env, jlongArray array, jsize start, jsize len, jlong *buf) +*******************************************************************************/ + +void DeleteGlobalRef(JNIEnv* env, jobject globalRef) { - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); + java_objectheader *o; + java_lang_Integer *refcount; + s4 val; -} + STATISTICS(jniinvokation()); -void SetFloatArrayRegion (JNIEnv* env, jfloatArray array, jsize start, jsize len, jfloat *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); +#if defined(USE_THREADS) + builtin_monitorenter(*global_ref_table); +#endif -} + o = vm_call_method(getmid, *global_ref_table, globalRef); -void SetDoubleArrayRegion (JNIEnv* env, jdoubleArray array, jsize start, jsize len, jdouble *buf) -{ - if (start<0 || len<0 || start+len>array->header.size) - exceptionptr = proto_java_lang_ArrayIndexOutOfBoundsException; - else - memcpy(&array->data[start],buf,len*sizeof(array->data[0])); -} + refcount = (java_lang_Integer *) o; -jint RegisterNatives (JNIEnv* env, jclass clazz, const JNINativeMethod *methods, jint nMethods) -{ - log_text("JNI-Call: RegisterNatives"); - return 0; -} + if (refcount == NULL) { + log_text("JNI-DeleteGlobalRef: unable to find global reference"); + return; + } + /* we can access the object itself, as we are in a synchronized + section */ -jint UnregisterNatives (JNIEnv* env, jclass clazz) -{ - log_text("JNI-Call: UnregisterNatives"); - return 0; -} + val = refcount->value - 1; -/******************************* monitor operations ********************************/ + if (val == 0) { + (void) vm_call_method(removemid, *global_ref_table, refcount); -jint MonitorEnter (JNIEnv* env, jobject obj) -{ - builtin_monitorenter(obj); - return 0; -} + } else { + /* we do not create a new object, but set the new value into + the old one */ + refcount->value = val; + } -jint MonitorExit (JNIEnv* env, jobject obj) -{ - builtin_monitorexit(obj); - return 0; +#if defined(USE_THREADS) + builtin_monitorexit(*global_ref_table); +#endif } -/************************************* JavaVM interface ****************************/ -#ifdef __cplusplus -#error CPP mode not supported yet -#else -jint GetJavaVM (JNIEnv* env, JavaVM **vm) -{ - log_text("JNI-Call: GetJavaVM"); - *vm=&javaVM; - return 0; -} -#endif /*__cplusplus*/ +/* ExceptionCheck ************************************************************** -void GetStringRegion (JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf) -{ - log_text("JNI-Call: GetStringRegion"); + Returns JNI_TRUE when there is a pending exception; otherwise, + returns JNI_FALSE. -} +*******************************************************************************/ -void GetStringUTFRegion (JNIEnv* env, jstring str, jsize start, jsize len, char *buf) +jboolean ExceptionCheck(JNIEnv *env) { - log_text("JNI-Call: GetStringUTFRegion"); + STATISTICS(jniinvokation()); + return *exceptionptr ? JNI_TRUE : JNI_FALSE; } -/****************** obtain direct pointer to array elements ***********************/ -void * GetPrimitiveArrayCritical (JNIEnv* env, jarray array, jboolean *isCopy) -{ - java_objectheader *s = (java_objectheader*) array; - arraydescriptor *desc = s->vftbl->arraydesc; +/* New JNI 1.4 functions ******************************************************/ - if (!desc) return NULL; +/* NewDirectByteBuffer ********************************************************* - return ((u1*)s) + desc->dataoffset; -} + Allocates and returns a direct java.nio.ByteBuffer referring to the + block of memory starting at the memory address address and + extending capacity bytes. +*******************************************************************************/ -void ReleasePrimitiveArrayCritical (JNIEnv* env, jarray array, void *carray, jint mode) +jobject NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity) { - log_text("JNI-Call: ReleasePrimitiveArrayCritical"); + java_objectheader *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *paddress; +#else + gnu_classpath_Pointer32 *paddress; +#endif - /* empty */ -} + STATISTICS(jniinvokation()); -/********* returns a pointer to an array of Unicode characters of the string *******/ + /* alocate a gnu.classpath.Pointer{32,64} object */ -const jchar * GetStringCritical (JNIEnv* env, jstring string, jboolean *isCopy) -{ - log_text("JNI-Call: GetStringCritical"); +#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; - return GetStringChars(env,string,isCopy); -} + /* fill gnu.classpath.Pointer{32,64} with address */ -/**************** native code no longer needs access to chars **********************/ + paddress->data = (ptrint) address; -void ReleaseStringCritical (JNIEnv* env, jstring string, const jchar *cstring) -{ - log_text("JNI-Call: ReleaseStringCritical"); + /* 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 */ - ReleaseStringChars(env,string,cstring); + return NewLocalRef(env, nbuf); } -jweak NewWeakGlobalRef (JNIEnv* env, jobject obj) -{ - log_text("JNI-Call: NewWeakGlobalRef"); +/* GetDirectBufferAddress ****************************************************** - return obj; -} + Fetches and returns the starting address of the memory region + referenced by the given direct java.nio.Buffer. +*******************************************************************************/ -void DeleteWeakGlobalRef (JNIEnv* env, jweak ref) +void *GetDirectBufferAddress(JNIEnv *env, jobject buf) { - log_text("JNI-Call: DeleteWeakGlobalRef"); + java_nio_DirectByteBufferImpl *nbuf; +#if SIZEOF_VOID_P == 8 + gnu_classpath_Pointer64 *address; +#else + gnu_classpath_Pointer32 *address; +#endif - /* empty */ + 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; } -/******************************* check for pending exception ***********************/ +/* GetDirectBufferCapacity ***************************************************** + Fetches and returns the capacity in bytes of the memory region + referenced by the given direct java.nio.Buffer. -jboolean ExceptionCheck(JNIEnv* env) +*******************************************************************************/ + +jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) { - log_text("JNI-Call: ExceptionCheck"); + java_nio_Buffer *nbuf; - return exceptionptr ? JNI_TRUE : JNI_FALSE; -} + 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) +/* AttachCurrentThread ********************************************************* + + Attaches the current thread to a Java VM. Returns a JNI interface + pointer in the JNIEnv argument. + + Trying to attach a thread that is already attached is a no-op. + + A native thread cannot be attached simultaneously to two Java VMs. + + When a thread is attached to the VM, the context class loader is + the bootstrap loader. + +*******************************************************************************/ + +jint AttachCurrentThread(JavaVM *vm, void **env, void *thr_args) { - log_text("AttachCurrentThread called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: AttachCurrentThread: IMPLEMENT ME!"); + +#if !defined(HAVE___THREAD) +/* cacao_thread_attach();*/ +#else + #error "No idea how to implement that. Perhaps Stefan knows" +#endif + + *env = &ptr_env; return 0; } @@ -2945,445 +5229,461 @@ jint AttachCurrentThread(JavaVM *vm, void **par1, void *par2) jint DetachCurrentThread(JavaVM *vm) { - log_text("DetachCurrentThread called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: DetachCurrentThread: IMPLEMENT ME!"); return 0; } -jint GetEnv(JavaVM *vm, void **environment, jint jniversion) +/* GetEnv ********************************************************************** + + If the current thread is not attached to the VM, sets *env to NULL, + and returns JNI_EDETACHED. If the specified version is not + supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise, + sets *env to the appropriate interface, and returns JNI_OK. + +*******************************************************************************/ + +jint GetEnv(JavaVM *vm, void **env, jint version) { - *environment = &env; + STATISTICS(jniinvokation()); - return 0; +#if defined(USE_THREADS) && defined(NATIVE_THREADS) + if (thread_getself() == NULL) { + *env = NULL; + + return JNI_EDETACHED; + } +#endif + + if ((version == JNI_VERSION_1_1) || (version == JNI_VERSION_1_2) || + (version == JNI_VERSION_1_4)) { + *env = &ptr_env; + + return JNI_OK; + } + +#if defined(ENABLE_JVMTI) + if (version == JVMTI_VERSION_1_0) { + *env = (void *) new_jvmtienv(); + + if (env != NULL) + return JNI_OK; + } +#endif + + *env = NULL; + + return JNI_EVERSION; } + jint AttachCurrentThreadAsDaemon(JavaVM *vm, void **par1, void *par2) { - log_text("AttachCurrentThreadAsDaemon called"); + STATISTICS(jniinvokation()); + + log_text("JNI-Call: AttachCurrentThreadAsDaemon: IMPLEMENT ME!"); return 0; } +/* JNI invocation table *******************************************************/ +const struct JNIInvokeInterface JNI_JavaVMTable = { + NULL, + NULL, + NULL, + DestroyJavaVM, + AttachCurrentThread, + DetachCurrentThread, + GetEnv, + AttachCurrentThreadAsDaemon +}; +/* JNI function table *********************************************************/ + +struct JNINativeInterface JNI_JNIEnvTable = { + NULL, + NULL, + NULL, + NULL, + GetVersion, + + DefineClass, + FindClass, + FromReflectedMethod, + FromReflectedField, + ToReflectedMethod, + GetSuperclass, + IsAssignableFrom, + ToReflectedField, + + Throw, + ThrowNew, + ExceptionOccurred, + ExceptionDescribe, + ExceptionClear, + FatalError, + PushLocalFrame, + PopLocalFrame, + + NewGlobalRef, + DeleteGlobalRef, + DeleteLocalRef, + IsSameObject, + NewLocalRef, + EnsureLocalCapacity, + + AllocObject, + NewObject, + NewObjectV, + NewObjectA, + + GetObjectClass, + IsInstanceOf, + + GetMethodID, + + CallObjectMethod, + CallObjectMethodV, + CallObjectMethodA, + CallBooleanMethod, + CallBooleanMethodV, + CallBooleanMethodA, + CallByteMethod, + CallByteMethodV, + CallByteMethodA, + CallCharMethod, + CallCharMethodV, + CallCharMethodA, + CallShortMethod, + CallShortMethodV, + CallShortMethodA, + CallIntMethod, + CallIntMethodV, + CallIntMethodA, + CallLongMethod, + CallLongMethodV, + CallLongMethodA, + CallFloatMethod, + CallFloatMethodV, + CallFloatMethodA, + CallDoubleMethod, + CallDoubleMethodV, + CallDoubleMethodA, + CallVoidMethod, + CallVoidMethodV, + CallVoidMethodA, + + CallNonvirtualObjectMethod, + CallNonvirtualObjectMethodV, + CallNonvirtualObjectMethodA, + CallNonvirtualBooleanMethod, + CallNonvirtualBooleanMethodV, + CallNonvirtualBooleanMethodA, + CallNonvirtualByteMethod, + CallNonvirtualByteMethodV, + CallNonvirtualByteMethodA, + CallNonvirtualCharMethod, + CallNonvirtualCharMethodV, + CallNonvirtualCharMethodA, + CallNonvirtualShortMethod, + CallNonvirtualShortMethodV, + CallNonvirtualShortMethodA, + CallNonvirtualIntMethod, + CallNonvirtualIntMethodV, + CallNonvirtualIntMethodA, + CallNonvirtualLongMethod, + CallNonvirtualLongMethodV, + CallNonvirtualLongMethodA, + CallNonvirtualFloatMethod, + CallNonvirtualFloatMethodV, + CallNonvirtualFloatMethodA, + CallNonvirtualDoubleMethod, + CallNonvirtualDoubleMethodV, + CallNonvirtualDoubleMethodA, + CallNonvirtualVoidMethod, + CallNonvirtualVoidMethodV, + CallNonvirtualVoidMethodA, + + GetFieldID, + + GetObjectField, + GetBooleanField, + GetByteField, + GetCharField, + GetShortField, + GetIntField, + GetLongField, + GetFloatField, + GetDoubleField, + SetObjectField, + SetBooleanField, + SetByteField, + SetCharField, + SetShortField, + SetIntField, + SetLongField, + SetFloatField, + SetDoubleField, + + GetStaticMethodID, + + CallStaticObjectMethod, + CallStaticObjectMethodV, + CallStaticObjectMethodA, + CallStaticBooleanMethod, + CallStaticBooleanMethodV, + CallStaticBooleanMethodA, + CallStaticByteMethod, + CallStaticByteMethodV, + CallStaticByteMethodA, + CallStaticCharMethod, + CallStaticCharMethodV, + CallStaticCharMethodA, + CallStaticShortMethod, + CallStaticShortMethodV, + CallStaticShortMethodA, + CallStaticIntMethod, + CallStaticIntMethodV, + CallStaticIntMethodA, + CallStaticLongMethod, + CallStaticLongMethodV, + CallStaticLongMethodA, + CallStaticFloatMethod, + CallStaticFloatMethodV, + CallStaticFloatMethodA, + CallStaticDoubleMethod, + CallStaticDoubleMethodV, + CallStaticDoubleMethodA, + CallStaticVoidMethod, + CallStaticVoidMethodV, + CallStaticVoidMethodA, + + GetStaticFieldID, + + GetStaticObjectField, + GetStaticBooleanField, + GetStaticByteField, + GetStaticCharField, + GetStaticShortField, + GetStaticIntField, + GetStaticLongField, + GetStaticFloatField, + GetStaticDoubleField, + SetStaticObjectField, + SetStaticBooleanField, + SetStaticByteField, + SetStaticCharField, + SetStaticShortField, + SetStaticIntField, + SetStaticLongField, + SetStaticFloatField, + SetStaticDoubleField, + + NewString, + GetStringLength, + GetStringChars, + ReleaseStringChars, + + NewStringUTF, + GetStringUTFLength, + GetStringUTFChars, + ReleaseStringUTFChars, + + GetArrayLength, + + NewObjectArray, + GetObjectArrayElement, + SetObjectArrayElement, + + NewBooleanArray, + NewByteArray, + NewCharArray, + NewShortArray, + NewIntArray, + NewLongArray, + NewFloatArray, + NewDoubleArray, + + GetBooleanArrayElements, + GetByteArrayElements, + GetCharArrayElements, + GetShortArrayElements, + GetIntArrayElements, + GetLongArrayElements, + GetFloatArrayElements, + GetDoubleArrayElements, + + ReleaseBooleanArrayElements, + ReleaseByteArrayElements, + ReleaseCharArrayElements, + ReleaseShortArrayElements, + ReleaseIntArrayElements, + ReleaseLongArrayElements, + ReleaseFloatArrayElements, + ReleaseDoubleArrayElements, + + GetBooleanArrayRegion, + GetByteArrayRegion, + GetCharArrayRegion, + GetShortArrayRegion, + GetIntArrayRegion, + GetLongArrayRegion, + GetFloatArrayRegion, + GetDoubleArrayRegion, + SetBooleanArrayRegion, + SetByteArrayRegion, + SetCharArrayRegion, + SetShortArrayRegion, + SetIntArrayRegion, + SetLongArrayRegion, + SetFloatArrayRegion, + SetDoubleArrayRegion, + + RegisterNatives, + UnregisterNatives, + + MonitorEnter, + MonitorExit, + + GetJavaVM, + + /* new JNI 1.2 functions */ + + GetStringRegion, + GetStringUTFRegion, + + GetPrimitiveArrayCritical, + ReleasePrimitiveArrayCritical, + + GetStringCritical, + ReleaseStringCritical, + + NewWeakGlobalRef, + DeleteWeakGlobalRef, + + ExceptionCheck, + + /* new JNI 1.4 functions */ + + NewDirectByteBuffer, + GetDirectBufferAddress, + GetDirectBufferCapacity +}; +/* Invocation API Functions ***************************************************/ +/* JNI_GetDefaultJavaVMInitArgs ************************************************ + Returns a default configuration for the Java VM. -/********************************* JNI invocation table ******************************/ +*******************************************************************************/ -struct _JavaVM javaVMTable={ - NULL, - NULL, - NULL, - &DestroyJavaVM, - &AttachCurrentThread, - &DetachCurrentThread, - &GetEnv, - &AttachCurrentThreadAsDaemon -}; +jint JNI_GetDefaultJavaVMInitArgs(void *vm_args) +{ + JavaVMInitArgs *_vm_args; -JavaVM javaVM = &javaVMTable; - - -/********************************* JNI function table ******************************/ - -struct JNI_Table envTable = { - NULL, - NULL, - NULL, - NULL, - &GetVersion, - &DefineClass, - &FindClass, - &FromReflectedMethod, - &FromReflectedField, - &ToReflectedMethod, - &GetSuperclass, - &IsAssignableForm, - &ToReflectedField, - &Throw, - &ThrowNew, - &ExceptionOccurred, - &ExceptionDescribe, - &ExceptionClear, - &FatalError, - &PushLocalFrame, - &PopLocalFrame, - &NewGlobalRef, - &DeleteGlobalRef, - &DeleteLocalRef, - &IsSameObject, - &NewLocalRef, - &EnsureLocalCapacity, - &AllocObject, - &NewObject, - &NewObjectV, - &NewObjectA, - &GetObjectClass, - &IsInstanceOf, - &GetMethodID, - &CallObjectMethod, - &CallObjectMethodV, - &CallObjectMethodA, - &CallBooleanMethod, - &CallBooleanMethodV, - &CallBooleanMethodA, - &CallByteMethod, - &CallByteMethodV, - &CallByteMethodA, - &CallCharMethod, - &CallCharMethodV, - &CallCharMethodA, - &CallShortMethod, - &CallShortMethodV, - &CallShortMethodA, - &CallIntMethod, - &CallIntMethodV, - &CallIntMethodA, - &CallLongMethod, - &CallLongMethodV, - &CallLongMethodA, - &CallFloatMethod, - &CallFloatMethodV, - &CallFloatMethodA, - &CallDoubleMethod, - &CallDoubleMethodV, - &CallDoubleMethodA, - &CallVoidMethod, - &CallVoidMethodV, - &CallVoidMethodA, - &CallNonvirtualObjectMethod, - &CallNonvirtualObjectMethodV, - &CallNonvirtualObjectMethodA, - &CallNonvirtualBooleanMethod, - &CallNonvirtualBooleanMethodV, - &CallNonvirtualBooleanMethodA, - &CallNonvirtualByteMethod, - &CallNonvirtualByteMethodV, - &CallNonvirtualByteMethodA, - &CallNonvirtualCharMethod, - &CallNonvirtualCharMethodV, - &CallNonvirtualCharMethodA, - &CallNonvirtualShortMethod, - &CallNonvirtualShortMethodV, - &CallNonvirtualShortMethodA, - &CallNonvirtualIntMethod, - &CallNonvirtualIntMethodV, - &CallNonvirtualIntMethodA, - &CallNonvirtualLongMethod, - &CallNonvirtualLongMethodV, - &CallNonvirtualLongMethodA, - &CallNonvirtualFloatMethod, - &CallNonvirtualFloatMethodV, - &CallNonvirtualFloatMethodA, - &CallNonvirtualDoubleMethod, - &CallNonvirtualDoubleMethodV, - &CallNonvirtualDoubleMethodA, - &CallNonvirtualVoidMethod, - &CallNonvirtualVoidMethodV, - &CallNonvirtualVoidMethodA, - &GetFieldID, - &GetObjectField, - &GetBooleanField, - &GetByteField, - &GetCharField, - &GetShortField, - &GetIntField, - &GetLongField, - &GetFloatField, - &GetDoubleField, - &SetObjectField, - &SetBooleanField, - &SetByteField, - &SetCharField, - &SetShortField, - &SetIntField, - &SetLongField, - &SetFloatField, - &SetDoubleField, - &GetStaticMethodID, - &CallStaticObjectMethod, - &CallStaticObjectMethodV, - &CallStaticObjectMethodA, - &CallStaticBooleanMethod, - &CallStaticBooleanMethodV, - &CallStaticBooleanMethodA, - &CallStaticByteMethod, - &CallStaticByteMethodV, - &CallStaticByteMethodA, - &CallStaticCharMethod, - &CallStaticCharMethodV, - &CallStaticCharMethodA, - &CallStaticShortMethod, - &CallStaticShortMethodV, - &CallStaticShortMethodA, - &CallStaticIntMethod, - &CallStaticIntMethodV, - &CallStaticIntMethodA, - &CallStaticLongMethod, - &CallStaticLongMethodV, - &CallStaticLongMethodA, - &CallStaticFloatMethod, - &CallStaticFloatMethodV, - &CallStaticFloatMethodA, - &CallStaticDoubleMethod, - &CallStaticDoubleMethodV, - &CallStaticDoubleMethodA, - &CallStaticVoidMethod, - &CallStaticVoidMethodV, - &CallStaticVoidMethodA, - &GetStaticFieldID, - &GetStaticObjectField, - &GetStaticBooleanField, - &GetStaticByteField, - &GetStaticCharField, - &GetStaticShortField, - &GetStaticIntField, - &GetStaticLongField, - &GetStaticFloatField, - &GetStaticDoubleField, - &SetStaticObjectField, - &SetStaticBooleanField, - &SetStaticByteField, - &SetStaticCharField, - &SetStaticShortField, - &SetStaticIntField, - &SetStaticLongField, - &SetStaticFloatField, - &SetStaticDoubleField, - &NewString, - &GetStringLength, - &GetStringChars, - &ReleaseStringChars, - &NewStringUTF, - &GetStringUTFLength, - &GetStringUTFChars, - &ReleaseStringUTFChars, - &GetArrayLength, - &NewObjectArray, - &GetObjectArrayElement, - &SetObjectArrayElement, - &NewBooleanArray, - &NewByteArray, - &NewCharArray, - &NewShortArray, - &NewIntArray, - &NewLongArray, - &NewFloatArray, - &NewDoubleArray, - &GetBooleanArrayElements, - &GetByteArrayElements, - &GetCharArrayElements, - &GetShortArrayElements, - &GetIntArrayElements, - &GetLongArrayElements, - &GetFloatArrayElements, - &GetDoubleArrayElements, - &ReleaseBooleanArrayElements, - &ReleaseByteArrayElements, - &ReleaseCharArrayElements, - &ReleaseShortArrayElements, - &ReleaseIntArrayElements, - &ReleaseLongArrayElements, - &ReleaseFloatArrayElements, - &ReleaseDoubleArrayElements, - &GetBooleanArrayRegion, - &GetByteArrayRegion, - &GetCharArrayRegion, - &GetShortArrayRegion, - &GetIntArrayRegion, - &GetLongArrayRegion, - &GetFloatArrayRegion, - &GetDoubleArrayRegion, - &SetBooleanArrayRegion, - &SetByteArrayRegion, - &SetCharArrayRegion, - &SetShortArrayRegion, - &SetIntArrayRegion, - &SetLongArrayRegion, - &SetFloatArrayRegion, - &SetDoubleArrayRegion, - &RegisterNatives, - &UnregisterNatives, - &MonitorEnter, - &MonitorExit, - &GetJavaVM, - &GetStringRegion, - &GetStringUTFRegion, - &GetPrimitiveArrayCritical, - &ReleasePrimitiveArrayCritical, - &GetStringCritical, - &ReleaseStringCritical, - &NewWeakGlobalRef, - &DeleteWeakGlobalRef, - &ExceptionCheck -}; + _vm_args = (JavaVMInitArgs *) vm_args; + /* GNU classpath currently supports JNI 1.2 */ -JNIEnv env = &envTable; + 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; +} +/* JNI_GetCreatedJavaVMs ******************************************************* + Returns all Java VMs that have been created. Pointers to VMs are written in + the buffer vmBuf in the order they are created. At most bufLen number of + entries will be written. The total number of created VMs is returned in + *nVMs. +*******************************************************************************/ +jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) +{ + log_text("JNI_GetCreatedJavaVMs: IMPLEMENT ME!!!"); -jobject *jni_method_invokeNativeHelper(JNIEnv *env,struct methodinfo *methodID,jobject obj, java_objectarray *params) { - int argcount; - jni_callblock *blk; - jobject ret; - char retT; - jobject retVal; - if (methodID==0) { - exceptionptr = native_new_and_init(class_java_lang_NoSuchMethodError); - return 0; - } - argcount=get_parametercount(methodID); + return 0; +} - if (obj && (!builtin_instanceof((java_objectheader*)obj,methodID->class))) { - (*env)->ThrowNew(env,loader_load(utf_new_char("java/lang/IllegalArgumentException")), - "Object parameter of wrong type in Java_java_lang_reflect_Method_invokeNative"); - return 0; - } +/* JNI_CreateJavaVM ************************************************************ + Loads and initializes a Java VM. The current thread becomes the main thread. + Sets the env argument to the JNI interface pointer of the main thread. - if (argcount>3) { - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - log_text("Too many arguments. invokeNativeHelper does not support that"); - return 0; - } +*******************************************************************************/ - if ( ((!params) && (argcount!=0)) || - (params && (params->header.size!=argcount)) - ) { - exceptionptr = native_new_and_init(loader_load(utf_new_char("java/lang/IllegalArgumentException"))); - return 0; - } +jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args) +{ + JavaVMInitArgs *_vm_args; + _Jv_JNIEnv *env; + localref_table *lrt; + /* get the arguments for the new JVM */ - if (!(methodID->flags & ACC_STATIC) && (!obj)) { - (*env)->ThrowNew(env,loader_load(utf_new_char("java/lang/NullPointerException")), - "Static mismatch in Java_java_lang_reflect_Method_invokeNative"); - return 0; - } + _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) */ - blk = MNEW(jni_callblock, 4 /*argcount+2*/); + env = NEW(_Jv_JNIEnv); - retT=fill_callblock_objA(obj,methodID->descriptor,blk,params); + env->env = &JNI_JNIEnvTable; - 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; - case 'I': { - s4 intVal; - intVal=(s4)asm_calljavafunction2(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Integer"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(I)V")),intVal); - } - break; - case 'B': { - s4 intVal; - intVal=(s4)asm_calljavafunction2(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Byte"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(B)V")),intVal); - } - break; - case 'C': { - s4 intVal; - intVal=(s4)asm_calljavafunction2(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Character"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(C)V")),intVal); - } - break; - case 'S': { - s4 intVal; - intVal=(s4)asm_calljavafunction2(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Short"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(S)V")),intVal); - } + *p_vm = (JavaVM *) &JNI_JavaVMTable; + *p_env = (void *) env; - case 'Z': { - s4 intVal; - intVal=(s4)asm_calljavafunction2(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Boolean"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(Z)V")),intVal); - } - break; - case 'J': { - jlong intVal; - intVal=asm_calljavafunction2long(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Long"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(J)V")),intVal); - } - break; - case 'F': { - jdouble floatVal; - floatVal=asm_calljavafunction2double(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Float"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(F)V")),floatVal); - } - break; - case 'D': { - jdouble floatVal; - floatVal=asm_calljavafunction2double(methodID, - argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - retVal=builtin_new(loader_load(utf_new_char("java/lang/Double"))); - CallVoidMethod(env,retVal, - class_resolvemethod(retVal->vftbl->class, - utf_new_char(""),utf_new_char("(D)V")),floatVal); - } - break; + /* XXX Set the global env variable. Maybe we should do that differently. */ - case 'L': /* fall through */ - case '[': retVal=asm_calljavafunction2(methodID,argcount+1,(argcount+1)*sizeof(jni_callblock),blk); - break; - default: { - /* if this happens the acception has already been set by fill_callblock_objA*/ - MFREE(blk, jni_callblock, 4 /*argcount+2*/); - return (jobject*)0; - } - } - MFREE(blk, jni_callblock, 4 /*argcount+2*/); + _Jv_env = env; - if (exceptionptr) - exceptionptr=native_new_and_init(loader_load(utf_new_char("java/lang/reflect/InvocationTargetException"))); - return retVal; + /* actually create the JVM */ -} + if (!vm_create(_vm_args)) + return -1; + /* setup the local ref table (must be created after vm_create) */ + + lrt = GCNEW(localref_table); + + lrt->capacity = LOCALREFTABLE_CAPACITY; + lrt->used = 0; + lrt->localframes = 1; + lrt->prev = LOCALREFTABLE; + + /* clear the references array (memset is faster then a for-loop) */ + + MSET(lrt->refs, 0, java_objectheader*, LOCALREFTABLE_CAPACITY); + + LOCALREFTABLE = lrt; + + return 0; +} /* @@ -3397,4 +5697,5 @@ jobject *jni_method_invokeNativeHelper(JNIEnv *env,struct methodinfo *methodID,j * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */