annotate src/share/vm/runtime/handles.cpp @ 1145:e018e6884bd8

6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
author ysr
date Wed, 23 Dec 2009 09:23:54 -0800
parents a61af66fc99e
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_handles.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
29 oop* HandleArea::allocate_handle(oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
30 assert(_handle_mark_nesting > 1, "memory leak: allocating handle outside HandleMark");
a61af66fc99e Initial load
duke
parents:
diff changeset
31 assert(_no_handle_mark_nesting == 0, "allocating handle inside NoHandleMark");
a61af66fc99e Initial load
duke
parents:
diff changeset
32 assert(SharedSkipVerify || obj->is_oop(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
33 return real_allocate_handle(obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
34 }
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 Handle::Handle(Thread* thread, oop obj) {
a61af66fc99e Initial load
duke
parents:
diff changeset
37 assert(thread == Thread::current(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
38 if (obj == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 _handle = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
40 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
41 _handle = thread->handle_area()->allocate_handle(obj);
a61af66fc99e Initial load
duke
parents:
diff changeset
42 }
a61af66fc99e Initial load
duke
parents:
diff changeset
43 }
a61af66fc99e Initial load
duke
parents:
diff changeset
44
a61af66fc99e Initial load
duke
parents:
diff changeset
45 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 static uintx chunk_oops_do(OopClosure* f, Chunk* chunk, char* chunk_top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
48 oop* bottom = (oop*) chunk->bottom();
a61af66fc99e Initial load
duke
parents:
diff changeset
49 oop* top = (oop*) chunk_top;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 uintx handles_visited = top - bottom;
a61af66fc99e Initial load
duke
parents:
diff changeset
51 assert(top >= bottom && top <= (oop*) chunk->top(), "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
52 // during GC phase 3, a handle may be a forward pointer that
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // is not yet valid, so loosen the assertion
a61af66fc99e Initial load
duke
parents:
diff changeset
54 while (bottom < top) {
a61af66fc99e Initial load
duke
parents:
diff changeset
55 // assert((*bottom)->is_oop(), "handle should point to oop");
a61af66fc99e Initial load
duke
parents:
diff changeset
56 assert(Universe::heap()->is_in(*bottom), "handle should be valid heap address");
a61af66fc99e Initial load
duke
parents:
diff changeset
57 f->do_oop(bottom++);
a61af66fc99e Initial load
duke
parents:
diff changeset
58 }
a61af66fc99e Initial load
duke
parents:
diff changeset
59 return handles_visited;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 }
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62 // Used for debugging handle allocation.
a61af66fc99e Initial load
duke
parents:
diff changeset
63 NOT_PRODUCT(jint _nof_handlemarks = 0;)
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 void HandleArea::oops_do(OopClosure* f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 uintx handles_visited = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
67 // First handle the current chunk. It is filled to the high water mark.
a61af66fc99e Initial load
duke
parents:
diff changeset
68 handles_visited += chunk_oops_do(f, _chunk, _hwm);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // Then handle all previous chunks. They are completely filled.
a61af66fc99e Initial load
duke
parents:
diff changeset
70 Chunk* k = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 while(k != _chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 handles_visited += chunk_oops_do(f, k, k->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
73 k = k->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // The thread local handle areas should not get very large
a61af66fc99e Initial load
duke
parents:
diff changeset
77 if (TraceHandleAllocation && handles_visited > TotalHandleAllocationLimit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
78 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
79 warning("%d: Visited in HandleMark : %d",
a61af66fc99e Initial load
duke
parents:
diff changeset
80 _nof_handlemarks, handles_visited);
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
82 warning("Visited in HandleMark : %d", handles_visited);
a61af66fc99e Initial load
duke
parents:
diff changeset
83 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
84 }
a61af66fc99e Initial load
duke
parents:
diff changeset
85 if (_prev != NULL) _prev->oops_do(f);
a61af66fc99e Initial load
duke
parents:
diff changeset
86 }
a61af66fc99e Initial load
duke
parents:
diff changeset
87
a61af66fc99e Initial load
duke
parents:
diff changeset
88 void HandleMark::initialize(Thread* thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 _thread = thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // Save area
a61af66fc99e Initial load
duke
parents:
diff changeset
91 _area = thread->handle_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // Save current top
a61af66fc99e Initial load
duke
parents:
diff changeset
93 _chunk = _area->_chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 _hwm = _area->_hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
95 _max = _area->_max;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 NOT_PRODUCT(_size_in_bytes = _area->_size_in_bytes;)
a61af66fc99e Initial load
duke
parents:
diff changeset
97 debug_only(_area->_handle_mark_nesting++);
a61af66fc99e Initial load
duke
parents:
diff changeset
98 assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");
a61af66fc99e Initial load
duke
parents:
diff changeset
99 debug_only(Atomic::inc(&_nof_handlemarks);)
a61af66fc99e Initial load
duke
parents:
diff changeset
100
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // Link this in the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
102 set_previous_handle_mark(thread->last_handle_mark());
a61af66fc99e Initial load
duke
parents:
diff changeset
103 thread->set_last_handle_mark(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
105
a61af66fc99e Initial load
duke
parents:
diff changeset
106
a61af66fc99e Initial load
duke
parents:
diff changeset
107 HandleMark::~HandleMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 HandleArea* area = _area; // help compilers with poor alias analysis
a61af66fc99e Initial load
duke
parents:
diff changeset
109 assert(area == _thread->handle_area(), "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
110 assert(area->_handle_mark_nesting > 0, "must stack allocate HandleMarks" );
a61af66fc99e Initial load
duke
parents:
diff changeset
111 debug_only(area->_handle_mark_nesting--);
a61af66fc99e Initial load
duke
parents:
diff changeset
112
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // Debug code to trace the number of handles allocated per mark/
a61af66fc99e Initial load
duke
parents:
diff changeset
114 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
115 if (TraceHandleAllocation) {
a61af66fc99e Initial load
duke
parents:
diff changeset
116 size_t handles = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
117 Chunk *c = _chunk->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 if (c == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 handles = area->_hwm - _hwm; // no new chunk allocated
a61af66fc99e Initial load
duke
parents:
diff changeset
120 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
121 handles = _max - _hwm; // add rest in first chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
122 while(c != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 handles += c->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
124 c = c->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126 handles -= area->_max - area->_hwm; // adjust for last trunk not full
a61af66fc99e Initial load
duke
parents:
diff changeset
127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
128 handles /= sizeof(void *); // Adjust for size of a handle
a61af66fc99e Initial load
duke
parents:
diff changeset
129 if (handles > HandleAllocationLimit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // Note: _nof_handlemarks is only set in debug mode
a61af66fc99e Initial load
duke
parents:
diff changeset
131 warning("%d: Allocated in HandleMark : %d", _nof_handlemarks, handles);
a61af66fc99e Initial load
duke
parents:
diff changeset
132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
134 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
135
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // Delete later chunks
a61af66fc99e Initial load
duke
parents:
diff changeset
137 if( _chunk->next() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 _chunk->next_chop();
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 // Roll back arena to saved top markers
a61af66fc99e Initial load
duke
parents:
diff changeset
141 area->_chunk = _chunk;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 area->_hwm = _hwm;
a61af66fc99e Initial load
duke
parents:
diff changeset
143 area->_max = _max;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 NOT_PRODUCT(area->set_size_in_bytes(_size_in_bytes);)
a61af66fc99e Initial load
duke
parents:
diff changeset
145 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // clear out first chunk (to detect allocation bugs)
a61af66fc99e Initial load
duke
parents:
diff changeset
147 if (ZapVMHandleArea) {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 memset(_hwm, badHandleValue, _max - _hwm);
a61af66fc99e Initial load
duke
parents:
diff changeset
149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
150 Atomic::dec(&_nof_handlemarks);
a61af66fc99e Initial load
duke
parents:
diff changeset
151 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
152
a61af66fc99e Initial load
duke
parents:
diff changeset
153 // Unlink this from the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
154 _thread->set_last_handle_mark(previous_handle_mark());
a61af66fc99e Initial load
duke
parents:
diff changeset
155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
156
a61af66fc99e Initial load
duke
parents:
diff changeset
157 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 NoHandleMark::NoHandleMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 HandleArea* area = Thread::current()->handle_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
161 area->_no_handle_mark_nesting++;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );
a61af66fc99e Initial load
duke
parents:
diff changeset
163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 NoHandleMark::~NoHandleMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
167 HandleArea* area = Thread::current()->handle_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
168 assert(area->_no_handle_mark_nesting > 0, "must stack allocate NoHandleMark" );
a61af66fc99e Initial load
duke
parents:
diff changeset
169 area->_no_handle_mark_nesting--;
a61af66fc99e Initial load
duke
parents:
diff changeset
170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
171
a61af66fc99e Initial load
duke
parents:
diff changeset
172
a61af66fc99e Initial load
duke
parents:
diff changeset
173 ResetNoHandleMark::ResetNoHandleMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
174 HandleArea* area = Thread::current()->handle_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
175 _no_handle_mark_nesting = area->_no_handle_mark_nesting;
a61af66fc99e Initial load
duke
parents:
diff changeset
176 area->_no_handle_mark_nesting = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180 ResetNoHandleMark::~ResetNoHandleMark() {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 HandleArea* area = Thread::current()->handle_area();
a61af66fc99e Initial load
duke
parents:
diff changeset
182 area->_no_handle_mark_nesting = _no_handle_mark_nesting;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
184
a61af66fc99e Initial load
duke
parents:
diff changeset
185 #endif