* Merged gcj-abi-2-dev-branch to trunk.
(Actual changes too large to list in the commit message; see ChangeLog.) From-SVN: r91270
This commit is contained in:
parent
ec0641f612
commit
367390404d
70 changed files with 11301 additions and 3355 deletions
|
@ -18,6 +18,7 @@ details. */
|
|||
|
||||
#include <gcj/cni.h>
|
||||
#include <jvm.h>
|
||||
#include <execution.h>
|
||||
|
||||
#include <java-threads.h>
|
||||
#include <java-interp.h>
|
||||
|
@ -33,6 +34,7 @@ details. */
|
|||
#include <java/lang/ClassNotFoundException.h>
|
||||
#include <java/lang/ClassCircularityError.h>
|
||||
#include <java/lang/IncompatibleClassChangeError.h>
|
||||
#include <java/lang/ClassFormatError.h>
|
||||
#include <java/lang/VirtualMachineError.h>
|
||||
#include <java/lang/VMClassLoader.h>
|
||||
#include <java/lang/reflect/Modifier.h>
|
||||
|
@ -41,156 +43,6 @@ details. */
|
|||
#include <java/io/Serializable.h>
|
||||
#include <java/lang/Cloneable.h>
|
||||
|
||||
void
|
||||
_Jv_WaitForState (jclass klass, int state)
|
||||
{
|
||||
if (klass->state >= state)
|
||||
return;
|
||||
|
||||
_Jv_MonitorEnter (klass) ;
|
||||
|
||||
if (klass->state == JV_STATE_COMPILED)
|
||||
{
|
||||
klass->state = JV_STATE_LOADED;
|
||||
if (gcj::verbose_class_flag)
|
||||
fprintf (stderr, "[Loaded (pre-compiled) %s]\n", klass->name->chars());
|
||||
}
|
||||
if (state == JV_STATE_LINKED)
|
||||
{
|
||||
// Must call _Jv_PrepareCompiledClass while holding the class
|
||||
// mutex.
|
||||
#ifdef INTERPRETER
|
||||
if (_Jv_IsInterpretedClass (klass))
|
||||
_Jv_PrepareClass (klass);
|
||||
#endif
|
||||
_Jv_PrepareCompiledClass (klass);
|
||||
_Jv_MonitorExit (klass);
|
||||
return;
|
||||
}
|
||||
|
||||
java::lang::Thread *self = java::lang::Thread::currentThread();
|
||||
|
||||
// this is similar to the strategy for class initialization.
|
||||
// if we already hold the lock, just leave.
|
||||
while (klass->state <= state
|
||||
&& klass->thread
|
||||
&& klass->thread != self)
|
||||
klass->wait ();
|
||||
|
||||
_Jv_MonitorExit (klass);
|
||||
|
||||
if (klass->state == JV_STATE_ERROR)
|
||||
throw new java::lang::LinkageError;
|
||||
}
|
||||
|
||||
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
|
||||
|
||||
/** This function does class-preparation for compiled classes.
|
||||
NOTE: It contains replicated functionality from
|
||||
_Jv_ResolvePoolEntry, and this is intentional, since that function
|
||||
lives in resolve.cc which is entirely conditionally compiled.
|
||||
*/
|
||||
void
|
||||
_Jv_PrepareCompiledClass (jclass klass)
|
||||
{
|
||||
jint state = klass->state;
|
||||
if (state >= JV_STATE_LINKED)
|
||||
return;
|
||||
|
||||
// Short-circuit, so that mutually dependent classes are ok.
|
||||
klass->state = JV_STATE_LINKED;
|
||||
|
||||
_Jv_Constants *pool = &klass->constants;
|
||||
|
||||
// Resolve class constants first, since other constant pool
|
||||
// entries may rely on these.
|
||||
for (int index = 1; index < pool->size; ++index)
|
||||
{
|
||||
if (pool->tags[index] == JV_CONSTANT_Class)
|
||||
{
|
||||
_Jv_Utf8Const *name = pool->data[index].utf8;
|
||||
|
||||
jclass found;
|
||||
if (name->first() == '[')
|
||||
found = _Jv_FindClassFromSignature (name->chars(),
|
||||
klass->loader);
|
||||
else
|
||||
found = _Jv_FindClass (name, klass->loader);
|
||||
|
||||
if (! found)
|
||||
{
|
||||
jstring str = name->toString();
|
||||
throw new java::lang::NoClassDefFoundError (str);
|
||||
}
|
||||
|
||||
pool->data[index].clazz = found;
|
||||
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
|
||||
}
|
||||
}
|
||||
|
||||
// If superclass looks like a constant pool entry,
|
||||
// resolve it now.
|
||||
if ((uaddr) klass->superclass < 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] < pool->size)
|
||||
klass->interfaces[i] = pool->data[(uaddr) klass->interfaces[i]].clazz;
|
||||
|
||||
// Resolve the remaining constant pool entries.
|
||||
for (int index = 1; index < pool->size; ++index)
|
||||
{
|
||||
if (pool->tags[index] == JV_CONSTANT_String)
|
||||
{
|
||||
jstring str;
|
||||
|
||||
str = _Jv_NewStringUtf8Const (pool->data[index].utf8);
|
||||
pool->data[index].o = str;
|
||||
pool->tags[index] |= JV_CONSTANT_ResolvedFlag;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INTERPRETER
|
||||
// FIXME: although the comment up top says that this function is
|
||||
// only called for compiled classes, it is actually called for every
|
||||
// class.
|
||||
if (! _Jv_IsInterpretedClass (klass))
|
||||
{
|
||||
#endif /* INTERPRETER */
|
||||
jfieldID f = JvGetFirstStaticField (klass);
|
||||
for (int n = JvNumStaticFields (klass); n > 0; --n)
|
||||
{
|
||||
int mod = f->getModifiers ();
|
||||
// If we have a static String field with a non-null initial
|
||||
// value, we know it points to a Utf8Const.
|
||||
_Jv_ResolveField(f, klass->loader);
|
||||
if (f->getClass () == &java::lang::String::class$
|
||||
&& java::lang::reflect::Modifier::isStatic (mod))
|
||||
{
|
||||
jstring *strp = (jstring *) f->u.addr;
|
||||
if (*strp)
|
||||
*strp = _Jv_NewStringUtf8Const ((_Jv_Utf8Const *) *strp);
|
||||
}
|
||||
f = f->getNextField ();
|
||||
}
|
||||
#ifdef INTERPRETER
|
||||
}
|
||||
#endif /* INTERPRETER */
|
||||
|
||||
if (klass->isInterface ())
|
||||
_Jv_LayoutInterfaceMethods (klass);
|
||||
|
||||
if (state == JV_STATE_COMPILED && gcj::verbose_class_flag)
|
||||
fprintf (stderr, "[Loaded (pre-compiled) %s]\n",
|
||||
klass->name->chars());
|
||||
|
||||
klass->notifyAll ();
|
||||
|
||||
_Jv_PushClass (klass);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A single class can have many "initiating" class loaders,
|
||||
// and a single "defining" class loader. The Defining
|
||||
|
@ -221,6 +73,8 @@ static _Jv_LoaderInfo *initiated_classes[HASH_LEN];
|
|||
static jclass loaded_classes[HASH_LEN];
|
||||
|
||||
// This is the root of a linked list of classes
|
||||
static jclass stack_head;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -323,11 +177,6 @@ _Jv_RegisterClasses (const jclass *classes)
|
|||
jclass klass = *classes;
|
||||
|
||||
(*_Jv_RegisterClassHook) (klass);
|
||||
|
||||
// registering a compiled class causes
|
||||
// it to be immediately "prepared".
|
||||
if (klass->state == JV_STATE_NOTHING)
|
||||
klass->state = JV_STATE_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,11 +190,6 @@ _Jv_RegisterClasses_Counted (const jclass * classes, size_t count)
|
|||
jclass klass = classes[i];
|
||||
|
||||
(*_Jv_RegisterClassHook) (klass);
|
||||
|
||||
// registering a compiled class causes
|
||||
// it to be immediately "prepared".
|
||||
if (klass->state == JV_STATE_NOTHING)
|
||||
klass->state = JV_STATE_COMPILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,8 +198,10 @@ _Jv_RegisterClassHookDefault (jclass klass)
|
|||
{
|
||||
jint hash = HASH_UTF (klass->name);
|
||||
|
||||
jclass check_class = loaded_classes[hash];
|
||||
|
||||
// The BC ABI makes this check unnecessary: we always resolve all
|
||||
// data references via the appropriate class loader, so the kludge
|
||||
// that required this check has gone.
|
||||
#if 0
|
||||
// If the class is already registered, don't re-register it.
|
||||
while (check_class != NULL)
|
||||
{
|
||||
|
@ -381,7 +227,11 @@ _Jv_RegisterClassHookDefault (jclass klass)
|
|||
|
||||
check_class = check_class->next;
|
||||
}
|
||||
#endif
|
||||
|
||||
// FIXME: this is really bogus!
|
||||
if (! klass->engine)
|
||||
klass->engine = &_Jv_soleCompiledEngine;
|
||||
klass->next = loaded_classes[hash];
|
||||
loaded_classes[hash] = klass;
|
||||
}
|
||||
|
@ -442,7 +292,7 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
|
|||
{
|
||||
// we need classes to be in the hash while
|
||||
// we're loading, so that they can refer to themselves.
|
||||
_Jv_WaitForState (klass, JV_STATE_LOADED);
|
||||
_Jv_Linker::wait_for_state (klass, JV_STATE_LOADED);
|
||||
}
|
||||
|
||||
return klass;
|
||||
|
@ -555,7 +405,7 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
|||
// cache one and reuse it. It is not necessary to synchronize this.
|
||||
if (!array_idt)
|
||||
{
|
||||
_Jv_PrepareConstantTimeTables (array_class);
|
||||
_Jv_Linker::wait_for_state(array_class, JV_STATE_PREPARED);
|
||||
array_idt = array_class->idt;
|
||||
array_depth = array_class->depth;
|
||||
array_ancestors = array_class->ancestors;
|
||||
|
@ -569,19 +419,19 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
|||
|
||||
using namespace java::lang::reflect;
|
||||
{
|
||||
// Array classes are "abstract final"...
|
||||
_Jv_ushort accflags = Modifier::FINAL | Modifier::ABSTRACT;
|
||||
// ... and inherit accessibility from element type, per vmspec 5.3.3.2
|
||||
accflags |= (element->accflags & Modifier::PUBLIC);
|
||||
accflags |= (element->accflags & Modifier::PROTECTED);
|
||||
accflags |= (element->accflags & Modifier::PRIVATE);
|
||||
// Array classes are "abstract final" and inherit accessibility
|
||||
// from element type, per vmspec 5.3.3.2
|
||||
_Jv_ushort accflags = (Modifier::FINAL | Modifier::ABSTRACT
|
||||
| (element->accflags
|
||||
& (Modifier::PUBLIC | Modifier::PROTECTED
|
||||
| Modifier::PRIVATE)));
|
||||
array_class->accflags = accflags;
|
||||
}
|
||||
|
||||
// An array class has no visible instance fields. "length" is invisible to
|
||||
// reflection.
|
||||
|
||||
// say this class is initialized and ready to go!
|
||||
// Say this class is initialized and ready to go!
|
||||
array_class->state = JV_STATE_DONE;
|
||||
|
||||
// vmspec, section 5.3.3 describes this
|
||||
|
@ -591,8 +441,6 @@ _Jv_NewArrayClass (jclass element, java::lang::ClassLoader *loader,
|
|||
element->arrayclass = array_class;
|
||||
}
|
||||
|
||||
static jclass stack_head;
|
||||
|
||||
// These two functions form a stack of classes. When a class is loaded
|
||||
// it is pushed onto the stack by the class loader; this is so that
|
||||
// StackTrace can quickly determine which classes have been loaded.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue