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/codeBlob.hpp"
 26 #include "code/codeCache.hpp"
 27 #include "code/nmethod.hpp"
 28 #include "code/scopeDesc.hpp"
 29 #include "compiler/oopMap.inline.hpp"
 30 #include "gc/shared/collectedHeap.hpp"
 31 #include "logging/log.hpp"
 32 #include "logging/logStream.hpp"
 33 #include "memory/allocation.inline.hpp"
 34 #include "memory/iterator.hpp"
 35 #include "memory/resourceArea.hpp"
 36 #include "oops/compressedOops.hpp"
 37 #include "runtime/atomic.hpp"
 38 #include "runtime/frame.inline.hpp"
 39 #include "runtime/handles.inline.hpp"
 40 #include "runtime/signature.hpp"
 41 #include "runtime/stackWatermarkSet.inline.hpp"
 42 #include "utilities/align.hpp"
 43 #include "utilities/lockFreeStack.hpp"
 44 #ifdef COMPILER1
 45 #include "c1/c1_Defs.hpp"
 46 #endif
 47 #ifdef COMPILER2
 48 #include "opto/optoreg.hpp"
 49 #endif
 50 #if INCLUDE_JVMCI
 51 #include "jvmci/jvmci_globals.hpp"
 52 #endif
 53 
 54 static_assert(sizeof(oop) == sizeof(intptr_t), "Derived pointer sanity check");
 55 
 56 static inline intptr_t derived_pointer_value(derived_pointer p) {
 57   return static_cast<intptr_t>(p);
 58 }
 59 
 60 static inline derived_pointer to_derived_pointer(intptr_t obj) {
 61   return static_cast<derived_pointer>(obj);
 62 }
 63 
 64 static inline intptr_t operator-(derived_pointer p, derived_pointer p1) {
 65   return derived_pointer_value(p) - derived_pointer_value(p1);
 66 }
 67 
 68 static inline derived_pointer operator+(derived_pointer p, intptr_t offset) {
 69   return static_cast<derived_pointer>(derived_pointer_value(p) + offset);
 70 }
 71 
 72 // OopMapStream
 73 
 74 OopMapStream::OopMapStream(const OopMap* oop_map)
 75   : _stream(oop_map->write_stream()->buffer()) {
 76   _size = oop_map->omv_count();
 77   _position = 0;
 78   _valid_omv = false;
 79 }
 80 
 81 OopMapStream::OopMapStream(const ImmutableOopMap* oop_map)
 82   : _stream(oop_map->data_addr()) {
 83   _size = oop_map->count();
 84   _position = 0;
 85   _valid_omv = false;
 86 }
 87 
 88 void OopMapStream::find_next() {
 89   if (_position++ < _size) {
 90     _omv.read_from(&_stream);
 91     _valid_omv = true;
 92     return;
 93   }
 94   _valid_omv = false;
 95 }
 96 
 97 
 98 // OopMap
 99 
100 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
101 // slots to hold 4-byte values like ints and floats in the LP64 build.
102 OopMap::OopMap(int frame_size, int arg_count) {
103   // OopMaps are usually quite so small, so pick a small initial size
104   set_write_stream(new CompressedWriteStream(32));
105   set_omv_count(0);
106   _num_oops = 0;
107   _has_derived_oops = false;
108   _index = -1;
109 
110 #ifdef ASSERT
111   _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
112   _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
113   for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
114 #endif
115 }
116 
117 
118 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
119   // This constructor does a deep copy
120   // of the source OopMap.
121   set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
122   set_omv_count(0);
123   set_offset(source->offset());
124   _num_oops = source->num_oops();
125   _has_derived_oops = source->has_derived_oops();
126   _index = -1;
127 
128 #ifdef ASSERT
129   _locs_length = source->_locs_length;
130   _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
131   for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
132 #endif
133 
134   // We need to copy the entries too.
135   for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
136     OopMapValue omv = oms.current();
137     omv.write_on(write_stream());
138     increment_count();
139   }
140 }
141 
142 
143 OopMap* OopMap::deep_copy() {
144   return new OopMap(_deep_copy_token, this);
145 }
146 
147 void OopMap::copy_data_to(address addr) const {
148   memcpy(addr, write_stream()->buffer(), write_stream()->position());
149 }
150 
151 class OopMapSort {
152 private:
153   const OopMap* _map;
154   OopMapValue* _values;
155   int _count;
156 
157 public:
158   OopMapSort(const OopMap* map) : _map(map), _count(0) {
159     _values = NEW_RESOURCE_ARRAY(OopMapValue, _map->omv_count());
160   }
161 
162   void sort();
163 
164   void print();
165 
166   void write(CompressedWriteStream* stream) {
167     for (int i = 0; i < _count; ++i) {
168       _values[i].write_on(stream);
169     }
170   }
171 
172 private:
173   int find_derived_position(OopMapValue omv, int start) {
174     assert(omv.type() == OopMapValue::derived_oop_value, "");
175 
176     VMReg base = omv.content_reg();
177     int i = start;
178 
179     for (; i < _count; ++i) {
180       if (base == _values[i].reg()) {
181 
182         for (int n = i + 1; n < _count; ++n) {
183           if (_values[i].type() != OopMapValue::derived_oop_value || _values[i].content_reg() != base) {
184             return n;
185           }
186 
187           if (derived_cost(_values[i]) > derived_cost(omv)) {
188             return n;
189           }
190         }
191         return _count;
192       }
193     }
194 
195     assert(false, "failed to find base");
196     return -1;
197   }
198 
199   int find_position(OopMapValue omv, int start) {
200     assert(omv.type() != OopMapValue::derived_oop_value, "");
201 
202     int i = start;
203     for (; i < _count; ++i) {
204       if (omv_cost(_values[i]) > omv_cost(omv)) {
205         return i;
206       }
207     }
208     assert(i < _map->omv_count(), "bounds check");
209     return i;
210   }
211 
212   void insert(OopMapValue value, int pos) {
213     assert(pos >= 0 && pos < _map->omv_count(), "bounds check");
214     assert(pos <= _count, "sanity");
215 
216     if (pos < _count) {
217       OopMapValue prev = _values[pos];
218 
219       for (int i = pos; i < _count; ++i) {
220         OopMapValue tmp = _values[i+1];
221         _values[i+1] = prev;
222         prev = tmp;
223       }
224     }
225     _values[pos] = value;
226 
227     ++_count;
228   }
229 
230   int omv_cost(OopMapValue omv) {
231     assert(omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value, "");
232     return reg_cost(omv.reg());
233   }
234 
235   int reg_cost(VMReg reg) {
236     if (reg->is_reg()) {
237       return 0;
238     }
239     return reg->reg2stack() * VMRegImpl::stack_slot_size;
240   }
241 
242   int derived_cost(OopMapValue omv) {
243     return reg_cost(omv.reg());
244   }
245 };
246 
247 void OopMapSort::sort() {
248 #ifdef ASSERT
249   for (OopMapStream oms(_map); !oms.is_done(); oms.next()) {
250     OopMapValue omv = oms.current();
251     assert(omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value ||
252            omv.type() == OopMapValue::derived_oop_value || omv.type() == OopMapValue::callee_saved_value, "");
253   }
254 #endif
255 
256   for (OopMapStream oms(_map); !oms.is_done(); oms.next()) {
257     if (oms.current().type() == OopMapValue::callee_saved_value) {
258       insert(oms.current(), _count);
259     }
260   }
261 
262   int start = _count;
263   for (OopMapStream oms(_map); !oms.is_done(); oms.next()) {
264     OopMapValue omv = oms.current();
265     if (omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value) {
266       int pos = find_position(omv, start);
267       insert(omv, pos);
268     }
269   }
270 
271   for (OopMapStream oms(_map); !oms.is_done(); oms.next()) {
272     OopMapValue omv = oms.current();
273     if (omv.type() == OopMapValue::derived_oop_value) {
274       int pos = find_derived_position(omv, start);
275       assert(pos > 0, "");
276       insert(omv, pos);
277     }
278   }
279 }
280 
281 void OopMapSort::print() {
282   for (int i = 0; i < _count; ++i) {
283     OopMapValue omv = _values[i];
284     if (omv.type() == OopMapValue::oop_value || omv.type() == OopMapValue::narrowoop_value) {
285       if (omv.reg()->is_reg()) {
286         tty->print_cr("[%c][%d] -> reg (%d)", omv.type() == OopMapValue::narrowoop_value ? 'n' : 'o', i, omv.reg()->value());
287       } else {
288         tty->print_cr("[%c][%d] -> stack (%d)", omv.type() == OopMapValue::narrowoop_value ? 'n' : 'o', i, omv.reg()->reg2stack() * VMRegImpl::stack_slot_size);
289       }
290     } else {
291       if (omv.content_reg()->is_reg()) {
292         tty->print_cr("[d][%d] -> reg (%d) stack (%d)", i, omv.content_reg()->value(), omv.reg()->reg2stack() * VMRegImpl::stack_slot_size);
293       } else if (omv.reg()->is_reg()) {
294         tty->print_cr("[d][%d] -> stack (%d) reg (%d)", i, omv.content_reg()->reg2stack() * VMRegImpl::stack_slot_size, omv.reg()->value());
295       } else {
296         int derived_offset = omv.reg()->reg2stack() * VMRegImpl::stack_slot_size;
297         int base_offset = omv.content_reg()->reg2stack() * VMRegImpl::stack_slot_size;
298         tty->print_cr("[d][%d] -> stack (%x) stack (%x)", i, base_offset, derived_offset);
299       }
300     }
301   }
302 }
303 
304 void OopMap::copy_and_sort_data_to(address addr) const {
305   OopMapSort sort(this);
306   sort.sort();
307   CompressedWriteStream* stream = new CompressedWriteStream(_write_stream->position());
308   sort.write(stream);
309 
310   assert(stream->position() == write_stream()->position(), "");
311   memcpy(addr, stream->buffer(), stream->position());
312 }
313 
314 int OopMap::heap_size() const {
315   int size = sizeof(OopMap);
316   int align = sizeof(void *) - 1;
317   size += write_stream()->position();
318   // Align to a reasonable ending point
319   size = ((size+align) & ~align);
320   return size;
321 }
322 
323 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
324 // slots to hold 4-byte values like ints and floats in the LP64 build.
325 void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
326 
327   assert(reg->value() < _locs_length, "too big reg value for stack size");
328   assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
329   debug_only( _locs_used[reg->value()] = x; )
330 
331   OopMapValue o(reg, x, optional);
332   o.write_on(write_stream());
333   increment_count();
334   if (x == OopMapValue::oop_value || x == OopMapValue::narrowoop_value) {
335     increment_num_oops();
336   } else if (x == OopMapValue::derived_oop_value) {
337     set_has_derived_oops(true);
338   }
339 }
340 
341 
342 void OopMap::set_oop(VMReg reg) {
343   set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad());
344 }
345 
346 
347 void OopMap::set_narrowoop(VMReg reg) {
348   set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());
349 }
350 
351 
352 void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) {
353   set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register);
354 }
355 
356 
357 void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
358   if( reg == derived_from_local_register ) {
359     // Actually an oop, derived shares storage with base,
360     set_oop(reg);
361   } else {
362     set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register);
363   }
364 }
365 
366 // OopMapSet
367 
368 OopMapSet::OopMapSet() : _list(MinOopMapAllocation) {}
369 
370 int OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
371   map->set_offset(pc_offset);
372 
373 #ifdef ASSERT
374   if(_list.length() > 0) {
375     OopMap* last = _list.last();
376     if (last->offset() == map->offset() ) {
377       fatal("OopMap inserted twice");
378     }
379     if (last->offset() > map->offset()) {
380       tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
381                       _list.length(),last->offset(),_list.length()+1,map->offset());
382     }
383   }
384 #endif // ASSERT
385 
386   int index = add(map);
387   map->_index = index;
388   return index;
389 }
390 
391 class AddDerivedOop : public DerivedOopClosure {
392  public:
393   enum {
394     SkipNull = true, NeedsLock = true
395   };
396 
397   virtual void do_derived_oop(derived_base* base, derived_pointer* derived) {
398 #if COMPILER2_OR_JVMCI
399     DerivedPointerTable::add(derived, base);
400 #endif // COMPILER2_OR_JVMCI
401   }
402 };
403 
404 class ProcessDerivedOop : public DerivedOopClosure {
405   OopClosure* _oop_cl;
406 
407 public:
408   ProcessDerivedOop(OopClosure* oop_cl) :
409       _oop_cl(oop_cl) {}
410 
411   enum {
412     SkipNull = true, NeedsLock = true
413   };
414 
415   virtual void do_derived_oop(derived_base* base, derived_pointer* derived) {
416     // All derived pointers must be processed before the base pointer of any derived pointer is processed.
417     // Otherwise, if two derived pointers use the same base, the second derived pointer will get an obscured
418     // offset, if the base pointer is processed in the first derived pointer.
419   derived_pointer derived_base = to_derived_pointer(*reinterpret_cast<intptr_t*>(base));
420     intptr_t offset = *derived - derived_base;
421     *derived = derived_base;
422     _oop_cl->do_oop((oop*)derived);
423     *derived = *derived + offset;
424   }
425 };
426 
427 class IgnoreDerivedOop : public DerivedOopClosure {
428   OopClosure* _oop_cl;
429 
430 public:
431   enum {
432     SkipNull = true, NeedsLock = true
433   };
434 
435   virtual void do_derived_oop(derived_base* base, derived_pointer* derived) {}
436 };
437 
438 void OopMapSet::oops_do(const frame* fr, const RegisterMap* reg_map, OopClosure* f, DerivedPointerIterationMode mode) {
439   find_map(fr)->oops_do(fr, reg_map, f, mode);
440 }
441 
442 void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f, DerivedOopClosure* df) {
443   find_map(fr)->oops_do(fr, reg_map, f, df);
444 }
445 
446 void ImmutableOopMap::oops_do(const frame *fr, const RegisterMap *reg_map,
447                               OopClosure* oop_fn, DerivedOopClosure* derived_oop_fn) const {
448   assert(derived_oop_fn != nullptr, "sanity");
449   OopMapDo<OopClosure, DerivedOopClosure, SkipNullValue> visitor(oop_fn, derived_oop_fn);
450   visitor.oops_do(fr, reg_map, this);
451 }
452 
453 void ImmutableOopMap::oops_do(const frame *fr, const RegisterMap *reg_map,
454                               OopClosure* oop_fn, DerivedPointerIterationMode derived_mode) const {
455   ProcessDerivedOop process_cl(oop_fn);
456   AddDerivedOop add_cl;
457   IgnoreDerivedOop ignore_cl;
458   DerivedOopClosure* derived_cl;
459   switch (derived_mode) {
460   case DerivedPointerIterationMode::_directly:
461     derived_cl = &process_cl;
462     break;
463   case DerivedPointerIterationMode::_with_table:
464     derived_cl = &add_cl;
465     break;
466   case DerivedPointerIterationMode::_ignore:
467     derived_cl = &ignore_cl;
468     break;
469   default:
470     guarantee (false, "unreachable");
471   }
472   OopMapDo<OopClosure, DerivedOopClosure, SkipNullValue> visitor(oop_fn, derived_cl);
473   visitor.oops_do(fr, reg_map, this);
474 }
475 
476 void ImmutableOopMap::all_type_do(const frame *fr, OopMapClosure* fn) const {
477   OopMapValue omv;
478   for (OopMapStream oms(this); !oms.is_done(); oms.next()) {
479     omv = oms.current();
480     if (fn->handle_type(omv.type())) {
481       fn->do_value(omv.reg(), omv.type());
482     }
483   }
484 }
485 
486 void ImmutableOopMap::all_type_do(const frame *fr, OopMapValue::oop_types type, OopMapClosure* fn) const {
487   OopMapValue omv;
488   for (OopMapStream oms(this); !oms.is_done(); oms.next()) {
489     omv = oms.current();
490     if (omv.type() == type) {
491       fn->do_value(omv.reg(), omv.type());
492     }
493   }
494 }
495 
496 static void update_register_map1(const ImmutableOopMap* oopmap, const frame* fr, RegisterMap* reg_map) {
497   for (OopMapStream oms(oopmap); !oms.is_done(); oms.next()) {
498     OopMapValue omv = oms.current();
499     if (omv.type() == OopMapValue::callee_saved_value) {
500       VMReg reg = omv.content_reg();
501       address loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
502       reg_map->set_location(reg, loc);
503     }
504   }
505 }
506 
507 // Update callee-saved register info for the following frame
508 void ImmutableOopMap::update_register_map(const frame *fr, RegisterMap *reg_map) const {
509   CodeBlob* cb = fr->cb();
510   assert(cb != nullptr, "no codeblob");
511   // Any reg might be saved by a safepoint handler (see generate_handler_blob).
512   assert( reg_map->_update_for_id == nullptr || fr->is_older(reg_map->_update_for_id),
513          "already updated this map; do not 'update' it twice!" );
514   debug_only(reg_map->_update_for_id = fr->id());
515 
516   // Check if caller must update oop argument
517   assert((reg_map->include_argument_oops() ||
518           !cb->caller_must_gc_arguments(reg_map->thread())),
519          "include_argument_oops should already be set");
520 
521   // Scan through oopmap and find location of all callee-saved registers
522   // (we do not do update in place, since info could be overwritten)
523 
524   update_register_map1(this, fr, reg_map);
525 }
526 
527 const ImmutableOopMap* OopMapSet::find_map(const frame *fr) {
528   return find_map(fr->cb(), fr->pc());
529 }
530 
531 const ImmutableOopMap* OopMapSet::find_map(const CodeBlob* cb, address pc) {
532   assert(cb != nullptr, "no codeblob");
533   const ImmutableOopMap* map = cb->oop_map_for_return_address(pc);
534   assert(map != nullptr, "no ptr map found");
535   return map;
536 }
537 
538 // Update callee-saved register info for the following frame
539 void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
540   find_map(fr)->update_register_map(fr, reg_map);
541 }
542 
543 //=============================================================================
544 // Non-Product code
545 
546 #ifndef PRODUCT
547 void OopMapSet::trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
548   // Print oopmap and regmap
549   tty->print_cr("------ ");
550   CodeBlob* cb = fr->cb();
551   const ImmutableOopMapSet* maps = cb->oop_maps();
552   const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
553   map->print();
554   if( cb->is_nmethod() ) {
555     nmethod* nm = (nmethod*)cb;
556     // native wrappers have no scope data, it is implied
557     if (nm->is_native_method()) {
558       tty->print("bci: 0 (native)");
559     } else {
560       ScopeDesc* scope  = nm->scope_desc_at(fr->pc());
561       tty->print("bci: %d ",scope->bci());
562     }
563   }
564   tty->cr();
565   fr->print_on(tty);
566   tty->print("     ");
567   cb->print_value_on(tty);  tty->cr();
568   if (reg_map != nullptr) {
569     reg_map->print();
570   }
571   tty->print_cr("------ ");
572 
573 }
574 #endif // PRODUCT
575 
576 // Printing code is present in product build for -XX:+PrintAssembly.
577 
578 static
579 void print_register_type(OopMapValue::oop_types x, VMReg optional,
580                          outputStream* st) {
581   switch( x ) {
582   case OopMapValue::oop_value:
583     st->print("Oop");
584     break;
585   case OopMapValue::narrowoop_value:
586     st->print("NarrowOop");
587     break;
588   case OopMapValue::callee_saved_value:
589     st->print("Callers_");
590     optional->print_on(st);
591     break;
592   case OopMapValue::derived_oop_value:
593     st->print("Derived_oop_");
594     optional->print_on(st);
595     break;
596   default:
597     ShouldNotReachHere();
598   }
599 }
600 
601 void OopMapValue::print_on(outputStream* st) const {
602   reg()->print_on(st);
603   st->print("=");
604   print_register_type(type(),content_reg(),st);
605   st->print(" ");
606 }
607 
608 void OopMapValue::print() const { print_on(tty); }
609 
610 void ImmutableOopMap::print_on(outputStream* st) const {
611   OopMapValue omv;
612   st->print("ImmutableOopMap {");
613   for(OopMapStream oms(this); !oms.is_done(); oms.next()) {
614     omv = oms.current();
615     omv.print_on(st);
616   }
617   st->print("}");
618 }
619 
620 void ImmutableOopMap::print() const { print_on(tty); }
621 
622 void OopMap::print_on(outputStream* st) const {
623   OopMapValue omv;
624   st->print("OopMap {");
625   for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
626     omv = oms.current();
627     omv.print_on(st);
628   }
629   // Print hex offset in addition.
630   st->print("off=%d/0x%x}", (int) offset(), (int) offset());
631 }
632 
633 void OopMap::print() const { print_on(tty); }
634 
635 void ImmutableOopMapSet::print_on(outputStream* st) const {
636   const ImmutableOopMap* last = nullptr;
637   const int len = count();
638 
639   st->print_cr("ImmutableOopMapSet contains %d OopMaps", len);
640 
641   for (int i = 0; i < len; i++) {
642     const ImmutableOopMapPair* pair = pair_at(i);
643     const ImmutableOopMap* map = pair->get_from(this);
644     if (map != last) {
645       st->cr();
646       map->print_on(st);
647       st->print(" pc offsets: ");
648     }
649     last = map;
650     st->print("%d ", pair->pc_offset());
651   }
652   st->cr();
653 }
654 
655 void ImmutableOopMapSet::print() const { print_on(tty); }
656 
657 void OopMapSet::print_on(outputStream* st) const {
658   const int len = _list.length();
659 
660   st->print_cr("OopMapSet contains %d OopMaps", len);
661 
662   for( int i = 0; i < len; i++) {
663     OopMap* m = at(i);
664     st->print_cr("#%d ",i);
665     m->print_on(st);
666     st->cr();
667   }
668   st->cr();
669 }
670 
671 void OopMapSet::print() const { print_on(tty); }
672 
673 bool OopMap::equals(const OopMap* other) const {
674   if (other->_omv_count != _omv_count) {
675     return false;
676   }
677   if (other->write_stream()->position() != write_stream()->position()) {
678     return false;
679   }
680   if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {
681     return false;
682   }
683   return true;
684 }
685 
686 int ImmutableOopMapSet::find_slot_for_offset(int pc_offset) const {
687   // we might not have an oopmap at asynchronous (non-safepoint) stackwalks
688   ImmutableOopMapPair* pairs = get_pairs();
689   for (int i = 0; i < _count; ++i) {
690     if (pairs[i].pc_offset() >= pc_offset) {
691       ImmutableOopMapPair* last = &pairs[i];
692       return last->pc_offset() == pc_offset ? i : -1;
693     }
694   }
695   return -1;
696 }
697 
698 const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {
699   ImmutableOopMapPair* pairs = get_pairs();
700   ImmutableOopMapPair* last  = nullptr;
701 
702   for (int i = 0; i < _count; ++i) {
703     if (pairs[i].pc_offset() >= pc_offset) {
704       last = &pairs[i];
705       break;
706     }
707   }
708 
709   // Heal Coverity issue: potential index out of bounds access.
710   guarantee(last != nullptr, "last may not be null");
711   assert(last->pc_offset() == pc_offset, "oopmap not found");
712   return last->get_from(this);
713 }
714 
715 ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap)
716   : _count(oopmap->count()), _num_oops(oopmap->num_oops()) {
717   _num_oops = oopmap->num_oops();
718   _has_derived_oops = oopmap->has_derived_oops();
719   address addr = data_addr();
720   oopmap->copy_and_sort_data_to(addr);
721 }
722 
723 bool ImmutableOopMap::has_any(OopMapValue::oop_types type) const {
724   for (OopMapStream oms(this); !oms.is_done(); oms.next()) {
725     if (oms.current().type() == type) {
726       return true;
727     }
728   }
729   return false;
730 }
731 
732 #ifdef ASSERT
733 int ImmutableOopMap::nr_of_bytes() const {
734   OopMapStream oms(this);
735 
736   while (!oms.is_done()) {
737     oms.next();
738   }
739   return sizeof(ImmutableOopMap) + oms.stream_position();
740 }
741 #endif
742 
743 ImmutableOopMapBuilder::ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _empty(nullptr), _last(nullptr), _empty_offset(-1), _last_offset(-1), _offset(0), _required(-1), _new_set(nullptr) {
744   _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
745 }
746 
747 int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
748   return align_up((int)sizeof(ImmutableOopMap) + map->data_size(), 8);
749 }
750 
751 int ImmutableOopMapBuilder::heap_size() {
752   int base = sizeof(ImmutableOopMapSet);
753   base = align_up(base, 8);
754 
755   // all of ours pc / offset pairs
756   int pairs = _set->size() * sizeof(ImmutableOopMapPair);
757   pairs = align_up(pairs, 8);
758 
759   for (int i = 0; i < _set->size(); ++i) {
760     int size = 0;
761     OopMap* map = _set->at(i);
762 
763     if (is_empty(map)) {
764       /* only keep a single empty map in the set */
765       if (has_empty()) {
766         _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
767       } else {
768         _empty_offset = _offset;
769         _empty = map;
770         size = size_for(map);
771         _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
772       }
773     } else if (is_last_duplicate(map)) {
774       /* if this entry is identical to the previous one, just point it there */
775       _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
776     } else {
777       /* not empty, not an identical copy of the previous entry */
778       size = size_for(map);
779       _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
780       _last_offset = _offset;
781       _last = map;
782     }
783 
784     assert(_mapping[i]._map == map, "check");
785     _offset += size;
786   }
787 
788   int total = base + pairs + _offset;
789   DEBUG_ONLY(total += 8);
790   _required = total;
791   return total;
792 }
793 
794 void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {
795   assert(offset < set->nr_of_bytes(), "check");
796   new ((address) pair) ImmutableOopMapPair(map->offset(), offset);
797 }
798 
799 int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {
800   fill_pair(pair, map, offset, set);
801   address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap
802 
803   new (addr) ImmutableOopMap(map);
804   return size_for(map);
805 }
806 
807 void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {
808   ImmutableOopMapPair* pairs = set->get_pairs();
809 
810   for (int i = 0; i < set->count(); ++i) {
811     const OopMap* map = _mapping[i]._map;
812     ImmutableOopMapPair* pair = nullptr;
813     int size = 0;
814 
815     if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {
816       size = fill_map(&pairs[i], map, _mapping[i]._offset, set);
817     } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {
818       fill_pair(&pairs[i], map, _mapping[i]._offset, set);
819     }
820 
821     //const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());
822     //assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");
823   }
824 }
825 
826 #ifdef ASSERT
827 void ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) {
828   for (int i = 0; i < 8; ++i) {
829     assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");
830   }
831 
832   for (int i = 0; i < set->count(); ++i) {
833     const ImmutableOopMapPair* pair = set->pair_at(i);
834     assert(pair->oopmap_offset() < set->nr_of_bytes(), "check size");
835     const ImmutableOopMap* map = pair->get_from(set);
836     int nr_of_bytes = map->nr_of_bytes();
837     assert(pair->oopmap_offset() + nr_of_bytes <= set->nr_of_bytes(), "check size + size");
838   }
839 }
840 #endif
841 
842 ImmutableOopMapSet* ImmutableOopMapBuilder::generate_into(address buffer) {
843   DEBUG_ONLY(memset(&buffer[_required-8], 0xff, 8));
844 
845   _new_set = new (buffer) ImmutableOopMapSet(_set, _required);
846   fill(_new_set, _required);
847 
848   DEBUG_ONLY(verify(buffer, _required, _new_set));
849 
850   return _new_set;
851 }
852 
853 ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
854   _required = heap_size();
855 
856   // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
857   address buffer = NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);
858   return generate_into(buffer);
859 }
860 
861 ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
862   ResourceMark mark;
863   ImmutableOopMapBuilder builder(oopmap_set);
864   return builder.build();
865 }
866 
867 void ImmutableOopMapSet::operator delete(void* p) {
868   FREE_C_HEAP_ARRAY(unsigned char, p);
869 }
870 
871 //------------------------------DerivedPointerTable---------------------------
872 
873 #if COMPILER2_OR_JVMCI
874 
875 class DerivedPointerTable::Entry : public CHeapObj<mtCompiler> {
876   derived_pointer* _location; // Location of derived pointer, also pointing to base
877   intptr_t         _offset;   // Offset from base pointer
878   Entry* volatile  _next;
879 
880   static Entry* volatile* next_ptr(Entry& entry) { return &entry._next; }
881 
882 public:
883   Entry(derived_pointer* location, intptr_t offset) :
884     _location(location), _offset(offset), _next(nullptr) {}
885 
886   derived_pointer* location() const { return _location; }
887   intptr_t offset() const { return _offset; }
888   Entry* next() const { return _next; }
889 
890   typedef LockFreeStack<Entry, &next_ptr> List;
891   static List* _list;
892 };
893 
894 DerivedPointerTable::Entry::List* DerivedPointerTable::Entry::_list = nullptr;
895 bool DerivedPointerTable::_active = false;
896 
897 bool DerivedPointerTable::is_empty() {
898   return Entry::_list == nullptr || Entry::_list->empty();
899 }
900 
901 void DerivedPointerTable::clear() {
902   // The first time, we create the list.  Otherwise it should be
903   // empty.  If not, then we have probably forgotton to call
904   // update_pointers after last GC/Scavenge.
905   assert (!_active, "should not be active");
906   assert(is_empty(), "table not empty");
907   if (Entry::_list == nullptr) {
908     void* mem = NEW_C_HEAP_OBJ(Entry::List, mtCompiler);
909     Entry::_list = ::new (mem) Entry::List();
910   }
911   _active = true;
912 }
913 
914 void DerivedPointerTable::add(derived_pointer* derived_loc, derived_base* base_loc) {
915   assert(Universe::heap()->is_in_or_null((void*)*base_loc), "not an oop");
916   assert(derived_loc != (void*)base_loc, "Base and derived in same location");
917   derived_pointer base_loc_as_derived_pointer =
918     static_cast<derived_pointer>(reinterpret_cast<intptr_t>(base_loc));
919   assert(*derived_loc != base_loc_as_derived_pointer, "location already added");
920   assert(Entry::_list != nullptr, "list must exist");
921   assert(is_active(), "table must be active here");
922   intptr_t offset = *derived_loc - to_derived_pointer(*reinterpret_cast<intptr_t*>(base_loc));
923   // This assert is invalid because derived pointers can be
924   // arbitrarily far away from their base.
925   // assert(offset >= -1000000, "wrong derived pointer info");
926 
927   if (TraceDerivedPointers) {
928     tty->print_cr(
929       "Add derived pointer@" INTPTR_FORMAT
930       " - Derived: " INTPTR_FORMAT
931       " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: %zd)",
932       p2i(derived_loc), derived_pointer_value(*derived_loc), intptr_t(*base_loc), p2i(base_loc), offset
933     );
934   }
935   // Set derived oop location to point to base.
936   *derived_loc = base_loc_as_derived_pointer;
937   Entry* entry = new Entry(derived_loc, offset);
938   Entry::_list->push(*entry);
939 }
940 
941 void DerivedPointerTable::update_pointers() {
942   assert(Entry::_list != nullptr, "list must exist");
943   Entry* entries = Entry::_list->pop_all();
944   while (entries != nullptr) {
945     Entry* entry = entries;
946     entries = entry->next();
947     derived_pointer* derived_loc = entry->location();
948     intptr_t offset  = entry->offset();
949     // The derived oop was setup to point to location of base
950     oop base = **reinterpret_cast<oop**>(derived_loc);
951     assert(Universe::heap()->is_in_or_null(base), "must be an oop");
952 
953     derived_pointer derived_base = to_derived_pointer(cast_from_oop<intptr_t>(base));
954     *derived_loc = derived_base + offset;
955     assert(*derived_loc - derived_base == offset, "sanity check");
956 
957     // assert(offset >= 0 && offset <= (intptr_t)(base->size() << LogHeapWordSize), "offset: %ld base->size: %zu relative: %d", offset, base->size() << LogHeapWordSize, *(intptr_t*)derived_loc <= 0);
958 
959     if (TraceDerivedPointers) {
960       tty->print_cr("Updating derived pointer@" INTPTR_FORMAT
961                     " - Derived: " INTPTR_FORMAT "  Base: " INTPTR_FORMAT " (Offset: %zd)",
962                     p2i(derived_loc), derived_pointer_value(*derived_loc), p2i(base), offset);
963     }
964 
965     // Delete entry
966     delete entry;
967   }
968   assert(Entry::_list->empty(), "invariant");
969   _active = false;
970 }
971 
972 #endif // COMPILER2_OR_JVMCI