mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			259 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| // natObject.cc - Implementation of the Object class.
 | ||
| 
 | ||
| /* Copyright (C) 1998, 1999, 2000  Free Software Foundation
 | ||
| 
 | ||
|    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 <gcj/cni.h>
 | ||
| #include <jvm.h>
 | ||
| #include <java/lang/Object.h>
 | ||
| #include <java-threads.h>
 | ||
| #include <java-signal.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>
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| // 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);
 | ||
| 	}
 | ||
|       // 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);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       if (! java::lang::Cloneable::class$.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_AllocBytesChecked (sizeof (_Jv_SyncInfo));
 | ||
|       _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 (__builtin_expect (INIT_NEEDED (this), false))
 | ||
|     sync_init ();
 | ||
|   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
 | ||
|   if (__builtin_expect (_Jv_CondNotify (&si->condition, &si->mutex), false))
 | ||
|     JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 
 | ||
|                                               ("current thread not owner")));
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Object::notifyAll (void)
 | ||
| {
 | ||
|   if (__builtin_expect (INIT_NEEDED (this), false))
 | ||
|     sync_init ();
 | ||
|   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
 | ||
|   if (__builtin_expect (_Jv_CondNotifyAll (&si->condition, &si->mutex), false))
 | ||
|     JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 
 | ||
|                                               ("current thread not owner")));
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| java::lang::Object::wait (jlong timeout, jint nanos)
 | ||
| {
 | ||
|   if (__builtin_expect (INIT_NEEDED (this), false))
 | ||
|     sync_init ();
 | ||
|   if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, false))
 | ||
|     JvThrow (new IllegalArgumentException);
 | ||
|   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
 | ||
|   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);        
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| //
 | ||
| // 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)
 | ||
| {
 | ||
| #ifndef HANDLE_SEGV
 | ||
|   if (__builtin_expect (! obj, false))
 | ||
|     JvThrow (new java::lang::NullPointerException);
 | ||
| #endif
 | ||
|   if (__builtin_expect (INIT_NEEDED (obj), false))
 | ||
|     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 (__builtin_expect (_Jv_MutexUnlock (&si->mutex), false))
 | ||
|     JvThrow (new java::lang::IllegalMonitorStateException);
 | ||
|   return 0;
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| _Jv_FinalizeObject (jobject obj)
 | ||
| {
 | ||
|   // Ignore exceptions.  From section 12.6 of the Java Language Spec.
 | ||
|   try
 | ||
|     {
 | ||
|       obj->finalize ();
 | ||
|     }
 | ||
|   catch (java::lang::Throwable *t)
 | ||
|     {
 | ||
|       // Ignore.
 | ||
|     }
 | ||
| }
 |