OSDN Git Service

* Makefile.in: New #defines and friends for Thread.h.
[pf3gnuchains/gcc-fork.git] / libjava / java / lang / natObject.cc
1 // natObject.cc - Implementation of the Object class.
2
3 /* Copyright (C) 1998, 1999, 2000  Free Software Foundation
4
5    This file is part of libgcj.
6
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9 details.  */
10
11 #include <config.h>
12
13 #include <string.h>
14
15 #pragma implementation "Object.h"
16
17 #include <gcj/cni.h>
18 #include <jvm.h>
19 #include <java/lang/Object.h>
20 #include <java-threads.h>
21 #include <java/lang/CloneNotSupportedException.h>
22 #include <java/lang/IllegalArgumentException.h>
23 #include <java/lang/IllegalMonitorStateException.h>
24 #include <java/lang/InterruptedException.h>
25 #include <java/lang/NullPointerException.h>
26 #include <java/lang/Class.h>
27 #include <java/lang/Cloneable.h>
28 #include <java/lang/Thread.h>
29
30 #define CloneableClass _CL_Q34java4lang9Cloneable
31 extern java::lang::Class CloneableClass;
32
33 \f
34
35 // This is used to represent synchronization information.
36 struct _Jv_SyncInfo
37 {
38 #if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
39   // We only need to keep track of initialization state if we can
40   // possibly finalize this object.
41   bool init;
42 #endif
43   _Jv_ConditionVariable_t condition;
44   _Jv_Mutex_t mutex;
45 };
46
47 \f
48
49 jclass
50 java::lang::Object::getClass (void)
51 {
52   _Jv_VTable **dt = (_Jv_VTable **) this;
53   return (*dt)->clas;
54 }
55
56 jint
57 java::lang::Object::hashCode (void)
58 {
59   return _Jv_HashCode (this);
60 }
61
62 jobject
63 java::lang::Object::clone (void)
64 {
65   jclass klass = getClass ();
66   jobject r;
67   jint size;
68
69   // We also clone arrays here.  If we put the array code into
70   // __JArray, then we'd have to figure out a way to find the array
71   // vtbl when creating a new array class.  This is easier, if uglier.
72   if (klass->isArray())
73     {
74       __JArray *array = (__JArray *) this;
75       jclass comp = getClass()->getComponentType();
76       jint eltsize;
77       if (comp->isPrimitive())
78         {
79           r = _Jv_NewPrimArray (comp, array->length);
80           eltsize = comp->size();
81         }
82       else
83         {
84           r = _Jv_NewObjectArray (array->length, comp, NULL);
85           eltsize = sizeof (jobject);
86         }
87       // We can't use sizeof on __JArray because we must account for
88       // alignment of the element type.
89       size = (_Jv_GetArrayElementFromElementType (array, comp) - (char *) array
90               + array->length * eltsize);
91     }
92   else
93     {
94       if (! CloneableClass.isAssignableFrom(klass))
95         JvThrow (new CloneNotSupportedException);
96
97       size = klass->size();
98       r = JvAllocObject (klass, size);
99     }
100
101   memcpy ((void *) r, (void *) this, size);
102   return r;
103 }
104
105
106 //
107 // Synchronization code.
108 //
109
110 // This global is used to make sure that only one thread sets an
111 // object's `sync_info' field.
112 static _Jv_Mutex_t sync_mutex;
113
114 // This macro is used to see if synchronization initialization is
115 // needed.
116 #if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
117 #  define INIT_NEEDED(Obj) (! (Obj)->sync_info \
118                             || ! ((_Jv_SyncInfo *) ((Obj)->sync_info))->init)
119 #else
120 #  define INIT_NEEDED(Obj) (! (Obj)->sync_info)
121 #endif
122
123 #if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
124 // If we have to run a destructor for a sync_info member, then this
125 // function is registered as a finalizer for the sync_info.
126 static void
127 finalize_sync_info (jobject obj)
128 {
129   _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj;
130 #if defined (_Jv_HaveCondDestroy)
131   _Jv_CondDestroy (&si->condition);
132 #endif
133 #if defined (_Jv_HaveMutexDestroy)
134   _Jv_MutexDestroy (&si->mutex);
135 #endif
136   si->init = false;
137 }
138 #endif
139
140 // This is called to initialize the sync_info element of an object.
141 void
142 java::lang::Object::sync_init (void)
143 {
144   _Jv_MutexLock (&sync_mutex);
145   // Check again to see if initialization is needed now that we have
146   // the lock.
147   if (INIT_NEEDED (this))
148     {
149       // We assume there are no pointers in the sync_info
150       // representation.
151       _Jv_SyncInfo *si;
152       // We always create a new sync_info, even if there is already
153       // one available.  Any given object can only be finalized once.
154       // If we get here and sync_info is not null, then it has already
155       // been finalized.  So if we just reinitialize the old one,
156       // we'll never be able to (re-)destroy the mutex and/or
157       // condition variable.
158       si = (_Jv_SyncInfo *) _Jv_AllocBytesChecked (sizeof (_Jv_SyncInfo));
159       _Jv_MutexInit (&si->mutex);
160       _Jv_CondInit (&si->condition);
161 #if defined (_Jv_HaveCondDestroy) || defined (_Jv_HaveMutexDestroy)
162       // Register a finalizer.
163       si->init = true;
164       _Jv_RegisterFinalizer (si, finalize_sync_info);
165 #endif
166       sync_info = (jobject) si;
167     }
168   _Jv_MutexUnlock (&sync_mutex);
169 }
170
171 void
172 java::lang::Object::notify (void)
173 {
174   if (INIT_NEEDED (this))
175     sync_init ();
176   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
177   if (_Jv_CondNotify (&si->condition, &si->mutex))
178     JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 
179                                               ("current thread not owner")));
180 }
181
182 void
183 java::lang::Object::notifyAll (void)
184 {
185   if (INIT_NEEDED (this))
186     sync_init ();
187   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
188   if (_Jv_CondNotifyAll (&si->condition, &si->mutex))
189     JvThrow (new IllegalMonitorStateException(JvNewStringLatin1 
190                                               ("current thread not owner")));
191 }
192
193 void
194 java::lang::Object::wait (jlong timeout, jint nanos)
195 {
196   if (INIT_NEEDED (this))
197     sync_init ();
198   if (timeout < 0 || nanos < 0 || nanos > 999999)
199     JvThrow (new IllegalArgumentException);
200   _Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
201   switch (_Jv_CondWait (&si->condition, &si->mutex, timeout, nanos))
202     {
203       case _JV_NOT_OWNER:
204         JvThrow (new IllegalMonitorStateException (JvNewStringLatin1 
205                           ("current thread not owner")));        
206       case _JV_INTERRUPTED:
207         if (Thread::interrupted ())
208           JvThrow (new InterruptedException);        
209     }
210 }
211
212 //
213 // Some runtime code.
214 //
215
216 // This function is called at system startup to initialize the
217 // `sync_mutex'.
218 void
219 _Jv_InitializeSyncMutex (void)
220 {
221   _Jv_MutexInit (&sync_mutex);
222 }
223
224 jint
225 _Jv_MonitorEnter (jobject obj)
226 {
227   if (! obj)
228     JvThrow (new java::lang::NullPointerException);
229   if (INIT_NEEDED (obj))
230     obj->sync_init ();
231   _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
232   return _Jv_MutexLock (&si->mutex);
233 }
234
235 jint
236 _Jv_MonitorExit (jobject obj)
237 {
238   JvAssert (obj);
239   JvAssert (! INIT_NEEDED (obj));
240   _Jv_SyncInfo *si = (_Jv_SyncInfo *) obj->sync_info;
241   if (_Jv_MutexUnlock (&si->mutex))
242     JvThrow (new java::lang::IllegalMonitorStateException);
243   return 0;
244 }
245
246 void
247 _Jv_FinalizeObject (jobject obj)
248 {
249   // Ignore exceptions.  From section 12.6 of the Java Language Spec.
250   try
251     {
252       obj->finalize ();
253     }
254   catch (java::lang::Throwable *t)
255     {
256       // Ignore.
257     }
258 }