instanceRefKlass.cpp 20.6 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genCollectedHeap.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/preserveException.hpp"
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif
D
duke 已提交
46

47 48 49
template <class T>
static void specialized_oop_follow_contents(instanceRefKlass* ref, oop obj) {
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
50
  T heap_oop = oopDesc::load_heap_oop(referent_addr);
D
duke 已提交
51 52
  debug_only(
    if(TraceReferenceGC && PrintGCDetails) {
53
      gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj);
D
duke 已提交
54 55
    }
  )
56 57
  if (!oopDesc::is_null(heap_oop)) {
    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
D
duke 已提交
58 59
    if (!referent->is_gc_marked() &&
        MarkSweep::ref_processor()->
60
          discover_reference(obj, ref->reference_type())) {
D
duke 已提交
61
      // reference already enqueued, referent will be traversed later
62
      ref->instanceKlass::oop_follow_contents(obj);
D
duke 已提交
63 64
      debug_only(
        if(TraceReferenceGC && PrintGCDetails) {
65
          gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, obj);
D
duke 已提交
66 67 68 69 70 71 72
        }
      )
      return;
    } else {
      // treat referent as normal oop
      debug_only(
        if(TraceReferenceGC && PrintGCDetails) {
73
          gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, obj);
D
duke 已提交
74 75 76 77 78 79
        }
      )
      MarkSweep::mark_and_push(referent_addr);
    }
  }
  // treat next as normal oop.  next is a link in the pending list.
80
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
D
duke 已提交
81 82 83 84 85 86
  debug_only(
    if(TraceReferenceGC && PrintGCDetails) {
      gclog_or_tty->print_cr("   Process next as normal " INTPTR_FORMAT, next_addr);
    }
  )
  MarkSweep::mark_and_push(next_addr);
87 88 89 90 91 92 93 94 95
  ref->instanceKlass::oop_follow_contents(obj);
}

void instanceRefKlass::oop_follow_contents(oop obj) {
  if (UseCompressedOops) {
    specialized_oop_follow_contents<narrowOop>(this, obj);
  } else {
    specialized_oop_follow_contents<oop>(this, obj);
  }
D
duke 已提交
96 97 98
}

#ifndef SERIALGC
99
template <class T>
100 101 102
void specialized_oop_follow_contents(instanceRefKlass* ref,
                                     ParCompactionManager* cm,
                                     oop obj) {
103
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
104
  T heap_oop = oopDesc::load_heap_oop(referent_addr);
D
duke 已提交
105 106
  debug_only(
    if(TraceReferenceGC && PrintGCDetails) {
107
      gclog_or_tty->print_cr("instanceRefKlass::oop_follow_contents " INTPTR_FORMAT, obj);
D
duke 已提交
108 109
    }
  )
110 111
  if (!oopDesc::is_null(heap_oop)) {
    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
D
duke 已提交
112 113
    if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) &&
        PSParallelCompact::ref_processor()->
114
          discover_reference(obj, ref->reference_type())) {
D
duke 已提交
115
      // reference already enqueued, referent will be traversed later
116
      ref->instanceKlass::oop_follow_contents(cm, obj);
D
duke 已提交
117 118
      debug_only(
        if(TraceReferenceGC && PrintGCDetails) {
119
          gclog_or_tty->print_cr("       Non NULL enqueued " INTPTR_FORMAT, obj);
D
duke 已提交
120 121 122 123 124 125 126
        }
      )
      return;
    } else {
      // treat referent as normal oop
      debug_only(
        if(TraceReferenceGC && PrintGCDetails) {
127
          gclog_or_tty->print_cr("       Non NULL normal " INTPTR_FORMAT, obj);
D
duke 已提交
128 129 130 131 132 133
        }
      )
      PSParallelCompact::mark_and_push(cm, referent_addr);
    }
  }
  // treat next as normal oop.  next is a link in the pending list.
134
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
D
duke 已提交
135 136 137 138 139 140
  debug_only(
    if(TraceReferenceGC && PrintGCDetails) {
      gclog_or_tty->print_cr("   Process next as normal " INTPTR_FORMAT, next_addr);
    }
  )
  PSParallelCompact::mark_and_push(cm, next_addr);
141
  ref->instanceKlass::oop_follow_contents(cm, obj);
D
duke 已提交
142 143
}

144 145 146 147 148 149 150 151 152
void instanceRefKlass::oop_follow_contents(ParCompactionManager* cm,
                                           oop obj) {
  if (UseCompressedOops) {
    specialized_oop_follow_contents<narrowOop>(this, cm, obj);
  } else {
    specialized_oop_follow_contents<oop>(this, cm, obj);
  }
}
#endif // SERIALGC
D
duke 已提交
153 154

#ifdef ASSERT
155 156 157 158
template <class T> void trace_reference_gc(const char *s, oop obj,
                                           T* referent_addr,
                                           T* next_addr,
                                           T* discovered_addr) {
D
duke 已提交
159
  if(TraceReferenceGC && PrintGCDetails) {
160
    gclog_or_tty->print_cr("%s obj " INTPTR_FORMAT, s, (address)obj);
D
duke 已提交
161
    gclog_or_tty->print_cr("     referent_addr/* " INTPTR_FORMAT " / "
162 163 164
         INTPTR_FORMAT, referent_addr,
         referent_addr ?
           (address)oopDesc::load_decode_heap_oop(referent_addr) : NULL);
D
duke 已提交
165
    gclog_or_tty->print_cr("     next_addr/* " INTPTR_FORMAT " / "
166 167
         INTPTR_FORMAT, next_addr,
         next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL);
D
duke 已提交
168
    gclog_or_tty->print_cr("     discovered_addr/* " INTPTR_FORMAT " / "
169 170 171
         INTPTR_FORMAT, discovered_addr,
         discovered_addr ?
           (address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL);
D
duke 已提交
172
  }
173
}
D
duke 已提交
174 175
#endif

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
template <class T> void specialized_oop_adjust_pointers(instanceRefKlass *ref, oop obj) {
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
  MarkSweep::adjust_pointer(referent_addr);
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
  MarkSweep::adjust_pointer(next_addr);
  T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
  MarkSweep::adjust_pointer(discovered_addr);
  debug_only(trace_reference_gc("instanceRefKlass::oop_adjust_pointers", obj,
                                referent_addr, next_addr, discovered_addr);)
}

int instanceRefKlass::oop_adjust_pointers(oop obj) {
  int size = size_helper();
  instanceKlass::oop_adjust_pointers(obj);

  if (UseCompressedOops) {
    specialized_oop_adjust_pointers<narrowOop>(this, obj);
  } else {
    specialized_oop_adjust_pointers<oop>(this, obj);
  }
D
duke 已提交
196 197 198
  return size;
}

199
#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains)        \
200 201 202 203 204
  if (closure->apply_to_weak_ref_discovered_field()) {                          \
    T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);           \
    closure->do_oop##nv_suffix(disc_addr);                                      \
  }                                                                             \
                                                                                \
205
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);           \
206 207
  T heap_oop = oopDesc::load_heap_oop(referent_addr);                           \
  if (!oopDesc::is_null(heap_oop) && contains(referent_addr)) {                 \
D
duke 已提交
208
    ReferenceProcessor* rp = closure->_ref_processor;                           \
209
    oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);                 \
D
duke 已提交
210
    if (!referent->is_gc_marked() && (rp != NULL) &&                            \
211
        rp->discover_reference(obj, reference_type())) {                        \
D
duke 已提交
212 213 214 215 216 217 218 219
      return size;                                                              \
    } else {                                                                    \
      /* treat referent as normal oop */                                        \
      SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
      closure->do_oop##nv_suffix(referent_addr);                                \
    }                                                                           \
  }                                                                             \
  /* treat next as normal oop */                                                \
220 221 222 223 224
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);                   \
  if (contains(next_addr)) {                                                    \
    SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
    closure->do_oop##nv_suffix(next_addr);                                      \
  }                                                                             \
D
duke 已提交
225
  return size;                                                                  \
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246


template <class T> bool contains(T *t) { return true; }

// Macro to define instanceRefKlass::oop_oop_iterate for virtual/nonvirtual for
// all closures.  Macros calling macros above for each oop size.

#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)        \
                                                                                \
int instanceRefKlass::                                                          \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) {                  \
  /* Get size before changing pointers */                                       \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
                                                                                \
  int size = instanceKlass::oop_oop_iterate##nv_suffix(obj, closure);           \
                                                                                \
  if (UseCompressedOops) {                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains);   \
  } else {                                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains);         \
  }                                                                             \
D
duke 已提交
247 248
}

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
#ifndef SERIALGC
#define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
                                                                                \
int instanceRefKlass::                                                          \
oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) {        \
  /* Get size before changing pointers */                                       \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
                                                                                \
  int size = instanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
                                                                                \
  if (UseCompressedOops) {                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains);   \
  } else {                                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains);         \
  }                                                                             \
}
#endif // !SERIALGC


D
duke 已提交
268 269 270 271 272 273 274 275 276
#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix)      \
                                                                                \
int instanceRefKlass::                                                          \
oop_oop_iterate##nv_suffix##_m(oop obj,                                         \
                               OopClosureType* closure,                         \
                               MemRegion mr) {                                  \
  SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
                                                                                \
  int size = instanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr);   \
277 278 279 280
  if (UseCompressedOops) {                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \
  } else {                                                                      \
    InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains);      \
D
duke 已提交
281 282 283 284
  }                                                                             \
}

ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
285 286 287 288 289
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
#ifndef SERIALGC
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // SERIALGC
D
duke 已提交
290
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
291
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
D
duke 已提交
292 293

#ifndef SERIALGC
294 295 296 297 298
template <class T>
void specialized_oop_push_contents(instanceRefKlass *ref,
                                   PSPromotionManager* pm, oop obj) {
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
  if (PSScavenge::should_scavenge(referent_addr)) {
D
duke 已提交
299
    ReferenceProcessor* rp = PSScavenge::reference_processor();
300
    if (rp->discover_reference(obj, ref->reference_type())) {
D
duke 已提交
301
      // reference already enqueued, referent and next will be traversed later
302
      ref->instanceKlass::oop_push_contents(pm, obj);
D
duke 已提交
303 304 305 306 307 308 309
      return;
    } else {
      // treat referent as normal oop
      pm->claim_or_forward_depth(referent_addr);
    }
  }
  // treat next as normal oop
310 311
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
  if (PSScavenge::should_scavenge(next_addr)) {
D
duke 已提交
312 313
    pm->claim_or_forward_depth(next_addr);
  }
314
  ref->instanceKlass::oop_push_contents(pm, obj);
D
duke 已提交
315 316
}

317 318 319 320 321 322 323
void instanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
  if (UseCompressedOops) {
    specialized_oop_push_contents<narrowOop>(this, pm, obj);
  } else {
    specialized_oop_push_contents<oop>(this, pm, obj);
  }
}
D
duke 已提交
324

325 326 327 328
template <class T>
void specialized_oop_update_pointers(instanceRefKlass *ref,
                                    ParCompactionManager* cm, oop obj) {
  T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
D
duke 已提交
329
  PSParallelCompact::adjust_pointer(referent_addr);
330
  T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
D
duke 已提交
331
  PSParallelCompact::adjust_pointer(next_addr);
332
  T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
D
duke 已提交
333
  PSParallelCompact::adjust_pointer(discovered_addr);
334 335 336
  debug_only(trace_reference_gc("instanceRefKlass::oop_update_ptrs", obj,
                                referent_addr, next_addr, discovered_addr);)
}
D
duke 已提交
337

338 339 340 341 342 343
int instanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
  instanceKlass::oop_update_pointers(cm, obj);
  if (UseCompressedOops) {
    specialized_oop_update_pointers<narrowOop>(this, cm, obj);
  } else {
    specialized_oop_update_pointers<oop>(this, cm, obj);
D
duke 已提交
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
  }
  return size_helper();
}
#endif // SERIALGC

void instanceRefKlass::update_nonstatic_oop_maps(klassOop k) {
  // Clear the nonstatic oop-map entries corresponding to referent
  // and nextPending field.  They are treated specially by the
  // garbage collector.
  // The discovered field is used only by the garbage collector
  // and is also treated specially.
  instanceKlass* ik = instanceKlass::cast(k);

  // Check that we have the right class
  debug_only(static bool first_time = true);
359
  assert(k == SystemDictionary::Reference_klass() && first_time,
D
duke 已提交
360 361
         "Invalid update of maps");
  debug_only(first_time = false);
362
  assert(ik->nonstatic_oop_map_count() == 1, "just checking");
D
duke 已提交
363 364 365 366 367 368

  OopMapBlock* map = ik->start_of_nonstatic_oop_maps();

  // Check that the current map is (2,4) - currently points at field with
  // offset 2 (words) and has 4 map entries.
  debug_only(int offset = java_lang_ref_Reference::referent_offset);
369
  debug_only(unsigned int count = ((java_lang_ref_Reference::discovered_offset -
370
    java_lang_ref_Reference::referent_offset)/heapOopSize) + 1);
D
duke 已提交
371 372 373

  if (UseSharedSpaces) {
    assert(map->offset() == java_lang_ref_Reference::queue_offset &&
374
           map->count() == 1, "just checking");
D
duke 已提交
375
  } else {
376
    assert(map->offset() == offset && map->count() == count,
D
duke 已提交
377 378 379 380
           "just checking");

    // Update map to (3,1) - point to offset of 3 (words) with 1 map entry.
    map->set_offset(java_lang_ref_Reference::queue_offset);
381
    map->set_count(1);
D
duke 已提交
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
  }
}


// Verification

void instanceRefKlass::oop_verify_on(oop obj, outputStream* st) {
  instanceKlass::oop_verify_on(obj, st);
  // Verify referent field
  oop referent = java_lang_ref_Reference::referent(obj);

  // We should make this general to all heaps
  GenCollectedHeap* gch = NULL;
  if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap)
    gch = GenCollectedHeap::heap();

  if (referent != NULL) {
    guarantee(referent->is_oop(), "referent field heap failed");
400
    if (gch != NULL && !gch->is_in_youngest(obj)) {
D
duke 已提交
401 402 403
      // We do a specific remembered set check here since the referent
      // field is not part of the oop mask and therefore skipped by the
      // regular verify code.
404 405 406 407 408 409 410 411
      if (UseCompressedOops) {
        narrowOop* referent_addr = (narrowOop*)java_lang_ref_Reference::referent_addr(obj);
        obj->verify_old_oop(referent_addr, true);
      } else {
        oop* referent_addr = (oop*)java_lang_ref_Reference::referent_addr(obj);
        obj->verify_old_oop(referent_addr, true);
      }
    }
D
duke 已提交
412 413 414 415
  }
  // Verify next field
  oop next = java_lang_ref_Reference::next(obj);
  if (next != NULL) {
416
    guarantee(next->is_oop(), "next field verify failed");
D
duke 已提交
417 418 419 420 421
    guarantee(next->is_instanceRef(), "next field verify failed");
    if (gch != NULL && !gch->is_in_youngest(obj)) {
      // We do a specific remembered set check here since the next field is
      // not part of the oop mask and therefore skipped by the regular
      // verify code.
422 423 424 425 426 427 428
      if (UseCompressedOops) {
        narrowOop* next_addr = (narrowOop*)java_lang_ref_Reference::next_addr(obj);
        obj->verify_old_oop(next_addr, true);
      } else {
        oop* next_addr = (oop*)java_lang_ref_Reference::next_addr(obj);
        obj->verify_old_oop(next_addr, true);
      }
D
duke 已提交
429 430 431 432
    }
  }
}

433
bool instanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
434
  if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
435 436 437 438
  Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
  return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
}

D
duke 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
void instanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
  // we may enter this with pending exception set
  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
  ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
  assert(ObjectSynchronizer::current_thread_holds_lock(
           JavaThread::current(), h_lock),
         "Locking should have succeeded");
  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
}

void instanceRefKlass::release_and_notify_pending_list_lock(
  BasicLock *pending_list_basic_lock) {
  // we may enter this with pending exception set
  PRESERVE_EXCEPTION_MARK;  // exceptions are never thrown, needed for TRAPS argument
  //
  Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
  assert(ObjectSynchronizer::current_thread_holds_lock(
           JavaThread::current(), h_lock),
         "Lock should be held");
  // Notify waiters on pending lists lock if there is any reference.
  if (java_lang_ref_Reference::pending_list() != NULL) {
    ObjectSynchronizer::notifyall(h_lock, THREAD);
  }
  ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
  if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
}