33213
|
1 |
/*
|
|
2 |
* Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
20 |
* or visit www.oracle.com if you need additional information or have any
|
|
21 |
* questions.
|
|
22 |
*
|
|
23 |
*/
|
|
24 |
|
|
25 |
#include "precompiled.hpp"
|
|
26 |
|
|
27 |
#include "gc/g1/bufferingOopClosure.hpp"
|
|
28 |
#include "gc/g1/g1CodeBlobClosure.hpp"
|
|
29 |
#include "gc/g1/g1CollectedHeap.hpp"
|
|
30 |
#include "gc/g1/g1OopClosures.inline.hpp"
|
|
31 |
#include "gc/g1/g1RootClosures.hpp"
|
|
32 |
|
|
33 |
class G1ParScanThreadState;
|
|
34 |
|
|
35 |
// Simple holder object for a complete set of closures used by the G1 evacuation code.
|
|
36 |
template <G1Mark Mark>
|
|
37 |
class G1SharedClosures VALUE_OBJ_CLASS_SPEC {
|
|
38 |
public:
|
|
39 |
G1ParCopyClosure<G1BarrierNone, Mark> _oops;
|
|
40 |
G1ParCopyClosure<G1BarrierKlass, Mark> _oop_in_klass;
|
|
41 |
G1KlassScanClosure _klass_in_cld_closure;
|
|
42 |
CLDToKlassAndOopClosure _clds;
|
|
43 |
G1CodeBlobClosure _codeblobs;
|
|
44 |
BufferingOopClosure _buffered_oops;
|
|
45 |
|
|
46 |
G1SharedClosures(G1CollectedHeap* g1h, G1ParScanThreadState* pss, bool process_only_dirty_klasses, bool must_claim_cld) :
|
|
47 |
_oops(g1h, pss),
|
|
48 |
_oop_in_klass(g1h, pss),
|
|
49 |
_klass_in_cld_closure(&_oop_in_klass, process_only_dirty_klasses),
|
|
50 |
_clds(&_klass_in_cld_closure, &_oops, must_claim_cld),
|
|
51 |
_codeblobs(&_oops),
|
|
52 |
_buffered_oops(&_oops) {}
|
|
53 |
};
|
|
54 |
|
|
55 |
class G1EvacuationClosures : public G1EvacuationRootClosures {
|
|
56 |
G1SharedClosures<G1MarkNone> _closures;
|
|
57 |
|
|
58 |
public:
|
|
59 |
G1EvacuationClosures(G1CollectedHeap* g1h,
|
|
60 |
G1ParScanThreadState* pss,
|
|
61 |
bool gcs_are_young) :
|
|
62 |
_closures(g1h, pss, gcs_are_young, /* must_claim_cld */ false) {}
|
|
63 |
|
|
64 |
OopClosure* weak_oops() { return &_closures._buffered_oops; }
|
|
65 |
OopClosure* strong_oops() { return &_closures._buffered_oops; }
|
|
66 |
|
|
67 |
CLDClosure* weak_clds() { return &_closures._clds; }
|
|
68 |
CLDClosure* strong_clds() { return &_closures._clds; }
|
|
69 |
CLDClosure* thread_root_clds() { return NULL; }
|
|
70 |
CLDClosure* second_pass_weak_clds() { return NULL; }
|
|
71 |
|
|
72 |
CodeBlobClosure* strong_codeblobs() { return &_closures._codeblobs; }
|
|
73 |
CodeBlobClosure* weak_codeblobs() { return &_closures._codeblobs; }
|
|
74 |
|
|
75 |
void flush() { _closures._buffered_oops.done(); }
|
|
76 |
double closure_app_seconds() { return _closures._buffered_oops.closure_app_seconds(); }
|
|
77 |
|
|
78 |
OopClosure* raw_strong_oops() { return &_closures._oops; }
|
|
79 |
|
|
80 |
bool trace_metadata() { return false; }
|
|
81 |
};
|
|
82 |
|
|
83 |
// Closures used during initial mark.
|
|
84 |
// The treatment of "weak" roots is selectable through the template parameter,
|
|
85 |
// this is usually used to control unloading of classes and interned strings.
|
|
86 |
template <G1Mark MarkWeak>
|
|
87 |
class G1InitalMarkClosures : public G1EvacuationRootClosures {
|
|
88 |
G1SharedClosures<G1MarkFromRoot> _strong;
|
|
89 |
G1SharedClosures<MarkWeak> _weak;
|
|
90 |
|
|
91 |
// Filter method to help with returning the appropriate closures
|
|
92 |
// depending on the class template parameter.
|
|
93 |
template <G1Mark Mark, typename T>
|
|
94 |
T* null_if(T* t) {
|
|
95 |
if (Mark == MarkWeak) {
|
|
96 |
return NULL;
|
|
97 |
}
|
|
98 |
return t;
|
|
99 |
}
|
|
100 |
|
|
101 |
public:
|
|
102 |
G1InitalMarkClosures(G1CollectedHeap* g1h,
|
|
103 |
G1ParScanThreadState* pss) :
|
|
104 |
_strong(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true),
|
|
105 |
_weak(g1h, pss, /* process_only_dirty_klasses */ false, /* must_claim_cld */ true) {}
|
|
106 |
|
|
107 |
OopClosure* weak_oops() { return &_weak._buffered_oops; }
|
|
108 |
OopClosure* strong_oops() { return &_strong._buffered_oops; }
|
|
109 |
|
|
110 |
// If MarkWeak is G1MarkPromotedFromRoot then the weak CLDs must be processed in a second pass.
|
|
111 |
CLDClosure* weak_clds() { return null_if<G1MarkPromotedFromRoot>(&_weak._clds); }
|
|
112 |
CLDClosure* strong_clds() { return &_strong._clds; }
|
|
113 |
|
|
114 |
// If MarkWeak is G1MarkFromRoot then all CLDs are processed by the weak and strong variants
|
|
115 |
// return a NULL closure for the following specialized versions in that case.
|
|
116 |
CLDClosure* thread_root_clds() { return null_if<G1MarkFromRoot>(&_strong._clds); }
|
|
117 |
CLDClosure* second_pass_weak_clds() { return null_if<G1MarkFromRoot>(&_weak._clds); }
|
|
118 |
|
|
119 |
CodeBlobClosure* strong_codeblobs() { return &_strong._codeblobs; }
|
|
120 |
CodeBlobClosure* weak_codeblobs() { return &_weak._codeblobs; }
|
|
121 |
|
|
122 |
void flush() {
|
|
123 |
_strong._buffered_oops.done();
|
|
124 |
_weak._buffered_oops.done();
|
|
125 |
}
|
|
126 |
|
|
127 |
double closure_app_seconds() {
|
|
128 |
return _strong._buffered_oops.closure_app_seconds() +
|
|
129 |
_weak._buffered_oops.closure_app_seconds();
|
|
130 |
}
|
|
131 |
|
|
132 |
OopClosure* raw_strong_oops() { return &_strong._oops; }
|
|
133 |
|
|
134 |
// If we are not marking all weak roots then we are tracing
|
|
135 |
// which metadata is alive.
|
|
136 |
bool trace_metadata() { return MarkWeak == G1MarkPromotedFromRoot; }
|
|
137 |
};
|
|
138 |
|
|
139 |
G1EvacuationRootClosures* G1EvacuationRootClosures::create_root_closures(G1ParScanThreadState* pss, G1CollectedHeap* g1h) {
|
|
140 |
if (g1h->collector_state()->during_initial_mark_pause()) {
|
|
141 |
if (ClassUnloadingWithConcurrentMark) {
|
|
142 |
return new G1InitalMarkClosures<G1MarkPromotedFromRoot>(g1h, pss);
|
|
143 |
} else {
|
|
144 |
return new G1InitalMarkClosures<G1MarkFromRoot>(g1h, pss);
|
|
145 |
}
|
|
146 |
} else {
|
|
147 |
return new G1EvacuationClosures(g1h, pss, g1h->collector_state()->gcs_are_young());
|
|
148 |
}
|
|
149 |
}
|