Mercurial > hg > truffle
annotate src/share/vm/code/debugInfoRec.cpp @ 14649:f6301b007a16
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 9758d9f36299 |
children | cefad50507d8 |
rev | line source |
---|---|
0 | 1 /* |
12146
9758d9f36299
8021954: VM SIGSEGV during classloading on MacOS; hs_err_pid file produced
coleenp
parents:
6725
diff
changeset
|
2 * Copyright (c) 1998, 2013, 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 | |
12146
9758d9f36299
8021954: VM SIGSEGV during classloading on MacOS; hs_err_pid file produced
coleenp
parents:
6725
diff
changeset
|
41 void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() { |
0 | 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 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
308 Metadata* 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()) || | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
1972
diff
changeset
|
314 (method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1 |
0 | 315 bci == -1, "illegal bci"); |
316 | |
317 // serialize the locals/expressions/monitors | |
318 stream()->write_int((intptr_t) locals); | |
319 stream()->write_int((intptr_t) expressions); | |
320 stream()->write_int((intptr_t) monitors); | |
321 | |
322 // Here's a tricky bit. We just wrote some bytes. | |
323 // Wouldn't it be nice to find that we had already | |
324 // written those same bytes somewhere else? | |
325 // If we get lucky this way, reset the stream | |
326 // and reuse the old bytes. By the way, this | |
327 // trick not only shares parent scopes, but also | |
328 // compresses equivalent non-safepoint PcDescs. | |
329 int shared_stream_offset = find_sharable_decode_offset(stream_offset); | |
330 if (shared_stream_offset != serialized_null) { | |
331 stream()->set_position(stream_offset); | |
332 last_pd->set_scope_decode_offset(shared_stream_offset); | |
333 } | |
334 } | |
335 | |
336 void DebugInformationRecorder::dump_object_pool(GrowableArray<ScopeValue*>* objects) { | |
337 guarantee( _pcs_length > 0, "safepoint must exist before describing scopes"); | |
338 PcDesc* last_pd = &_pcs[_pcs_length-1]; | |
339 if (objects != NULL) { | |
340 for (int i = objects->length() - 1; i >= 0; i--) { | |
341 ((ObjectValue*) objects->at(i))->set_visited(false); | |
342 } | |
343 } | |
344 int offset = serialize_scope_values(objects); | |
345 last_pd->set_obj_decode_offset(offset); | |
346 } | |
347 | |
348 void DebugInformationRecorder::end_scopes(int pc_offset, bool is_safepoint) { | |
349 assert(_recording_state == (is_safepoint? rs_safepoint: rs_non_safepoint), | |
350 "nesting of recording calls"); | |
351 debug_only(_recording_state = rs_null); | |
352 | |
353 // Try to compress away an equivalent non-safepoint predecessor. | |
354 // (This only works because we have previously recognized redundant | |
355 // scope trees and made them use a common scope_decode_offset.) | |
356 if (_pcs_length >= 2 && recording_non_safepoints()) { | |
357 PcDesc* last = last_pc(); | |
358 PcDesc* prev = prev_pc(); | |
359 // If prev is (a) not a safepoint and (b) has the same | |
360 // stream pointer, then it can be coalesced into the last. | |
361 // This is valid because non-safepoints are only sought | |
362 // with pc_desc_near, which (when it misses prev) will | |
363 // search forward until it finds last. | |
364 // In addition, it does not matter if the last PcDesc | |
365 // is for a safepoint or not. | |
1014
8e954aedbb81
6889869: assert(!Interpreter::bytecode_should_reexecute(code),"should not reexecute")
never
parents:
989
diff
changeset
|
366 if (_prev_safepoint_pc < prev->pc_offset() && prev->is_same_info(last)) { |
0 | 367 assert(prev == last-1, "sane"); |
368 prev->set_pc_offset(pc_offset); | |
369 _pcs_length -= 1; | |
370 NOT_PRODUCT(++dir_stats.chunks_elided); | |
371 } | |
372 } | |
373 | |
374 // We have just recorded this safepoint. | |
375 // Remember it in case the previous paragraph needs to know. | |
376 if (is_safepoint) { | |
377 _prev_safepoint_pc = pc_offset; | |
378 } | |
379 } | |
380 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
381 #ifdef ASSERT |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
382 bool DebugInformationRecorder::recorders_frozen() { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
383 return _oop_recorder->is_complete() || _oop_recorder->is_complete(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
384 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
385 |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
386 void DebugInformationRecorder::mark_recorders_frozen() { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
387 _oop_recorder->freeze(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
388 } |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
389 #endif // PRODUCT |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
390 |
0 | 391 DebugToken* DebugInformationRecorder::create_scope_values(GrowableArray<ScopeValue*>* values) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
392 assert(!recorders_frozen(), "not frozen yet"); |
0 | 393 return (DebugToken*) (intptr_t) serialize_scope_values(values); |
394 } | |
395 | |
396 | |
397 DebugToken* DebugInformationRecorder::create_monitor_values(GrowableArray<MonitorValue*>* monitors) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
398 assert(!recorders_frozen(), "not frozen yet"); |
0 | 399 return (DebugToken*) (intptr_t) serialize_monitor_values(monitors); |
400 } | |
401 | |
402 | |
403 int DebugInformationRecorder::data_size() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
404 debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts |
0 | 405 return _stream->position(); |
406 } | |
407 | |
408 | |
409 int DebugInformationRecorder::pcs_size() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
410 debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts |
0 | 411 if (last_pc()->pc_offset() != PcDesc::upper_offset_limit) |
412 add_new_pc_offset(PcDesc::upper_offset_limit); | |
413 return _pcs_length * sizeof(PcDesc); | |
414 } | |
415 | |
416 | |
417 void DebugInformationRecorder::copy_to(nmethod* nm) { | |
418 nm->copy_scopes_data(stream()->buffer(), stream()->position()); | |
419 nm->copy_scopes_pcs(_pcs, _pcs_length); | |
420 } | |
421 | |
422 | |
423 void DebugInformationRecorder::verify(const nmethod* code) { | |
424 Unimplemented(); | |
425 } | |
426 | |
427 #ifndef PRODUCT | |
428 void DebugInformationRecorder::print_statistics() { | |
429 dir_stats.print(); | |
430 } | |
431 #endif //PRODUCT |