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:
parent
cacbc3505b
commit
2b3d3db68d
8 changed files with 401 additions and 34 deletions
|
@ -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.
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -192,6 +192,7 @@ extern "Java"
|
|||
class Short;
|
||||
class StackOverflowError;
|
||||
class String;
|
||||
class String$CaseInsensitiveComparator;
|
||||
class StringBuffer;
|
||||
class StringIndexOutOfBoundsException;
|
||||
class System;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
304
libjava/java/lang/ref/natReference.cc
Normal file
304
libjava/java/lang/ref/natReference.cc
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue