// resolve.cc - Code for linking and resolving classes and pool entries.
-/* Copyright (C) 1999 Red Hat, Inc.
+/* Copyright (C) 1999, 2000 Red Hat, Inc.
This file is part of libgcj.
static void throw_class_format_error (char *msg)
__attribute__ ((__noreturn__));
-#define StringClass _CL_Q34java4lang6String
-extern java::lang::Class StringClass;
#define ClassObject _CL_Q34java4lang6Object
extern java::lang::Class ClassObject;
#define ObjectClass _CL_Q34java4lang6Object
have code -- for static constructors. */
for (int i = 0; i < clz->method_count; i++)
{
- _Jv_InterpMethod *imeth = clz->interpreted_methods[i];
+ _Jv_MethodBase *imeth = clz->interpreted_methods[i];
- if (imeth != 0) // it could be abstract or native
+ if ((clz->methods[i].accflags & Modifier::NATIVE) != 0)
{
- clz->methods[i].ncode = imeth->ncode ();
+ // You might think we could use a virtual `ncode' method in
+ // the _Jv_MethodBase and unify the native and non-native
+ // cases. Well, we can't, because we don't allocate these
+ // objects using `new', and thus they don't get a vtable.
+ _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
+ clz->methods[i].ncode = jnim->ncode ();
}
- else
+ else if (imeth != 0) // it could be abstract
{
- if ((clz->methods[i].accflags & Modifier::NATIVE) != 0)
- {
- JvThrow
- (new java::lang::VirtualMachineError
- (JvNewStringLatin1
- ("the interpreter does not support native methods")));
- }
+ _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
+ clz->methods[i].ncode = im->ncode ();
}
}
return;
}
- /* FIXME: native methods for interpreted classes should be handled, I
- * dunno exactly how, but it seems that we should try to find them at
- * this point, and if we fail, try again after <clinit>, since it
- * could have caused additional code to be loaded. Interfaces cannot
- * have native methods (not even for static initialization). */
-
-
/* Now onto the actual job: vtable layout. First, count how many new
methods we have */
int new_method_count = 0;
+ (sizeof (void*) * (vtable_count)));
vtable->clas = clz;
- /* copy super class' vtable entries (index 0 goes unused). */
- memcpy ((void*)&vtable->method[1],
- (void*)&super_class->vtable->method[1],
- sizeof (void*) * super_class->vtable_method_count);
+ {
+ jclass effective_superclass = super_class;
+
+ /* If super_class is abstract or an interface it has no vtable.
+ We need to find a real one... */
+ while (effective_superclass && effective_superclass->vtable == NULL)
+ effective_superclass = effective_superclass->superclass;
+
+ /* copy super class' vtable entries (index 0 goes unused). */
+ if (effective_superclass && effective_superclass->vtable)
+ memcpy ((void*)&vtable->method[1],
+ (void*)&effective_superclass->vtable->method[1],
+ sizeof (void*) * effective_superclass->vtable_method_count);
+ }
/* now, install our own vtable entries, reprise... */
for (int i = 0; i < clz->method_count; i++)
break;
case 'Z':
+ // On some platforms a bool is a byte, on others an int.
+ if (sizeof (jboolean) == sizeof (jbyte))
+ return &ffi_type_sint8;
+ else
+ {
+ JvAssert (sizeof (jbyte) == sizeof (jint));
+ return &ffi_type_sint32;
+ }
+ break;
+
case 'B':
return &ffi_type_sint8;
break;
int arg_count,
jboolean staticp,
ffi_cif *cif,
- ffi_type **arg_types)
+ ffi_type **arg_types,
+ ffi_type **rtype_p)
{
unsigned char *ptr = (unsigned char*) signature->data;
arg_count, rtype, arg_types) != FFI_OK)
throw_internal_error ("ffi_prep_cif failed");
+ if (rtype_p != NULL)
+ *rtype_p = rtype;
+
return item_count;
}
arg_count,
staticp,
&closure->cif,
- &closure->arg_types[0]);
+ &closure->arg_types[0],
+ NULL);
ffi_closure_fun fun;
args_raw_size = ffi_raw_size (&closure->cif);
+ JvAssert ((self->accflags & Modifier::NATIVE) == 0);
+
if ((self->accflags & Modifier::SYNCHRONIZED) != 0)
{
if (staticp)
}
ffi_prep_raw_closure (&closure->closure,
- &closure->cif,
- fun,
- (void*)this);
+ &closure->cif,
+ fun,
+ (void*) this);
self->ncode = (void*)closure;
return self->ncode;
}
+void *
+_Jv_JNIMethod::ncode ()
+{
+ using namespace java::lang::reflect;
+
+ if (self->ncode != 0)
+ return self->ncode;
+
+ jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
+ int arg_count = count_arguments (self->signature, staticp);
+
+ ncode_closure *closure =
+ (ncode_closure*)_Jv_AllocBytesChecked (sizeof (ncode_closure)
+ + arg_count * sizeof (ffi_type*));
+
+ ffi_type *rtype;
+ init_cif (self->signature,
+ arg_count,
+ staticp,
+ &closure->cif,
+ &closure->arg_types[0],
+ &rtype);
+
+ ffi_closure_fun fun;
+
+ args_raw_size = ffi_raw_size (&closure->cif);
+
+ // Initialize the argument types and CIF that represent the actual
+ // underlying JNI function.
+ int extra_args = 1;
+ if ((self->accflags & Modifier::STATIC))
+ ++extra_args;
+ jni_arg_types = (ffi_type **) _Jv_Malloc ((extra_args + arg_count)
+ * sizeof (ffi_type *));
+ int offset = 0;
+ jni_arg_types[offset++] = &ffi_type_pointer;
+ if ((self->accflags & Modifier::STATIC))
+ jni_arg_types[offset++] = &ffi_type_pointer;
+ memcpy (&jni_arg_types[offset], &closure->arg_types[0],
+ arg_count * sizeof (ffi_type *));
+
+ if (ffi_prep_cif (&jni_cif, FFI_DEFAULT_ABI,
+ extra_args + arg_count, rtype,
+ jni_arg_types) != FFI_OK)
+ throw_internal_error ("ffi_prep_cif failed for JNI function");
+
+ JvAssert ((self->accflags & Modifier::NATIVE) != 0);
+
+ // FIXME: for now we assume that all native methods for
+ // interpreted code use JNI.
+ fun = (ffi_closure_fun) &_Jv_JNIMethod::call;
+
+ ffi_prep_raw_closure (&closure->closure,
+ &closure->cif,
+ fun,
+ (void*) this);
+
+ self->ncode = (void *) closure;
+ return self->ncode;
+}
+
+
/* A _Jv_ResolvedMethod is what is put in the constant pool for a
* MethodRef or InterfacemethodRef. */
static _Jv_ResolvedMethod*
arg_count,
staticp,
&result->cif,
- &result->arg_types[0]);
+ &result->arg_types[0],
+ NULL);
result->vtable_index = vtable_index;
result->method = method;