comparison src/share/vm/code/icBuffer.cpp @ 6725:da91efe96a93

6964458: Reimplement class meta-data storage to use native memory Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author coleenp
date Sat, 01 Sep 2012 13:25:18 -0400
parents 1d1603768966
children 7d815d842ee0 cd3d6a6b95d9
comparison
equal deleted inserted replaced
6724:36d1d483d5d6 6725:da91efe96a93
1 /* 1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
30 #include "gc_interface/collectedHeap.inline.hpp" 30 #include "gc_interface/collectedHeap.inline.hpp"
31 #include "interpreter/interpreter.hpp" 31 #include "interpreter/interpreter.hpp"
32 #include "interpreter/linkResolver.hpp" 32 #include "interpreter/linkResolver.hpp"
33 #include "memory/resourceArea.hpp" 33 #include "memory/resourceArea.hpp"
34 #include "memory/universe.inline.hpp" 34 #include "memory/universe.inline.hpp"
35 #include "oops/methodOop.hpp" 35 #include "oops/method.hpp"
36 #include "oops/oop.inline.hpp" 36 #include "oops/oop.inline.hpp"
37 #include "oops/oop.inline2.hpp" 37 #include "oops/oop.inline2.hpp"
38 #include "runtime/mutexLocker.hpp" 38 #include "runtime/mutexLocker.hpp"
39 #include "runtime/stubRoutines.hpp" 39 #include "runtime/stubRoutines.hpp"
40 #ifdef TARGET_ARCH_x86 40 #ifdef TARGET_ARCH_x86
57 DEF_STUB_INTERFACE(ICStub); 57 DEF_STUB_INTERFACE(ICStub);
58 58
59 StubQueue* InlineCacheBuffer::_buffer = NULL; 59 StubQueue* InlineCacheBuffer::_buffer = NULL;
60 ICStub* InlineCacheBuffer::_next_stub = NULL; 60 ICStub* InlineCacheBuffer::_next_stub = NULL;
61 61
62 CompiledICHolder* InlineCacheBuffer::_pending_released = NULL;
63 int InlineCacheBuffer::_pending_count = 0;
62 64
63 void ICStub::finalize() { 65 void ICStub::finalize() {
64 if (!is_empty()) { 66 if (!is_empty()) {
65 ResourceMark rm; 67 ResourceMark rm;
66 CompiledIC *ic = CompiledIC_at(ic_site()); 68 CompiledIC *ic = CompiledIC_at(CodeCache::find_nmethod(ic_site()), ic_site());
67 assert(CodeCache::find_nmethod(ic->instruction_address()) != NULL, "inline cache in non-nmethod?"); 69 assert(CodeCache::find_nmethod(ic->instruction_address()) != NULL, "inline cache in non-nmethod?");
68 70
69 assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer"); 71 assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
70 ic->set_cached_oop(cached_oop()); 72 ic->set_ic_destination_and_value(destination(), cached_value());
71 ic->set_ic_destination(destination());
72 } 73 }
73 } 74 }
74 75
75 76
76 address ICStub::destination() const { 77 address ICStub::destination() const {
77 return InlineCacheBuffer::ic_buffer_entry_point(code_begin()); 78 return InlineCacheBuffer::ic_buffer_entry_point(code_begin());
78 } 79 }
79 80
80 oop ICStub::cached_oop() const { 81 void* ICStub::cached_value() const {
81 return InlineCacheBuffer::ic_buffer_cached_oop(code_begin()); 82 return InlineCacheBuffer::ic_buffer_cached_value(code_begin());
82 } 83 }
83 84
84 85
85 void ICStub::set_stub(CompiledIC *ic, oop cached_value, address dest_addr) { 86 void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) {
86 // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we 87 // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we
87 // store the location of the inline cache. Then we have enough information recreate the CompiledIC 88 // store the location of the inline cache. Then we have enough information recreate the CompiledIC
88 // object when we need to remove the stub. 89 // object when we need to remove the stub.
89 _ic_site = ic->instruction_address(); 90 _ic_site = ic->instruction_address();
90 91
91 // Assemble new stub 92 // Assemble new stub
92 InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_value, dest_addr); 93 InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr);
93 assert(destination() == dest_addr, "can recover destination"); 94 assert(destination() == dest_addr, "can recover destination");
94 assert(cached_oop() == cached_value, "can recover destination"); 95 assert(cached_value() == cached_val, "can recover destination");
95 } 96 }
96 97
97 98
98 void ICStub::clear() { 99 void ICStub::clear() {
100 if (CompiledIC::is_icholder_entry(destination())) {
101 InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value());
102 }
99 _ic_site = NULL; 103 _ic_site = NULL;
100 } 104 }
101 105
102 106
103 #ifndef PRODUCT 107 #ifndef PRODUCT
159 tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs()); 163 tty->print_cr("[updating inline caches with %d stubs]", buffer()->number_of_stubs());
160 } 164 }
161 buffer()->remove_all(); 165 buffer()->remove_all();
162 init_next_stub(); 166 init_next_stub();
163 } 167 }
168 release_pending_icholders();
164 } 169 }
165 170
166 171
167 bool InlineCacheBuffer::contains(address instruction_address) { 172 bool InlineCacheBuffer::contains(address instruction_address) {
168 return buffer()->contains(instruction_address); 173 return buffer()->contains(instruction_address);
177 void InlineCacheBuffer_init() { 182 void InlineCacheBuffer_init() {
178 InlineCacheBuffer::initialize(); 183 InlineCacheBuffer::initialize();
179 } 184 }
180 185
181 186
182 void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, oop cached_oop, address entry) { 187 void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) {
183 assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint"); 188 assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint");
184 assert (CompiledIC_lock->is_locked(), ""); 189 assert (CompiledIC_lock->is_locked(), "");
185 assert(cached_oop == NULL || cached_oop->is_perm(), "must belong to perm. space"); 190 if (TraceICBuffer) {
186 if (TraceICBuffer) { tty->print_cr(" create transition stub for " INTPTR_FORMAT, ic->instruction_address()); } 191 tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT,
192 ic->instruction_address(), entry, cached_value);
193 }
187 194
188 // If an transition stub is already associate with the inline cache, then we remove the association. 195 // If an transition stub is already associate with the inline cache, then we remove the association.
189 if (ic->is_in_transition_state()) { 196 if (ic->is_in_transition_state()) {
190 ICStub* old_stub = ICStub_from_destination_address(ic->stub_address()); 197 ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());
191 old_stub->clear(); 198 old_stub->clear();
192 } 199 }
193 200
194 // allocate and initialize new "out-of-line" inline-cache 201 // allocate and initialize new "out-of-line" inline-cache
195 ICStub* ic_stub = get_next_stub(); 202 ICStub* ic_stub = get_next_stub();
196 ic_stub->set_stub(ic, cached_oop, entry); 203 ic_stub->set_stub(ic, cached_value, entry);
197 204
198 // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache 205 // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache
199 ic->set_ic_destination(ic_stub->code_begin()); 206 ic->set_ic_destination(ic_stub);
200 207
201 set_next_stub(new_ic_stub()); // can cause safepoint synchronization 208 set_next_stub(new_ic_stub()); // can cause safepoint synchronization
202 } 209 }
203 210
204 211
206 ICStub* stub = ICStub_from_destination_address(ic->stub_address()); 213 ICStub* stub = ICStub_from_destination_address(ic->stub_address());
207 return stub->destination(); 214 return stub->destination();
208 } 215 }
209 216
210 217
211 oop InlineCacheBuffer::cached_oop_for(CompiledIC *ic) { 218 void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {
212 ICStub* stub = ICStub_from_destination_address(ic->stub_address()); 219 ICStub* stub = ICStub_from_destination_address(ic->stub_address());
213 return stub->cached_oop(); 220 return stub->cached_value();
214 } 221 }
222
223
224 // Free CompiledICHolder*s that are no longer in use
225 void InlineCacheBuffer::release_pending_icholders() {
226 assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint");
227 CompiledICHolder* holder = _pending_released;
228 _pending_released = NULL;
229 while (holder != NULL) {
230 CompiledICHolder* next = holder->next();
231 delete holder;
232 holder = next;
233 _pending_count--;
234 }
235 assert(_pending_count == 0, "wrong count");
236 }
237
238 // Enqueue this icholder for release during the next safepoint. It's
239 // not safe to free them until them since they might be visible to
240 // another thread.
241 void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) {
242 MutexLockerEx mex(InlineCacheBuffer_lock);
243 icholder->set_next(_pending_released);
244 _pending_released = icholder;
245 _pending_count++;
246 if (TraceICBuffer) {
247 tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", icholder);
248 }
249 }