Mercurial > hg > graal-compiler
annotate src/share/vm/code/debugInfoRec.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | f95d63e2154a |
children | 5857923e563c 1d7922586cf6 |
rev | line source |
---|---|
0 | 1 /* |
1972 | 2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1253
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1253
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1253
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "code/debugInfoRec.hpp" | |
27 #include "code/scopeDesc.hpp" | |
28 #include "prims/jvmtiExport.hpp" | |
0 | 29 |
30 // Private definition. | |
31 // There is one DIR_Chunk for each scope and values array. | |
32 // A chunk can potentially be used more than once. | |
33 // We keep track of these chunks in order to detect | |
34 // repetition and enable sharing. | |
35 class DIR_Chunk { | |
36 friend class DebugInformationRecorder; | |
37 int _offset; // location in the stream of this scope | |
38 int _length; // number of bytes in the stream | |
39 int _hash; // hash of stream bytes (for quicker reuse) | |
40 | |
41 void* operator new(size_t ignore, DebugInformationRecorder* dir) { | |
42 assert(ignore == sizeof(DIR_Chunk), ""); | |
43 if (dir->_next_chunk >= dir->_next_chunk_limit) { | |
44 const int CHUNK = 100; | |
45 dir->_next_chunk = NEW_RESOURCE_ARRAY(DIR_Chunk, CHUNK); | |
46 dir->_next_chunk_limit = dir->_next_chunk + CHUNK; | |
47 } | |
48 return dir->_next_chunk++; | |
49 } | |
50 | |
51 DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) { | |
52 _offset = offset; | |
53 _length = length; | |
54 unsigned int hash = 0; | |
55 address p = dir->stream()->buffer() + _offset; | |
56 for (int i = 0; i < length; i++) { | |
57 if (i == 6) break; | |
58 hash *= 127; | |
59 hash += p[i]; | |
60 } | |
61 _hash = hash; | |
62 } | |
63 | |
64 DIR_Chunk* find_match(GrowableArray<DIR_Chunk*>* arr, | |
65 int start_index, | |
66 DebugInformationRecorder* dir) { | |
67 int end_index = arr->length(); | |
68 int hash = this->_hash, length = this->_length; | |
69 address buf = dir->stream()->buffer(); | |
70 for (int i = end_index; --i >= start_index; ) { | |
71 DIR_Chunk* that = arr->at(i); | |
72 if (hash == that->_hash && | |
73 length == that->_length && | |
74 0 == memcmp(buf + this->_offset, buf + that->_offset, length)) { | |
75 return that; | |
76 } | |
77 } | |
78 return NULL; | |
79 } | |
80 }; | |
81 | |
82 static inline bool compute_recording_non_safepoints() { | |
83 if (JvmtiExport::should_post_compiled_method_load() | |
84 && FLAG_IS_DEFAULT(DebugNonSafepoints)) { | |
85 // The default value of this flag is taken to be true, | |
86 // if JVMTI is looking at nmethod codes. | |
87 // We anticipate that JVMTI may wish to participate in profiling. | |
88 return true; | |
89 } | |
90 | |
91 // If the flag is set manually, use it, whether true or false. | |
92 // Otherwise, if JVMTI is not in the picture, use the default setting. | |
93 // (This is true in debug, just for the exercise, false in product mode.) | |
94 return DebugNonSafepoints; | |
95 } | |
96 | |
97 DebugInformationRecorder::DebugInformationRecorder(OopRecorder* oop_recorder) | |
98 : _recording_non_safepoints(compute_recording_non_safepoints()) | |
99 { | |
100 _pcs_size = 100; | |
101 _pcs = NEW_RESOURCE_ARRAY(PcDesc, _pcs_size); | |
102 _pcs_length = 0; | |
103 | |
104 _prev_safepoint_pc = PcDesc::lower_offset_limit; | |
105 | |
106 _stream = new DebugInfoWriteStream(this, 10 * K); | |
107 // make sure that there is no stream_decode_offset that is zero | |
108 _stream->write_byte((jbyte)0xFF); | |
109 | |
110 // make sure that we can distinguish the value "serialized_null" from offsets | |
111 assert(_stream->position() > serialized_null, "sanity"); | |
112 | |
113 _oop_recorder = oop_recorder; | |
114 | |
115 _all_chunks = new GrowableArray<DIR_Chunk*>(300); | |
116 _shared_chunks = new GrowableArray<DIR_Chunk*>(30); | |
117 _next_chunk = _next_chunk_limit = NULL; | |
118 | |
119 add_new_pc_offset(PcDesc::lower_offset_limit); // sentinel record | |
120 | |
121 debug_only(_recording_state = rs_null); | |
122 } | |
123 | |
124 | |
125 void DebugInformationRecorder::add_oopmap(int pc_offset, OopMap* map) { | |
126 // !!!!! Preserve old style handling of oopmaps for now | |
127 _oopmaps->add_gc_map(pc_offset, map); | |
128 } | |
129 | |
130 void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) { | |
131 assert(!_oop_recorder->is_complete(), "not frozen yet"); | |
132 // Store the new safepoint | |
133 | |
134 // Add the oop map | |
135 add_oopmap(pc_offset, map); | |
136 | |
137 add_new_pc_offset(pc_offset); | |
138 | |
139 assert(_recording_state == rs_null, "nesting of recording calls"); | |
140 debug_only(_recording_state = rs_safepoint); | |
141 } | |
142 | |
143 void DebugInformationRecorder::add_non_safepoint(int pc_offset) { | |
144 assert(!_oop_recorder->is_complete(), "not frozen yet"); | |
145 assert(_recording_non_safepoints, "must be recording non-safepoints"); | |
146 | |
147 add_new_pc_offset(pc_offset); | |
148 | |
149 assert(_recording_state == rs_null, "nesting of recording calls"); | |
150 debug_only(_recording_state = rs_non_safepoint); | |
151 } | |
152 | |
153 void DebugInformationRecorder::add_new_pc_offset(int pc_offset) { | |
154 assert(_pcs_length == 0 || last_pc()->pc_offset() < pc_offset, | |
155 "must specify a new, larger pc offset"); | |
156 | |
157 // add the pcdesc | |
158 if (_pcs_length == _pcs_size) { | |
159 // Expand | |
160 int new_pcs_size = _pcs_size * 2; | |
161 PcDesc* new_pcs = NEW_RESOURCE_ARRAY(PcDesc, new_pcs_size); | |
162 for (int index = 0; index < _pcs_length; index++) { | |
163 new_pcs[index] = _pcs[index]; | |
164 } | |
165 _pcs_size = new_pcs_size; | |
166 _pcs = new_pcs; | |
167 } | |
168 assert(_pcs_size > _pcs_length, "There must be room for after expanding"); | |
169 | |
170 _pcs[_pcs_length++] = PcDesc(pc_offset, DebugInformationRecorder::serialized_null, | |
171 DebugInformationRecorder::serialized_null); | |
172 } | |
173 | |
174 | |
175 int DebugInformationRecorder::serialize_monitor_values(GrowableArray<MonitorValue*>* monitors) { | |
176 if (monitors == NULL || monitors->is_empty()) return DebugInformationRecorder::serialized_null; | |
177 assert(_recording_state == rs_safepoint, "must be recording a safepoint"); | |
178 int result = stream()->position(); | |
179 stream()->write_int(monitors->length()); | |
180 for (int index = 0; index < monitors->length(); index++) { | |
181 monitors->at(index)->write_on(stream()); | |
182 } | |
183 assert(result != serialized_null, "sanity"); | |
184 | |
185 // (See comment below on DebugInformationRecorder::describe_scope.) | |
186 int shared_result = find_sharable_decode_offset(result); | |
187 if (shared_result != serialized_null) { | |
188 stream()->set_position(result); | |
189 result = shared_result; | |
190 } | |
191 | |
192 return result; | |
193 } | |
194 | |
195 | |
196 int DebugInformationRecorder::serialize_scope_values(GrowableArray<ScopeValue*>* values) { | |
197 if (values == NULL || values->is_empty()) return DebugInformationRecorder::serialized_null; | |
198 assert(_recording_state == rs_safepoint, "must be recording a safepoint"); | |
199 int result = stream()->position(); | |
200 assert(result != serialized_null, "sanity"); | |
201 stream()->write_int(values->length()); | |
202 for (int index = 0; index < values->length(); index++) { | |
203 values->at(index)->write_on(stream()); | |
204 } | |
205 | |
206 // (See comment below on DebugInformationRecorder::describe_scope.) | |
207 int shared_result = find_sharable_decode_offset(result); | |
208 if (shared_result != serialized_null) { | |
209 stream()->set_position(result); | |
210 result = shared_result; | |
211 } | |
212 | |
213 return result; | |
214 } | |
215 | |
216 | |
217 #ifndef PRODUCT | |
218 // These variables are put into one block to reduce relocations | |
219 // and make it simpler to print from the debugger. | |
220 static | |
221 struct dir_stats_struct { | |
222 int chunks_queried; | |
223 int chunks_shared; | |
224 int chunks_reshared; | |
225 int chunks_elided; | |
226 | |
227 void print() { | |
228 tty->print_cr("Debug Data Chunks: %d, shared %d+%d, non-SP's elided %d", | |
229 chunks_queried, | |
230 chunks_shared, chunks_reshared, | |
231 chunks_elided); | |
232 } | |
233 } dir_stats; | |
234 #endif //PRODUCT | |
235 | |
236 | |
237 int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { | |
238 // Only pull this trick if non-safepoint recording | |
239 // is enabled, for now. | |
240 if (!recording_non_safepoints()) | |
241 return serialized_null; | |
242 | |
243 NOT_PRODUCT(++dir_stats.chunks_queried); | |
244 int stream_length = stream()->position() - stream_offset; | |
245 assert(stream_offset != serialized_null, "should not be null"); | |
246 assert(stream_length != 0, "should not be empty"); | |
247 | |
248 DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this); | |
249 | |
250 // Look in previously shared scopes first: | |
251 DIR_Chunk* ms = ns->find_match(_shared_chunks, 0, this); | |
252 if (ms != NULL) { | |
253 NOT_PRODUCT(++dir_stats.chunks_reshared); | |
254 assert(ns+1 == _next_chunk, ""); | |
255 _next_chunk = ns; | |
256 return ms->_offset; | |
257 } | |
258 | |
259 // Look in recently encountered scopes next: | |
260 const int MAX_RECENT = 50; | |
261 int start_index = _all_chunks->length() - MAX_RECENT; | |
262 if (start_index < 0) start_index = 0; | |
263 ms = ns->find_match(_all_chunks, start_index, this); | |
264 if (ms != NULL) { | |
265 NOT_PRODUCT(++dir_stats.chunks_shared); | |
266 // Searching in _all_chunks is limited to a window, | |
267 // but searching in _shared_chunks is unlimited. | |
268 _shared_chunks->append(ms); | |
269 assert(ns+1 == _next_chunk, ""); | |
270 _next_chunk = ns; | |
271 return ms->_offset; | |
272 } | |
273 | |
274 // No match. Add this guy to the list, in hopes of future shares. | |
275 _all_chunks->append(ns); | |
276 return serialized_null; | |
277 } | |
278 | |
279 | |
280 // must call add_safepoint before: it sets PcDesc and this routine uses | |
281 // the last PcDesc set | |
282 void DebugInformationRecorder::describe_scope(int pc_offset, | |
283 ciMethod* method, | |
284 int bci, | |
900
9987d9d5eb0e
6833129: specjvm98 fails with NullPointerException in the compiler with -XX:DeoptimizeALot
cfang
parents:
0
diff
changeset
|
285 bool reexecute, |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1014
diff
changeset
|
286 bool is_method_handle_invoke, |
1253
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1135
diff
changeset
|
287 bool return_oop, |
0 | 288 DebugToken* locals, |
289 DebugToken* expressions, | |
290 DebugToken* monitors) { | |
291 assert(_recording_state != rs_null, "nesting of recording calls"); | |
292 PcDesc* last_pd = last_pc(); | |
293 assert(last_pd->pc_offset() == pc_offset, "must be last pc"); | |
294 int sender_stream_offset = last_pd->scope_decode_offset(); | |
295 // update the stream offset of current pc desc | |
296 int stream_offset = stream()->position(); | |
297 last_pd->set_scope_decode_offset(stream_offset); | |
298 | |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1014
diff
changeset
|
299 // Record flags into pcDesc. |
931
72088be4b386
6873116: Modify reexecute implementation to use pcDesc to record the reexecute bit
cfang
parents:
900
diff
changeset
|
300 last_pd->set_should_reexecute(reexecute); |
1135
e66fd840cb6b
6893081: method handle & invokedynamic code needs additional cleanup (post 6815692, 6858164)
twisti
parents:
1014
diff
changeset
|
301 last_pd->set_is_method_handle_invoke(is_method_handle_invoke); |
1253
f70b0d9ab095
6910618: C2: Error: assert(d->is_oop(),"JVM_ArrayCopy: dst not an oop")
kvn
parents:
1135
diff
changeset
|
302 last_pd->set_return_oop(return_oop); |
931
72088be4b386
6873116: Modify reexecute implementation to use pcDesc to record the reexecute bit
cfang
parents:
900
diff
changeset
|
303 |
0 | 304 // serialize sender stream offest |
305 stream()->write_int(sender_stream_offset); | |
306 | |
307 // serialize scope | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
931
diff
changeset
|
308 jobject method_enc = (method == NULL)? NULL: method->constant_encoding(); |
0 | 309 stream()->write_int(oop_recorder()->find_index(method_enc)); |
931
72088be4b386
6873116: Modify reexecute implementation to use pcDesc to record the reexecute bit
cfang
parents:
900
diff
changeset
|
310 stream()->write_bci(bci); |
0 | 311 assert(method == NULL || |
312 (method->is_native() && bci == 0) || | |
313 (!method->is_native() && 0 <= bci && bci < method->code_size()) || | |
314 bci == -1, "illegal bci"); | |
315 | |
316 // serialize the locals/expressions/monitors | |
317 stream()->write_int((intptr_t) locals); | |
318 stream()->write_int((intptr_t) expressions); | |
319 stream()->write_int((intptr_t) monitors); | |
320 | |
321 // Here's a tricky bit. We just wrote some bytes. | |
322 // Wouldn't it be nice to find that we had already | |
323 // written those same bytes somewhere else? | |
324 // If we get lucky this way, reset the stream | |
325 // and reuse the old bytes. By the way, this | |
326 // trick not only shares parent scopes, but also | |
327 // compresses equivalent non-safepoint PcDescs. | |
328 int shared_stream_offset = find_sharable_decode_offset(stream_offset); | |
329 if (shared_stream_offset != serialized_null) { | |
330 stream()->set_position(stream_offset); | |
331 last_pd->set_scope_decode_offset(shared_stream_offset); | |
332 } | |
333 } | |
334 | |
335 void DebugInformationRecorder::dump_object_pool(GrowableArray<ScopeValue*>* objects) { | |
336 guarantee( _pcs_length > 0, "safepoint must exist before describing scopes"); | |
337 PcDesc* last_pd = &_pcs[_pcs_length-1]; | |
338 if (objects != NULL) { | |
339 for (int i = objects->length() - 1; i >= 0; i--) { | |
340 ((ObjectValue*) objects->at(i))->set_visited(false); | |
341 } | |
342 } | |
343 int offset = serialize_scope_values(objects); | |
344 last_pd->set_obj_decode_offset(offset); | |
345 } | |
346 | |
347 void DebugInformationRecorder::end_scopes(int pc_offset, bool is_safepoint) { | |
348 assert(_recording_state == (is_safepoint? rs_safepoint: rs_non_safepoint), | |
349 "nesting of recording calls"); | |
350 debug_only(_recording_state = rs_null); | |
351 | |
352 // Try to compress away an equivalent non-safepoint predecessor. | |
353 // (This only works because we have previously recognized redundant | |
354 // scope trees and made them use a common scope_decode_offset.) | |
355 if (_pcs_length >= 2 && recording_non_safepoints()) { | |
356 PcDesc* last = last_pc(); | |
357 PcDesc* prev = prev_pc(); | |
358 // If prev is (a) not a safepoint and (b) has the same | |
359 // stream pointer, then it can be coalesced into the last. | |
360 // This is valid because non-safepoints are only sought | |
361 // with pc_desc_near, which (when it misses prev) will | |
362 // search forward until it finds last. | |
363 // In addition, it does not matter if the last PcDesc | |
364 // is for a safepoint or not. | |
1014
8e954aedbb81
6889869: assert(!Interpreter::bytecode_should_reexecute(code),"should not reexecute")
never
parents:
989
diff
changeset
|
365 if (_prev_safepoint_pc < prev->pc_offset() && prev->is_same_info(last)) { |
0 | 366 assert(prev == last-1, "sane"); |
367 prev->set_pc_offset(pc_offset); | |
368 _pcs_length -= 1; | |
369 NOT_PRODUCT(++dir_stats.chunks_elided); | |
370 } | |
371 } | |
372 | |
373 // We have just recorded this safepoint. | |
374 // Remember it in case the previous paragraph needs to know. | |
375 if (is_safepoint) { | |
376 _prev_safepoint_pc = pc_offset; | |
377 } | |
378 } | |
379 | |
380 DebugToken* DebugInformationRecorder::create_scope_values(GrowableArray<ScopeValue*>* values) { | |
381 assert(!_oop_recorder->is_complete(), "not frozen yet"); | |
382 return (DebugToken*) (intptr_t) serialize_scope_values(values); | |
383 } | |
384 | |
385 | |
386 DebugToken* DebugInformationRecorder::create_monitor_values(GrowableArray<MonitorValue*>* monitors) { | |
387 assert(!_oop_recorder->is_complete(), "not frozen yet"); | |
388 return (DebugToken*) (intptr_t) serialize_monitor_values(monitors); | |
389 } | |
390 | |
391 | |
392 int DebugInformationRecorder::data_size() { | |
393 debug_only(_oop_recorder->oop_size()); // mark it "frozen" for asserts | |
394 return _stream->position(); | |
395 } | |
396 | |
397 | |
398 int DebugInformationRecorder::pcs_size() { | |
399 debug_only(_oop_recorder->oop_size()); // mark it "frozen" for asserts | |
400 if (last_pc()->pc_offset() != PcDesc::upper_offset_limit) | |
401 add_new_pc_offset(PcDesc::upper_offset_limit); | |
402 return _pcs_length * sizeof(PcDesc); | |
403 } | |
404 | |
405 | |
406 void DebugInformationRecorder::copy_to(nmethod* nm) { | |
407 nm->copy_scopes_data(stream()->buffer(), stream()->position()); | |
408 nm->copy_scopes_pcs(_pcs, _pcs_length); | |
409 } | |
410 | |
411 | |
412 void DebugInformationRecorder::verify(const nmethod* code) { | |
413 Unimplemented(); | |
414 } | |
415 | |
416 #ifndef PRODUCT | |
417 void DebugInformationRecorder::print_statistics() { | |
418 dir_stats.print(); | |
419 } | |
420 #endif //PRODUCT |