#include <stdio.h>
+#ifdef USE_LIBFFI
+#include <ffi.h>
+#endif
+
#include <java-interp.h>
+// Set GC_DEBUG before including gc.h!
+#ifdef LIBGCJ_GC_DEBUG
+# define GC_DEBUG
+#endif
+#include <gc.h>
+
#include <jvm.h>
#include <gcj/cni.h>
#include <string.h>
// pass in the descriptor and check that way, because when
// the field is already resolved there is no easy way to
// find its descriptor again.
- if ( (field->isResolved () ?
- _Jv_equalUtf8Classnames (type_name, field->type->name) :
- _Jv_equalUtf8Classnames (
- type_name, (_Jv_Utf8Const *) field->type)) )
+ if ((field->isResolved ()
+ ? _Jv_equalUtf8Classnames (type_name, field->type->name)
+ : _Jv_equalUtf8Classnames (type_name,
+ (_Jv_Utf8Const *) field->type)))
{
*declarer = search;
return field;
{
using namespace java::lang::reflect;
+ if (GC_base (klass) && klass->constants.data
+ && ! GC_base (klass->constants.data))
+ {
+ jsize count = klass->constants.size;
+ if (count)
+ {
+ _Jv_word* constants
+ = (_Jv_word*) _Jv_AllocRawObj (count * sizeof (_Jv_word));
+ memcpy ((void*)constants,
+ (void*)klass->constants.data,
+ count * sizeof (_Jv_word));
+ klass->constants.data = constants;
+ }
+ }
+
_Jv_Constants *pool = &klass->constants;
if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
throw new java::lang::NoSuchMethodError (sb->toString());
}
- int vtable_index = -1;
- if (pool->tags[index] != JV_CONSTANT_InterfaceMethodref)
- vtable_index = (jshort)the_method->index;
-
pool->data[index].rmethod
= klass->engine->resolve_method(the_method,
found_class,
((the_method->accflags
- & Modifier::STATIC) != 0),
- vtable_index);
+ & Modifier::STATIC) != 0));
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
}
break;
#define INITIAL_IOFFSETS_LEN 4
#define INITIAL_IFACES_LEN 4
-static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };
+static _Jv_IDispatchTable null_idt = {SHRT_MAX, 0, {}};
// Generate tables for constant-time assignment testing and interface
// method lookup. This implements the technique described by Per Bothner
return;
}
- klass->idt =
- (_Jv_IDispatchTable *) _Jv_AllocRawObj (sizeof (_Jv_IDispatchTable));
-
_Jv_ifaces ifaces;
ifaces.count = 0;
ifaces.len = INITIAL_IFACES_LEN;
{
// The classes pointed to by the itable will always be reachable
// via other paths.
- klass->idt->cls.itable =
- (void **) _Jv_AllocBytes (itable_size * sizeof (void *));
- klass->idt->cls.itable_length = itable_size;
+ int idt_bytes = sizeof (_Jv_IDispatchTable) + (itable_size
+ * sizeof (void *));
+ klass->idt = (_Jv_IDispatchTable *) _Jv_AllocBytes (idt_bytes);
+ klass->idt->itable_length = itable_size;
jshort *itable_offsets =
(jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
for (int i = 0; i < ifaces.count; i++)
{
- ifaces.list[i]->idt->iface.ioffsets[cls_iindex] =
- itable_offsets[i];
+ ifaces.list[i]->ioffsets[cls_iindex] = itable_offsets[i];
}
- klass->idt->cls.iindex = cls_iindex;
+ klass->idt->iindex = cls_iindex;
_Jv_Free (ifaces.list);
_Jv_Free (itable_offsets);
}
else
{
- klass->idt->cls.iindex = SHRT_MAX;
+ klass->idt->iindex = SHRT_MAX;
}
}
result += get_interfaces (klass->interfaces[i], ifaces);
}
}
-
+
if (klass->isInterface())
- result += klass->method_count + 1;
+ {
+ // We want to add 1 plus the number of interface methods here.
+ // But, we take special care to skip <clinit>.
+ ++result;
+ for (int i = 0; i < klass->method_count; ++i)
+ {
+ if (klass->methods[i].name->first() != '<')
+ ++result;
+ }
+ }
else if (klass->superclass)
result += get_interfaces (klass->superclass, ifaces);
return result;
_Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces,
jshort *itable_offsets)
{
- void **itable = klass->idt->cls.itable;
+ void **itable = klass->idt->itable;
jshort itable_pos = 0;
for (int i = 0; i < ifaces->count; i++)
itable_offsets[i] = itable_pos;
itable_pos = append_partial_itable (klass, iface, itable, itable_pos);
- /* Create interface dispatch table for iface */
- if (iface->idt == NULL)
+ /* Create ioffsets table for iface */
+ if (iface->ioffsets == NULL)
{
- iface->idt
- = (_Jv_IDispatchTable *) _Jv_AllocRawObj (sizeof (_Jv_IDispatchTable));
-
// The first element of ioffsets is its length (itself included).
jshort *ioffsets = (jshort *) _Jv_AllocBytes (INITIAL_IOFFSETS_LEN
* sizeof (jshort));
for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++)
ioffsets[i] = -1;
- iface->idt->iface.ioffsets = ioffsets;
+ iface->ioffsets = ioffsets;
}
}
}
void *data)
{
throw new java::lang::NoClassDefFoundError(
- _Jv_NewStringUtf8Const( (_Jv_Utf8Const *) data));
+ _Jv_NewStringUtf8Const((_Jv_Utf8Const *) data));
}
#else
// A variant of the NoClassDefFoundError throwing method that can
// Returns the offset at which the next partial ITable should be appended.
jshort
_Jv_Linker::append_partial_itable (jclass klass, jclass iface,
- void **itable, jshort pos)
+ void **itable, jshort pos)
{
using namespace java::lang::reflect;
for (int j=0; j < iface->method_count; j++)
{
+ // Skip '<clinit>' here.
+ if (iface->methods[j].name->first() == '<')
+ continue;
+
meth = NULL;
for (jclass cl = klass; cl; cl = cl->getSuperclass())
{
break;
}
- if (meth && (meth->name->first() == '<'))
- {
- // leave a placeholder in the itable for hidden init methods.
- itable[pos] = NULL;
- }
- else if (meth)
+ if (meth)
{
if ((meth->accflags & Modifier::STATIC) != 0)
throw new java::lang::IncompatibleClassChangeError
// Interface Dispatch Table, we just compare the first element to see if it
// matches the desired interface. So how can we find the correct offset?
// Our solution is to keep a vector of candiate offsets in each interface
-// (idt->iface.ioffsets), and in each class we have an index
-// (idt->cls.iindex) used to select the correct offset from ioffsets.
+// (ioffsets), and in each class we have an index (idt->iindex) used to
+// select the correct offset from ioffsets.
//
// Calculate and return iindex for a new class.
// ifaces is a vector of num interfaces that the class implements.
{
if (j >= num)
goto found;
- if (i >= ifaces[j]->idt->iface.ioffsets[0])
+ if (i >= ifaces[j]->ioffsets[0])
continue;
- int ioffset = ifaces[j]->idt->iface.ioffsets[i];
+ int ioffset = ifaces[j]->ioffsets[i];
/* We can potentially share this position with another class. */
if (ioffset >= 0 && ioffset != offsets[j])
break; /* Nope. Try next i. */
found:
for (j = 0; j < num; j++)
{
- int len = ifaces[j]->idt->iface.ioffsets[0];
+ int len = ifaces[j]->ioffsets[0];
if (i >= len)
{
// Resize ioffsets.
int newlen = 2 * len;
if (i >= newlen)
newlen = i + 3;
- jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
+
+ jshort *old_ioffsets = ifaces[j]->ioffsets;
jshort *new_ioffsets = (jshort *) _Jv_AllocBytes (newlen
* sizeof(jshort));
memcpy (&new_ioffsets[1], &old_ioffsets[1],
while (len < newlen)
new_ioffsets[len++] = -1;
- ifaces[j]->idt->iface.ioffsets = new_ioffsets;
+ ifaces[j]->ioffsets = new_ioffsets;
}
- ifaces[j]->idt->iface.ioffsets[i] = offsets[j];
+ ifaces[j]->ioffsets[i] = offsets[j];
}
_Jv_MutexUnlock (&iindex_mutex);
}
#ifdef USE_LIBFFI
-
// We use a structure of this type to store the closure that
// represents a missing method.
struct method_closure
ffi_type *arg_types[1];
};
-#endif // USE_LIBFFI
-
void *
_Jv_Linker::create_error_method (_Jv_Utf8Const *class_name)
{
-#ifdef USE_LIBFFI
method_closure *closure
= (method_closure *) _Jv_AllocBytes(sizeof (method_closure));
// Initializes the cif and the closure. If that worked the closure
// is returned and can be used as a function pointer in a class'
// atable.
- if (ffi_prep_cif (&closure->cif, FFI_DEFAULT_ABI, 1, &ffi_type_void,
- closure->arg_types) == FFI_OK
- && ffi_prep_closure (&closure->closure, &closure->cif,
+ if ( ffi_prep_cif (&closure->cif,
+ FFI_DEFAULT_ABI,
+ 1,
+ &ffi_type_void,
+ closure->arg_types) == FFI_OK
+ && ffi_prep_closure (&closure->closure,
+ &closure->cif,
_Jv_ThrowNoClassDefFoundErrorTrampoline,
class_name) == FFI_OK)
return &closure->closure;
buffer->append (_Jv_NewStringUtf8Const(class_name));
throw new java::lang::InternalError(buffer->toString());
}
+}
#else
+void *
+_Jv_Linker::create_error_method (_Jv_Utf8Const *)
+{
// Codepath for platforms which do not support (or want) libffi.
// You have to accept that it is impossible to provide the name
// of the missing class then.
return (void *) _Jv_ThrowNoClassDefFoundError;
-#endif
}
+#endif // USE_LIBFFI
// Functions for indirect dispatch (symbolic virtual binding) support.
}
// Try fields only if the target class exists.
- if ( target_class != NULL )
+ if (target_class != NULL)
{
wait_for_state(target_class, JV_STATE_PREPARED);
jclass found_class;
else
instance_size = java::lang::Object::class$.size();
+ klass->engine->allocate_field_initializers (klass);
+
for (int i = 0; i < klass->field_count; i++)
{
int field_size;
// It is safe to resolve the field here, since it's a
// primitive class, which does not cause loading to happen.
resolve_field (field, klass->loader);
-
field_size = field->type->size ();
field_align = get_alignment_from_class (field->type);
}
}
}
-#if 0 // Should be redundant now
- // If superclass looks like a constant pool entry,
- // resolve it now.
- if ((uaddr) klass->superclass < (uaddr) pool->size)
- klass->superclass = pool->data[(uaddr) klass->superclass].clazz;
-
- // Likewise for interfaces.
- for (int i = 0; i < klass->interface_count; i++)
- {
- if ((uaddr) klass->interfaces[i] < (uaddr) pool->size)
- klass->interfaces[i]
- = pool->data[(uaddr) klass->interfaces[i]].clazz;
- }
-#endif
-
// Resolve the remaining constant pool entries.
for (int index = 1; index < pool->size; ++index)
{
}
}
if (codesource == NULL)
- codesource = "<no code source>";
+ codesource = (char *) "<no code source>";
- char *abi;
+ const char *abi;
if (_Jv_IsInterpretedClass (klass))
abi = "bytecode";
else if (_Jv_IsBinaryCompatibilityABI (klass))
java::lang::Thread *save = klass->thread;
klass->thread = self;
+ // Allocate memory for static fields and constants.
+ if (GC_base (klass) && klass->fields && ! GC_base (klass->fields))
+ {
+ jsize count = klass->field_count;
+ if (count)
+ {
+ _Jv_Field* fields
+ = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field));
+ memcpy ((void*)fields,
+ (void*)klass->fields,
+ count * sizeof (_Jv_Field));
+ klass->fields = fields;
+ }
+ }
+
// Print some debugging info if requested. Interpreted classes are
// handled in defineclass, so we only need to handle the two
// pre-compiled cases here.