1999-04-07 22:42:40 +08:00
|
|
|
|
// natObject.cc - Implementation of the Object class.
|
|
|
|
|
|
2000-03-08 03:55:28 +08:00
|
|
|
|
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
|
1999-04-07 22:42:40 +08:00
|
|
|
|
|
|
|
|
|
This file is part of libgcj.
|
|
|
|
|
|
|
|
|
|
This software is copyrighted work licensed under the terms of the
|
|
|
|
|
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
|
|
|
|
|
details. */
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#pragma implementation "Object.h"
|
|
|
|
|
|
1999-09-11 06:03:10 +08:00
|
|
|
|
#include <gcj/cni.h>
|
1999-04-07 22:42:40 +08:00
|
|
|
|
#include <jvm.h>
|
|
|
|
|
#include <java/lang/Object.h>
|
|
|
|
|
#include <java-threads.h>
|
2000-04-09 09:26:20 +08:00
|
|
|
|
#include <java-signal.h>
|
1999-04-07 22:42:40 +08:00
|
|
|
|
#include <java/lang/CloneNotSupportedException.h>
|
|
|
|
|
#include <java/lang/IllegalArgumentException.h>
|
|
|
|
|
#include <java/lang/IllegalMonitorStateException.h>
|
|
|
|
|
#include <java/lang/InterruptedException.h>
|
|
|
|
|
#include <java/lang/NullPointerException.h>
|
|
|
|
|
#include <java/lang/Class.h>
|
|
|
|
|
#include <java/lang/Cloneable.h>
|
|
|
|
|
#include <java/lang/Thread.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is used to represent synchronization information.
|
|
|
|
|
struct _Jv_SyncInfo
|
|
|
|
|
{
|
|
|
|
|
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
|
|
|
|
|
// We only need to keep track of initialization state if we can
|
|
|
|
|
// possibly finalize this object.
|
|
|
|
|
bool init;
|
|
|
|
|
#endif
|
|
|
|
|
_Jv_ConditionVariable_t condition;
|
|
|
|
|
_Jv_Mutex_t mutex;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
jclass
|
|
|
|
|
java::lang::Object::getClass (void)
|
|
|
|
|
{
|
|
|
|
|
_Jv_VTable **dt = (_Jv_VTable **) this;
|
|
|
|
|
return (*dt)->clas;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jint
|
|
|
|
|
java::lang::Object::hashCode (void)
|
|
|
|
|
{
|
|
|
|
|
return _Jv_HashCode (this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jobject
|
|
|
|
|
java::lang::Object::clone (void)
|
|
|
|
|
{
|
|
|
|
|
jclass klass = getClass ();
|
|
|
|
|
jobject r;
|
|
|
|
|
jint size;
|
|
|
|
|
|
|
|
|
|
// We also clone arrays here. If we put the array code into
|
|
|
|
|
// __JArray, then we'd have to figure out a way to find the array
|
|
|
|
|
// vtbl when creating a new array class. This is easier, if uglier.
|
|
|
|
|
if (klass->isArray())
|
|
|
|
|
{
|
|
|
|
|
__JArray *array = (__JArray *) this;
|
|
|
|
|
jclass comp = getClass()->getComponentType();
|
|
|
|
|
jint eltsize;
|
|
|
|
|
if (comp->isPrimitive())
|
|
|
|
|
{
|
|
|
|
|
r = _Jv_NewPrimArray (comp, array->length);
|
|
|
|
|
eltsize = comp->size();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
r = _Jv_NewObjectArray (array->length, comp, NULL);
|
|
|
|
|
eltsize = sizeof (jobject);
|
|
|
|
|
}
|
1999-11-25 08:36:51 +08:00
|
|
|
|
// We can't use sizeof on __JArray because we must account for
|
|
|
|
|
// alignment of the element type.
|
|
|
|
|
size = (_Jv_GetArrayElementFromElementType (array, comp) - (char *) array
|
|
|
|
|
+ array->length * eltsize);
|
1999-04-07 22:42:40 +08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
natField.cc (BooleanClass): Don't define.
* java/lang/reflect/natField.cc (BooleanClass): Don't define.
* java/lang/reflect/natArray.cc (BooleanClass): Don't define.
* java/lang/Class.h (Object): Added `class$' field.
* java/lang/Object.h (Object): Added `class$' field.
* defineclass.cc (ClassClass): Use `class$' form.
(ClassObject): Likewise.
* resolve.cc (ClassObject): Use `class$' form.
(ObjectClass): Likewise.
* interpret.cc (ClassError): Removed.
* java/net/natPlainDatagramSocketImpl.cc (BooleanClass): Use
`class$' form.
(IntegerClass): Likewise.
* java/net/natPlainSocketImpl.cc (BooleanClass): Use `class$'
form.
* java/lang/natClassLoader.cc (CloneableClass): Use `class$' form.
(ObjectClass, ClassClass, VMClassLoaderClass, ClassLoaderClass,
SerializableClass): Likewise.
Include Serializable.h, Cloneable.h.
* java/lang/natSystem.cc (SystemClass): Removed.
(init_properties): Use `class$' form.
* java/lang/natObject.cc (CloneableClass): Removed.
(clone): Use `class$' form.
* java/lang/natClass.cc (CloneableClass): Use `class$' form.
(ObjectClass, ErrorClass, ClassClass, MethodClass, FieldClass,
ConstructorClass): Likewise.
* java/lang/reflect/natMethod.cc (ObjectClass): Use `class$' form.
(ClassClass, VoidClass, ByteClass, ShortClass, CharacterClass,
IntegerClass, LongClass, FloatClass, DoubleClass): Likewise.
* java/io/natObjectInputStream.cc (ObjectClass): Use `class$'
form.
(ClassClass): Likewise.
* include/jvm.h (StringClass): Use `class$' form.
* prims.cc (ObjectClass): Removed.
(_Jv_RunMain): Use `class$' form.
(_Jv_AllocObject): Likewise.
* jni.cc (ClassClass): Use `class$' form.
(ThrowableClass): Likewise.
(ObjectClass): Likewise.
(MethodClass): Likewise.
(ThreadGroupClass): Likewise.
(NativeThreadClass): Likewise.
* boehm.cc (ObjectClass): Removed.
(ClassClass): Removed.
(_Jv_MarkObj): Use `class$' form.
* gcj/field.h (JvFieldIsRef): Use `class$' form.
Include RawData.h.
From-SVN: r36740
2000-10-06 09:49:32 +08:00
|
|
|
|
if (! java::lang::Cloneable::class$.isAssignableFrom(klass))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
JvThrow (new CloneNotSupportedException);
|
|
|
|
|
|
|
|
|
|
size = klass->size();
|
|
|
|
|
r = JvAllocObject (klass, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy ((void *) r, (void *) this, size);
|
|
|
|
|
return r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Synchronization code.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// This global is used to make sure that only one thread sets an
|
|
|
|
|
// object's `sync_info' field.
|
|
|
|
|
static _Jv_Mutex_t sync_mutex;
|
|
|
|
|
|
|
|
|
|
// This macro is used to see if synchronization initialization is
|
|
|
|
|
// needed.
|
|
|
|
|
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
|
|
|
|
|
# define INIT_NEEDED(Obj) (! (Obj)->sync_info \
|
|
|
|
|
|| ! ((_Jv_SyncInfo *) ((Obj)->sync_info))->init)
|
|
|
|
|
#else
|
|
|
|
|
# define INIT_NEEDED(Obj) (! (Obj)->sync_info)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
|
|
|
|
|
// If we have to run a destructor for a sync_info member, then this
|
|
|
|
|
// function is registered as a finalizer for the sync_info.
|
|
|
|
|
static void
|
|
|
|
|
finalize_sync_info (jobject obj)
|
|
|
|
|
{
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj;
|
|
|
|
|
#if defined (_Jv_HaveCondDestroy)
|
|
|
|
|
_Jv_CondDestroy (&si->condition);
|
|
|
|
|
#endif
|
|
|
|
|
#if defined (_Jv_HaveMutexDestroy)
|
|
|
|
|
_Jv_MutexDestroy (&si->mutex);
|
|
|
|
|
#endif
|
|
|
|
|
si->init = false;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// This is called to initialize the sync_info element of an object.
|
|
|
|
|
void
|
|
|
|
|
java::lang::Object::sync_init (void)
|
|
|
|
|
{
|
|
|
|
|
_Jv_MutexLock (&sync_mutex);
|
|
|
|
|
// Check again to see if initialization is needed now that we have
|
|
|
|
|
// the lock.
|
|
|
|
|
if (INIT_NEEDED (this))
|
|
|
|
|
{
|
|
|
|
|
// We assume there are no pointers in the sync_info
|
|
|
|
|
// representation.
|
|
|
|
|
_Jv_SyncInfo *si;
|
|
|
|
|
// We always create a new sync_info, even if there is already
|
|
|
|
|
// one available. Any given object can only be finalized once.
|
|
|
|
|
// If we get here and sync_info is not null, then it has already
|
|
|
|
|
// been finalized. So if we just reinitialize the old one,
|
|
|
|
|
// we'll never be able to (re-)destroy the mutex and/or
|
|
|
|
|
// condition variable.
|
1999-05-10 17:28:54 +08:00
|
|
|
|
si = (_Jv_SyncInfo *) _Jv_AllocBytesChecked (sizeof (_Jv_SyncInfo));
|
1999-04-07 22:42:40 +08:00
|
|
|
|
_Jv_MutexInit (&si->mutex);
|
|
|
|
|
_Jv_CondInit (&si->condition);
|
|
|
|
|
#if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
|
|
|
|
|
// Register a finalizer.
|
|
|
|
|
si->init = true;
|
|
|
|
|
_Jv_RegisterFinalizer (si, finalize_sync_info);
|
|
|
|
|
#endif
|
|
|
|
|
sync_info = (jobject) si;
|
|
|
|
|
}
|
|
|
|
|
_Jv_MutexUnlock (&sync_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Object::notify (void)
|
|
|
|
|
{
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (INIT_NEEDED (this), false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
sync_init ();
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (_Jv_CondNotify (&si->condition, &si->mutex), false))
|
1999-12-24 09:00:46 +08:00
|
|
|
|
JvThrow (new IllegalMonitorStateException(JvNewStringLatin1
|
|
|
|
|
("current thread not owner")));
|
1999-04-07 22:42:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Object::notifyAll (void)
|
|
|
|
|
{
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (INIT_NEEDED (this), false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
sync_init ();
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (_Jv_CondNotifyAll (&si->condition, &si->mutex), false))
|
1999-12-24 09:00:46 +08:00
|
|
|
|
JvThrow (new IllegalMonitorStateException(JvNewStringLatin1
|
|
|
|
|
("current thread not owner")));
|
1999-04-07 22:42:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
java::lang::Object::wait (jlong timeout, jint nanos)
|
|
|
|
|
{
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (INIT_NEEDED (this), false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
sync_init ();
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
JvThrow (new IllegalArgumentException);
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
|
2000-03-28 10:22:24 +08:00
|
|
|
|
switch (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos))
|
|
|
|
|
{
|
|
|
|
|
case _JV_NOT_OWNER:
|
|
|
|
|
JvThrow (new IllegalMonitorStateException (JvNewStringLatin1
|
|
|
|
|
("current thread not owner")));
|
|
|
|
|
case _JV_INTERRUPTED:
|
|
|
|
|
if (Thread::interrupted ())
|
|
|
|
|
JvThrow (new InterruptedException);
|
|
|
|
|
}
|
1999-04-07 22:42:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Some runtime code.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// This function is called at system startup to initialize the
|
|
|
|
|
// `sync_mutex'.
|
|
|
|
|
void
|
|
|
|
|
_Jv_InitializeSyncMutex (void)
|
|
|
|
|
{
|
|
|
|
|
_Jv_MutexInit (&sync_mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jint
|
|
|
|
|
_Jv_MonitorEnter (jobject obj)
|
|
|
|
|
{
|
2000-04-09 09:26:20 +08:00
|
|
|
|
#ifndef HANDLE_SEGV
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (! obj, false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
JvThrow (new java::lang::NullPointerException);
|
2000-04-09 09:26:20 +08:00
|
|
|
|
#endif
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (INIT_NEEDED (obj), false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
obj->sync_init ();
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
|
|
|
|
|
return _Jv_MutexLock (&si->mutex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
jint
|
|
|
|
|
_Jv_MonitorExit (jobject obj)
|
|
|
|
|
{
|
|
|
|
|
JvAssert (obj);
|
|
|
|
|
JvAssert (! INIT_NEEDED (obj));
|
|
|
|
|
_Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
|
2000-05-05 10:56:14 +08:00
|
|
|
|
if (__builtin_expect (_Jv_MutexUnlock (&si->mutex), false))
|
1999-04-07 22:42:40 +08:00
|
|
|
|
JvThrow (new java::lang::IllegalMonitorStateException);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_Jv_FinalizeObject (jobject obj)
|
|
|
|
|
{
|
2000-03-03 04:25:20 +08:00
|
|
|
|
// Ignore exceptions. From section 12.6 of the Java Language Spec.
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
obj->finalize ();
|
|
|
|
|
}
|
|
|
|
|
catch (java::lang::Throwable *t)
|
|
|
|
|
{
|
|
|
|
|
// Ignore.
|
|
|
|
|
}
|
1999-04-07 22:42:40 +08:00
|
|
|
|
}
|