Mercurial > hg > graal-compiler
annotate src/share/vm/services/memTrackWorker.cpp @ 7046:b6a8f2d23057
VM support for deferred reads and writes: ScopeDesc, DebugInfo, DebugInfoRecorder
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Tue, 27 Nov 2012 13:43:04 +0100 |
parents | 33143ee07800 |
children | ecd24264898b |
rev | line source |
---|---|
6197 | 1 /* |
2 * Copyright (c) 2012, 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 #include "runtime/threadCritical.hpp" | |
27 #include "services/memTracker.hpp" | |
28 #include "services/memTrackWorker.hpp" | |
29 #include "utilities/decoder.hpp" | |
30 #include "utilities/vmError.hpp" | |
31 | |
32 MemTrackWorker::MemTrackWorker() { | |
33 // create thread uses cgc thread type for now. We should revisit | |
34 // the option, or create new thread type. | |
35 _has_error = !os::create_thread(this, os::cgc_thread); | |
36 set_name("MemTrackWorker", 0); | |
37 | |
38 // initial generation circuit buffer | |
39 if (!has_error()) { | |
40 _head = _tail = 0; | |
41 for(int index = 0; index < MAX_GENERATIONS; index ++) { | |
42 _gen[index] = NULL; | |
43 } | |
44 } | |
45 NOT_PRODUCT(_sync_point_count = 0;) | |
46 NOT_PRODUCT(_merge_count = 0;) | |
47 NOT_PRODUCT(_last_gen_in_use = 0;) | |
48 } | |
49 | |
50 MemTrackWorker::~MemTrackWorker() { | |
51 for (int index = 0; index < MAX_GENERATIONS; index ++) { | |
52 MemRecorder* rc = _gen[index]; | |
53 if (rc != NULL) { | |
54 delete rc; | |
55 } | |
56 } | |
57 } | |
58 | |
59 void* MemTrackWorker::operator new(size_t size) { | |
60 assert(false, "use nothrow version"); | |
61 return NULL; | |
62 } | |
63 | |
64 void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) { | |
65 return allocate(size, false, mtNMT); | |
66 } | |
67 | |
68 void MemTrackWorker::start() { | |
69 os::start_thread(this); | |
70 } | |
71 | |
72 /* | |
73 * Native memory tracking worker thread loop: | |
74 * 1. merge one generation of memory recorders to staging area | |
75 * 2. promote staging data to memory snapshot | |
76 * | |
77 * This thread can run through safepoint. | |
78 */ | |
79 | |
80 void MemTrackWorker::run() { | |
81 assert(MemTracker::is_on(), "native memory tracking is off"); | |
82 this->initialize_thread_local_storage(); | |
83 this->record_stack_base_and_size(); | |
84 MemSnapshot* snapshot = MemTracker::get_snapshot(); | |
85 assert(snapshot != NULL, "Worker should not be started"); | |
86 MemRecorder* rec; | |
87 | |
88 while (!MemTracker::shutdown_in_progress()) { | |
89 NOT_PRODUCT(_last_gen_in_use = generations_in_use();) | |
90 { | |
91 // take a recorder from earliest generation in buffer | |
92 ThreadCritical tc; | |
93 rec = _gen[_head]; | |
94 if (rec != NULL) { | |
95 _gen[_head] = rec->next(); | |
96 } | |
97 assert(count_recorder(_gen[_head]) <= MemRecorder::_instance_count, | |
98 "infinite loop after dequeue"); | |
99 } | |
100 if (rec != NULL) { | |
101 // merge the recorder into staging area | |
6599
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
102 if (!snapshot->merge(rec)) { |
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
103 MemTracker::shutdown(MemTracker::NMT_out_of_memory); |
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
104 } else { |
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
105 NOT_PRODUCT(_merge_count ++;) |
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
106 } |
6197 | 107 MemTracker::release_thread_recorder(rec); |
108 } else { | |
109 // no more recorder to merge, promote staging area | |
110 // to snapshot | |
111 if (_head != _tail) { | |
112 { | |
113 ThreadCritical tc; | |
114 if (_gen[_head] != NULL || _head == _tail) { | |
115 continue; | |
116 } | |
117 // done with this generation, increment _head pointer | |
118 _head = (_head + 1) % MAX_GENERATIONS; | |
119 } | |
120 // promote this generation data to snapshot | |
6741
33143ee07800
7181995: NMT ON: NMT assertion failure assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record
zgu
parents:
6599
diff
changeset
|
121 if (!snapshot->promote()) { |
33143ee07800
7181995: NMT ON: NMT assertion failure assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record
zgu
parents:
6599
diff
changeset
|
122 // failed to promote, means out of memory |
33143ee07800
7181995: NMT ON: NMT assertion failure assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record
zgu
parents:
6599
diff
changeset
|
123 MemTracker::shutdown(MemTracker::NMT_out_of_memory); |
33143ee07800
7181995: NMT ON: NMT assertion failure assert(cur_vm->is_uncommit_record() || cur_vm->is_deallocation_record
zgu
parents:
6599
diff
changeset
|
124 } |
6197 | 125 } else { |
126 snapshot->wait(1000); | |
127 ThreadCritical tc; | |
128 // check if more data arrived | |
129 if (_gen[_head] == NULL) { | |
130 _gen[_head] = MemTracker::get_pending_recorders(); | |
131 } | |
132 } | |
133 } | |
134 } | |
135 assert(MemTracker::shutdown_in_progress(), "just check"); | |
136 | |
6599
4acebbe310e1
7185614: NMT ON: "check by caller" assertion failed on nsk ThreadMXBean test
zgu
parents:
6197
diff
changeset
|
137 // transits to final shutdown |
6197 | 138 MemTracker::final_shutdown(); |
139 } | |
140 | |
141 // at synchronization point, where 'safepoint visible' Java threads are blocked | |
142 // at a safepoint, and the rest of threads are blocked on ThreadCritical lock. | |
143 // The caller MemTracker::sync() already takes ThreadCritical before calling this | |
144 // method. | |
145 // | |
146 // Following tasks are performed: | |
147 // 1. add all recorders in pending queue to current generation | |
148 // 2. increase generation | |
149 | |
150 void MemTrackWorker::at_sync_point(MemRecorder* rec) { | |
151 NOT_PRODUCT(_sync_point_count ++;) | |
152 assert(count_recorder(rec) <= MemRecorder::_instance_count, | |
153 "pending queue has infinite loop"); | |
154 | |
155 bool out_of_generation_buffer = false; | |
156 // check shutdown state inside ThreadCritical | |
157 if (MemTracker::shutdown_in_progress()) return; | |
158 // append the recorders to the end of the generation | |
159 if( rec != NULL) { | |
160 MemRecorder* cur_head = _gen[_tail]; | |
161 if (cur_head == NULL) { | |
162 _gen[_tail] = rec; | |
163 } else { | |
164 while (cur_head->next() != NULL) { | |
165 cur_head = cur_head->next(); | |
166 } | |
167 cur_head->set_next(rec); | |
168 } | |
169 } | |
170 assert(count_recorder(rec) <= MemRecorder::_instance_count, | |
171 "after add to current generation has infinite loop"); | |
172 // we have collected all recorders for this generation. If there is data, | |
173 // we need to increment _tail to start a new generation. | |
174 if (_gen[_tail] != NULL || _head == _tail) { | |
175 _tail = (_tail + 1) % MAX_GENERATIONS; | |
176 out_of_generation_buffer = (_tail == _head); | |
177 } | |
178 | |
179 if (out_of_generation_buffer) { | |
180 MemTracker::shutdown(MemTracker::NMT_out_of_generation); | |
181 } | |
182 } | |
183 | |
184 #ifndef PRODUCT | |
185 int MemTrackWorker::count_recorder(const MemRecorder* head) { | |
186 int count = 0; | |
187 while(head != NULL) { | |
188 count ++; | |
189 head = head->next(); | |
190 } | |
191 return count; | |
192 } | |
193 | |
194 int MemTrackWorker::count_pending_recorders() const { | |
195 int count = 0; | |
196 for (int index = 0; index < MAX_GENERATIONS; index ++) { | |
197 MemRecorder* head = _gen[index]; | |
198 if (head != NULL) { | |
199 count += count_recorder(head); | |
200 } | |
201 } | |
202 return count; | |
203 } | |
204 #endif |