javaprims.h: Rebuilt class list.

* gcj/javaprims.h: Rebuilt class list.
	* boehm.cc (_Jv_GCRegisterDisappearingLink): New function.
	(_Jv_GCCanReclaimSoftReference): New function.
	* include/jvm.h (_Jv_GCRegisterDisappearingLink): Declare.
	(_Jv_GCCanReclaimSoftReference): Declare.
	* java/lang/ref/Reference.java (referent): Now a RawData.
	(create): Renamed from `created'.  Added object argument.
	(Reference): Don't initialize `referent' here.
	* Makefile.in: Rebuilt.
	* Makefile.am (nat_source_files): Added new file.
	* java/lang/ref/natReference.cc: New file.

From-SVN: r45958
This commit is contained in:
Tom Tromey 2001-10-02 14:31:47 +00:00 committed by Tom Tromey
parent cacbc3505b
commit 2b3d3db68d
8 changed files with 401 additions and 34 deletions

View file

@ -1,5 +1,17 @@
2001-10-01 Tom Tromey <tromey@redhat.com>
* gcj/javaprims.h: Rebuilt class list.
* boehm.cc (_Jv_GCRegisterDisappearingLink): New function.
(_Jv_GCCanReclaimSoftReference): New function.
* include/jvm.h (_Jv_GCRegisterDisappearingLink): Declare.
(_Jv_GCCanReclaimSoftReference): Declare.
* java/lang/ref/Reference.java (referent): Now a RawData.
(create): Renamed from `created'. Added object argument.
(Reference): Don't initialize `referent' here.
* Makefile.in: Rebuilt.
* Makefile.am (nat_source_files): Added new file.
* java/lang/ref/natReference.cc: New file.
* prims.cc (_Jv_NewMultiArrayUnchecked): New method.
(_Jv_NewMultiArray): Use it. Check each array dimension.
(_Jv_NewMultiArray): Likewise.

View file

@ -1511,6 +1511,7 @@ java/lang/natStringBuffer.cc \
java/lang/natSystem.cc \
java/lang/natThread.cc \
java/lang/natThrowable.cc \
java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \
java/lang/reflect/natConstructor.cc \
java/lang/reflect/natField.cc \

View file

@ -63,16 +63,13 @@ host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
AMTAR = @AMTAR@
AM_RUNTESTFLAGS = @AM_RUNTESTFLAGS@
AR = @AR@
AS = @AS@
AWK = @AWK@
CC = @CC@
COMPPATH = @COMPPATH@
CXX = @CXX@
CXXCPP = @CXXCPP@
DEPDIR = @DEPDIR@
DIRLTDL = @DIRLTDL@
DIVIDESPEC = @DIVIDESPEC@
DLLTOOL = @DLLTOOL@
@ -89,7 +86,6 @@ GCSPEC = @GCSPEC@
GCTESTSPEC = @GCTESTSPEC@
HASH_SYNC_SPEC = @HASH_SYNC_SPEC@
INCLTDL = @INCLTDL@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JC1GCSPEC = @JC1GCSPEC@
LIBFFI = @LIBFFI@
LIBGCJDEBUG = @LIBGCJDEBUG@
@ -122,34 +118,43 @@ ZINCS = @ZINCS@
ZLIBS = @ZLIBS@
ZLIBSPEC = @ZLIBSPEC@
ZLIBTESTSPEC = @ZLIBTESTSPEC@
am__include = @am__include@
am__quote = @am__quote@
here = @here@
install_sh = @install_sh@
libgcj_basedir = @libgcj_basedir@
mkinstalldirs = @mkinstalldirs@
AUTOMAKE_OPTIONS = foreign
@TESTSUBDIR_TRUE@SUBDIRS = @TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
@TESTSUBDIR_FALSE@SUBDIRS = @TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
@USE_LIBDIR_TRUE@toolexeclibdir = @USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
@USE_LIBDIR_FALSE@toolexeclibdir = @USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
@USE_LIBDIR_FALSE@toolexecdir = @USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
@XLIB_AWT_TRUE@cond_x_ltlibrary = @XLIB_AWT_TRUE@libgcjx.la
@XLIB_AWT_FALSE@cond_x_ltlibrary =
@TESTSUBDIR_TRUE@SUBDIRS = \
@TESTSUBDIR_TRUE@$(DIRLTDL) testsuite gcj include
@TESTSUBDIR_FALSE@SUBDIRS = \
@TESTSUBDIR_FALSE@$(DIRLTDL) gcj include
@USE_LIBDIR_TRUE@toolexeclibdir = \
@USE_LIBDIR_TRUE@$(libdir)$(MULTISUBDIR)
@USE_LIBDIR_FALSE@toolexeclibdir = \
@USE_LIBDIR_FALSE@$(toolexecdir)/lib$(MULTISUBDIR)
@USE_LIBDIR_FALSE@toolexecdir = \
@USE_LIBDIR_FALSE@$(exec_prefix)/$(target_alias)
@XLIB_AWT_TRUE@cond_x_ltlibrary = \
@XLIB_AWT_TRUE@libgcjx.la
@XLIB_AWT_FALSE@cond_x_ltlibrary = \
toolexeclib_LTLIBRARIES = libgcj.la $(cond_x_ltlibrary)
toolexeclib_DATA = libgcj.spec
data_DATA = libgcj.jar
@NATIVE_TRUE@bin_PROGRAMS = @NATIVE_TRUE@jv-convert gij rmic rmiregistry
@NATIVE_TRUE@bin_PROGRAMS = \
@NATIVE_TRUE@jv-convert gij rmic rmiregistry
bin_SCRIPTS = addr2name.awk
@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = @CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
@CANADIAN_FALSE@ZIP = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
@CANADIAN_TRUE@GCJH = @CANADIAN_TRUE@gcjh
@CANADIAN_FALSE@GCJH = @CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
@CANADIAN_TRUE@@NULL_TARGET_TRUE@ZIP = \
@CANADIAN_TRUE@@NULL_TARGET_TRUE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
@CANADIAN_TRUE@@NULL_TARGET_FALSE@ZIP = \
@CANADIAN_TRUE@@NULL_TARGET_FALSE@jar
@CANADIAN_FALSE@ZIP = \
@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/fastjar/jar$(EXEEXT)
@CANADIAN_TRUE@GCJH = \
@CANADIAN_TRUE@gcjh
@CANADIAN_FALSE@GCJH = \
@CANADIAN_FALSE@$(MULTIBUILDTOP)../$(COMPPATH)/gcc/gcjh$(EXEEXT)
GCJ_WITH_FLAGS = $(GCJ) --encoding=UTF-8
@ -169,8 +174,10 @@ AM_CXXFLAGS = -fno-rtti -fnon-call-exceptions \
@LIBGCJ_CXXFLAGS@ @X_CFLAGS@ $(WARNINGS) -D_GNU_SOURCE \
-DPREFIX="\"$(prefix)\""
@USING_GCC_TRUE@AM_CFLAGS = @USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
@USING_GCC_FALSE@AM_CFLAGS = @USING_GCC_FALSE@@LIBGCJ_CFLAGS@
@USING_GCC_TRUE@AM_CFLAGS = \
@USING_GCC_TRUE@@LIBGCJ_CFLAGS@ $(WARNINGS)
@USING_GCC_FALSE@AM_CFLAGS = \
@USING_GCC_FALSE@@LIBGCJ_CFLAGS@
JCFLAGS = -g
JC1FLAGS = @LIBGCJ_JAVAFLAGS@ $(GCJFLAGS)
@ -239,7 +246,8 @@ extra_headers = java/lang/Object.h java/lang/Class.h
NM = nm
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = @NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@noinst_PROGRAMS = \
@NATIVE_TRUE@@MAINTAINER_MODE_TRUE@gen-from-JIS
CONVERT_DIR = gnu/gcj/convert
@ -1243,6 +1251,7 @@ java/lang/natStringBuffer.cc \
java/lang/natSystem.cc \
java/lang/natThread.cc \
java/lang/natThrowable.cc \
java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \
java/lang/reflect/natConstructor.cc \
java/lang/reflect/natField.cc \
@ -1396,12 +1405,12 @@ java/lang/natDouble.lo java/lang/natFloat.lo java/lang/natMath.lo \
java/lang/natObject.lo java/lang/natRuntime.lo java/lang/natString.lo \
java/lang/natStringBuffer.lo java/lang/natSystem.lo \
java/lang/natThread.lo java/lang/natThrowable.lo \
java/lang/reflect/natArray.lo java/lang/reflect/natConstructor.lo \
java/lang/reflect/natField.lo java/lang/reflect/natMethod.lo \
java/net/natInetAddress.lo java/net/natPlainDatagramSocketImpl.lo \
java/net/natPlainSocketImpl.lo java/text/natCollator.lo \
java/util/natResourceBundle.lo java/util/zip/natDeflater.lo \
java/util/zip/natInflater.lo
java/lang/ref/natReference.lo java/lang/reflect/natArray.lo \
java/lang/reflect/natConstructor.lo java/lang/reflect/natField.lo \
java/lang/reflect/natMethod.lo java/net/natInetAddress.lo \
java/net/natPlainDatagramSocketImpl.lo java/net/natPlainSocketImpl.lo \
java/text/natCollator.lo java/util/natResourceBundle.lo \
java/util/zip/natDeflater.lo java/util/zip/natInflater.lo
libgcjx_la_OBJECTS = gnu/gcj/xlib/natClip.lo \
gnu/gcj/xlib/natColormap.lo gnu/gcj/xlib/natDisplay.lo \
gnu/gcj/xlib/natDrawable.lo gnu/gcj/xlib/natFont.lo \
@ -1445,7 +1454,7 @@ libgcj-test.spec.in libgcj.spec.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = gtar
TAR = tar
GZIP_ENV = --best
DIST_SUBDIRS = @DIRLTDL@ testsuite gcj include @DIRLTDL@ gcj include
DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
@ -1841,6 +1850,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \
.deps/java/lang/ref/PhantomReference.P .deps/java/lang/ref/Reference.P \
.deps/java/lang/ref/ReferenceQueue.P \
.deps/java/lang/ref/SoftReference.P .deps/java/lang/ref/WeakReference.P \
.deps/java/lang/ref/natReference.P \
.deps/java/lang/reflect/AccessibleObject.P \
.deps/java/lang/reflect/Array.P .deps/java/lang/reflect/Constructor.P \
.deps/java/lang/reflect/Field.P \
@ -2483,7 +2493,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \

View file

@ -543,6 +543,19 @@ _Jv_AllocTraceOne (jsize size /* includes vtable slot */)
#endif /* JV_HASH_SYNCHRONIZATION */
void
_Jv_GCRegisterDisappearingLink (jobject *objp)
{
GC_general_register_disappearing_link ((GC_PTR *) objp, (GC_PTR) *objp);
}
jboolean
_Jv_GCCanReclaimSoftReference (jobject obj)
{
// For now, always reclaim soft references. FIXME.
return true;
}
#if 0
void
_Jv_InitGC (void)

View file

@ -192,6 +192,7 @@ extern "Java"
class Short;
class StackOverflowError;
class String;
class String$CaseInsensitiveComparator;
class StringBuffer;
class StringIndexOutOfBoundsException;
class System;

View file

@ -166,6 +166,13 @@ void _Jv_RunGC (void);
/* Disable and enable GC. */
void _Jv_DisableGC (void);
void _Jv_EnableGC (void);
/* Register a disappearing link. This is a field F which should be
cleared when *F is found to be inaccessible. This is used in the
implementation of java.lang.ref.Reference. */
void _Jv_GCRegisterDisappearingLink (jobject *objp);
/* Return true if OBJECT should be reclaimed. This is used to
implement soft references. */
jboolean _Jv_GCCanReclaimSoftReference (jobject obj);
/* Return approximation of total size of heap. */
long _Jv_GCTotalMemory (void);

View file

@ -64,8 +64,21 @@ public abstract class Reference
/**
* The underlying object. This field is handled in a special way by
* the garbage collection.
* GCJ LOCAL:
* This is a RawData because it must be disguised from the GC.
* END GCJ LOCAL
*/
Object referent;
gnu.gcj.RawData referent;
/**
* This is like REFERENT but is not scanned by the GC. We keep a
* copy around so that we can see when clear() has been called.
* GCJ LOCAL:
* This field doesn't exist in Classpath; we use it to detect
* clearing.
* END GCJ LOCAL
*/
gnu.gcj.RawData copy;
/**
* The queue this reference is registered on. This is null, if this
@ -97,7 +110,7 @@ public abstract class Reference
*/
Reference(Object ref)
{
referent = ref;
create (ref);
}
/**
@ -112,10 +125,15 @@ public abstract class Reference
{
if (q == null)
throw new NullPointerException();
referent = ref;
queue = q;
create (ref);
}
/**
* Notifies the VM that a new Reference has been created.
*/
private native void create (Object o);
/**
* Returns the object, this reference refers to.
* @return the object, this reference refers to, or null if the
@ -138,6 +156,7 @@ public abstract class Reference
public void clear()
{
referent = null;
copy = null;
}
/**

View file

@ -0,0 +1,304 @@
// natReference.cc - Native code for References
/* Copyright (C) 2001 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. */
// Written by Tom Tromey <tromey@redhat.com>
#include <config.h>
#include <gcj/cni.h>
#include <jvm.h>
#include <java/lang/Throwable.h>
#include <java/lang/ref/Reference.h>
#include <java/lang/ref/SoftReference.h>
#include <java/lang/ref/WeakReference.h>
#include <java/lang/ref/PhantomReference.h>
#include <java/lang/ref/ReferenceQueue.h>
static void finalize_reference (jobject ref);
static void finalize_referred_to_object (jobject obj);
enum weight
{
SOFT = 0,
WEAK = 1,
FINALIZE = 2,
PHANTOM = 3,
// This is used to mark the head of a list.
HEAD = 4,
// This is used to mark a deleted item.
DELETED = 5
};
// Objects of this type are used in the hash table to keep track of
// the mapping between a finalizable object and the various References
// which refer to it.
struct object_list
{
// The reference object. This is NULL for FINALIZE weight.
jobject reference;
// The weight of this object.
enum weight weight;
// Next in list.
object_list *next;
};
// Hash table used to hold mapping from object to References. The
// object_list item in the hash holds the object itself in the
// reference field; chained to it are all the references sorted in
// order of weight (lowest first).
static object_list *hash = NULL;
// Number of slots used in HASH.
static int hash_count = 0;
// Number of slots total in HASH. Must be power of 2.
static int hash_size = 0;
static object_list *
find_slot (jobject key)
{
jint hcode = _Jv_HashCode (key);
/* step must be non-zero, and relatively prime with hash_size. */
jint step = (hcode ^ (hcode >> 16)) | 1;
int start_index = hcode & (hash_size - 1);
int index = start_index;
int deleted_index = -1;
for (;;)
{
object_list *ptr = &hash[index];
if (ptr->reference == key)
return ptr;
else if (ptr->reference == NULL)
{
if (deleted_index == -1)
return ptr;
else
return &hash[deleted_index];
}
else if (ptr->weight == DELETED)
deleted_index = index;
index = (index + step) & (hash_size - 1);
JvAssert (index != start_index);
}
}
static void
rehash ()
{
if (hash == NULL)
{
hash_size = 1024;
hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list));
memset (hash, 0, hash_size * sizeof (object_list));
}
else
{
object_list *old = hash;
int i = hash_size;
hash_size *= 2;
hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list));
memset (hash, 0, hash_size * sizeof (object_list));
while (--i >= 0)
{
if (old[i].reference == NULL || old[i].weight == DELETED)
continue;
object_list *newslot = find_slot (old[i].reference);
*newslot = old[i];
}
_Jv_Free (old);
}
}
// Remove a Reference.
static void
remove_from_hash (jobject obj)
{
java::lang::ref::Reference *ref
= reinterpret_cast<java::lang::ref::Reference *> (obj);
object_list *head = find_slot (ref->copy);
object_list **link = &head->next;
head = head->next;
while (head && head->reference != ref)
{
link = &head->next;
head = head->next;
}
// Remove the slot.
if (head)
{
*link = head->next;
_Jv_Free (head);
}
}
// FIXME what happens if an object's finalizer creates a Reference to
// the object, and the object has never before been added to the hash?
// Madness!
// Add an item to the hash table. If the item is new, we also add a
// finalizer item. We keep items in the hash table until they are
// completely collected; this lets us know when an item is new, even
// if it has been resurrected after its finalizer has been run.
static void
add_to_hash (java::lang::ref::Reference *the_reference)
{
JvSynchronize sync (java::lang::ref::Reference::lock);
if (3 * hash_count >= 2 * hash_size)
rehash ();
jobject referent = the_reference->referent;
object_list *item = find_slot (referent);
if (item->reference == NULL)
{
// New item, so make an entry for the finalizer.
item->reference = referent;
item->weight = HEAD;
item->next = (object_list *) _Jv_Malloc (sizeof (object_list));
item->next->reference = NULL;
item->next->weight = FINALIZE;
item->next->next = NULL;
++hash_count;
}
object_list *n = (object_list *) _Jv_Malloc (sizeof (object_list));
n->reference = the_reference;
enum weight w = PHANTOM;
if (java::lang::ref::SoftReference::class$.isInstance (the_reference))
w = SOFT;
else if (java::lang::ref::WeakReference::class$.isInstance (the_reference))
w = WEAK;
n->weight = w;
object_list **link = &item->next;
object_list *iter = *link;
while (iter && iter->weight < n->weight)
{
link = &iter->next;
iter = *link;
}
*link = n;
n->next = (*link) ? (*link)->next : NULL;
}
// This is called when an object is ready to be finalized. This
// actually implements the appropriate Reference semantics.
static void
finalize_referred_to_object (jobject obj)
{
JvSynchronize sync (java::lang::ref::Reference::lock);
object_list *list = find_slot (obj);
object_list *head = list->next;
if (head == NULL)
{
// We have a truly dead object: the object's finalizer has been
// run, all the object's references have been processed, and the
// object is unreachable. There is, at long last, no way to
// resurrect it.
list->weight = DELETED;
--hash_count;
return;
}
enum weight w = head->weight;
if (w == FINALIZE)
{
// If we have a Reference A to a Reference B, and B is
// finalized, then we have to take special care to make sure
// that B is properly deregistered. This is super gross. FIXME
// will it fail if B's finalizer resurrects B?
if (java::lang::ref::Reference::class$.isInstance (obj))
finalize_reference (obj);
else
_Jv_FinalizeObject (obj);
list->next = head->next;
_Jv_Free (head);
}
else if (w != SOFT || _Jv_GCCanReclaimSoftReference (obj))
{
// If we just decided to reclaim a soft reference, we might as
// well do all the weak references at the same time.
if (w == SOFT)
w = WEAK;
while (head && head->weight <= w)
{
java::lang::ref::Reference *ref
= reinterpret_cast<java::lang::ref::Reference *> (head->reference);
// If the copy is already NULL then the user must have
// called Reference.clear().
if (ref->copy != NULL)
{
if (w == PHANTOM)
ref->referent = ref->copy;
else
ref->copy = NULL;
ref->enqueue ();
}
object_list *next = head->next;
_Jv_Free (head);
head = next;
}
list->next = head;
}
// Re-register this finalizer. We always re-register because we
// can't know until the next collection cycle whether or not the
// object is truly unreachable.
_Jv_RegisterFinalizer (obj, finalize_referred_to_object);
}
// This is called when a Reference object is finalized. If there is a
// Reference pointing to this Reference then that case is handled by
// finalize_referred_to_object.
static void
finalize_reference (jobject ref)
{
JvSynchronize sync (java::lang::ref::Reference::lock);
remove_from_hash (ref);
// The user might have a subclass of Reference with a finalizer.
_Jv_FinalizeObject (ref);
}
void
::java::lang::ref::Reference::create (jobject ref)
{
// Nothing says you can't make a Reference with a NULL referent.
// But there's nothing to do in such a case.
referent = reinterpret_cast<gnu::gcj::RawData *> (ref);
copy = referent;
if (referent != NULL)
{
JvSynchronize sync (java::lang::ref::Reference::lock);
// `this' is a new Reference object. We register a new
// finalizer for pointed-to object and we arrange a special
// finalizer for ourselves as well.
_Jv_RegisterFinalizer (this, finalize_reference);
_Jv_RegisterFinalizer (referent, finalize_referred_to_object);
jobject *objp = reinterpret_cast<jobject *> (&referent);
_Jv_GCRegisterDisappearingLink (objp);
add_to_hash (this);
}
}