comparison src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp @ 342:37f87013dfd8

6711316: Open source the Garbage-First garbage collector Summary: First mercurial integration of the code for the Garbage-First garbage collector. Reviewed-by: apetrusenko, iveresov, jmasa, sgoldman, tonyp, ysr
author ysr
date Thu, 05 Jun 2008 15:57:56 -0700
parents
children df6caf649ff7
comparison
equal deleted inserted replaced
189:0b27f3512f9e 342:37f87013dfd8
1 /*
2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 // A BufferingOops closure tries to separate out the cost of finding roots
26 // from the cost of applying closures to them. It maintains an array of
27 // ref-containing locations. Until the array is full, applying the closure
28 // to an oop* merely records that location in the array. Since this
29 // closure app cost is small, an elapsed timer can approximately attribute
30 // all of this cost to the cost of finding the roots. When the array fills
31 // up, the wrapped closure is applied to all elements, keeping track of
32 // this elapsed time of this process, and leaving the array empty.
33 // The caller must be sure to call "done" to process any unprocessed
34 // buffered entriess.
35
36 class Generation;
37 class HeapRegion;
38
39 class BufferingOopClosure: public OopClosure {
40 protected:
41 enum PrivateConstants {
42 BufferLength = 1024
43 };
44
45 oop *_buffer[BufferLength];
46 oop **_buffer_top;
47 oop **_buffer_curr;
48
49 OopClosure *_oc;
50 double _closure_app_seconds;
51
52 void process_buffer () {
53
54 double start = os::elapsedTime();
55 for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
56 _oc->do_oop(*curr);
57 }
58 _buffer_curr = _buffer;
59 _closure_app_seconds += (os::elapsedTime() - start);
60 }
61
62 public:
63 virtual void do_oop(narrowOop* p) {
64 guarantee(false, "NYI");
65 }
66 virtual void do_oop(oop *p) {
67 if (_buffer_curr == _buffer_top) {
68 process_buffer();
69 }
70
71 *_buffer_curr = p;
72 ++_buffer_curr;
73 }
74 void done () {
75 if (_buffer_curr > _buffer) {
76 process_buffer();
77 }
78 }
79 double closure_app_seconds () {
80 return _closure_app_seconds;
81 }
82 BufferingOopClosure (OopClosure *oc) :
83 _oc(oc),
84 _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength),
85 _closure_app_seconds(0.0) { }
86 };
87
88 class BufferingOopsInGenClosure: public OopsInGenClosure {
89 BufferingOopClosure _boc;
90 OopsInGenClosure* _oc;
91 public:
92 BufferingOopsInGenClosure(OopsInGenClosure *oc) :
93 _boc(oc), _oc(oc) {}
94
95 virtual void do_oop(narrowOop* p) {
96 guarantee(false, "NYI");
97 }
98
99 virtual void do_oop(oop* p) {
100 assert(generation()->is_in_reserved(p), "Must be in!");
101 _boc.do_oop(p);
102 }
103
104 void done() {
105 _boc.done();
106 }
107
108 double closure_app_seconds () {
109 return _boc.closure_app_seconds();
110 }
111
112 void set_generation(Generation* gen) {
113 OopsInGenClosure::set_generation(gen);
114 _oc->set_generation(gen);
115 }
116
117 void reset_generation() {
118 // Make sure we finish the current work with the current generation.
119 _boc.done();
120 OopsInGenClosure::reset_generation();
121 _oc->reset_generation();
122 }
123
124 };
125
126
127 class BufferingOopsInHeapRegionClosure: public OopsInHeapRegionClosure {
128 private:
129 enum PrivateConstants {
130 BufferLength = 1024
131 };
132
133 oop *_buffer[BufferLength];
134 oop **_buffer_top;
135 oop **_buffer_curr;
136
137 HeapRegion *_hr_buffer[BufferLength];
138 HeapRegion **_hr_curr;
139
140 OopsInHeapRegionClosure *_oc;
141 double _closure_app_seconds;
142
143 void process_buffer () {
144
145 assert((_hr_curr - _hr_buffer) == (_buffer_curr - _buffer),
146 "the two lengths should be the same");
147
148 double start = os::elapsedTime();
149 HeapRegion **hr_curr = _hr_buffer;
150 HeapRegion *hr_prev = NULL;
151 for (oop **curr = _buffer; curr < _buffer_curr; ++curr) {
152 HeapRegion *region = *hr_curr;
153 if (region != hr_prev) {
154 _oc->set_region(region);
155 hr_prev = region;
156 }
157 _oc->do_oop(*curr);
158 ++hr_curr;
159 }
160 _buffer_curr = _buffer;
161 _hr_curr = _hr_buffer;
162 _closure_app_seconds += (os::elapsedTime() - start);
163 }
164
165 public:
166 virtual void do_oop(narrowOop *p) {
167 guarantee(false, "NYI");
168 }
169
170 virtual void do_oop(oop *p) {
171 if (_buffer_curr == _buffer_top) {
172 assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr");
173 process_buffer();
174 }
175
176 *_buffer_curr = p;
177 ++_buffer_curr;
178 *_hr_curr = _from;
179 ++_hr_curr;
180 }
181 void done () {
182 if (_buffer_curr > _buffer) {
183 assert(_hr_curr > _hr_buffer, "_hr_curr should be consistent with _buffer_curr");
184 process_buffer();
185 }
186 }
187 double closure_app_seconds () {
188 return _closure_app_seconds;
189 }
190 BufferingOopsInHeapRegionClosure (OopsInHeapRegionClosure *oc) :
191 _oc(oc),
192 _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength),
193 _hr_curr(_hr_buffer),
194 _closure_app_seconds(0.0) { }
195 };