1 /* 2 * Copyright (c) 1998, 2025, 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 "code/debugInfoRec.hpp" 26 #include "code/scopeDesc.hpp" 27 #include "compiler/oopMap.hpp" 28 #include "prims/jvmtiExport.hpp" 29 #include "runtime/globals_extension.hpp" 30 31 // Private definition. 32 // There is one DIR_Chunk for each scope and values array. 33 // A chunk can potentially be used more than once. 34 // We keep track of these chunks in order to detect 35 // repetition and enable sharing. 36 class DIR_Chunk { 37 private: 38 int _offset; // location in the stream of this scope 39 int _length; // number of bytes in the stream 40 int _hash; // hash of stream bytes (for quicker reuse) 41 DebugInformationRecorder* _DIR; 42 43 public: 44 int offset() { return _offset; } 45 46 void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() { 47 assert(ignore == sizeof(DIR_Chunk), ""); 48 if (dir->_next_chunk >= dir->_next_chunk_limit) { 49 const int CHUNK = 100; 50 dir->_next_chunk = NEW_RESOURCE_ARRAY(DIR_Chunk, CHUNK); 51 dir->_next_chunk_limit = dir->_next_chunk + CHUNK; 52 } 53 return dir->_next_chunk++; 54 } 55 56 DIR_Chunk(int offset, int length, DebugInformationRecorder* dir) { 57 _offset = offset; 58 _length = length; 59 _DIR = dir; 60 unsigned int hash = 0; 61 address p = dir->stream()->buffer() + _offset; 62 for (int i = 0; i < length; i++) { 63 if (i == 6) break; 64 hash *= 127; 65 hash += p[i]; 66 } 67 _hash = hash; 68 } 69 70 DIR_Chunk* find_match(GrowableArray<DIR_Chunk*>* arr, 71 int start_index, 72 DebugInformationRecorder* dir) { 73 int end_index = arr->length(); 74 int hash = this->_hash, length = this->_length; 75 address buf = dir->stream()->buffer(); 76 for (int i = end_index; --i >= start_index; ) { 77 DIR_Chunk* that = arr->at(i); 78 if (hash == that->_hash && 79 length == that->_length && 80 0 == memcmp(buf + this->_offset, buf + that->_offset, length)) { 81 return that; 82 } 83 } 84 return nullptr; 85 } 86 87 static int compare(DIR_Chunk* const & a, DIR_Chunk* const & b) { 88 if (b->_hash > a->_hash) { 89 return 1; 90 } 91 if (b->_hash < a->_hash) { 92 return -1; 93 } 94 if (b->_length > a->_length) { 95 return 1; 96 } 97 if (b->_length < a->_length) { 98 return -1; 99 } 100 address buf = a->_DIR->stream()->buffer(); 101 return memcmp(buf + b->_offset, buf + a->_offset, a->_length); 102 } 103 }; 104 105 static inline bool compute_recording_non_safepoints() { 106 if (JvmtiExport::should_post_compiled_method_load() 107 && FLAG_IS_DEFAULT(DebugNonSafepoints)) { 108 // The default value of this flag is taken to be true, 109 // if JVMTI is looking at nmethod codes. 110 // We anticipate that JVMTI may wish to participate in profiling. 111 return true; 112 } 113 114 // If the flag is set manually, use it, whether true or false. 115 // Otherwise, if JVMTI is not in the picture, use the default setting. 116 // (This is true in debug, just for the exercise, false in product mode.) 117 return DebugNonSafepoints; 118 } 119 120 DebugInformationRecorder::DebugInformationRecorder(OopRecorder* oop_recorder) 121 : _recording_non_safepoints(compute_recording_non_safepoints()) 122 { 123 _pcs_size = 100; 124 _pcs = NEW_RESOURCE_ARRAY(PcDesc, _pcs_size); 125 _pcs_length = 0; 126 127 _prev_safepoint_pc = PcDesc::lower_offset_limit; 128 129 _stream = new DebugInfoWriteStream(this, 10 * K); 130 // make sure that there is no stream_decode_offset that is zero 131 _stream->write_byte((jbyte)0xFF); 132 133 // make sure that we can distinguish the value "serialized_null" from offsets 134 assert(_stream->position() > serialized_null, "sanity"); 135 136 _oop_recorder = oop_recorder; 137 138 _all_chunks = new GrowableArray<DIR_Chunk*>(300); 139 _next_chunk = _next_chunk_limit = nullptr; 140 141 add_new_pc_offset(PcDesc::lower_offset_limit); // sentinel record 142 143 debug_only(_recording_state = rs_null); 144 } 145 146 147 void DebugInformationRecorder::add_oopmap(int pc_offset, OopMap* map) { 148 // !!!!! Preserve old style handling of oopmaps for now 149 _oopmaps->add_gc_map(pc_offset, map); 150 } 151 152 void DebugInformationRecorder::add_safepoint(int pc_offset, OopMap* map) { 153 assert(!_oop_recorder->is_complete(), "not frozen yet"); 154 // Store the new safepoint 155 156 // Add the oop map 157 add_oopmap(pc_offset, map); 158 159 add_new_pc_offset(pc_offset); 160 161 assert(_recording_state == rs_null, "nesting of recording calls"); 162 debug_only(_recording_state = rs_safepoint); 163 } 164 165 void DebugInformationRecorder::add_non_safepoint(int pc_offset) { 166 assert(!_oop_recorder->is_complete(), "not frozen yet"); 167 assert(_recording_non_safepoints, "must be recording non-safepoints"); 168 169 add_new_pc_offset(pc_offset); 170 171 assert(_recording_state == rs_null, "nesting of recording calls"); 172 debug_only(_recording_state = rs_non_safepoint); 173 } 174 175 void DebugInformationRecorder::add_new_pc_offset(int pc_offset) { 176 assert(_pcs_length == 0 || last_pc()->pc_offset() < pc_offset, 177 "must specify a new, larger pc offset: %d >= %d", last_pc()->pc_offset(), pc_offset); 178 179 // add the pcdesc 180 if (_pcs_length == _pcs_size) { 181 // Expand 182 int new_pcs_size = _pcs_size * 2; 183 PcDesc* new_pcs = NEW_RESOURCE_ARRAY(PcDesc, new_pcs_size); 184 for (int index = 0; index < _pcs_length; index++) { 185 new_pcs[index] = _pcs[index]; 186 } 187 _pcs_size = new_pcs_size; 188 _pcs = new_pcs; 189 } 190 assert(_pcs_size > _pcs_length, "There must be room for after expanding"); 191 192 _pcs[_pcs_length++] = PcDesc(pc_offset, DebugInformationRecorder::serialized_null, 193 DebugInformationRecorder::serialized_null); 194 } 195 196 197 int DebugInformationRecorder::serialize_monitor_values(GrowableArray<MonitorValue*>* monitors) { 198 if (monitors == nullptr || monitors->is_empty()) return DebugInformationRecorder::serialized_null; 199 assert(_recording_state == rs_safepoint, "must be recording a safepoint"); 200 int result = stream()->position(); 201 stream()->write_int(monitors->length()); 202 for (int index = 0; index < monitors->length(); index++) { 203 monitors->at(index)->write_on(stream()); 204 } 205 assert(result != serialized_null, "sanity"); 206 207 // (See comment below on DebugInformationRecorder::describe_scope.) 208 int shared_result = find_sharable_decode_offset(result); 209 if (shared_result != serialized_null) { 210 stream()->set_position(result); 211 result = shared_result; 212 } 213 214 return result; 215 } 216 217 218 int DebugInformationRecorder::serialize_scope_values(GrowableArray<ScopeValue*>* values) { 219 if (values == nullptr || values->is_empty()) return DebugInformationRecorder::serialized_null; 220 assert(_recording_state == rs_safepoint, "must be recording a safepoint"); 221 int result = stream()->position(); 222 assert(result != serialized_null, "sanity"); 223 stream()->write_int(values->length()); 224 for (int index = 0; index < values->length(); index++) { 225 values->at(index)->write_on(stream()); 226 } 227 228 // (See comment below on DebugInformationRecorder::describe_scope.) 229 int shared_result = find_sharable_decode_offset(result); 230 if (shared_result != serialized_null) { 231 stream()->set_position(result); 232 result = shared_result; 233 } 234 235 return result; 236 } 237 238 239 #ifndef PRODUCT 240 // These variables are put into one block to reduce relocations 241 // and make it simpler to print from the debugger. 242 static 243 struct dir_stats_struct { 244 int chunks_queried; 245 int chunks_shared; 246 int chunks_elided; 247 248 void print() { 249 tty->print_cr("Debug Data Chunks: %d, shared %d, non-SP's elided %d", 250 chunks_queried, chunks_shared, chunks_elided); 251 } 252 } dir_stats; 253 #endif //PRODUCT 254 255 256 int DebugInformationRecorder::find_sharable_decode_offset(int stream_offset) { 257 NOT_PRODUCT(++dir_stats.chunks_queried); 258 int stream_length = stream()->position() - stream_offset; 259 assert(stream_offset != serialized_null, "should not be null"); 260 assert(stream_length != 0, "should not be empty"); 261 262 DIR_Chunk* ns = new(this) DIR_Chunk(stream_offset, stream_length, this); 263 264 DIR_Chunk* match = _all_chunks->insert_sorted<DIR_Chunk::compare>(ns); 265 if (match != ns) { 266 // Found an existing chunk 267 NOT_PRODUCT(++dir_stats.chunks_shared); 268 assert(ns+1 == _next_chunk, ""); 269 _next_chunk = ns; 270 return match->offset(); 271 } else { 272 // Inserted this chunk, so nothing to do 273 return serialized_null; 274 } 275 } 276 277 278 // must call add_safepoint before: it sets PcDesc and this routine uses 279 // the last PcDesc set 280 void DebugInformationRecorder::describe_scope(int pc_offset, 281 const methodHandle& methodH, 282 ciMethod* method, 283 int bci, 284 bool reexecute, 285 bool rethrow_exception, 286 bool is_method_handle_invoke, 287 bool return_oop, 288 bool has_ea_local_in_scope, 289 bool arg_escape, 290 DebugToken* locals, 291 DebugToken* expressions, 292 DebugToken* monitors) { 293 assert(_recording_state != rs_null, "nesting of recording calls"); 294 PcDesc* last_pd = last_pc(); 295 assert(last_pd->pc_offset() == pc_offset, "must be last pc"); 296 int sender_stream_offset = last_pd->scope_decode_offset(); 297 // update the stream offset of current pc desc 298 int stream_offset = stream()->position(); 299 last_pd->set_scope_decode_offset(stream_offset); 300 301 // Record flags into pcDesc. 302 last_pd->set_should_reexecute(reexecute); 303 last_pd->set_rethrow_exception(rethrow_exception); 304 last_pd->set_is_method_handle_invoke(is_method_handle_invoke); 305 last_pd->set_return_oop(return_oop); 306 last_pd->set_has_ea_local_in_scope(has_ea_local_in_scope); 307 last_pd->set_arg_escape(arg_escape); 308 309 // serialize sender stream offset 310 stream()->write_int(sender_stream_offset); 311 312 // serialize scope 313 Metadata* method_enc; 314 if (method != nullptr) { 315 method_enc = method->constant_encoding(); 316 } else if (methodH.not_null()) { 317 method_enc = methodH(); 318 } else { 319 method_enc = nullptr; 320 } 321 int method_enc_index = oop_recorder()->find_index(method_enc); 322 stream()->write_int(method_enc_index); 323 stream()->write_bci(bci); 324 assert(method == nullptr || 325 (method->is_native() && bci == 0) || 326 (!method->is_native() && 0 <= bci && bci < method->code_size()) || 327 bci == -1, "illegal bci"); 328 329 // serialize the locals/expressions/monitors 330 stream()->write_int((intptr_t) locals); 331 stream()->write_int((intptr_t) expressions); 332 stream()->write_int((intptr_t) monitors); 333 334 // Here's a tricky bit. We just wrote some bytes. 335 // Wouldn't it be nice to find that we had already 336 // written those same bytes somewhere else? 337 // If we get lucky this way, reset the stream 338 // and reuse the old bytes. By the way, this 339 // trick not only shares parent scopes, but also 340 // compresses equivalent non-safepoint PcDescs. 341 int shared_stream_offset = find_sharable_decode_offset(stream_offset); 342 if (shared_stream_offset != serialized_null) { 343 stream()->set_position(stream_offset); 344 last_pd->set_scope_decode_offset(shared_stream_offset); 345 } 346 } 347 348 void DebugInformationRecorder::dump_object_pool(GrowableArray<ScopeValue*>* objects) { 349 guarantee( _pcs_length > 0, "safepoint must exist before describing scopes"); 350 PcDesc* last_pd = &_pcs[_pcs_length-1]; 351 if (objects != nullptr) { 352 for (int i = objects->length() - 1; i >= 0; i--) { 353 objects->at(i)->as_ObjectValue()->set_visited(false); 354 } 355 } 356 int offset = serialize_scope_values(objects); 357 last_pd->set_obj_decode_offset(offset); 358 } 359 360 void DebugInformationRecorder::end_scopes(int pc_offset, bool is_safepoint) { 361 assert(_recording_state == (is_safepoint? rs_safepoint: rs_non_safepoint), 362 "nesting of recording calls"); 363 debug_only(_recording_state = rs_null); 364 365 // Try to compress away an equivalent non-safepoint predecessor. 366 // (This only works because we have previously recognized redundant 367 // scope trees and made them use a common scope_decode_offset.) 368 if (_pcs_length >= 2 && recording_non_safepoints()) { 369 PcDesc* last = last_pc(); 370 PcDesc* prev = prev_pc(); 371 // If prev is (a) not a safepoint and (b) has the same 372 // stream pointer, then it can be coalesced into the last. 373 // This is valid because non-safepoints are only sought 374 // with pc_desc_near, which (when it misses prev) will 375 // search forward until it finds last. 376 // In addition, it does not matter if the last PcDesc 377 // is for a safepoint or not. 378 if (_prev_safepoint_pc < prev->pc_offset() && prev->is_same_info(last)) { 379 assert(prev == last-1, "sane"); 380 prev->set_pc_offset(pc_offset); 381 _pcs_length -= 1; 382 NOT_PRODUCT(++dir_stats.chunks_elided); 383 } 384 } 385 386 // We have just recorded this safepoint. 387 // Remember it in case the previous paragraph needs to know. 388 if (is_safepoint) { 389 _prev_safepoint_pc = pc_offset; 390 } 391 } 392 393 #ifdef ASSERT 394 bool DebugInformationRecorder::recorders_frozen() { 395 return _oop_recorder->is_complete(); 396 } 397 398 void DebugInformationRecorder::mark_recorders_frozen() { 399 _oop_recorder->freeze(); 400 } 401 #endif // PRODUCT 402 403 DebugToken* DebugInformationRecorder::create_scope_values(GrowableArray<ScopeValue*>* values) { 404 assert(!recorders_frozen(), "not frozen yet"); 405 return (DebugToken*) (intptr_t) serialize_scope_values(values); 406 } 407 408 409 DebugToken* DebugInformationRecorder::create_monitor_values(GrowableArray<MonitorValue*>* monitors) { 410 assert(!recorders_frozen(), "not frozen yet"); 411 return (DebugToken*) (intptr_t) serialize_monitor_values(monitors); 412 } 413 414 415 int DebugInformationRecorder::data_size() { 416 debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts 417 return _stream->position(); 418 } 419 420 421 int DebugInformationRecorder::pcs_size() { 422 debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts 423 if (last_pc()->pc_offset() != PcDesc::upper_offset_limit) 424 add_new_pc_offset(PcDesc::upper_offset_limit); 425 return _pcs_length * sizeof(PcDesc); 426 } 427 428 429 void DebugInformationRecorder::copy_to(nmethod* nm) { 430 nm->copy_scopes_data(stream()->buffer(), stream()->position()); 431 nm->copy_scopes_pcs(_pcs, _pcs_length); 432 } 433 434 435 void DebugInformationRecorder::verify(const nmethod* code) { 436 Unimplemented(); 437 } 438 439 #ifndef PRODUCT 440 void DebugInformationRecorder::print_statistics() { 441 dir_stats.print(); 442 } 443 #endif //PRODUCT