OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [java/] [lang/] [ref/] [natReference.cc] - Blame information for rev 758

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 758 jeremybenn
// natReference.cc - Native code for References
2
 
3
/* Copyright (C) 2001, 2002, 2003, 2005, 2006  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
// Written by Tom Tromey <tromey@redhat.com>
12
 
13
#include <config.h>
14
 
15
#include <gcj/cni.h>
16
#include <jvm.h>
17
#include <java/lang/Throwable.h>
18
#include <java/lang/ref/Reference.h>
19
#include <java/lang/ref/SoftReference.h>
20
#include <java/lang/ref/WeakReference.h>
21
#include <java/lang/ref/PhantomReference.h>
22
#include <java/lang/ref/ReferenceQueue.h>
23
 
24
static void finalize_reference (jobject ref);
25
static void finalize_referred_to_object (jobject obj);
26
 
27
 
28
 
29
enum weight
30
{
31
  SOFT = 0,
32
  WEAK = 1,
33
  FINALIZE = 2,
34
  PHANTOM = 3,
35
 
36
  // This is used to mark the head of a list.
37
  HEAD = 4,
38
 
39
  // This is used to mark a deleted item.
40
  DELETED = 5
41
};
42
 
43
// Objects of this type are used in the hash table to keep track of
44
// the mapping between a finalizable object and the various References
45
// which refer to it.
46
struct object_list
47
{
48
  // The reference object.  This is NULL for FINALIZE weight.
49
  jobject reference;
50
 
51
  // The weight of this object.
52
  enum weight weight;
53
 
54
  // Next in list.
55
  object_list *next;
56
};
57
 
58
// Hash table used to hold mapping from object to References.  The
59
// object_list item in the hash holds the object itself in the
60
// reference field; chained to it are all the references sorted in
61
// order of weight (lowest first).
62
static object_list *hash = NULL;
63
 
64
// Number of slots used in HASH.
65
static int hash_count = 0;
66
 
67
// Number of slots total in HASH.  Must be power of 2.
68
static int hash_size = 0;
69
 
70
#define DELETED_REFERENCE  ((jobject) -1)
71
 
72
static object_list *
73
find_slot (jobject key)
74
{
75
  jint hcode = _Jv_HashCode (key);
76
  /* step must be non-zero, and relatively prime with hash_size. */
77
  jint step = (hcode ^ (hcode >> 16)) | 1;
78
  int start_index = hcode & (hash_size - 1);
79
  int index = start_index;
80
  int deleted_index = -1;
81
  do
82
    {
83
      object_list *ptr = &hash[index];
84
      if (ptr->reference == key)
85
        return ptr;
86
      else if (ptr->reference == NULL)
87
        {
88
          if (deleted_index == -1)
89
            return ptr;
90
          else
91
            return &hash[deleted_index];
92
        }
93
      else if (ptr->weight == DELETED)
94
        {
95
          deleted_index = index;
96
          JvAssert (ptr->reference == DELETED_REFERENCE);
97
        }
98
      index = (index + step) & (hash_size - 1);
99
    }
100
  while (index != start_index);
101
  // Note that we can have INDEX == START_INDEX if the table has no
102
  // NULL entries but does have DELETED entries.
103
  JvAssert (deleted_index >= 0);
104
  return &hash[deleted_index];
105
}
106
 
107
static void
108
rehash ()
109
{
110
  if (hash == NULL)
111
    {
112
      hash_size = 1024;
113
      hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list));
114
      memset (hash, 0, hash_size * sizeof (object_list));
115
    }
116
  else
117
    {
118
      object_list *old = hash;
119
      int i = hash_size;
120
 
121
      hash_size *= 2;
122
      hash = (object_list *) _Jv_Malloc (hash_size * sizeof (object_list));
123
      memset (hash, 0, hash_size * sizeof (object_list));
124
 
125
      while (--i >= 0)
126
        {
127
          if (old[i].reference == NULL || old[i].weight == DELETED)
128
            continue;
129
          object_list *newslot = find_slot (old[i].reference);
130
          *newslot = old[i];
131
        }
132
 
133
      _Jv_Free (old);
134
    }
135
}
136
 
137
// Remove a Reference.
138
static void
139
remove_from_hash (jobject obj)
140
{
141
  java::lang::ref::Reference *ref
142
    = reinterpret_cast<java::lang::ref::Reference *> (obj);
143
  object_list *head = find_slot (ref->copy);
144
 
145
  // We might have found a new slot.  We can just ignore that here.
146
  if (head->reference != ref->copy)
147
    return;
148
 
149
  object_list **link = &head->next;
150
  head = head->next;
151
 
152
  while (head && head->reference != ref)
153
    {
154
      link = &head->next;
155
      head = head->next;
156
    }
157
 
158
  // Remove the slot.
159
  if (head)
160
    {
161
      *link = head->next;
162
      _Jv_Free (head);
163
    }
164
}
165
 
166
// Return list head if object is in hash, NULL otherwise.
167
object_list *
168
in_hash (jobject obj)
169
{
170
  // The hash table might not yet be initialized.
171
  if (hash == NULL)
172
    return NULL;
173
  object_list *head = find_slot (obj);
174
  if (head->reference != obj)
175
    return NULL;
176
  return head;
177
}
178
 
179
// FIXME what happens if an object's finalizer creates a Reference to
180
// the object, and the object has never before been added to the hash?
181
// Madness!
182
 
183
// Add an item to the hash table.  If the item is new, we also add a
184
// finalizer item.  We keep items in the hash table until they are
185
// completely collected; this lets us know when an item is new, even
186
// if it has been resurrected after its finalizer has been run.
187
static void
188
add_to_hash (java::lang::ref::Reference *the_reference)
189
{
190
  JvSynchronize sync (java::lang::ref::Reference::lock);
191
 
192
  if (3 * hash_count >= 2 * hash_size)
193
    rehash ();
194
 
195
  // Use `copy' here because the `referent' field has been cleared.
196
  jobject referent = the_reference->copy;
197
  object_list *item = find_slot (referent);
198
  if (item->reference == NULL || item->reference == DELETED_REFERENCE)
199
    {
200
      // New item, so make an entry for the finalizer.
201
      item->reference = referent;
202
      item->weight = HEAD;
203
 
204
      item->next = (object_list *) _Jv_Malloc (sizeof (object_list));
205
      item->next->reference = NULL;
206
      item->next->weight = FINALIZE;
207
      item->next->next = NULL;
208
      ++hash_count;
209
    }
210
 
211
  object_list *n = (object_list *) _Jv_Malloc (sizeof (object_list));
212
  n->reference = the_reference;
213
 
214
  enum weight w = PHANTOM;
215
  if (java::lang::ref::SoftReference::class$.isInstance (the_reference))
216
    w = SOFT;
217
  else if (java::lang::ref::WeakReference::class$.isInstance (the_reference))
218
    w = WEAK;
219
  n->weight = w;
220
 
221
  object_list **link = &item->next;
222
  object_list *iter = *link;
223
  while (iter && iter->weight < n->weight)
224
    {
225
      link = &iter->next;
226
      iter = *link;
227
    }
228
  n->next = *link;
229
  *link = n;
230
}
231
 
232
// Add a FINALIZE entry if one doesn't exist.
233
static void
234
maybe_add_finalize (object_list *entry, jobject obj)
235
{
236
  object_list **link = &entry->next;
237
  object_list *iter = *link;
238
  while (iter && iter->weight < FINALIZE)
239
    {
240
      link = &iter->next;
241
      iter = *link;
242
    }
243
 
244
  // We want at most one FINALIZE entry in the queue.
245
  if (iter && iter->weight == FINALIZE)
246
    return;
247
 
248
  object_list *n = (object_list *) _Jv_Malloc (sizeof (object_list));
249
  n->reference = obj;
250
  n->weight = FINALIZE;
251
  n->next = *link;
252
  *link = n;
253
}
254
 
255
// This is called when an object is ready to be finalized.  This
256
// actually implements the appropriate Reference semantics.
257
static void
258
finalize_referred_to_object (jobject obj)
259
{
260
  JvSynchronize sync (java::lang::ref::Reference::lock);
261
 
262
  object_list *list = find_slot (obj);
263
  object_list *head = list->next;
264
  if (head == NULL)
265
    {
266
      // We have a truly dead object: the object's finalizer has been
267
      // run, all the object's references have been processed, and the
268
      // object is unreachable.  There is, at long last, no way to
269
      // resurrect it.
270
      list->reference = DELETED_REFERENCE;
271
      list->weight = DELETED;
272
      --hash_count;
273
      return;
274
    }
275
 
276
  enum weight w = head->weight;
277
  if (w == FINALIZE)
278
    {
279
      // Update the list first, as _Jv_FinalizeString might end up
280
      // looking at this data structure.
281
      list->next = head->next;
282
      _Jv_Free (head);
283
 
284
      // If we have a Reference A to a Reference B, and B is
285
      // finalized, then we have to take special care to make sure
286
      // that B is properly deregistered.  This is super gross.  FIXME
287
      // will it fail if B's finalizer resurrects B?
288
      if (java::lang::ref::Reference::class$.isInstance (obj))
289
        finalize_reference (obj);
290
      else if (obj->getClass() == &java::lang::String::class$)
291
        _Jv_FinalizeString (obj);
292
      else
293
        _Jv_FinalizeObject (obj);
294
    }
295
  else if (w != SOFT || _Jv_GCCanReclaimSoftReference (obj))
296
    {
297
      // If we just decided to reclaim a soft reference, we might as
298
      // well do all the weak references at the same time.
299
      if (w == SOFT)
300
        w = WEAK;
301
 
302
      while (head && head->weight <= w)
303
        {
304
          java::lang::ref::Reference *ref
305
            = reinterpret_cast<java::lang::ref::Reference *> (head->reference);
306
          if (! ref->cleared)
307
            ref->enqueue ();
308
 
309
          object_list *next = head->next;
310
          _Jv_Free (head);
311
          head = next;
312
        }
313
      list->next = head;
314
    }
315
 
316
  // Re-register this finalizer.  We always re-register because we
317
  // can't know until the next collection cycle whether or not the
318
  // object is truly unreachable.
319
  _Jv_RegisterFinalizer (obj, finalize_referred_to_object);
320
}
321
 
322
// This is called when a Reference object is finalized.  If there is a
323
// Reference pointing to this Reference then that case is handled by
324
// finalize_referred_to_object.
325
static void
326
finalize_reference (jobject ref)
327
{
328
  JvSynchronize sync (java::lang::ref::Reference::lock);
329
  remove_from_hash (ref);
330
  // The user might have a subclass of Reference with a finalizer.
331
  _Jv_FinalizeObject (ref);
332
}
333
 
334
void
335
_Jv_RegisterStringFinalizer (jobject str)
336
{
337
  // This function might be called before any other Reference method,
338
  // so we must ensure the class is initialized.
339
  _Jv_InitClass (&java::lang::ref::Reference::class$);
340
  JvSynchronize sync (java::lang::ref::Reference::lock);
341
  // If the object is in our hash table, then we might need to add a
342
  // new FINALIZE entry.  Otherwise, we just register an ordinary
343
  // finalizer.
344
  object_list *entry = in_hash (str);
345
  if (entry)
346
    maybe_add_finalize (entry, str);
347
  else
348
    _Jv_RegisterFinalizer ((void *) str, _Jv_FinalizeString);
349
}
350
 
351
void
352
::java::lang::ref::Reference::create (jobject ref)
353
{
354
  // Nothing says you can't make a Reference with a NULL referent.
355
  // But there's nothing to do in such a case.
356
  referent = reinterpret_cast<gnu::gcj::RawData *> (ref);
357
  copy = referent;
358
  if (referent != NULL)
359
    {
360
      JvSynchronize sync (java::lang::ref::Reference::lock);
361
      // `this' is a new Reference object.  We register a new
362
      // finalizer for pointed-to object and we arrange a special
363
      // finalizer for ourselves as well.
364
      _Jv_RegisterFinalizer (this, finalize_reference);
365
      _Jv_RegisterFinalizer (referent, finalize_referred_to_object);
366
      gnu::gcj::RawData **p = &referent;
367
     _Jv_GCRegisterDisappearingLink ((jobject *) p);
368
      add_to_hash (this);
369
    }
370
}
371
 
372
::java::lang::Object *
373
::java::lang::ref::Reference::get()
374
{
375
  JvSynchronize sync (lock);
376
  return referent;
377
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.