diff options
Diffstat (limited to 'libjava/java/lang/natObject.cc')
-rw-r--r-- | libjava/java/lang/natObject.cc | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/libjava/java/lang/natObject.cc b/libjava/java/lang/natObject.cc new file mode 100644 index 0000000..7b26769 --- /dev/null +++ b/libjava/java/lang/natObject.cc @@ -0,0 +1,241 @@ +// natObject.cc - Implementation of the Object class. + +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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" + +#include <cni.h> +#include <jvm.h> +#include <java/lang/Object.h> +#include <java-threads.h> +#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> + +#define CloneableClass _CL_Q34java4lang9Cloneable +extern java::lang::Class CloneableClass; + + + +// 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); + } + size = sizeof (__JArray) + array->length * eltsize; + } + else + { + if (! CloneableClass.isAssignableFrom(klass)) + 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. + si = (_Jv_SyncInfo *) _Jv_AllocBytes (sizeof (_Jv_SyncInfo)); + // FIXME: what if si == NULL? + _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) +{ + if (INIT_NEEDED (this)) + sync_init (); + _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; + if (_Jv_CondNotify (&si->condition, &si->mutex)) + JvThrow (new IllegalMonitorStateException); +} + +void +java::lang::Object::notifyAll (void) +{ + if (INIT_NEEDED (this)) + sync_init (); + _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; + if (_Jv_CondNotifyAll (&si->condition, &si->mutex)) + JvThrow (new IllegalMonitorStateException); +} + +void +java::lang::Object::wait (jlong timeout, jint nanos) +{ + if (INIT_NEEDED (this)) + sync_init (); + if (timeout < 0 || nanos < 0 || nanos > 999999) + JvThrow (new IllegalArgumentException); + _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info; + if (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos)) + JvThrow (new IllegalMonitorStateException); + if (Thread::interrupted()) + JvThrow (new InterruptedException); +} + +// +// 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) +{ + if (! obj) + JvThrow (new java::lang::NullPointerException); + if (INIT_NEEDED (obj)) + 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; + if (_Jv_MutexUnlock (&si->mutex)) + JvThrow (new java::lang::IllegalMonitorStateException); + return 0; +} + +void +_Jv_FinalizeObject (jobject obj) +{ + java::lang::Object::hack12_6(obj); +} |