src/share/vm/code/icBuffer.cpp

changeset 4037
da91efe96a93
parent 2708
1d1603768966
child 4318
cd3d6a6b95d9
     1.1 --- a/src/share/vm/code/icBuffer.cpp	Fri Aug 31 16:39:35 2012 -0700
     1.2 +++ b/src/share/vm/code/icBuffer.cpp	Sat Sep 01 13:25:18 2012 -0400
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -32,7 +32,7 @@
    1.11  #include "interpreter/linkResolver.hpp"
    1.12  #include "memory/resourceArea.hpp"
    1.13  #include "memory/universe.inline.hpp"
    1.14 -#include "oops/methodOop.hpp"
    1.15 +#include "oops/method.hpp"
    1.16  #include "oops/oop.inline.hpp"
    1.17  #include "oops/oop.inline2.hpp"
    1.18  #include "runtime/mutexLocker.hpp"
    1.19 @@ -59,16 +59,17 @@
    1.20  StubQueue* InlineCacheBuffer::_buffer    = NULL;
    1.21  ICStub*    InlineCacheBuffer::_next_stub = NULL;
    1.22  
    1.23 +CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;
    1.24 +int InlineCacheBuffer::_pending_count = 0;
    1.25  
    1.26  void ICStub::finalize() {
    1.27    if (!is_empty()) {
    1.28      ResourceMark rm;
    1.29 -    CompiledIC *ic = CompiledIC_at(ic_site());
    1.30 +    CompiledIC *ic = CompiledIC_at(CodeCache::find_nmethod(ic_site()), ic_site());
    1.31      assert(CodeCache::find_nmethod(ic->instruction_address()) != NULL, "inline cache in non-nmethod?");
    1.32  
    1.33      assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
    1.34 -    ic->set_cached_oop(cached_oop());
    1.35 -    ic->set_ic_destination(destination());
    1.36 +    ic->set_ic_destination_and_value(destination(), cached_value());
    1.37    }
    1.38  }
    1.39  
    1.40 @@ -77,25 +78,28 @@
    1.41    return InlineCacheBuffer::ic_buffer_entry_point(code_begin());
    1.42  }
    1.43  
    1.44 -oop ICStub::cached_oop() const {
    1.45 -  return InlineCacheBuffer::ic_buffer_cached_oop(code_begin());
    1.46 +void* ICStub::cached_value() const {
    1.47 +  return InlineCacheBuffer::ic_buffer_cached_value(code_begin());
    1.48  }
    1.49  
    1.50  
    1.51 -void ICStub::set_stub(CompiledIC *ic, oop cached_value, address dest_addr) {
    1.52 +void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) {
    1.53    // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we
    1.54    // store the location of the inline cache. Then we have enough information recreate the CompiledIC
    1.55    // object when we need to remove the stub.
    1.56    _ic_site = ic->instruction_address();
    1.57  
    1.58    // Assemble new stub
    1.59 -  InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_value, dest_addr);
    1.60 +  InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr);
    1.61    assert(destination() == dest_addr,   "can recover destination");
    1.62 -  assert(cached_oop() == cached_value, "can recover destination");
    1.63 +  assert(cached_value() == cached_val, "can recover destination");
    1.64  }
    1.65  
    1.66  
    1.67  void ICStub::clear() {
    1.68 +  if (CompiledIC::is_icholder_entry(destination())) {
    1.69 +    InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());
    1.70 +  }
    1.71    _ic_site = NULL;
    1.72  }
    1.73  
    1.74 @@ -161,6 +165,7 @@
    1.75      buffer()->remove_all();
    1.76      init_next_stub();
    1.77    }
    1.78 +  release_pending_icholders();
    1.79  }
    1.80  
    1.81  
    1.82 @@ -179,11 +184,13 @@
    1.83  }
    1.84  
    1.85  
    1.86 -void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, oop cached_oop, address entry) {
    1.87 +void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {
    1.88    assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");
    1.89    assert (CompiledIC_lock->is_locked(), "");
    1.90 -  assert(cached_oop == NULL || cached_oop->is_perm(), "must belong to perm. space");
    1.91 -  if (TraceICBuffer) { tty->print_cr("  create transition stub for " INTPTR_FORMAT, ic->instruction_address()); }
    1.92 +  if (TraceICBuffer) {
    1.93 +    tty->print_cr("  create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
    1.94 +                  ic->instruction_address(), entry, cached_value);
    1.95 +  }
    1.96  
    1.97    // If an transition stub is already associate with the inline cache, then we remove the association.
    1.98    if (ic->is_in_transition_state()) {
    1.99 @@ -193,10 +200,10 @@
   1.100  
   1.101    // allocate and initialize new "out-of-line" inline-cache
   1.102    ICStub* ic_stub = get_next_stub();
   1.103 -  ic_stub->set_stub(ic, cached_oop, entry);
   1.104 +  ic_stub->set_stub(ic, cached_value, entry);
   1.105  
   1.106    // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache
   1.107 -  ic->set_ic_destination(ic_stub->code_begin());
   1.108 +  ic->set_ic_destination(ic_stub);
   1.109  
   1.110    set_next_stub(new_ic_stub()); // can cause safepoint synchronization
   1.111  }
   1.112 @@ -208,7 +215,35 @@
   1.113  }
   1.114  
   1.115  
   1.116 -oop InlineCacheBuffer::cached_oop_for(CompiledIC *ic) {
   1.117 +void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {
   1.118    ICStub* stub = ICStub_from_destination_address(ic->stub_address());
   1.119 -  return stub->cached_oop();
   1.120 +  return stub->cached_value();
   1.121  }
   1.122 +
   1.123 +
   1.124 +// Free CompiledICHolder*s that are no longer in use
   1.125 +void InlineCacheBuffer::release_pending_icholders() {
   1.126 +  assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");
   1.127 +  CompiledICHolder* holder = _pending_released;
   1.128 +  _pending_released = NULL;
   1.129 +  while (holder != NULL) {
   1.130 +    CompiledICHolder* next = holder->next();
   1.131 +    delete holder;
   1.132 +    holder = next;
   1.133 +    _pending_count--;
   1.134 +  }
   1.135 +  assert(_pending_count == 0, "wrong count");
   1.136 +}
   1.137 +
   1.138 +// Enqueue this icholder for release during the next safepoint.  It's
   1.139 +// not safe to free them until them since they might be visible to
   1.140 +// another thread.
   1.141 +void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {
   1.142 +  MutexLockerEx mex(InlineCacheBuffer_lock);
   1.143 +  icholder->set_next(_pending_released);
   1.144 +  _pending_released = icholder;
   1.145 +  _pending_count++;
   1.146 +  if (TraceICBuffer) {
   1.147 +    tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", icholder);
   1.148 +  }
   1.149 +}

mercurial