src/share/vm/code/codeCache.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
hotspot Cdiff src/share/vm/code/codeCache.cpp
src/share/vm/code/codeCache.cpp
Print this page
*** 21,30 ****
--- 21,31 ----
* questions.
*
*/
#include "precompiled.hpp"
+ #include "aot/aotLoader.hpp"
#include "code/codeBlob.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/dependencies.hpp"
#include "code/icBuffer.hpp"
*** 126,135 ****
--- 127,138 ----
}
};
// Iterate over all CodeHeaps
#define FOR_ALL_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _heaps->begin(); heap != _heaps->end(); ++heap)
+ #define FOR_ALL_NMETHOD_HEAPS(heap) for (GrowableArrayIterator<CodeHeap*> heap = _nmethod_heaps->begin(); heap != _nmethod_heaps->end(); ++heap)
+
// Iterate over all CodeBlobs (cb) on the given CodeHeap
#define FOR_ALL_BLOBS(cb, heap) for (CodeBlob* cb = first_blob(heap); cb != NULL; cb = next_blob(heap, cb))
address CodeCache::_low_bound = 0;
address CodeCache::_high_bound = 0;
*** 137,146 ****
--- 140,151 ----
bool CodeCache::_needs_cache_clean = false;
nmethod* CodeCache::_scavenge_root_nmethods = NULL;
// Initialize array of CodeHeaps
GrowableArray<CodeHeap*>* CodeCache::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+ GrowableArray<CodeHeap*>* CodeCache::_compiled_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
+ GrowableArray<CodeHeap*>* CodeCache::_nmethod_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<CodeHeap*> (CodeBlobType::All, true);
void CodeCache::check_heap_sizes(size_t non_nmethod_size, size_t profiled_size, size_t non_profiled_size, size_t cache_size, bool all_set) {
size_t total_size = non_nmethod_size + profiled_size + non_profiled_size;
// Prepare error message
const char* error = "Invalid code heap sizes";
*** 363,381 ****
}
ShouldNotReachHere();
return NULL;
}
void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) {
// Check if heap is needed
if (!heap_available(code_blob_type)) {
return;
}
// Create CodeHeap
CodeHeap* heap = new CodeHeap(name, code_blob_type);
! _heaps->append(heap);
// Reserve Space
size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
size_initial = round_to(size_initial, os::vm_page_size());
if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) {
--- 368,408 ----
}
ShouldNotReachHere();
return NULL;
}
+ int CodeCache::code_heap_compare(CodeHeap* const &lhs, CodeHeap* const &rhs) {
+ if (lhs->code_blob_type() == rhs->code_blob_type()) {
+ return (lhs > rhs) ? 1 : ((lhs < rhs) ? -1 : 0);
+ } else {
+ return lhs->code_blob_type() - rhs->code_blob_type();
+ }
+ }
+
+ void CodeCache::add_heap(CodeHeap* heap) {
+ assert(!Universe::is_fully_initialized(), "late heap addition?");
+
+ _heaps->insert_sorted<code_heap_compare>(heap);
+
+ int type = heap->code_blob_type();
+ if (code_blob_type_accepts_compiled(type)) {
+ _compiled_heaps->insert_sorted<code_heap_compare>(heap);
+ }
+ if (code_blob_type_accepts_nmethod(type)) {
+ _nmethod_heaps->insert_sorted<code_heap_compare>(heap);
+ }
+ }
+
void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) {
// Check if heap is needed
if (!heap_available(code_blob_type)) {
return;
}
// Create CodeHeap
CodeHeap* heap = new CodeHeap(name, code_blob_type);
! add_heap(heap);
// Reserve Space
size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
size_initial = round_to(size_initial, os::vm_page_size());
if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) {
*** 387,397 ****
}
CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
assert(cb != NULL, "CodeBlob is null");
FOR_ALL_HEAPS(heap) {
! if ((*heap)->contains(cb)) {
return *heap;
}
}
ShouldNotReachHere();
return NULL;
--- 414,424 ----
}
CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
assert(cb != NULL, "CodeBlob is null");
FOR_ALL_HEAPS(heap) {
! if ((*heap)->contains(cb->code_begin())) {
return *heap;
}
}
ShouldNotReachHere();
return NULL;
*** 424,437 ****
assert_locked_or_safepoint(CodeCache_lock);
assert(heap != NULL, "heap is null");
return (CodeBlob*)heap->next(cb);
}
- CodeBlob* CodeCache::next_blob(CodeBlob* cb) {
- return next_blob(get_code_heap(cb), cb);
- }
-
/**
* Do not seize the CodeCache lock here--if the caller has not
* already done so, we are going to lose bigtime, since the code
* cache will contain a garbage CodeBlob until the caller can
* run the constructor for the CodeBlob subclass he is busy
--- 451,460 ----
*** 492,502 ****
CompileBroker::handle_full_code_cache(orig_code_blob_type);
return NULL;
}
if (PrintCodeCacheExtension) {
ResourceMark rm;
! if (_heaps->length() >= 1) {
tty->print("%s", heap->name());
} else {
tty->print("CodeCache");
}
tty->print_cr(" extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (" SSIZE_FORMAT " bytes)",
--- 515,525 ----
CompileBroker::handle_full_code_cache(orig_code_blob_type);
return NULL;
}
if (PrintCodeCacheExtension) {
ResourceMark rm;
! if (_nmethod_heaps->length() >= 1) {
tty->print("%s", heap->name());
} else {
tty->print("CodeCache");
}
tty->print_cr(" extended to [" INTPTR_FORMAT ", " INTPTR_FORMAT "] (" SSIZE_FORMAT " bytes)",
*** 557,566 ****
--- 580,593 ----
}
}
return false;
}
+ bool CodeCache::contains(nmethod *nm) {
+ return contains((void *)nm);
+ }
+
// This method is safe to call without holding the CodeCache_lock, as long as a dead CodeBlob is not
// looked up (i.e., one that has been marked for deletion). It only depends on the _segmap to contain
// valid indices, which it will always do, as long as the CodeBlob is not in the process of being recycled.
CodeBlob* CodeCache::find_blob(void* start) {
CodeBlob* result = find_blob_unsafe(start);
*** 573,584 ****
// what you are doing)
CodeBlob* CodeCache::find_blob_unsafe(void* start) {
// NMT can walk the stack before code cache is created
if (_heaps != NULL && !_heaps->is_empty()) {
FOR_ALL_HEAPS(heap) {
! CodeBlob* result = (CodeBlob*) (*heap)->find_start(start);
! if (result != NULL && result->blob_contains((address)start)) {
return result;
}
}
}
return NULL;
--- 600,611 ----
// what you are doing)
CodeBlob* CodeCache::find_blob_unsafe(void* start) {
// NMT can walk the stack before code cache is created
if (_heaps != NULL && !_heaps->is_empty()) {
FOR_ALL_HEAPS(heap) {
! CodeBlob* result = (*heap)->find_blob_unsafe(start);
! if (result != NULL) {
return result;
}
}
}
return NULL;
*** 590,600 ****
return (nmethod*)cb;
}
void CodeCache::blobs_do(void f(CodeBlob* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
! FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
f(cb);
}
}
}
--- 617,627 ----
return (nmethod*)cb;
}
void CodeCache::blobs_do(void f(CodeBlob* nm)) {
assert_locked_or_safepoint(CodeCache_lock);
! FOR_ALL_NMETHOD_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
f(cb);
}
}
}
*** 611,620 ****
--- 638,648 ----
assert_locked_or_safepoint(CodeCache_lock);
NMethodIterator iter;
while(iter.next_alive()) {
iter.method()->metadata_do(f);
}
+ AOTLoader::metadata_do(f);
}
int CodeCache::alignment_unit() {
return (int)_heaps->first()->alignment_unit();
}
*** 632,646 ****
}
}
void CodeCache::blobs_do(CodeBlobClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
! FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (cb->is_alive()) {
f->do_code_blob(cb);
-
#ifdef ASSERT
if (cb->is_nmethod())
((nmethod*)cb)->verify_scavenge_root_oops();
#endif //ASSERT
}
--- 660,673 ----
}
}
void CodeCache::blobs_do(CodeBlobClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
! FOR_ALL_NMETHOD_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (cb->is_alive()) {
f->do_code_blob(cb);
#ifdef ASSERT
if (cb->is_nmethod())
((nmethod*)cb)->verify_scavenge_root_oops();
#endif //ASSERT
}
*** 833,849 ****
#ifdef ASSERT
// make sure that we aren't leaking icholders
int count = 0;
FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
! if (cb->is_nmethod()) {
! nmethod* nm = (nmethod*)cb;
count += nm->verify_icholder_relocations();
}
}
}
-
assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
CompiledICHolder::live_count(), "must agree");
#endif
}
--- 860,875 ----
#ifdef ASSERT
// make sure that we aren't leaking icholders
int count = 0;
FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
! CompiledMethod *nm = cb->as_compiled_method_or_null();
! if (nm != NULL) {
count += nm->verify_icholder_relocations();
}
}
}
assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
CompiledICHolder::live_count(), "must agree");
#endif
}
*** 900,910 ****
return (heap != NULL) ? heap->nmethod_count() : 0;
}
int CodeCache::nmethod_count() {
int count = 0;
! FOR_ALL_HEAPS(heap) {
count += (*heap)->nmethod_count();
}
return count;
}
--- 926,936 ----
return (heap != NULL) ? heap->nmethod_count() : 0;
}
int CodeCache::nmethod_count() {
int count = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
count += (*heap)->nmethod_count();
}
return count;
}
*** 931,941 ****
return (heap != NULL) ? (address)heap->high_boundary() : NULL;
}
size_t CodeCache::capacity() {
size_t cap = 0;
! FOR_ALL_HEAPS(heap) {
cap += (*heap)->capacity();
}
return cap;
}
--- 957,967 ----
return (heap != NULL) ? (address)heap->high_boundary() : NULL;
}
size_t CodeCache::capacity() {
size_t cap = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
cap += (*heap)->capacity();
}
return cap;
}
*** 944,962 ****
return (heap != NULL) ? heap->unallocated_capacity() : 0;
}
size_t CodeCache::unallocated_capacity() {
size_t unallocated_cap = 0;
! FOR_ALL_HEAPS(heap) {
unallocated_cap += (*heap)->unallocated_capacity();
}
return unallocated_cap;
}
size_t CodeCache::max_capacity() {
size_t max_cap = 0;
! FOR_ALL_HEAPS(heap) {
max_cap += (*heap)->max_capacity();
}
return max_cap;
}
--- 970,988 ----
return (heap != NULL) ? heap->unallocated_capacity() : 0;
}
size_t CodeCache::unallocated_capacity() {
size_t unallocated_cap = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
unallocated_cap += (*heap)->unallocated_capacity();
}
return unallocated_cap;
}
size_t CodeCache::max_capacity() {
size_t max_cap = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
max_cap += (*heap)->max_capacity();
}
return max_cap;
}
*** 978,1004 ****
return result;
}
size_t CodeCache::bytes_allocated_in_freelists() {
size_t allocated_bytes = 0;
! FOR_ALL_HEAPS(heap) {
allocated_bytes += (*heap)->allocated_in_freelist();
}
return allocated_bytes;
}
int CodeCache::allocated_segments() {
int number_of_segments = 0;
! FOR_ALL_HEAPS(heap) {
number_of_segments += (*heap)->allocated_segments();
}
return number_of_segments;
}
size_t CodeCache::freelists_length() {
size_t length = 0;
! FOR_ALL_HEAPS(heap) {
length += (*heap)->freelist_length();
}
return length;
}
--- 1004,1030 ----
return result;
}
size_t CodeCache::bytes_allocated_in_freelists() {
size_t allocated_bytes = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
allocated_bytes += (*heap)->allocated_in_freelist();
}
return allocated_bytes;
}
int CodeCache::allocated_segments() {
int number_of_segments = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
number_of_segments += (*heap)->allocated_segments();
}
return number_of_segments;
}
size_t CodeCache::freelists_length() {
size_t length = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
length += (*heap)->freelist_length();
}
return length;
}
*** 1037,1046 ****
--- 1063,1074 ----
os::register_code_area((char*)low_bound(), (char*)high_bound());
}
void codeCache_init() {
CodeCache::initialize();
+ // Load AOT libraries and add AOT code heaps.
+ AOTLoader::initialize();
}
//------------------------------------------------------------------------------------------------
int CodeCache::number_of_nmethods_with_dependencies() {
*** 1100,1109 ****
--- 1128,1146 ----
CodeBlob *cb = find_blob(start);
assert(cb == NULL || cb->is_compiled(), "did not find an compiled_method");
return (CompiledMethod*)cb;
}
+ bool CodeCache::is_far_target(address target) {
+ #if INCLUDE_AOT
+ return NativeCall::is_far_call(_low_bound, target) ||
+ NativeCall::is_far_call(_high_bound, target);
+ #else
+ return false;
+ #endif
+ }
+
#ifdef HOTSWAP
int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) {
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int number_of_marked_CodeBlobs = 0;
*** 1202,1212 ****
#ifdef HOTSWAP
// Flushes compiled methods dependent on dependee in the evolutionary sense
void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
// --- Compile_lock is not held. However we are at a safepoint.
assert_locked_or_safepoint(Compile_lock);
! if (number_of_nmethods_with_dependencies() == 0) return;
// CodeCache can only be updated by a thread_in_VM and they will all be
// stopped during the safepoint so CodeCache will be safe to update without
// holding the CodeCache_lock.
--- 1239,1249 ----
#ifdef HOTSWAP
// Flushes compiled methods dependent on dependee in the evolutionary sense
void CodeCache::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
// --- Compile_lock is not held. However we are at a safepoint.
assert_locked_or_safepoint(Compile_lock);
! if (number_of_nmethods_with_dependencies() == 0 && !UseAOT) return;
// CodeCache can only be updated by a thread_in_VM and they will all be
// stopped during the safepoint so CodeCache will be safe to update without
// holding the CodeCache_lock.
*** 1314,1324 ****
}
}
void CodeCache::print_memory_overhead() {
size_t wasted_bytes = 0;
! FOR_ALL_HEAPS(heap) {
CodeHeap* curr_heap = *heap;
for (CodeBlob* cb = (CodeBlob*)curr_heap->first(); cb != NULL; cb = (CodeBlob*)curr_heap->next(cb)) {
HeapBlock* heap_block = ((HeapBlock*)cb) - 1;
wasted_bytes += heap_block->length() * CodeCacheSegmentSize - cb->size();
}
--- 1351,1361 ----
}
}
void CodeCache::print_memory_overhead() {
size_t wasted_bytes = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
CodeHeap* curr_heap = *heap;
for (CodeBlob* cb = (CodeBlob*)curr_heap->first(); cb != NULL; cb = (CodeBlob*)curr_heap->next(cb)) {
HeapBlock* heap_block = ((HeapBlock*)cb) - 1;
wasted_bytes += heap_block->length() * CodeCacheSegmentSize - cb->size();
}
*** 1360,1371 ****
int nmethodNative = 0;
int max_nm_size = 0;
ResourceMark rm;
int i = 0;
! FOR_ALL_HEAPS(heap) {
! if ((_heaps->length() >= 1) && Verbose) {
tty->print_cr("-- %s --", (*heap)->name());
}
FOR_ALL_BLOBS(cb, *heap) {
total++;
if (cb->is_nmethod()) {
--- 1397,1408 ----
int nmethodNative = 0;
int max_nm_size = 0;
ResourceMark rm;
int i = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
! if ((_nmethod_heaps->length() >= 1) && Verbose) {
tty->print_cr("-- %s --", (*heap)->name());
}
FOR_ALL_BLOBS(cb, *heap) {
total++;
if (cb->is_nmethod()) {
*** 1457,1467 ****
if (!Verbose) return;
CodeBlob_sizes live;
CodeBlob_sizes dead;
! FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (!cb->is_alive()) {
dead.add(cb);
} else {
live.add(cb);
--- 1494,1504 ----
if (!Verbose) return;
CodeBlob_sizes live;
CodeBlob_sizes dead;
! FOR_ALL_NMETHOD_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (!cb->is_alive()) {
dead.add(cb);
} else {
live.add(cb);
*** 1483,1493 ****
// print the oop_map usage
int code_size = 0;
int number_of_blobs = 0;
int number_of_oop_maps = 0;
int map_size = 0;
! FOR_ALL_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (cb->is_alive()) {
number_of_blobs++;
code_size += cb->code_size();
ImmutableOopMapSet* set = cb->oop_maps();
--- 1520,1530 ----
// print the oop_map usage
int code_size = 0;
int number_of_blobs = 0;
int number_of_oop_maps = 0;
int map_size = 0;
! FOR_ALL_NMETHOD_HEAPS(heap) {
FOR_ALL_BLOBS(cb, *heap) {
if (cb->is_alive()) {
number_of_blobs++;
code_size += cb->code_size();
ImmutableOopMapSet* set = cb->oop_maps();
*** 1566,1602 ****
" adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'",
blob_count(), nmethod_count(), adapter_count(),
unallocated_capacity());
}
- // Initialize iterator to given compiled method
- void CompiledMethodIterator::initialize(CompiledMethod* cm) {
- _code_blob = (CodeBlob*)cm;
- if (!SegmentedCodeCache) {
- // Iterate over all CodeBlobs
- _code_blob_type = CodeBlobType::All;
- } else if (cm != NULL) {
- _code_blob_type = CodeCache::get_code_blob_type(cm);
- } else {
- // Only iterate over method code heaps, starting with non-profiled
- _code_blob_type = CodeBlobType::MethodNonProfiled;
- }
- }
-
- // Advance iterator to the next compiled method in the current code heap
- bool CompiledMethodIterator::next_compiled_method() {
- // Get first method CodeBlob
- if (_code_blob == NULL) {
- _code_blob = CodeCache::first_blob(_code_blob_type);
- if (_code_blob == NULL) {
- return false;
- } else if (_code_blob->is_nmethod()) {
- return true;
- }
- }
- // Search for next method CodeBlob
- _code_blob = CodeCache::next_blob(_code_blob);
- while (_code_blob != NULL && !_code_blob->is_compiled()) {
- _code_blob = CodeCache::next_blob(_code_blob);
- }
- return _code_blob != NULL;
- }
--- 1603,1607 ----
src/share/vm/code/codeCache.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File