diff options
author | Tom Tromey <tromey@cygnus.com> | 2000-02-04 20:49:27 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2000-02-04 20:49:27 +0000 |
commit | facc279fc19a31c23323ce3eeac869eb14d07bda (patch) | |
tree | f2e35a2ea96bcecfa7499a5ec8161bd2528c22d5 /libjava/jni.cc | |
parent | a89608cbebb11969af54ba5a5354302fab2a0b4b (diff) | |
download | gcc-facc279fc19a31c23323ce3eeac869eb14d07bda.zip gcc-facc279fc19a31c23323ce3eeac869eb14d07bda.tar.gz gcc-facc279fc19a31c23323ce3eeac869eb14d07bda.tar.bz2 |
defineclass.cc (handleMethodsBegin): Allocate _Jv_MethodBase pointers.
* defineclass.cc (handleMethodsBegin): Allocate _Jv_MethodBase
pointers.
(handleMethodsEnd): Fixed error messages. Create a _Jv_JNIMethod
if the method is native.
* resolve.cc (ncode): Don't handle native methods.
(_Jv_JNIMethod::ncode): New method.
(_Jv_PrepareClass): Handle native methods.
* jni.cc (call): Renamed from _Jv_JNI_conversion_call.
Include AbstractMethodError.h.
(add_char): New function.
(mangled_name): Likewise.
* include/java-interp.h (class _Jv_JNIMethod): New class.
(class _Jv_MethodBase): New class.
(class _Jv_InterpMethod): Derive from _Jv_MethodBase.
(_Jv_InterpClass): Changed `interpreted_methods' field to type
`_Jv_MethodBase'.
* include/jvm.h (_Jv_FindSymbolInExecutable): Declare.
* java/lang/natRuntime.cc (libraries_size, libraries_count,
libraries): New globals.
(add_library): New function.
(_Jv_FindSymbolInExecutable): New function.
* java/lang/natClassLoader.cc (initiated_classes, loaded_classes):
Now static.
From-SVN: r31790
Diffstat (limited to 'libjava/jni.cc')
-rw-r--r-- | libjava/jni.cc | 128 |
1 files changed, 119 insertions, 9 deletions
diff --git a/libjava/jni.cc b/libjava/jni.cc index cb72261..da964e1 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -32,6 +32,7 @@ details. */ #include <java/lang/Throwable.h> #include <java/lang/ArrayIndexOutOfBoundsException.h> #include <java/lang/StringIndexOutOfBoundsException.h> +#include <java/lang/AbstractMethodError.h> #include <java/lang/InstantiationException.h> #include <java/lang/NoSuchFieldError.h> #include <java/lang/NoSuchMethodError.h> @@ -1204,15 +1205,101 @@ _Jv_JNI_FromReflectedMethod (JNIEnv *, jobject method) +// Add a character to the buffer, encoding properly. +static void +add_char (char *buf, jchar c, int *here) +{ + if (c == '_') + { + buf[(*here)++] = '_'; + buf[(*here)++] = '1'; + } + else if (c == ';') + { + buf[(*here)++] = '_'; + buf[(*here)++] = '2'; + } + else if (c == '[') + { + buf[(*here)++] = '_'; + buf[(*here)++] = '3'; + } + else if (c == '/') + buf[(*here)++] = '_'; + if ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z')) + buf[(*here)++] = (char) c; + else + { + // "Unicode" character. + buf[(*here)++] = '_'; + buf[(*here)++] = '0'; + for (int i = 0; i < 4; ++i) + { + int val = c & 0x0f; + buf[(*here) + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val); + c >>= 4; + } + *here += 4; + } +} + +// Compute a mangled name for a native function. This computes the +// long name, and also returns an index which indicates where a NUL +// can be placed to create the short name. This function assumes that +// the buffer is large enough for its results. +static void +mangled_name (jclass klass, _Jv_Utf8Const *func_name, + _Jv_Utf8Const *signature, char *buf, int *long_start) +{ + strcpy (buf, "Java_"); + int here = 5; + + // Add fully qualified class name. + jchar *chars = _Jv_GetStringChars (klass->getName ()); + jint len = klass->getName ()->length (); + for (int i = 0; i < len; ++i) + add_char (buf, chars[i], &here); + + // Don't use add_char because we need a literal `_'. + buf[here++] = '_'; + + const unsigned char *fn = (const unsigned char *) func_name->data; + const unsigned char *limit = fn + func_name->length; + for (int i = 0; ; ++i) + { + int ch = UTF8_GET (fn, limit); + if (ch < 0) + break; + add_char (buf, ch, &here); + } + + // This is where the long signature begins. + *long_start = here; + buf[here++] = '_'; + buf[here++] = '_'; + + const unsigned char *sig = (const unsigned char *) signature->data; + limit = sig + signature->length; + JvAssert (signature[0] == '('); + for (int i = 1; ; ++i) + { + int ch = UTF8_GET (sig, limit); + if (ch == ')' || ch < 0) + break; + add_char (buf, ch, &here); + } + + buf[here] = '\0'; +} + // This function is the stub which is used to turn an ordinary (CNI) // method call into a JNI call. void -_Jv_JNI_conversion_call (ffi_cif *cif, - void *ret, - ffi_raw *args, - void *__this) +_Jv_JNIMethod::call (ffi_cif *cif, void *ret, ffi_raw *args, void *__this) { - _Jv_InterpMethod* _this = (_Jv_InterpMethod*)__this; + _Jv_JNIMethod* _this = (_Jv_JNIMethod *) __this; JNIEnv env; _Jv_JNI_LocalFrame *frame @@ -1234,10 +1321,33 @@ _Jv_JNI_conversion_call (ffi_cif *cif, // now we assume a conservative GC, and we assume that the // references are on the stack somewhere. - ffi_raw_call (cif, - NULL, // FIXME: function pointer. - ret, - args); + // We cache the value that we find, of course, but if we don't find + // a value we don't cache that fact -- we might subsequently load a + // library which finds the function in question. + if (_this->function == NULL) + { + char buf[10 + 6 * (_this->self->name->length + + _this->self->signature->length)]; + int long_start; + mangled_name (_this->defining_class, _this->self->name, + _this->self->signature, buf, &long_start); + char c = buf[long_start]; + buf[long_start] = '\0'; + _this->function = _Jv_FindSymbolInExecutable (buf); + if (_this->function == NULL) + { + buf[long_start] = c; + _this->function = _Jv_FindSymbolInExecutable (buf); + if (_this->function == NULL) + { + jstring str = JvNewStringUTF (_this->self->name->data); + JvThrow (new java::lang::AbstractMethodError (str)); + } + } + } + + // The actual call to the JNI function. + ffi_raw_call (cif, (void (*) (...)) _this->function, ret, args); do { |