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 +}