1/*
2 * Copyright (c) 1998, 2015, 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 "code/codeBlob.hpp"
27#include "code/codeCache.hpp"
28#include "code/nmethod.hpp"
29#include "code/scopeDesc.hpp"
30#include "compiler/oopMap.hpp"
31#include "gc/shared/collectedHeap.hpp"
32#include "memory/allocation.inline.hpp"
33#include "memory/resourceArea.hpp"
34#include "runtime/frame.inline.hpp"
35#include "runtime/signature.hpp"
36#include "utilities/align.hpp"
37#ifdef COMPILER1
38#include "c1/c1_Defs.hpp"
39#endif
40#ifdef COMPILER2
41#include "opto/optoreg.hpp"
42#endif
43#ifdef SPARC
44#include "vmreg_sparc.inline.hpp"
45#endif
46
47// OopMapStream
48
49OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
50  _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
51  _mask = oop_types_mask;
52  _size = oop_map->omv_count();
53  _position = 0;
54  _valid_omv = false;
55}
56
57OopMapStream::OopMapStream(const ImmutableOopMap* oop_map, int oop_types_mask) {
58  _stream = new CompressedReadStream(oop_map->data_addr());
59  _mask = oop_types_mask;
60  _size = oop_map->count();
61  _position = 0;
62  _valid_omv = false;
63}
64
65void OopMapStream::find_next() {
66  while(_position++ < _size) {
67    _omv.read_from(_stream);
68    if(((int)_omv.type() & _mask) > 0) {
69      _valid_omv = true;
70      return;
71    }
72  }
73  _valid_omv = false;
74}
75
76
77// OopMap
78
79// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
80// slots to hold 4-byte values like ints and floats in the LP64 build.
81OopMap::OopMap(int frame_size, int arg_count) {
82  // OopMaps are usually quite so small, so pick a small initial size
83  set_write_stream(new CompressedWriteStream(32));
84  set_omv_count(0);
85
86#ifdef ASSERT
87  _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
88  _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
89  for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
90#endif
91}
92
93
94OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
95  // This constructor does a deep copy
96  // of the source OopMap.
97  set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
98  set_omv_count(0);
99  set_offset(source->offset());
100
101#ifdef ASSERT
102  _locs_length = source->_locs_length;
103  _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
104  for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
105#endif
106
107  // We need to copy the entries too.
108  for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
109    OopMapValue omv = oms.current();
110    omv.write_on(write_stream());
111    increment_count();
112  }
113}
114
115
116OopMap* OopMap::deep_copy() {
117  return new OopMap(_deep_copy_token, this);
118}
119
120void OopMap::copy_data_to(address addr) const {
121  memcpy(addr, write_stream()->buffer(), write_stream()->position());
122}
123
124int OopMap::heap_size() const {
125  int size = sizeof(OopMap);
126  int align = sizeof(void *) - 1;
127  size += write_stream()->position();
128  // Align to a reasonable ending point
129  size = ((size+align) & ~align);
130  return size;
131}
132
133// frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
134// slots to hold 4-byte values like ints and floats in the LP64 build.
135void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
136
137  assert(reg->value() < _locs_length, "too big reg value for stack size");
138  assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
139  debug_only( _locs_used[reg->value()] = x; )
140
141  OopMapValue o(reg, x);
142
143  if(x == OopMapValue::callee_saved_value) {
144    // This can never be a stack location, so we don't need to transform it.
145    assert(optional->is_reg(), "Trying to callee save a stack location");
146    o.set_content_reg(optional);
147  } else if(x == OopMapValue::derived_oop_value) {
148    o.set_content_reg(optional);
149  }
150
151  o.write_on(write_stream());
152  increment_count();
153}
154
155
156void OopMap::set_oop(VMReg reg) {
157  set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad());
158}
159
160
161void OopMap::set_value(VMReg reg) {
162  // At this time, we don't need value entries in our OopMap.
163}
164
165
166void OopMap::set_narrowoop(VMReg reg) {
167  set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());
168}
169
170
171void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) {
172  set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register);
173}
174
175
176void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
177  if( reg == derived_from_local_register ) {
178    // Actually an oop, derived shares storage with base,
179    set_oop(reg);
180  } else {
181    set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register);
182  }
183}
184
185// OopMapSet
186
187OopMapSet::OopMapSet() {
188  set_om_size(MinOopMapAllocation);
189  set_om_count(0);
190  OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size());
191  set_om_data(temp);
192}
193
194
195void OopMapSet::grow_om_data() {
196  int new_size = om_size() * 2;
197  OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
198  memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
199  set_om_size(new_size);
200  set_om_data(new_data);
201}
202
203void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
204  assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
205
206  if(om_count() >= om_size()) {
207    grow_om_data();
208  }
209  map->set_offset(pc_offset);
210
211#ifdef ASSERT
212  if(om_count() > 0) {
213    OopMap* last = at(om_count()-1);
214    if (last->offset() == map->offset() ) {
215      fatal("OopMap inserted twice");
216    }
217    if(last->offset() > map->offset()) {
218      tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
219                      om_count(),last->offset(),om_count()+1,map->offset());
220    }
221  }
222#endif // ASSERT
223
224  set(om_count(),map);
225  increment_count();
226}
227
228
229int OopMapSet::heap_size() const {
230  // The space we use
231  int size = sizeof(OopMap);
232  int align = sizeof(void *) - 1;
233  size = ((size+align) & ~align);
234  size += om_count() * sizeof(OopMap*);
235
236  // Now add in the space needed for the indivdiual OopMaps
237  for(int i=0; i < om_count(); i++) {
238    size += at(i)->heap_size();
239  }
240  // We don't need to align this, it will be naturally pointer aligned
241  return size;
242}
243
244
245OopMap* OopMapSet::singular_oop_map() {
246  guarantee(om_count() == 1, "Make sure we only have a single gc point");
247  return at(0);
248}
249
250
251OopMap* OopMapSet::find_map_at_offset(int pc_offset) const {
252  int i, len = om_count();
253  assert( len > 0, "must have pointer maps" );
254
255  // Scan through oopmaps. Stop when current offset is either equal or greater
256  // than the one we are looking for.
257  for( i = 0; i < len; i++) {
258    if( at(i)->offset() >= pc_offset )
259      break;
260  }
261
262  assert( i < len, "oopmap not found" );
263
264  OopMap* m = at(i);
265  assert( m->offset() == pc_offset, "oopmap not found" );
266  return m;
267}
268
269class DoNothingClosure: public OopClosure {
270 public:
271  void do_oop(oop* p)       {}
272  void do_oop(narrowOop* p) {}
273};
274static DoNothingClosure do_nothing;
275
276static void add_derived_oop(oop* base, oop* derived) {
277#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
278  COMPILER1_PRESENT(ShouldNotReachHere();)
279#endif // !defined(TIERED) && !defined(INCLUDE_JVMCI)
280#if defined(COMPILER2) || INCLUDE_JVMCI
281  DerivedPointerTable::add(derived, base);
282#endif // COMPILER2 || INCLUDE_JVMCI
283}
284
285
286#ifndef PRODUCT
287static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
288  // Print oopmap and regmap
289  tty->print_cr("------ ");
290  CodeBlob* cb = fr->cb();
291  const ImmutableOopMapSet* maps = cb->oop_maps();
292  const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
293  map->print();
294  if( cb->is_nmethod() ) {
295    nmethod* nm = (nmethod*)cb;
296    // native wrappers have no scope data, it is implied
297    if (nm->is_native_method()) {
298      tty->print("bci: 0 (native)");
299    } else {
300      ScopeDesc* scope  = nm->scope_desc_at(fr->pc());
301      tty->print("bci: %d ",scope->bci());
302    }
303  }
304  tty->cr();
305  fr->print_on(tty);
306  tty->print("     ");
307  cb->print_value_on(tty);  tty->cr();
308  reg_map->print();
309  tty->print_cr("------ ");
310
311}
312#endif // PRODUCT
313
314void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) {
315  // add derived oops to a table
316  all_do(fr, reg_map, f, add_derived_oop, &do_nothing);
317}
318
319
320void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
321                       OopClosure* oop_fn, void derived_oop_fn(oop*, oop*),
322                       OopClosure* value_fn) {
323  CodeBlob* cb = fr->cb();
324  assert(cb != NULL, "no codeblob");
325
326  NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
327
328  const ImmutableOopMapSet* maps = cb->oop_maps();
329  const ImmutableOopMap* map = cb->oop_map_for_return_address(fr->pc());
330  assert(map != NULL, "no ptr map found");
331
332  // handle derived pointers first (otherwise base pointer may be
333  // changed before derived pointer offset has been collected)
334  OopMapValue omv;
335  {
336    OopMapStream oms(map,OopMapValue::derived_oop_value);
337    if (!oms.is_done()) {
338#ifndef TIERED
339      COMPILER1_PRESENT(ShouldNotReachHere();)
340#if INCLUDE_JVMCI
341      if (UseJVMCICompiler) {
342        ShouldNotReachHere();
343      }
344#endif
345#endif // !TIERED
346      // Protect the operation on the derived pointers.  This
347      // protects the addition of derived pointers to the shared
348      // derived pointer table in DerivedPointerTable::add().
349      MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
350      do {
351        omv = oms.current();
352        oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
353        guarantee(loc != NULL, "missing saved register");
354        oop *derived_loc = loc;
355        oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
356        // Ignore NULL oops and decoded NULL narrow oops which
357        // equal to Universe::narrow_oop_base when a narrow oop
358        // implicit null check is used in compiled code.
359        // The narrow_oop_base could be NULL or be the address
360        // of the page below heap depending on compressed oops mode.
361        if (base_loc != NULL && *base_loc != (oop)NULL && !Universe::is_narrow_oop_base(*base_loc)) {
362          derived_oop_fn(base_loc, derived_loc);
363        }
364        oms.next();
365      }  while (!oms.is_done());
366    }
367  }
368
369  // We want coop and oop oop_types
370  int mask = OopMapValue::oop_value | OopMapValue::narrowoop_value;
371  {
372    for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) {
373      omv = oms.current();
374      oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
375      // It should be an error if no location can be found for a
376      // register mentioned as contained an oop of some kind.  Maybe
377      // this was allowed previously because value_value items might
378      // be missing?
379      guarantee(loc != NULL, "missing saved register");
380      if ( omv.type() == OopMapValue::oop_value ) {
381        oop val = *loc;
382        if (val == (oop)NULL || Universe::is_narrow_oop_base(val)) {
383          // Ignore NULL oops and decoded NULL narrow oops which
384          // equal to Universe::narrow_oop_base when a narrow oop
385          // implicit null check is used in compiled code.
386          // The narrow_oop_base could be NULL or be the address
387          // of the page below heap depending on compressed oops mode.
388          continue;
389        }
390#ifdef ASSERT
391        if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
392            !Universe::heap()->is_in_or_null(*loc)) {
393          tty->print_cr("# Found non oop pointer.  Dumping state at failure");
394          // try to dump out some helpful debugging information
395          trace_codeblob_maps(fr, reg_map);
396          omv.print();
397          tty->print_cr("register r");
398          omv.reg()->print();
399          tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc);
400          // do the real assert.
401          assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer");
402        }
403#endif // ASSERT
404        oop_fn->do_oop(loc);
405      } else if ( omv.type() == OopMapValue::narrowoop_value ) {
406        narrowOop *nl = (narrowOop*)loc;
407#ifndef VM_LITTLE_ENDIAN
408        VMReg vmReg = omv.reg();
409        // Don't do this on SPARC float registers as they can be individually addressed
410        if (!vmReg->is_stack() SPARC_ONLY(&& !vmReg->is_FloatRegister())) {
411          // compressed oops in registers only take up 4 bytes of an
412          // 8 byte register but they are in the wrong part of the
413          // word so adjust loc to point at the right place.
414          nl = (narrowOop*)((address)nl + 4);
415        }
416#endif
417        oop_fn->do_oop(nl);
418      }
419    }
420  }
421}
422
423
424// Update callee-saved register info for the following frame
425void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
426  ResourceMark rm;
427  CodeBlob* cb = fr->cb();
428  assert(cb != NULL, "no codeblob");
429
430  // Any reg might be saved by a safepoint handler (see generate_handler_blob).
431  assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
432         "already updated this map; do not 'update' it twice!" );
433  debug_only(reg_map->_update_for_id = fr->id());
434
435  // Check if caller must update oop argument
436  assert((reg_map->include_argument_oops() ||
437          !cb->caller_must_gc_arguments(reg_map->thread())),
438         "include_argument_oops should already be set");
439
440  // Scan through oopmap and find location of all callee-saved registers
441  // (we do not do update in place, since info could be overwritten)
442
443  address pc = fr->pc();
444  const ImmutableOopMap* map  = cb->oop_map_for_return_address(pc);
445  assert(map != NULL, "no ptr map found");
446  DEBUG_ONLY(int nof_callee = 0;)
447
448  for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
449    OopMapValue omv = oms.current();
450    VMReg reg = omv.content_reg();
451    oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
452    reg_map->set_location(reg, (address) loc);
453    DEBUG_ONLY(nof_callee++;)
454  }
455
456  // Check that runtime stubs save all callee-saved registers
457#ifdef COMPILER2
458  assert(cb->is_compiled_by_c1() || cb->is_compiled_by_jvmci() || !cb->is_runtime_stub() ||
459         (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
460         "must save all");
461#endif // COMPILER2
462}
463
464//=============================================================================
465// Non-Product code
466
467#ifndef PRODUCT
468
469bool ImmutableOopMap::has_derived_pointer() const {
470#if !defined(TIERED) && !defined(INCLUDE_JVMCI)
471  COMPILER1_PRESENT(return false);
472#endif // !TIERED
473#if defined(COMPILER2) || INCLUDE_JVMCI
474  OopMapStream oms(this,OopMapValue::derived_oop_value);
475  return oms.is_done();
476#else
477  return false;
478#endif // COMPILER2 || INCLUDE_JVMCI
479}
480
481#endif //PRODUCT
482
483// Printing code is present in product build for -XX:+PrintAssembly.
484
485static
486void print_register_type(OopMapValue::oop_types x, VMReg optional,
487                         outputStream* st) {
488  switch( x ) {
489  case OopMapValue::oop_value:
490    st->print("Oop");
491    break;
492  case OopMapValue::narrowoop_value:
493    st->print("NarrowOop");
494    break;
495  case OopMapValue::callee_saved_value:
496    st->print("Callers_");
497    optional->print_on(st);
498    break;
499  case OopMapValue::derived_oop_value:
500    st->print("Derived_oop_");
501    optional->print_on(st);
502    break;
503  default:
504    ShouldNotReachHere();
505  }
506}
507
508void OopMapValue::print_on(outputStream* st) const {
509  reg()->print_on(st);
510  st->print("=");
511  print_register_type(type(),content_reg(),st);
512  st->print(" ");
513}
514
515void ImmutableOopMap::print_on(outputStream* st) const {
516  OopMapValue omv;
517  st->print("ImmutableOopMap{");
518  for(OopMapStream oms(this); !oms.is_done(); oms.next()) {
519    omv = oms.current();
520    omv.print_on(st);
521  }
522  st->print("}");
523}
524
525void OopMap::print_on(outputStream* st) const {
526  OopMapValue omv;
527  st->print("OopMap{");
528  for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
529    omv = oms.current();
530    omv.print_on(st);
531  }
532  st->print("off=%d}", (int) offset());
533}
534
535void ImmutableOopMapSet::print_on(outputStream* st) const {
536  const ImmutableOopMap* last = NULL;
537  for (int i = 0; i < _count; ++i) {
538    const ImmutableOopMapPair* pair = pair_at(i);
539    const ImmutableOopMap* map = pair->get_from(this);
540    if (map != last) {
541      st->cr();
542      map->print_on(st);
543      st->print("pc offsets: ");
544    }
545    last = map;
546    st->print("%d ", pair->pc_offset());
547  }
548}
549
550void OopMapSet::print_on(outputStream* st) const {
551  int i, len = om_count();
552
553  st->print_cr("OopMapSet contains %d OopMaps\n",len);
554
555  for( i = 0; i < len; i++) {
556    OopMap* m = at(i);
557    st->print_cr("#%d ",i);
558    m->print_on(st);
559    st->cr();
560  }
561}
562
563bool OopMap::equals(const OopMap* other) const {
564  if (other->_omv_count != _omv_count) {
565    return false;
566  }
567  if (other->write_stream()->position() != write_stream()->position()) {
568    return false;
569  }
570  if (memcmp(other->write_stream()->buffer(), write_stream()->buffer(), write_stream()->position()) != 0) {
571    return false;
572  }
573  return true;
574}
575
576const ImmutableOopMap* ImmutableOopMapSet::find_map_at_offset(int pc_offset) const {
577  ImmutableOopMapPair* pairs = get_pairs();
578  ImmutableOopMapPair* last = NULL;
579
580  for (int i = 0; i < _count; ++i) {
581    if (pairs[i].pc_offset() >= pc_offset) {
582      last = &pairs[i];
583      break;
584    }
585  }
586
587  assert(last->pc_offset() == pc_offset, "oopmap not found");
588  return last->get_from(this);
589}
590
591const ImmutableOopMap* ImmutableOopMapPair::get_from(const ImmutableOopMapSet* set) const {
592  return set->oopmap_at_offset(_oopmap_offset);
593}
594
595ImmutableOopMap::ImmutableOopMap(const OopMap* oopmap) : _count(oopmap->count()) {
596  address addr = data_addr();
597  oopmap->copy_data_to(addr);
598}
599
600#ifdef ASSERT
601int ImmutableOopMap::nr_of_bytes() const {
602  OopMapStream oms(this);
603
604  while (!oms.is_done()) {
605    oms.next();
606  }
607  return sizeof(ImmutableOopMap) + oms.stream_position();
608}
609#endif
610
611ImmutableOopMapBuilder::ImmutableOopMapBuilder(const OopMapSet* set) : _set(set), _new_set(NULL), _empty(NULL), _last(NULL), _empty_offset(-1), _last_offset(-1), _offset(0), _required(-1) {
612  _mapping = NEW_RESOURCE_ARRAY(Mapping, _set->size());
613}
614
615int ImmutableOopMapBuilder::size_for(const OopMap* map) const {
616  return align_up((int)sizeof(ImmutableOopMap) + map->data_size(), 8);
617}
618
619int ImmutableOopMapBuilder::heap_size() {
620  int base = sizeof(ImmutableOopMapSet);
621  base = align_up(base, 8);
622
623  // all of ours pc / offset pairs
624  int pairs = _set->size() * sizeof(ImmutableOopMapPair);
625  pairs = align_up(pairs, 8);
626
627  for (int i = 0; i < _set->size(); ++i) {
628    int size = 0;
629    OopMap* map = _set->at(i);
630
631    if (is_empty(map)) {
632      /* only keep a single empty map in the set */
633      if (has_empty()) {
634        _mapping[i].set(Mapping::OOPMAP_EMPTY, _empty_offset, 0, map, _empty);
635      } else {
636        _empty_offset = _offset;
637        _empty = map;
638        size = size_for(map);
639        _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
640      }
641    } else if (is_last_duplicate(map)) {
642      /* if this entry is identical to the previous one, just point it there */
643      _mapping[i].set(Mapping::OOPMAP_DUPLICATE, _last_offset, 0, map, _last);
644    } else {
645      /* not empty, not an identical copy of the previous entry */
646      size = size_for(map);
647      _mapping[i].set(Mapping::OOPMAP_NEW, _offset, size, map);
648      _last_offset = _offset;
649      _last = map;
650    }
651
652    assert(_mapping[i]._map == map, "check");
653    _offset += size;
654  }
655
656  int total = base + pairs + _offset;
657  DEBUG_ONLY(total += 8);
658  _required = total;
659  return total;
660}
661
662void ImmutableOopMapBuilder::fill_pair(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {
663  assert(offset < set->nr_of_bytes(), "check");
664  new ((address) pair) ImmutableOopMapPair(map->offset(), offset);
665}
666
667int ImmutableOopMapBuilder::fill_map(ImmutableOopMapPair* pair, const OopMap* map, int offset, const ImmutableOopMapSet* set) {
668  fill_pair(pair, map, offset, set);
669  address addr = (address) pair->get_from(_new_set); // location of the ImmutableOopMap
670
671  new (addr) ImmutableOopMap(map);
672  return size_for(map);
673}
674
675void ImmutableOopMapBuilder::fill(ImmutableOopMapSet* set, int sz) {
676  ImmutableOopMapPair* pairs = set->get_pairs();
677
678  for (int i = 0; i < set->count(); ++i) {
679    const OopMap* map = _mapping[i]._map;
680    ImmutableOopMapPair* pair = NULL;
681    int size = 0;
682
683    if (_mapping[i]._kind == Mapping::OOPMAP_NEW) {
684      size = fill_map(&pairs[i], map, _mapping[i]._offset, set);
685    } else if (_mapping[i]._kind == Mapping::OOPMAP_DUPLICATE || _mapping[i]._kind == Mapping::OOPMAP_EMPTY) {
686      fill_pair(&pairs[i], map, _mapping[i]._offset, set);
687    }
688
689    const ImmutableOopMap* nv = set->find_map_at_offset(map->offset());
690    assert(memcmp(map->data(), nv->data_addr(), map->data_size()) == 0, "check identity");
691  }
692}
693
694#ifdef ASSERT
695void ImmutableOopMapBuilder::verify(address buffer, int size, const ImmutableOopMapSet* set) {
696  for (int i = 0; i < 8; ++i) {
697    assert(buffer[size - 8 + i] == (unsigned char) 0xff, "overwritten memory check");
698  }
699
700  for (int i = 0; i < set->count(); ++i) {
701    const ImmutableOopMapPair* pair = set->pair_at(i);
702    assert(pair->oopmap_offset() < set->nr_of_bytes(), "check size");
703    const ImmutableOopMap* map = pair->get_from(set);
704    int nr_of_bytes = map->nr_of_bytes();
705    assert(pair->oopmap_offset() + nr_of_bytes <= set->nr_of_bytes(), "check size + size");
706  }
707}
708#endif
709
710ImmutableOopMapSet* ImmutableOopMapBuilder::generate_into(address buffer) {
711  DEBUG_ONLY(memset(&buffer[_required-8], 0xff, 8));
712
713  _new_set = new (buffer) ImmutableOopMapSet(_set, _required);
714  fill(_new_set, _required);
715
716  DEBUG_ONLY(verify(buffer, _required, _new_set));
717
718  return _new_set;
719}
720
721ImmutableOopMapSet* ImmutableOopMapBuilder::build() {
722  _required = heap_size();
723
724  // We need to allocate a chunk big enough to hold the ImmutableOopMapSet and all of its ImmutableOopMaps
725  address buffer = (address) NEW_C_HEAP_ARRAY(unsigned char, _required, mtCode);
726  return generate_into(buffer);
727}
728
729ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) {
730  ResourceMark mark;
731  ImmutableOopMapBuilder builder(oopmap_set);
732  return builder.build();
733}
734
735
736//------------------------------DerivedPointerTable---------------------------
737
738#if defined(COMPILER2) || INCLUDE_JVMCI
739
740class DerivedPointerEntry : public CHeapObj<mtCompiler> {
741 private:
742  oop*     _location; // Location of derived pointer (also pointing to the base)
743  intptr_t _offset;   // Offset from base pointer
744 public:
745  DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
746  oop* location()    { return _location; }
747  intptr_t  offset() { return _offset; }
748};
749
750
751GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
752bool DerivedPointerTable::_active = false;
753
754
755void DerivedPointerTable::clear() {
756  // The first time, we create the list.  Otherwise it should be
757  // empty.  If not, then we have probably forgotton to call
758  // update_pointers after last GC/Scavenge.
759  assert (!_active, "should not be active");
760  assert(_list == NULL || _list->length() == 0, "table not empty");
761  if (_list == NULL) {
762    _list = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap
763  }
764  _active = true;
765}
766
767
768// Returns value of location as an int
769intptr_t value_of_loc(oop *pointer) { return cast_from_oop<intptr_t>((*pointer)); }
770
771
772void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) {
773  assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop");
774  assert(derived_loc != base_loc, "Base and derived in same location");
775  if (_active) {
776    assert(*derived_loc != (oop)base_loc, "location already added");
777    assert(_list != NULL, "list must exist");
778    intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc);
779    // This assert is invalid because derived pointers can be
780    // arbitrarily far away from their base.
781    // assert(offset >= -1000000, "wrong derived pointer info");
782
783    if (TraceDerivedPointers) {
784      tty->print_cr(
785        "Add derived pointer@" INTPTR_FORMAT
786        " - Derived: " INTPTR_FORMAT
787        " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: " INTX_FORMAT ")",
788        p2i(derived_loc), p2i((address)*derived_loc), p2i((address)*base_loc), p2i(base_loc), offset
789      );
790    }
791    // Set derived oop location to point to base.
792    *derived_loc = (oop)base_loc;
793    assert_lock_strong(DerivedPointerTableGC_lock);
794    DerivedPointerEntry *entry = new DerivedPointerEntry(derived_loc, offset);
795    _list->append(entry);
796  }
797}
798
799
800void DerivedPointerTable::update_pointers() {
801  assert(_list != NULL, "list must exist");
802  for(int i = 0; i < _list->length(); i++) {
803    DerivedPointerEntry* entry = _list->at(i);
804    oop* derived_loc = entry->location();
805    intptr_t offset  = entry->offset();
806    // The derived oop was setup to point to location of base
807    oop  base        = **(oop**)derived_loc;
808    assert(Universe::heap()->is_in_or_null(base), "must be an oop");
809
810    *derived_loc = (oop)(((address)base) + offset);
811    assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check");
812
813    if (TraceDerivedPointers) {
814      tty->print_cr("Updating derived pointer@" INTPTR_FORMAT
815                    " - Derived: " INTPTR_FORMAT "  Base: " INTPTR_FORMAT " (Offset: " INTX_FORMAT ")",
816          p2i(derived_loc), p2i((address)*derived_loc), p2i((address)base), offset);
817    }
818
819    // Delete entry
820    delete entry;
821    _list->at_put(i, NULL);
822  }
823  // Clear list, so it is ready for next traversal (this is an invariant)
824  if (TraceDerivedPointers && !_list->is_empty()) {
825    tty->print_cr("--------------------------");
826  }
827  _list->clear();
828  _active = false;
829}
830
831#endif // COMPILER2 || INCLUDE_JVMCI
832