X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fnative%2Fnative.c;h=37f86f45c72fbd3da3442479f1440b929d0d0271;hb=9f859ad50d3d5d98c185d40b86b2179bc4dc9aeb;hp=82816965772b9f8075f49c13416e48096c0851bb;hpb=7b504fe41b0bc911e92756e4193d76087d602a63;p=cacao.git diff --git a/src/native/native.c b/src/native/native.c index 828169657..37f86f45c 100644 --- a/src/native/native.c +++ b/src/native/native.c @@ -1,9 +1,9 @@ /* src/native/native.c - table of native functions - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006, 2007 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,246 +19,66 @@ 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. - - Contact: cacao@complang.tuwien.ac.at - - Authors: Reinhard Grafl - Roman Obermaisser - Andreas Krall - - Changes: Christian Thalinger - - $Id: native.c 2891 2005-07-04 20:31:45Z twisti $ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ +#include "config.h" + #include +#include -#if !defined(ENABLE_STATICVM) -# include "libltdl/ltdl.h" +#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H) +# include #endif -#include "config.h" -#include "types.h" -#include "cacao/cacao.h" +#include + +#include "vm/types.h" + #include "mm/memory.h" + #include "native/jni.h" #include "native/native.h" -#include "native/include/java_lang_Throwable.h" + +#include "native/vm/nativevm.h" + +#include "threads/lock-common.h" + +#include "toolbox/avl.h" +#include "toolbox/hashtable.h" #include "toolbox/logging.h" + #include "vm/builtin.h" #include "vm/exceptions.h" #include "vm/global.h" -#include "vm/loader.h" -#include "vm/options.h" -#include "vm/resolve.h" #include "vm/stringlocal.h" -#include "vm/tables.h" +#include "vm/vm.h" + #include "vm/jit/asmpart.h" #include "vm/jit/jit.h" +#include "vmcore/loader.h" +#include "vmcore/options.h" +#include "vm/resolve.h" -/* include table of native functions ******************************************/ - -#include "native/include/java_lang_Cloneable.h" -#include "native/include/java_util_Properties.h" -#include "native/include/java_io_InputStream.h" -#include "native/include/java_io_PrintStream.h" - -#include "native/include/gnu_classpath_VMStackWalker.h" -#include "native/include/gnu_classpath_VMSystemProperties.h" -#include "native/include/java_lang_Class.h" -#include "native/include/java_lang_Object.h" -#include "native/include/java_lang_VMClass.h" -#include "native/include/java_lang_VMClassLoader.h" -#include "native/include/java_lang_VMObject.h" -#include "native/include/java_lang_VMRuntime.h" -#include "native/include/java_lang_VMString.h" -#include "native/include/java_lang_VMSystem.h" -#include "native/include/java_lang_VMThread.h" -#include "native/include/java_lang_VMThrowable.h" -#include "native/include/java_lang_reflect_Constructor.h" -#include "native/include/java_lang_reflect_Field.h" -#include "native/include/java_lang_reflect_Proxy.h" -#include "native/include/java_lang_reflect_Method.h" -#include "native/include/java_security_VMAccessController.h" - -#if defined(ENABLE_STATICVM) - -/* these are required to prevent compiler warnings */ - -#include "native/include/java_net_DatagramPacket.h" -#include "native/include/java_net_InetAddress.h" -#include "native/include/java_net_SocketImpl.h" - -#include "native/include/gnu_java_net_PlainDatagramSocketImpl.h" -#include "native/include/gnu_java_net_PlainSocketImpl.h" -#include "native/include/gnu_java_nio_PipeImpl.h" -#include "native/include/gnu_java_nio_channels_FileChannelImpl.h" -#include "native/include/gnu_java_nio_charset_iconv_IconvEncoder.h" -#include "native/include/gnu_java_nio_charset_iconv_IconvDecoder.h" -#include "native/include/java_lang_VMProcess.h" -#include "native/include/java_nio_MappedByteBufferImpl.h" -#include "native/include/java_nio_channels_spi_SelectorProvider.h" - -/* now include the native table */ - -#include "native/nativetable.inc" - -#else /* defined(ENABLE_STATICVM) */ - -/* Ensure that symbols for functions implemented within CACAO are used and */ -/* exported to dlopen. */ - -static functionptr dummynativetable[] = { - (functionptr) Java_gnu_classpath_VMStackWalker_getClassContext, - - (functionptr) Java_gnu_classpath_VMSystemProperties_preInit, - - (functionptr) Java_java_lang_VMClass_isInstance, - (functionptr) Java_java_lang_VMClass_isAssignableFrom, - (functionptr) Java_java_lang_VMClass_isInterface, - (functionptr) Java_java_lang_VMClass_isPrimitive, - (functionptr) Java_java_lang_VMClass_getName, - (functionptr) Java_java_lang_VMClass_getSuperclass, - (functionptr) Java_java_lang_VMClass_getInterfaces, - (functionptr) Java_java_lang_VMClass_getComponentType, - (functionptr) Java_java_lang_VMClass_getModifiers, - (functionptr) Java_java_lang_VMClass_getDeclaringClass, - (functionptr) Java_java_lang_VMClass_getDeclaredClasses, - (functionptr) Java_java_lang_VMClass_getDeclaredFields, - (functionptr) Java_java_lang_VMClass_getDeclaredMethods, - (functionptr) Java_java_lang_VMClass_getDeclaredConstructors, - (functionptr) Java_java_lang_VMClass_getClassLoader, - (functionptr) Java_java_lang_VMClass_forName, - (functionptr) Java_java_lang_VMClass_isArray, - (functionptr) Java_java_lang_VMClass_initialize, - (functionptr) Java_java_lang_VMClass_loadArrayClass, - (functionptr) Java_java_lang_VMClass_throwException, - - (functionptr) Java_java_lang_VMClassLoader_defineClass, - (functionptr) Java_java_lang_VMClassLoader_resolveClass, - (functionptr) Java_java_lang_VMClassLoader_loadClass, - (functionptr) Java_java_lang_VMClassLoader_getPrimitiveClass, - (functionptr) Java_java_lang_VMClassLoader_nativeGetResources, - - (functionptr) Java_java_lang_VMObject_getClass, - (functionptr) Java_java_lang_VMObject_clone, - (functionptr) Java_java_lang_VMObject_notify, - (functionptr) Java_java_lang_VMObject_notifyAll, - (functionptr) Java_java_lang_VMObject_wait, - - (functionptr) Java_java_lang_VMRuntime_availableProcessors, - (functionptr) Java_java_lang_VMRuntime_freeMemory, - (functionptr) Java_java_lang_VMRuntime_totalMemory, - (functionptr) Java_java_lang_VMRuntime_maxMemory, - (functionptr) Java_java_lang_VMRuntime_gc, - (functionptr) Java_java_lang_VMRuntime_runFinalization, - (functionptr) Java_java_lang_VMRuntime_runFinalizationForExit, - (functionptr) Java_java_lang_VMRuntime_traceInstructions, - (functionptr) Java_java_lang_VMRuntime_traceMethodCalls, - (functionptr) Java_java_lang_VMRuntime_runFinalizersOnExit, - (functionptr) Java_java_lang_VMRuntime_exit, - (functionptr) Java_java_lang_VMRuntime_nativeLoad, - (functionptr) Java_java_lang_VMRuntime_mapLibraryName, - - (functionptr) Java_java_lang_VMString_intern, - - (functionptr) Java_java_lang_VMSystem_arraycopy, - (functionptr) Java_java_lang_VMSystem_identityHashCode, - - (functionptr) Java_java_lang_VMThread_start, - (functionptr) Java_java_lang_VMThread_interrupt, - (functionptr) Java_java_lang_VMThread_isInterrupted, - (functionptr) Java_java_lang_VMThread_suspend, - (functionptr) Java_java_lang_VMThread_resume, - (functionptr) Java_java_lang_VMThread_nativeSetPriority, - (functionptr) Java_java_lang_VMThread_nativeStop, - (functionptr) Java_java_lang_VMThread_currentThread, - (functionptr) Java_java_lang_VMThread_yield, - (functionptr) Java_java_lang_VMThread_interrupted, - (functionptr) Java_java_lang_VMThread_holdsLock, - - (functionptr) Java_java_lang_VMThrowable_fillInStackTrace, - (functionptr) Java_java_lang_VMThrowable_getStackTrace, - - (functionptr) Java_java_lang_reflect_Constructor_getModifiers, - (functionptr) Java_java_lang_reflect_Constructor_constructNative, - - (functionptr) Java_java_lang_reflect_Field_getModifiers, - (functionptr) Java_java_lang_reflect_Field_getType, - (functionptr) Java_java_lang_reflect_Field_get, - (functionptr) Java_java_lang_reflect_Field_getBoolean, - (functionptr) Java_java_lang_reflect_Field_getByte, - (functionptr) Java_java_lang_reflect_Field_getChar, - (functionptr) Java_java_lang_reflect_Field_getShort, - (functionptr) Java_java_lang_reflect_Field_getInt, - (functionptr) Java_java_lang_reflect_Field_getLong, - (functionptr) Java_java_lang_reflect_Field_getFloat, - (functionptr) Java_java_lang_reflect_Field_getDouble, - (functionptr) Java_java_lang_reflect_Field_set, - (functionptr) Java_java_lang_reflect_Field_setBoolean, - (functionptr) Java_java_lang_reflect_Field_setByte, - (functionptr) Java_java_lang_reflect_Field_setChar, - (functionptr) Java_java_lang_reflect_Field_setShort, - (functionptr) Java_java_lang_reflect_Field_setInt, - (functionptr) Java_java_lang_reflect_Field_setLong, - (functionptr) Java_java_lang_reflect_Field_setFloat, - (functionptr) Java_java_lang_reflect_Field_setDouble, - - (functionptr) Java_java_lang_reflect_Proxy_getProxyClass0, - (functionptr) Java_java_lang_reflect_Proxy_getProxyData0, - (functionptr) Java_java_lang_reflect_Proxy_generateProxyClass0, - - (functionptr) Java_java_lang_reflect_Method_getModifiers, - (functionptr) Java_java_lang_reflect_Method_getReturnType, - (functionptr) Java_java_lang_reflect_Method_getParameterTypes, - (functionptr) Java_java_lang_reflect_Method_getExceptionTypes, - (functionptr) Java_java_lang_reflect_Method_invokeNative, - - (functionptr) Java_java_security_VMAccessController_getStack, -}; - -#endif /* defined(ENABLE_STATICVM) */ - - -/************* use classinfo structure as java.lang.Class object **************/ - -bool use_class_as_object(classinfo *c) -{ - if (!c->classvftbl) { - /* is the class loaded */ - if (!c->loaded) { -/* if (!class_load(c)) */ -/* throw_exception_exit(); */ - log_text("use_class_as_object: class_load should not happen"); - assert(0); - } - - /* is the class linked */ - if (!c->linked) - if (!link_class(c)) - return false; - - assert(class_java_lang_Class); +#if defined(ENABLE_JVMTI) +#include "native/jvmti/cacaodbg.h" +#endif - c->header.vftbl = class_java_lang_Class->vftbl; - c->classvftbl = true; - } - return true; -} +/* include table of native functions ******************************************/ +#if defined(WITH_STATIC_CLASSPATH) +# include "native/nativetable.inc" +#endif -/************************** tables for methods ********************************/ -#undef JOWENN_DEBUG -#undef JOWENN_DEBUG1 +/* tables for methods *********************************************************/ -#ifdef ENABLE_STATICVM +#if defined(WITH_STATIC_CLASSPATH) #define NATIVETABLESIZE (sizeof(nativetable)/sizeof(struct nativeref)) /* table for fast string comparison */ @@ -269,201 +89,93 @@ static bool nativecompdone = false; #endif -/* XXX don't define this in a header file!!! */ +/* global variables ***********************************************************/ -static struct nativeCall nativeCalls[] = -{ -#include "nativecalls.inc" -}; +static avl_tree_t *tree_native_methods; -#define NATIVECALLSSIZE (sizeof(nativeCalls) / sizeof(struct nativeCall)) +#if defined(ENABLE_LTDL) +static hashtable *hashtable_library; +#endif -struct nativeCompCall nativeCompCalls[NATIVECALLSSIZE]; +/* prototypes *****************************************************************/ -/* global variables ***********************************************************/ - -#if !defined(ENABLE_STATICVM) -static hashtable library_hash; -static lt_dlhandle mainhandle; -#endif +static s4 native_tree_native_methods_comparator(const void *treenode, const void *node); -/* native_loadclasses ********************************************************** +/* native_init ***************************************************************** - Load classes required for native methods. + Initializes the native subsystem. *******************************************************************************/ bool native_init(void) { -#if !defined(ENABLE_STATICVM) - void *p; - - /* We need to access the dummy native table, not only to remove a warning */ - /* but to be sure that the table is not optimized away (gcc does this */ - /* since 3.4). */ - - p = &dummynativetable; - +#if defined(ENABLE_LTDL) /* initialize libltdl */ - if (lt_dlinit()) { - /* XXX how can we throw an exception here? */ - log_text(lt_dlerror()); - - return false; - } - - /* get the handle for the main program */ - - if (!(mainhandle = lt_dlopen(NULL))) - return false; + if (lt_dlinit()) + vm_abort("native_init: lt_dlinit failed: %s\n", lt_dlerror()); /* initialize library hashtable, 10 entries should be enough */ - init_hashtable(&library_hash, 10); + hashtable_library = NEW(hashtable); + hashtable_create(hashtable_library, 10); #endif + /* initialize the native methods table */ + + tree_native_methods = avl_create(&native_tree_native_methods_comparator); + /* everything's ok */ return true; } -/* native_library_hash_add ***************************************************** - - Adds an entry to the native library hashtable. - -*******************************************************************************/ - -#if !defined(ENABLE_STATICVM) -void native_library_hash_add(utf *filename, java_objectheader *loader, - lt_dlhandle handle) -{ - library_hash_loader_entry *le; - library_hash_name_entry *ne; /* library name */ - u4 key; /* hashkey */ - u4 slot; /* slot in hashtable */ +/* native_tree_native_methods_comparator *************************************** - /* normally addresses are aligned to 4, 8 or 16 bytes */ + Comparison function for AVL tree of native methods. - key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */ - slot = key & (library_hash.size - 1); - le = library_hash.ptr[slot]; + IN: + treenode....node in the tree + node........node to compare with tree-node - /* search external hash chain for the entry */ - - while (le) { - if (le->loader == loader) - break; - - le = le->hashlink; /* next element in external chain */ - } - - /* no loader found? create a new entry */ - - if (!le) { - le = NEW(library_hash_loader_entry); - - le->loader = loader; - le->namelink = NULL; - - /* insert entry into hashtable */ - - le->hashlink = (library_hash_loader_entry *) library_hash.ptr[slot]; - library_hash.ptr[slot] = le; - - /* update number of hashtable-entries */ - - library_hash.entries++; - } - - - /* search for library name */ - - ne = le->namelink; - - while (ne) { - if (ne->name == filename) - return; - - ne = ne->hashlink; /* next element in external chain */ - } - - /* not found? add the library name to the classloader */ - - ne = NEW(library_hash_name_entry); - - ne->name = filename; - ne->handle = handle; - - /* insert entry into external chain */ - - ne->hashlink = le->namelink; - le->namelink = ne; -} -#endif /* !defined(ENABLE_STATICVM) */ - - -/* native_findfunction ********************************************************* - - Looks up a method (must have the same class name, method name, - descriptor and 'static'ness) and returns a function pointer to it. - Returns: function pointer or NULL (if there is no such method) - - Remark: For faster operation, the names/descriptors are converted - from C strings to Unicode the first time this function is called. + RETURN VALUE: + -1, 0, +1 *******************************************************************************/ -#if defined(ENABLE_STATICVM) -functionptr native_findfunction(utf *cname, utf *mname, utf *desc, - bool isstatic) +static s4 native_tree_native_methods_comparator(const void *treenode, const void *node) { - /* entry of table for fast string comparison */ - struct nativecompref *n; - s4 i; + const native_methods_node_t *treenmn; + const native_methods_node_t *nmn; - isstatic = isstatic ? true : false; - - if (!nativecompdone) { - for (i = 0; i < NATIVETABLESIZE; i++) { - nativecomptable[i].classname = - utf_new_char(nativetable[i].classname); - - nativecomptable[i].methodname = - utf_new_char(nativetable[i].methodname); - - nativecomptable[i].descriptor = - utf_new_char(nativetable[i].descriptor); - - nativecomptable[i].isstatic = nativetable[i].isstatic; - nativecomptable[i].func = nativetable[i].func; - } + treenmn = treenode; + nmn = node; - nativecompdone = true; - } + /* these are for walking the tree */ - for (i = 0; i < NATIVETABLESIZE; i++) { - n = &(nativecomptable[i]); + if (treenmn->classname < nmn->classname) + return -1; + else if (treenmn->classname > nmn->classname) + return 1; - if (cname == n->classname && mname == n->methodname && - desc == n->descriptor && isstatic == n->isstatic) - return n->func; - } + if (treenmn->name < nmn->name) + return -1; + else if (treenmn->name > nmn->name) + return 1; - - /* no function was found, throw exception */ + if (treenmn->descriptor < nmn->descriptor) + return -1; + else if (treenmn->descriptor > nmn->descriptor) + return 1; - *exceptionptr = - new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError, - mname); + /* all pointers are equal, we have found the entry */ - return NULL; + return 0; } -#endif /* defined(ENABLE_STATICVM) */ /* native_make_overloaded_function ********************************************* @@ -472,17 +184,23 @@ functionptr native_findfunction(utf *cname, utf *mname, utf *desc, *******************************************************************************/ -#if !defined(ENABLE_STATICVM) -static char *native_make_overloaded_function(char *name, utf *desc) +#if !defined(WITH_STATIC_CLASSPATH) +static utf *native_make_overloaded_function(utf *name, utf *descriptor) { char *newname; s4 namelen; char *utf_ptr; u2 c; s4 i; + s4 dumpsize; + utf *u; - utf_ptr = desc->text; - namelen = strlen(name) + strlen("__") + strlen("0"); + /* mark memory */ + + dumpsize = dump_size(); + + utf_ptr = descriptor->text; + namelen = strlen(name->text) + strlen("__") + strlen("0"); /* calculate additional length */ @@ -514,15 +232,14 @@ static char *native_make_overloaded_function(char *name, utf *desc) } } - /* reallocate memory */ - i = strlen(name); + i = strlen(name->text); newname = DMNEW(char, namelen); - MCOPY(newname, name, char, i); + MCOPY(newname, name->text, char, i); - utf_ptr = desc->text; + utf_ptr = descriptor->text; newname[i++] = '_'; newname[i++] = '_'; @@ -566,715 +283,677 @@ static char *native_make_overloaded_function(char *name, utf *desc) newname[i] = '\0'; - return newname; + /* make a utf-string */ + + u = utf_new_char(newname); + + /* release memory */ + + dump_release(dumpsize); + + return u; } -/* native_resolve_function ***************************************************** +/* native_insert_char ********************************************************** - Resolves a native function, maybe from a dynamic library. + Inserts the passed UTF character into the native method name. If + necessary it is escaped properly. *******************************************************************************/ -functionptr native_resolve_function(methodinfo *m) +static s4 native_insert_char(char *name, u4 pos, u2 c) { - lt_ptr sym; - char *name; - char *newname; - s4 namelen; - char *utf_ptr; - char *utf_endptr; - s4 dumpsize; - library_hash_loader_entry *le; - library_hash_name_entry *ne; - u4 key; /* hashkey */ - u4 slot; /* slot in hashtable */ - u4 i; + s4 val; + s4 i; + switch (c) { + case '/': + case '.': + /* replace '/' or '.' with '_' */ + name[pos] = '_'; + break; - /* verbose output */ + case '_': + /* escape sequence for '_' is '_1' */ + name[pos] = '_'; + name[++pos] = '1'; + break; + + case ';': + /* escape sequence for ';' is '_2' */ + name[pos] = '_'; + name[++pos] = '2'; + break; + + case '[': + /* escape sequence for '[' is '_1' */ + name[pos] = '_'; + name[++pos] = '3'; + break; + + default: + if (isalnum(c)) + name[pos] = c; + else { + /* unicode character */ + name[pos] = '_'; + name[++pos] = '0'; + + for (i = 0; i < 4; ++i) { + val = c & 0x0f; + name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val); + c >>= 4; + } - if (opt_verbosejni) { - printf("[Dynamic-linking native method "); - utf_display_classname(m->class->name); - printf("."); - utf_display(m->name); - printf(" ... "); + pos += 4; + } + break; } - - /* calculate length of native function name */ - namelen = strlen("Java_") + utf_strlen(m->class->name) + strlen("_") + - utf_strlen(m->name) + strlen("0"); + /* return the new buffer index */ - /* check for underscores in class name */ + return pos; +} - utf_ptr = m->class->name->text; - utf_endptr = UTF_END(m->class->name); - while (utf_ptr < utf_endptr) - if (utf_nextu2(&utf_ptr) == '_') - namelen++; +/* native_method_symbol ******************************************************** - /* check for underscores in method name */ + Generate a method-symbol string out of the class name and the + method name. - utf_ptr = m->name->text; - utf_endptr = UTF_END(m->name); +*******************************************************************************/ - while (utf_ptr < utf_endptr) - if (utf_nextu2(&utf_ptr) == '_') - namelen++; +static utf *native_method_symbol(utf *classname, utf *methodname) +{ + char *name; + s4 namelen; + char *utf_ptr; + char *utf_endptr; + u2 c; + u4 pos; + s4 dumpsize; + utf *u; - /* allocate memory */ + /* mark memory */ dumpsize = dump_size(); - name = DMNEW(char, namelen); - - - /* generate name of native functions */ + /* Calculate length of native function name. We multiply the + class and method name length by 6 as this is the maxium + escape-sequence that can be generated (unicode). */ - strcpy(name, "Java_"); - i = strlen("Java_"); + namelen = + strlen("Java_") + + utf_get_number_of_u2s(classname) * 6 + + strlen("_") + + utf_get_number_of_u2s(methodname) * 6 + + strlen("0"); - utf_ptr = m->class->name->text; - utf_endptr = UTF_END(m->class->name); + /* allocate memory */ - for (; utf_ptr < utf_endptr; utf_ptr++, i++) { - name[i] = *utf_ptr; + name = DMNEW(char, namelen); - /* escape sequence for '_' is '_1' */ + /* generate name of native functions */ - if (name[i] == '_') - name[++i] = '1'; + strcpy(name, "Java_"); + pos = strlen("Java_"); - /* replace '/' with '_' */ + utf_ptr = classname->text; + utf_endptr = UTF_END(classname); - if (name[i] == '/') - name[i] = '_'; + for (; utf_ptr < utf_endptr; utf_ptr++, pos++) { + c = *utf_ptr; + pos = native_insert_char(name, pos, c); } /* seperator between class and method */ - name[i++] = '_'; + name[pos++] = '_'; - utf_ptr = m->name->text; - utf_endptr = UTF_END(m->name); + utf_ptr = methodname->text; + utf_endptr = UTF_END(methodname); - for (; utf_ptr < utf_endptr; utf_ptr++, i++) { - name[i] = *utf_ptr; - - /* escape sequence for '_' is '_1' */ - - if (name[i] == '_') - name[++i] = '1'; + for (; utf_ptr < utf_endptr; utf_ptr++, pos++) { + c = *utf_ptr; + pos = native_insert_char(name, pos, c); } /* close string */ - name[i] = '\0'; + name[pos] = '\0'; + /* check for an buffer overflow */ - /* check the library hash entries of the classloader of the methods's */ - /* class */ + assert(pos <= namelen); - sym = NULL; + /* make a utf-string */ - /* normally addresses are aligned to 4, 8 or 16 bytes */ + u = utf_new_char(name); + + /* release memory */ - key = ((u4) (ptrint) m->class->classloader) >> 4; /* align to 16-byte */ - slot = key & (library_hash.size - 1); - le = library_hash.ptr[slot]; + dump_release(dumpsize); - /* iterate through loaders in this hash slot */ + return u; +} - while (le && !sym) { - /* iterate through names in this loader */ - ne = le->namelink; - - while (ne && !sym) { - sym = lt_dlsym(ne->handle, name); +/* native_method_register ****************************************************** - if (!sym) - sym = lt_dlsym(ne->handle, newname); + Register a native method in the native method table. - ne = ne->hashlink; +*******************************************************************************/ + +void native_method_register(utf *classname, const JNINativeMethod *methods, + int32_t count) +{ + native_methods_node_t *nmn; + utf *name; + utf *descriptor; + int32_t i; + + /* insert all methods passed */ + + for (i = 0; i < count; i++) { + if (opt_verbosejni) { + printf("[Registering JNI native method "); + utf_display_printable_ascii_classname(classname); + printf(".%s]\n", methods[i].name); } - le = le->hashlink; - } + /* generate the utf8 names */ - if (sym) - if (opt_verbosejni) - printf("JNI ]\n"); + name = utf_new_char(methods[i].name); + descriptor = utf_new_char(methods[i].signature); + /* allocate a new tree node */ - /* if not found, try to find the native function symbol in the main */ - /* program */ + nmn = NEW(native_methods_node_t); - if (!sym) { - sym = lt_dlsym(mainhandle, name); + nmn->classname = classname; + nmn->name = name; + nmn->descriptor = descriptor; + nmn->function = (functionptr) (ptrint) methods[i].fnPtr; - if (!sym) { - /* we didn't find the symbol yet, try to resolve an overloaded */ - /* function (having the types in it's name) */ + /* insert the method into the tree */ - newname = native_make_overloaded_function(name, m->descriptor); + avl_insert(tree_native_methods, nmn); + } +} - /* try to find the overloaded symbol */ - sym = lt_dlsym(mainhandle, newname); - } +/* native_method_find ********************************************************** - if (sym) - if (opt_verbosejni) - printf("internal ]\n"); - } + Find a native method in the native method table. +*******************************************************************************/ - /* no symbol found? throw exception */ +static functionptr native_method_find(methodinfo *m) +{ + native_methods_node_t tmpnmn; + native_methods_node_t *nmn; - if (!sym) - *exceptionptr = - new_exception_utfmessage(string_java_lang_UnsatisfiedLinkError, - m->name); + /* fill the temporary structure used for searching the tree */ - /* release memory */ + tmpnmn.classname = m->class->name; + tmpnmn.name = m->name; + tmpnmn.descriptor = m->descriptor; - dump_release(dumpsize); + /* find the entry in the AVL-tree */ + + nmn = avl_find(tree_native_methods, &tmpnmn); + + if (nmn == NULL) + return NULL; - return (functionptr) (ptrint) sym; + return nmn->function; } -#endif /* !defined(ENABLE_STATICVM) */ -/****************** function class_findfield_approx **************************** - - searches in 'classinfo'-structure for a field with the - specified name +/* native_library_open ********************************************************* + + Open a native library with the given utf8 name. *******************************************************************************/ - -fieldinfo *class_findfield_approx(classinfo *c, utf *name) + +#if defined(ENABLE_LTDL) +lt_dlhandle native_library_open(utf *filename) { - s4 i; + lt_dlhandle handle; - for (i = 0; i < c->fieldscount; i++) { - /* compare field names */ - if ((c->fields[i].name == name)) - return &(c->fields[i]); + if (opt_verbosejni) { + printf("[Loading native library "); + utf_display_printable_ascii(filename); + printf(" ... "); } - /* field was not found, raise exception */ - *exceptionptr = new_exception(string_java_lang_NoSuchFieldException); + /* try to open the library */ - return NULL; -} + handle = lt_dlopen(filename->text); + if (handle == NULL) { + if (opt_verbose) { + log_start(); + log_print("native_library_load: lt_dlopen failed: "); + log_print(lt_dlerror()); + log_finish(); + } -s4 class_findfield_index_approx(classinfo *c, utf *name) -{ - s4 i; - - for (i = 0; i < c->fieldscount; i++) { - /* compare field names */ - if ((c->fields[i].name == name)) - return i; + return NULL; } - /* field was not found, raise exception */ - *exceptionptr = new_exception(string_java_lang_NoSuchFieldException); - - return -1; + return handle; } +#endif -/* native_new_and_init ********************************************************* +/* native_library_add ********************************************************** + + Adds an entry to the native library hashtable. - Creates a new object on the heap and calls the initializer. - Returns the object pointer or NULL if memory is exhausted. - *******************************************************************************/ -java_objectheader *native_new_and_init(classinfo *c) +#if defined(ENABLE_LTDL) +void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle) { - methodinfo *m; - java_objectheader *o; - - if (!c) - return *exceptionptr; - - /* create object */ + hashtable_library_loader_entry *le; + hashtable_library_name_entry *ne; /* library name */ + u4 key; /* hashkey */ + u4 slot; /* slot in hashtable */ - o = builtin_new(c); - - if (!o) - return NULL; + LOCK_MONITOR_ENTER(hashtable_library->header); - /* find initializer */ + /* normally addresses are aligned to 4, 8 or 16 bytes */ - m = class_findmethod(c, utf_init, utf_void__void); - - /* initializer not found */ + key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */ + slot = key & (hashtable_library->size - 1); + le = hashtable_library->ptr[slot]; - if (!m) - return o; + /* search external hash chain for the entry */ - /* call initializer */ + while (le) { + if (le->loader == loader) + break; - asm_calljavafunction(m, o, NULL, NULL, NULL); + le = le->hashlink; /* next element in external chain */ + } - return o; -} + /* no loader found? create a new entry */ + if (le == NULL) { + le = NEW(hashtable_library_loader_entry); -java_objectheader *native_new_and_init_string(classinfo *c, java_lang_String *s) -{ - methodinfo *m; - java_objectheader *o; + le->loader = loader; + le->namelink = NULL; - if (!c) - return *exceptionptr; + /* insert entry into hashtable */ - /* create object */ + le->hashlink = + (hashtable_library_loader_entry *) hashtable_library->ptr[slot]; + hashtable_library->ptr[slot] = le; - o = builtin_new(c); + /* update number of hashtable-entries */ - if (!o) - return NULL; + hashtable_library->entries++; + } - /* find initializer */ - m = class_resolveclassmethod(c, - utf_init, - utf_java_lang_String__void, - NULL, - true); + /* search for library name */ - /* initializer not found */ + ne = le->namelink; - if (!m) - return NULL; + while (ne) { + if (ne->name == filename) { + LOCK_MONITOR_EXIT(hashtable_library->header); - /* call initializer */ + return; + } - asm_calljavafunction(m, o, s, NULL, NULL); + ne = ne->hashlink; /* next element in external chain */ + } - return o; -} + /* not found? add the library name to the classloader */ + ne = NEW(hashtable_library_name_entry); -java_objectheader *native_new_and_init_int(classinfo *c, s4 i) -{ - methodinfo *m; - java_objectheader *o; + ne->name = filename; + ne->handle = handle; - if (!c) - return *exceptionptr; + /* insert entry into external chain */ - /* create object */ + ne->hashlink = le->namelink; + le->namelink = ne; - o = builtin_new(c); - - if (!o) - return NULL; + LOCK_MONITOR_EXIT(hashtable_library->header); +} +#endif - /* find initializer */ - m = class_resolveclassmethod(c, utf_init, utf_int__void, NULL, true); +/* native_library_find ********************************************************* - /* initializer not found */ + Find an entry in the native library hashtable. - if (!m) - return NULL; +*******************************************************************************/ - /* call initializer */ +#if defined(ENABLE_LTDL) +hashtable_library_name_entry *native_library_find(utf *filename, + classloader *loader) +{ + hashtable_library_loader_entry *le; + hashtable_library_name_entry *ne; /* library name */ + u4 key; /* hashkey */ + u4 slot; /* slot in hashtable */ - asm_calljavafunction(m, o, (void *) (ptrint) i, NULL, NULL); + /* normally addresses are aligned to 4, 8 or 16 bytes */ - return o; -} + key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */ + slot = key & (hashtable_library->size - 1); + le = hashtable_library->ptr[slot]; + /* search external hash chain for the entry */ -java_objectheader *native_new_and_init_throwable(classinfo *c, java_lang_Throwable *t) -{ - methodinfo *m; - java_objectheader *o; + while (le) { + if (le->loader == loader) + break; - if (!c) - return *exceptionptr; + le = le->hashlink; /* next element in external chain */ + } - /* create object */ + /* no loader found? return NULL */ - o = builtin_new(c); - - if (!o) + if (le == NULL) return NULL; - /* find initializer */ - - m = class_findmethod(c, utf_init, utf_java_lang_Throwable__void); - - /* initializer not found */ - - if (!m) - return NULL; + /* search for library name */ - /* call initializer */ + ne = le->namelink; - asm_calljavafunction(m, o, t, NULL, NULL); + while (ne) { + if (ne->name == filename) + return ne; - return o; -} + ne = ne->hashlink; /* next element in external chain */ + } + /* return entry, if no entry was found, ne is NULL */ -void copy_vftbl(vftbl_t **dest, vftbl_t *src) -{ - *dest = src; -#if 0 - /* XXX this kind of copying does not work (in the general - * case). The interface tables would have to be copied, too. I - * don't see why we should make a copy anyway. -Edwin - */ - *dest = mem_alloc(sizeof(vftbl) + sizeof(methodptr)*(src->vftbllength-1)); - memcpy(*dest, src, sizeof(vftbl) - sizeof(methodptr)); - memcpy(&(*dest)->table, &src->table, src->vftbllength * sizeof(methodptr)); -#endif + return ne; } +#endif /* !defined(WITH_STATIC_CLASSPATH) */ -/****************************************************************************************** +/* native_findfunction ********************************************************* - creates method signature (excluding return type) from array of - class-objects representing the parameters of the method + Looks up a method (must have the same class name, method name, + descriptor and 'static'ness) and returns a function pointer to it. + Returns: function pointer or NULL (if there is no such method) -*******************************************************************************************/ + Remark: For faster operation, the names/descriptors are converted + from C strings to Unicode the first time this function is called. +*******************************************************************************/ -utf *create_methodsig(java_objectarray* types, char *retType) +#if defined(WITH_STATIC_CLASSPATH) +functionptr native_findfunction(utf *cname, utf *mname, utf *desc, + bool isstatic) { - char *buffer; /* buffer for building the desciptor */ - char *pos; /* current position in buffer */ - utf *result; /* the method signature */ - u4 buffer_size = 3; /* minimal size=3: room for parenthesis and returntype */ - u4 i, j; - - if (!types) return NULL; - - /* determine required buffer-size */ - for (i = 0; i < types->header.size; i++) { - classinfo *c = (classinfo *) types->data[i]; - buffer_size = buffer_size + c->name->blength + 2; - } - - if (retType) buffer_size += strlen(retType); - - /* allocate buffer */ - buffer = MNEW(char, buffer_size); - pos = buffer; - - /* method-desciptor starts with parenthesis */ - *pos++ = '('; - - for (i = 0; i < types->header.size; i++) { - char ch; - - /* current argument */ - classinfo *c = (classinfo *) types->data[i]; - - /* current position in utf-text */ - char *utf_ptr = c->name->text; - - /* determine type of argument */ - if ((ch = utf_nextu2(&utf_ptr)) == '[') { - /* arrayclass */ - for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) { - *pos++ = *utf_ptr; /* copy text */ - } - - } else { - /* check for primitive types */ - for (j = 0; j < PRIMITIVETYPE_COUNT; j++) { - char *utf_pos = utf_ptr - 1; - char *primitive = primitivetype_table[j].wrapname; - - /* compare text */ - while (utf_pos < UTF_END(c->name)) { - if (*utf_pos++ != *primitive++) goto nomatch; - } + /* entry of table for fast string comparison */ + struct nativecompref *n; + s4 i; - /* primitive type found */ - *pos++ = primitivetype_table[j].typesig; - goto next_type; + isstatic = isstatic ? true : false; + + if (!nativecompdone) { + for (i = 0; i < NATIVETABLESIZE; i++) { + nativecomptable[i].classname = + utf_new_char(nativetable[i].classname); - nomatch: - ; - } + nativecomptable[i].methodname = + utf_new_char(nativetable[i].methodname); - /* no primitive type and no arrayclass, so must be object */ - *pos++ = 'L'; + nativecomptable[i].descriptor = + utf_new_char(nativetable[i].descriptor); - /* copy text */ - for (utf_ptr--; utf_ptr < UTF_END(c->name); utf_ptr++) { - *pos++ = *utf_ptr; - } + nativecomptable[i].isstatic = nativetable[i].isstatic; + nativecomptable[i].func = nativetable[i].func; + } - *pos++ = ';'; + nativecompdone = true; + } - next_type: - ; - } - } + for (i = 0; i < NATIVETABLESIZE; i++) { + n = &(nativecomptable[i]); - *pos++ = ')'; + if (cname == n->classname && mname == n->methodname && + desc == n->descriptor && isstatic == n->isstatic) + return n->func; + } - if (retType) { - for (i = 0; i < strlen(retType); i++) { - *pos++ = retType[i]; - } - } + /* no function was found, throw exception */ - /* create utf-string */ - result = utf_new(buffer, (pos - buffer)); - MFREE(buffer, char, buffer_size); + exceptions_throw_unsatisfiedlinkerror(mname); - return result; + return NULL; } +#endif /* defined(WITH_STATIC_CLASSPATH) */ -/* native_get_parametertypes *************************************************** +/* native_resolve_function ***************************************************** - Use the descriptor of a method to generate a java/lang/Class array - which contains the classes of the parametertypes of the method. + Resolves a native function, maybe from a dynamic library. *******************************************************************************/ -java_objectarray *native_get_parametertypes(methodinfo *m) +functionptr native_resolve_function(methodinfo *m) { - methoddesc *md; - typedesc *paramtypes; - s4 paramcount; - java_objectarray *oa; - s4 i; + classloader *cl; + utf *name; + utf *newname; + functionptr f; +#if defined(ENABLE_LTDL) + hashtable_library_loader_entry *le; + hashtable_library_name_entry *ne; + u4 key; /* hashkey */ + u4 slot; /* slot in hashtable */ +#endif +#if defined(WITH_CLASSPATH_SUN) + methodinfo *method_findNative; + java_handle_t *s; +#endif - md = m->parseddesc; + cl = m->class->classloader; - /* is the descriptor fully parsed? */ + /* verbose output */ - if (!m->parseddesc->params) - if (!descriptor_params_from_paramtypes(md, m->flags)) - return NULL; + if (opt_verbosejni) { + printf("[Dynamic-linking native method "); + utf_display_printable_ascii_classname(m->class->name); + printf("."); + utf_display_printable_ascii(m->name); + printf(" ... "); + } - paramtypes = md->paramtypes; - paramcount = md->paramcount; + /* generate method symbol string */ - /* skip `this' pointer */ + name = native_method_symbol(m->class->name, m->name); - if (!(m->flags & ACC_STATIC)) { - paramtypes++; - paramcount--; - } + /* generate overloaded function (having the types in it's name) */ - /* create class-array */ + newname = native_make_overloaded_function(name, m->descriptor); - oa = builtin_anewarray(paramcount, class_java_lang_Class); + /* check the library hash entries of the classloader of the + methods's class */ - if (!oa) - return NULL; + f = NULL; - /* get classes */ +#if defined(ENABLE_LTDL) + /* normally addresses are aligned to 4, 8 or 16 bytes */ - for (i = 0; i < paramcount; i++) { - if (!resolve_class_from_typedesc(¶mtypes[i], true, false, - (classinfo **) &oa->data[i])) - return NULL; + key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */ + slot = key & (hashtable_library->size - 1); + le = hashtable_library->ptr[slot]; + + /* iterate through loaders in this hash slot */ + + while ((le != NULL) && (f == NULL)) { + /* iterate through names in this loader */ + + ne = le->namelink; + + while ((ne != NULL) && (f == NULL)) { + f = (functionptr) (ptrint) lt_dlsym(ne->handle, name->text); + + if (f == NULL) + f = (functionptr) (ptrint) lt_dlsym(ne->handle, newname->text); + + ne = ne->hashlink; + } - use_class_as_object((classinfo *) oa->data[i]); + le = le->hashlink; } - return oa; -} +# if defined(WITH_CLASSPATH_SUN) + if (f == NULL) { + /* We can resolve the function directly from + java.lang.ClassLoader as it's a static function. */ + /* XXX should be done in native_init */ + method_findNative = + class_resolveclassmethod(class_java_lang_ClassLoader, + utf_findNative, + utf_java_lang_ClassLoader_java_lang_String__J, + class_java_lang_ClassLoader, + true); -/* native_get_exceptiontypes *************************************************** + if (method_findNative == NULL) + return NULL; - Get the exceptions which can be thrown by a method. + /* try the normal name */ -*******************************************************************************/ + s = javastring_new(name); -java_objectarray *native_get_exceptiontypes(methodinfo *m) -{ - u2 excount; - java_objectarray *oa; - classinfo *c; - u2 i; + f = (functionptr) (intptr_t) vm_call_method_long(method_findNative, + NULL, cl, s); - /* create class-array */ + /* if not found, try the mangled name */ - oa = builtin_anewarray(excount, class_java_lang_Class); + if (f == NULL) { + s = javastring_new(newname); - if (!oa) - return NULL; + f = (functionptr) (intptr_t) vm_call_method_long(method_findNative, + NULL, cl, s); + } + } +# endif - /* get exceptions */ + if (f != NULL) + if (opt_verbosejni) + printf("JNI ]\n"); +#endif - excount = m->thrownexceptionscount; + /* If not found, try to find the native function symbol in the + main program. */ - for (i = 0; i < excount; i++) { - if (!resolve_classref_or_classinfo(NULL, m->thrownexceptions[i], - resolveEager, true, false, &c)) - return NULL; + if (f == NULL) { + f = native_method_find(m); - use_class_as_object(c); + if (f != NULL) + if (opt_verbosejni) + printf("internal ]\n"); + } - oa->data[i] = (java_objectheader *) c; - } +#if defined(ENABLE_JVMTI) + /* fire Native Method Bind event */ + if (jvmti) jvmti_NativeMethodBind(m, f, &f); +#endif - return oa; -} + /* no symbol found? throw exception */ + + if (f == NULL) { + if (opt_verbosejni) + printf("failed ]\n"); + exceptions_throw_unsatisfiedlinkerror(m->name); + } -/* native_get_returntype ******************************************************* + return f; +} +#endif /* !defined(WITH_STATIC_CLASSPATH) */ - Get the returntype class of a method. +/* native_new_and_init ********************************************************* + + Creates a new object on the heap and calls the initializer. + Returns the object pointer or NULL if memory is exhausted. + *******************************************************************************/ -classinfo *native_get_returntype(methodinfo *m) +java_handle_t *native_new_and_init(classinfo *c) { - classinfo *c; - - if (!resolve_class_from_typedesc(&(m->parseddesc->returntype), true, false, - &c)) - return NULL; + methodinfo *m; + java_handle_t *o; - use_class_as_object(c); + if (c == NULL) + vm_abort("native_new_and_init: c == NULL"); - return c; -} + /* create object */ + o = builtin_new(c); + + if (o == NULL) + return NULL; -/*****************************************************************************/ -/*****************************************************************************/ + /* try to find the initializer */ + m = class_findmethod(c, utf_init, utf_void__void); + + /* ATTENTION: returning the object here is ok, since the class may + not have an initializer */ -/*--------------------------------------------------------*/ -void printNativeCall(nativeCall nc) { - int i,j; + if (m == NULL) + return o; - printf("\n%s's Native Methods call:\n",nc.classname); fflush(stdout); - for (i=0; iaCalled = %s %s %s\n",i,j, - nc.methods[i].methodCalls[j].classname, - nc.methods[i].methodCalls[j].methodname, - nc.methods[i].methodCalls[j].descriptor);fflush(stdout); - } - } - printf("-+++++--------------------\n");fflush(stdout); -} + (void) vm_call_method(m, o); -/*--------------------------------------------------------*/ -void printCompNativeCall(nativeCompCall nc) { - int i,j; - printf("printCompNativeCall BEGIN\n");fflush(stdout); - printf("\n%s's Native Comp Methods call:\n",nc.classname->text);fflush(stdout); - utf_display(nc.classname); fflush(stdout); - - for (i=0; itext,nc.methods[i].descriptor->text);fflush(stdout); - utf_display(nc.methods[i].methodname); fflush(stdout); - utf_display(nc.methods[i].descriptor);fflush(stdout); - printf("\n");fflush(stdout); - - for (j=0; jbCalled = ",i,j);fflush(stdout); - utf_display(nc.methods[i].methodCalls[j].classname);fflush(stdout); - utf_display(nc.methods[i].methodCalls[j].methodname); fflush(stdout); - utf_display(nc.methods[i].methodCalls[j].descriptor);fflush(stdout); - printf("\n");fflush(stdout); - } - } -printf("---------------------\n");fflush(stdout); + return o; } -/*--------------------------------------------------------*/ -classMeth findNativeMethodCalls(utf *c, utf *m, utf *d ) +java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s) { - int i = 0; - int j = 0; - int cnt = 0; - classMeth mc; - mc.i_class = i; - mc.j_method = j; - mc.methCnt = cnt; - - return mc; -} + methodinfo *m; + java_handle_t *o; -/*--------------------------------------------------------*/ -nativeCall* findNativeClassCalls(char *aclassname ) { -int i; + if (c == NULL) + vm_abort("native_new_and_init_string: c == NULL"); -for (i=0;iclassname = utf_new_char(nc.classname); - ncc->methCnt = nc.methCnt; - - for (i=0; imethods[i].methodname = utf_new_char(nc.methods[i].methodname); - ncc->methods[i].descriptor = utf_new_char(nc.methods[i].descriptor); - ncc->callCnt[i] = nc.callCnt[i]; - - for (j=0; jmethods[i].methodCalls[j].classname = utf_new_char(nc.methods[i].methodCalls[j].classname); - - if (strcmp("", nc.methods[i].methodCalls[j].methodname) != 0) { - ncc->methods[i].methodCalls[j].methodname = utf_new_char(nc.methods[i].methodCalls[j].methodname); - ncc->methods[i].methodCalls[j].descriptor = utf_new_char(nc.methods[i].methodCalls[j].descriptor); - } - else { - ncc->methods[i].methodCalls[j].methodname = NULL; - ncc->methods[i].methodCalls[j].descriptor = NULL; - } - } - } -} + o = builtin_new(c); + + if (o == NULL) + return NULL; + /* find initializer */ + m = class_findmethod(c, utf_init, utf_java_lang_String__void); -/*--------------------------------------------------------*/ + /* initializer not found */ -bool natcall2utf(bool natcallcompdone) { -int i; + if (m == NULL) + return NULL; -if (natcallcompdone) - return true; + /* call initializer */ -for (i=0;i