gcc/libjava/java/lang/natObject.cc

262 lines
6.9 KiB
C++
Raw Normal View History

1999-04-07 16:42:40 +02:00
// natObject.cc - Implementation of the Object class.
/* Copyright (C) 1998, 1999, 2000 Free Software Foundation
1999-04-07 16:42:40 +02: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"
#include <gcj/cni.h>
1999-04-07 16:42:40 +02:00
#include <jvm.h>
#include <java/lang/Object.h>
#include <java-threads.h>
#include <java-signal.h>
1999-04-07 16:42:40 +02: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>
#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);
}
// 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 16:42:40 +02:00
}
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_AllocBytesChecked (sizeof (_Jv_SyncInfo));
1999-04-07 16:42:40 +02: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)
{
if (__builtin_expect (INIT_NEEDED (this), 0))
1999-04-07 16:42:40 +02:00
sync_init ();
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
if (__builtin_expect (_Jv_CondNotify (&si->condition, &si->mutex), 0))
JvThrow (new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner")));
1999-04-07 16:42:40 +02:00
}
void
java::lang::Object::notifyAll (void)
{
if (__builtin_expect (INIT_NEEDED (this), 0))
1999-04-07 16:42:40 +02:00
sync_init ();
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
if (__builtin_expect (_Jv_CondNotifyAll (&si->condition, &si->mutex), 0))
JvThrow (new IllegalMonitorStateException(JvNewStringLatin1
("current thread not owner")));
1999-04-07 16:42:40 +02:00
}
void
java::lang::Object::wait (jlong timeout, jint nanos)
{
if (__builtin_expect (INIT_NEEDED (this), 0))
1999-04-07 16:42:40 +02:00
sync_init ();
if (__builtin_expect (timeout < 0 || nanos < 0 || nanos > 999999, 0))
1999-04-07 16:42:40 +02:00
JvThrow (new IllegalArgumentException);
_Jv_SyncInfo *si = (_Jv_SyncInfo *) sync_info;
Makefile.in: New #defines and friends for Thread.h. * Makefile.in: New #defines and friends for Thread.h. * posix-threads.cc: (struct starter): Remove `object'. (_Jv_CondWait): Use interruptable condition variables and new recursive mutexes. New return codes on interrupt or non-ownership of mutex. (_Jv_CondNotify): Ditto. (_Jv_CondNotifyAll): Ditto. (_Jv_ThreadInterrupt): Set thread interrupt flag directly. Interrupt the target thread by signaling its wait condition. (_Jv_ThreadInitData): Set `thread_obj' in the thread data struct, not the starter struct. Initialize wait_mutex and wait_cond. (_Jv_MutexLock): New recursive mutex implementation. Moved from posix-threads.h. (_Jv_MutexUnlock): Ditto. (really_start): Set info->data->thread from pthread_self() to work around a race condition. Destroy wait_mutex and wait_cond when run() returns. * java/lang/Thread.java: (isInterrupted_): Renamed to overloaded `isInterrupted(boolean)'. Clear interrupted flag if clear_flag is set. startable_flag: New private field. (Thread): Initialize `startable_flag'. (toString): Check for null thread group. * java/lang/natThread.cc: (struct natThread): New fields `join_mutex', `join_cond'. Removed fields `joiner', `next'. (class locker): Removed. (initialize_native): Initialize `join_cond' and `join_mutex'. (interrupt): Now just calls _Jv_ThreadInterrupt(). (join): Simplified. Just wait on the target thread's join condition. (finish_): Remove join list code. Unset thread group. Signal potential joiners by notifying the dying threads join_cond. (start): Check for illegal restarts. * java/lang/natObject.cc: Check for return value of _Jv_CondWait and act appropriatly. * include/posix-threads.h: Remove all HAVE_RECURSIVE_MUTEX related #defines and #ifdefs. (struct _Jv_Thread_t): New fields `thread_obj', `wait_cond', `wait_mutex', `next'. (struct _Jv_ConditionVariable_t): Define as a struct instead of directly mapping to pthread_cond_t. (struct _Jv_Mutex_t): New recursive implementation. (_Jv_PthreadCheckMonitor): Reimplemented. Simple `owner' check. _Jv_HaveCondDestroy: Never define this for posix-threads. (_Jv_CondNotify): Remove inline implementation(s), prototype instead. (_Jv_CondNotifyAll): Ditto. (_Jv_MutexLock): Ditto. (_Jv_MutexUnlock): Ditto. (_Jv_MutexInit): Changed to reflect new mutex implementation. (_Jv_MutexDestroy): Ditto. (_Jv_CondDestroy): Removed. (_Jv_PthreadGetMutex): Removed. * include/win32-threads.h: (_Jv_CondNotify): Guess _JV_NOT_OWNER on an error. Add a FIXME about this. (_Jv_CondNotifyAll): Ditto. * win32-threads.cc: (_Jv_CondWait): Return 0 on a timeout. Guess _JV_NOT_OWNER on other errors. Add FIXME. From-SVN: r32773
2000-03-28 04:22:24 +02: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 16:42:40 +02: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)
{
#ifndef HANDLE_SEGV
if (__builtin_expect (! obj, 0))
1999-04-07 16:42:40 +02:00
JvThrow (new java::lang::NullPointerException);
#endif
if (__builtin_expect (INIT_NEEDED (obj), 0))
1999-04-07 16:42:40 +02: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;
if (__builtin_expect (_Jv_MutexUnlock (&si->mutex), 0))
1999-04-07 16:42:40 +02:00
JvThrow (new java::lang::IllegalMonitorStateException);
return 0;
}
void
_Jv_FinalizeObject (jobject obj)
{
java-interp.h: Don't include MethodInvocation.h. * include/java-interp.h: Don't include MethodInvocation.h. (class _Jv_InterpMethod): Don't make MethodInvocation a friend. * Makefile.in: Rebuilt. * Makefile.am (gnu/gcj/runtime/MethodInvocation.h): Removed. (ordinary_java_source_files): Don't mention MethodInvocation.java. * gnu/gcj/runtime/MethodInvocation.java: Removed. * interpret.cc (MethodInvocation::continue1): Removed. (run): Handle exceptions here. * java/lang/ClassLoader.java (defineClass1, defineClass2): Removed. * java/lang/natClassLoader.cc (defineClass0): Catch exceptions here. (defineClass2): Removed. * java/lang/reflect/Method.java (hack_trampoline, hack_call): Removed. * java/lang/reflect/natMethod.cc (_Jv_CallAnyMethodA): Catch exceptions here. (hack_call): Removed. * java/lang/Class.h (Class): Removed hackRunInitializers, hackTrampoline. * java/lang/natClass.cc (hackRunInitializers): Removed. (initializeClass): Catch exceptions here. Include ExceptionInInitializerError.h. * java/lang/Class.java (hackTrampoline, hackRunInitializers): Removed. * java/lang/Object.h (Object): Don't mention hack12_6. * java/lang/natObject.cc (_Jv_FinalizeObject): Catch exceptions here. * java/lang/Object.java (hack12_6): Removed. * java/lang/natThread.cc (run_): Renamed. Catch exceptions here. (start): Use run_, not run__. * java/lang/Thread.java (run_): Renamed from run__; old run_ removed. * jni.cc (_Jv_JNI_FindClass): Handle exceptions. (_Jv_JNI_EnsureLocalCapacity): Likewise. (_Jv_JNI_DefineClass): Likewise. (_Jv_JNI_ThrowNew): Likewise. (_Jv_JNI_AllocObject): Likewise. (_Jv_JNI_GetAnyMethodID): Likewise. (_Jv_JNI_CallAnyMethodV): Likewise. (_Jv_JNI_CallAnyMethodA): Likewise. (_Jv_JNI_CallAnyVoidMethodV): Likewise. (_Jv_JNI_CallAnyVoidMethodA): Likewise. (_Jv_JNI_GetAnyFieldID): Likewise. (_Jv_JNI_NewString): Likewise. (_Jv_JNI_NewStringUTF): Likewise. (_Jv_JNI_GetStringUTFChars): Likewise. (_Jv_JNI_NewObjectArray): Likewise. (_Jv_JNI_NewPrimitiveArray): Likewise. (_Jv_JNI_GetPrimitiveArrayRegion): Likewise. (_Jv_JNI_GetStringRegion): Likewise. (_Jv_JNI_GetStringUTFRegion): Likewise. (_Jv_JNI_SetPrimitiveArrayRegion): Likewise. (_Jv_JNI_MonitorEnter): Likewise. (_Jv_JNI_MonitorExit): Likewise. (_Jv_JNI_ToReflectedField): Likewise. (_Jv_JNI_ToReflectedMethod): Likewise. (_Jv_JNI_RegisterNatives): Likewise. (_Jv_JNI_AttachCurrentThread): Likewise. (_Jv_JNI_DestroyJavaVM): Likewise. From-SVN: r32294
2000-03-02 21:25:20 +01:00
// Ignore exceptions. From section 12.6 of the Java Language Spec.
try
{
obj->finalize ();
}
catch (java::lang::Throwable *t)
{
// Ignore.
}
1999-04-07 16:42:40 +02:00
}