1 /*
   2  * Copyright 1998-2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *
  23  */
  24 
  25 # include "incls/_precompiled.incl"
  26 # include "incls/_oopMap.cpp.incl"
  27 
  28 // OopMapStream
  29 
  30 OopMapStream::OopMapStream(OopMap* oop_map) {
  31   if(oop_map->omv_data() == NULL) {
  32     _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
  33   } else {
  34     _stream = new CompressedReadStream(oop_map->omv_data());
  35   }
  36   _mask = OopMapValue::type_mask_in_place;
  37   _size = oop_map->omv_count();
  38   _position = 0;
  39   _valid_omv = false;
  40 }
  41 
  42 
  43 OopMapStream::OopMapStream(OopMap* oop_map, int oop_types_mask) {
  44   if(oop_map->omv_data() == NULL) {
  45     _stream = new CompressedReadStream(oop_map->write_stream()->buffer());
  46   } else {
  47     _stream = new CompressedReadStream(oop_map->omv_data());
  48   }
  49   _mask = oop_types_mask;
  50   _size = oop_map->omv_count();
  51   _position = 0;
  52   _valid_omv = false;
  53 }
  54 
  55 
  56 void OopMapStream::find_next() {
  57   while(_position++ < _size) {
  58     _omv.read_from(_stream);
  59     if(((int)_omv.type() & _mask) > 0) {
  60       _valid_omv = true;
  61       return;
  62     }
  63   }
  64   _valid_omv = false;
  65 }
  66 
  67 
  68 // OopMap
  69 
  70 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
  71 // slots to hold 4-byte values like ints and floats in the LP64 build.
  72 OopMap::OopMap(int frame_size, int arg_count) {
  73   // OopMaps are usually quite so small, so pick a small initial size
  74   set_write_stream(new CompressedWriteStream(32));
  75   set_omv_data(NULL);
  76   set_omv_count(0);
  77 
  78 #ifdef ASSERT
  79   _locs_length = VMRegImpl::stack2reg(0)->value() + frame_size + arg_count;
  80   _locs_used   = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
  81   for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
  82 #endif
  83 }
  84 
  85 
  86 OopMap::OopMap(OopMap::DeepCopyToken, OopMap* source) {
  87   // This constructor does a deep copy
  88   // of the source OopMap.
  89   set_write_stream(new CompressedWriteStream(source->omv_count() * 2));
  90   set_omv_data(NULL);
  91   set_omv_count(0);
  92   set_offset(source->offset());
  93 
  94 #ifdef ASSERT
  95   _locs_length = source->_locs_length;
  96   _locs_used = NEW_RESOURCE_ARRAY(OopMapValue::oop_types, _locs_length);
  97   for(int i = 0; i < _locs_length; i++) _locs_used[i] = OopMapValue::unused_value;
  98 #endif
  99 
 100   // We need to copy the entries too.
 101   for (OopMapStream oms(source); !oms.is_done(); oms.next()) {
 102     OopMapValue omv = oms.current();
 103     omv.write_on(write_stream());
 104     increment_count();
 105   }
 106 }
 107 
 108 
 109 OopMap* OopMap::deep_copy() {
 110   return new OopMap(_deep_copy_token, this);
 111 }
 112 
 113 
 114 void OopMap::copy_to(address addr) {
 115   memcpy(addr,this,sizeof(OopMap));
 116   memcpy(addr + sizeof(OopMap),write_stream()->buffer(),write_stream()->position());
 117   OopMap* new_oop = (OopMap*)addr;
 118   new_oop->set_omv_data_size(write_stream()->position());
 119   new_oop->set_omv_data((unsigned char *)(addr + sizeof(OopMap)));
 120   new_oop->set_write_stream(NULL);
 121 }
 122 
 123 
 124 int OopMap::heap_size() const {
 125   int size = sizeof(OopMap);
 126   int align = sizeof(void *) - 1;
 127   if(write_stream() != NULL) {
 128     size += write_stream()->position();
 129   } else {
 130     size += omv_data_size();
 131   }
 132   // Align to a reasonable ending point
 133   size = ((size+align) & ~align);
 134   return size;
 135 }
 136 
 137 // frame_size units are stack-slots (4 bytes) NOT intptr_t; we can name odd
 138 // slots to hold 4-byte values like ints and floats in the LP64 build.
 139 void OopMap::set_xxx(VMReg reg, OopMapValue::oop_types x, VMReg optional) {
 140 
 141   assert(reg->value() < _locs_length, "too big reg value for stack size");
 142   assert( _locs_used[reg->value()] == OopMapValue::unused_value, "cannot insert twice" );
 143   debug_only( _locs_used[reg->value()] = x; )
 144 
 145   OopMapValue o(reg, x);
 146 
 147   if(x == OopMapValue::callee_saved_value) {
 148     // This can never be a stack location, so we don't need to transform it.
 149     assert(optional->is_reg(), "Trying to callee save a stack location");
 150     o.set_content_reg(optional);
 151   } else if(x == OopMapValue::derived_oop_value) {
 152     o.set_content_reg(optional);
 153   }
 154 
 155   o.write_on(write_stream());
 156   increment_count();
 157 }
 158 
 159 
 160 void OopMap::set_oop(VMReg reg) {
 161   set_xxx(reg, OopMapValue::oop_value, VMRegImpl::Bad());
 162 }
 163 
 164 
 165 void OopMap::set_value(VMReg reg) {
 166   // At this time, we only need value entries in our OopMap when ZapDeadCompiledLocals is active.
 167   if (ZapDeadCompiledLocals)
 168     set_xxx(reg, OopMapValue::value_value, VMRegImpl::Bad());
 169 }
 170 
 171 
 172 void OopMap::set_narrowoop(VMReg reg) {
 173   set_xxx(reg, OopMapValue::narrowoop_value, VMRegImpl::Bad());
 174 }
 175 
 176 
 177 void OopMap::set_callee_saved(VMReg reg, VMReg caller_machine_register ) {
 178   set_xxx(reg, OopMapValue::callee_saved_value, caller_machine_register);
 179 }
 180 
 181 
 182 void OopMap::set_derived_oop(VMReg reg, VMReg derived_from_local_register ) {
 183   if( reg == derived_from_local_register ) {
 184     // Actually an oop, derived shares storage with base,
 185     set_oop(reg);
 186   } else {
 187     set_xxx(reg, OopMapValue::derived_oop_value, derived_from_local_register);
 188   }
 189 }
 190 
 191 // OopMapSet
 192 
 193 OopMapSet::OopMapSet() {
 194   set_om_size(MinOopMapAllocation);
 195   set_om_count(0);
 196   OopMap** temp = NEW_RESOURCE_ARRAY(OopMap*, om_size());
 197   set_om_data(temp);
 198 }
 199 
 200 
 201 void OopMapSet::grow_om_data() {
 202   int new_size = om_size() * 2;
 203   OopMap** new_data = NEW_RESOURCE_ARRAY(OopMap*, new_size);
 204   memcpy(new_data,om_data(),om_size() * sizeof(OopMap*));
 205   set_om_size(new_size);
 206   set_om_data(new_data);
 207 }
 208 
 209 
 210 void OopMapSet::copy_to(address addr) {
 211   address temp = addr;
 212   int align = sizeof(void *) - 1;
 213   // Copy this
 214   memcpy(addr,this,sizeof(OopMapSet));
 215   temp += sizeof(OopMapSet);
 216   temp = (address)((intptr_t)(temp + align) & ~align);
 217   // Do the needed fixups to the new OopMapSet
 218   OopMapSet* new_set = (OopMapSet*)addr;
 219   new_set->set_om_data((OopMap**)temp);
 220   // Allow enough space for the OopMap pointers
 221   temp += (om_count() * sizeof(OopMap*));
 222 
 223   for(int i=0; i < om_count(); i++) {
 224     OopMap* map = at(i);
 225     map->copy_to((address)temp);
 226     new_set->set(i,(OopMap*)temp);
 227     temp += map->heap_size();
 228   }
 229   // This "locks" the OopMapSet
 230   new_set->set_om_size(-1);
 231 }
 232 
 233 
 234 void OopMapSet::add_gc_map(int pc_offset, OopMap *map ) {
 235   assert(om_size() != -1,"Cannot grow a fixed OopMapSet");
 236 
 237   if(om_count() >= om_size()) {
 238     grow_om_data();
 239   }
 240   map->set_offset(pc_offset);
 241 
 242 #ifdef ASSERT
 243   if(om_count() > 0) {
 244     OopMap* last = at(om_count()-1);
 245     if (last->offset() == map->offset() ) {
 246       fatal("OopMap inserted twice");
 247     }
 248     if(last->offset() > map->offset()) {
 249       tty->print_cr( "WARNING, maps not sorted: pc[%d]=%d, pc[%d]=%d",
 250                       om_count(),last->offset(),om_count()+1,map->offset());
 251     }
 252   }
 253 #endif // ASSERT
 254 
 255   set(om_count(),map);
 256   increment_count();
 257 }
 258 
 259 
 260 int OopMapSet::heap_size() const {
 261   // The space we use
 262   int size = sizeof(OopMap);
 263   int align = sizeof(void *) - 1;
 264   size = ((size+align) & ~align);
 265   size += om_count() * sizeof(OopMap*);
 266 
 267   // Now add in the space needed for the indivdiual OopMaps
 268   for(int i=0; i < om_count(); i++) {
 269     size += at(i)->heap_size();
 270   }
 271   // We don't need to align this, it will be naturally pointer aligned
 272   return size;
 273 }
 274 
 275 
 276 OopMap* OopMapSet::singular_oop_map() {
 277   guarantee(om_count() == 1, "Make sure we only have a single gc point");
 278   return at(0);
 279 }
 280 
 281 
 282 OopMap* OopMapSet::find_map_at_offset(int pc_offset) const {
 283   int i, len = om_count();
 284   assert( len > 0, "must have pointer maps" );
 285 
 286   // Scan through oopmaps. Stop when current offset is either equal or greater
 287   // than the one we are looking for.
 288   for( i = 0; i < len; i++) {
 289     if( at(i)->offset() >= pc_offset )
 290       break;
 291   }
 292 
 293   assert( i < len, "oopmap not found" );
 294 
 295   OopMap* m = at(i);
 296   assert( m->offset() == pc_offset, "oopmap not found" );
 297   return m;
 298 }
 299 
 300 class DoNothingClosure: public OopClosure {
 301  public:
 302   void do_oop(oop* p)       {}
 303   void do_oop(narrowOop* p) {}
 304 };
 305 static DoNothingClosure do_nothing;
 306 
 307 static void add_derived_oop(oop* base, oop* derived) {
 308 #ifndef TIERED
 309   COMPILER1_PRESENT(ShouldNotReachHere();)
 310 #endif // TIERED
 311 #ifdef COMPILER2
 312   DerivedPointerTable::add(derived, base);
 313 #endif // COMPILER2
 314 }
 315 
 316 
 317 #ifndef PRODUCT
 318 static void trace_codeblob_maps(const frame *fr, const RegisterMap *reg_map) {
 319   // Print oopmap and regmap
 320   tty->print_cr("------ ");
 321   CodeBlob* cb = fr->cb();
 322   OopMapSet* maps = cb->oop_maps();
 323   OopMap* map = cb->oop_map_for_return_address(fr->pc());
 324   map->print();
 325   if( cb->is_nmethod() ) {
 326     nmethod* nm = (nmethod*)cb;
 327     // native wrappers have no scope data, it is implied
 328     if (nm->is_native_method()) {
 329       tty->print("bci: 0 (native)");
 330     } else {
 331       ScopeDesc* scope  = nm->scope_desc_at(fr->pc());
 332       tty->print("bci: %d ",scope->bci());
 333     }
 334   }
 335   tty->cr();
 336   fr->print_on(tty);
 337   tty->print("     ");
 338   cb->print_value_on(tty);  tty->cr();
 339   reg_map->print();
 340   tty->print_cr("------ ");
 341 
 342 }
 343 #endif // PRODUCT
 344 
 345 void OopMapSet::oops_do(const frame *fr, const RegisterMap* reg_map, OopClosure* f) {
 346   // add derived oops to a table
 347   all_do(fr, reg_map, f, add_derived_oop, &do_nothing);
 348 }
 349 
 350 
 351 void OopMapSet::all_do(const frame *fr, const RegisterMap *reg_map,
 352                        OopClosure* oop_fn, void derived_oop_fn(oop*, oop*),
 353                        OopClosure* value_fn) {
 354   CodeBlob* cb = fr->cb();
 355   assert(cb != NULL, "no codeblob");
 356 
 357   NOT_PRODUCT(if (TraceCodeBlobStacks) trace_codeblob_maps(fr, reg_map);)
 358 
 359   OopMapSet* maps = cb->oop_maps();
 360   OopMap* map = cb->oop_map_for_return_address(fr->pc());
 361   assert(map != NULL, "no ptr map found");
 362 
 363   // handle derived pointers first (otherwise base pointer may be
 364   // changed before derived pointer offset has been collected)
 365   OopMapValue omv;
 366   {
 367     OopMapStream oms(map,OopMapValue::derived_oop_value);
 368     if (!oms.is_done()) {
 369 #ifndef TIERED
 370       COMPILER1_PRESENT(ShouldNotReachHere();)
 371 #endif // !TIERED
 372       // Protect the operation on the derived pointers.  This
 373       // protects the addition of derived pointers to the shared
 374       // derived pointer table in DerivedPointerTable::add().
 375       MutexLockerEx x(DerivedPointerTableGC_lock, Mutex::_no_safepoint_check_flag);
 376       do {
 377         omv = oms.current();
 378         oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
 379         if ( loc != NULL ) {
 380           oop *base_loc    = fr->oopmapreg_to_location(omv.content_reg(), reg_map);
 381           oop *derived_loc = loc;
 382 #ifdef _LP64
 383           if (Universe::narrow_oop_base() == (address)(void*)(*base_loc)) {
 384              // Compiled code may produce decoded oop = narrow_oop_base
 385              // when a narrow oop implicit null check is used.
 386              // The narrow_oop_base could be NULL or be the address
 387              // of the page below heap. Skip both cases since nobody
 388              // is interesting in NULL.
 389           } else
 390 #endif
 391           derived_oop_fn(base_loc, derived_loc);
 392         }
 393         oms.next();
 394       }  while (!oms.is_done());
 395     }
 396   }
 397 
 398   // We want coop, value and oop oop_types
 399   int mask = OopMapValue::oop_value | OopMapValue::value_value | OopMapValue::narrowoop_value;
 400   {
 401     for (OopMapStream oms(map,mask); !oms.is_done(); oms.next()) {
 402       omv = oms.current();
 403       oop* loc = fr->oopmapreg_to_location(omv.reg(),reg_map);
 404       if ( loc != NULL ) {
 405         if ( omv.type() == OopMapValue::oop_value ) {
 406 #ifdef _LP64
 407           if (Universe::narrow_oop_base() == (address)(void*)(*loc)) {
 408              // Compiled code may produce decoded oop = narrow_oop_base
 409              // when a narrow oop implicit null check is used.
 410              // The narrow_oop_base could be NULL or be the address
 411              // of the page below heap. Skip both cases since nobody
 412              // is interesting in NULL.
 413              continue;
 414           }
 415 #endif
 416 #ifdef ASSERT
 417           if ((((uintptr_t)loc & (sizeof(*loc)-1)) != 0) ||
 418              !Universe::heap()->is_in_or_null(*loc)) {
 419             tty->print_cr("# Found non oop pointer.  Dumping state at failure");
 420             // try to dump out some helpful debugging information
 421             trace_codeblob_maps(fr, reg_map);
 422             omv.print();
 423             tty->print_cr("register r");
 424             omv.reg()->print();
 425             tty->print_cr("loc = %p *loc = %p\n", loc, (address)*loc);
 426             // do the real assert.
 427             assert(Universe::heap()->is_in_or_null(*loc), "found non oop pointer");
 428           }
 429 #endif // ASSERT
 430           oop_fn->do_oop(loc);
 431         } else if ( omv.type() == OopMapValue::value_value ) {
 432           assert((*loc) == (oop)NULL || Universe::narrow_oop_base() != (address)(void*)(*loc),
 433                  "found non valid value pointer");
 434           value_fn->do_oop(loc);
 435         } else if ( omv.type() == OopMapValue::narrowoop_value ) {
 436           narrowOop *nl = (narrowOop*)loc;
 437 #ifndef VM_LITTLE_ENDIAN
 438           if (!omv.reg()->is_stack()) {
 439             // compressed oops in registers only take up 4 bytes of an
 440             // 8 byte register but they are in the wrong part of the
 441             // word so adjust loc to point at the right place.
 442             nl = (narrowOop*)((address)nl + 4);
 443           }
 444 #endif
 445           oop_fn->do_oop(nl);
 446         }
 447       }
 448     }
 449   }
 450 }
 451 
 452 
 453 // Update callee-saved register info for the following frame
 454 void OopMapSet::update_register_map(const frame *fr, RegisterMap *reg_map) {
 455   ResourceMark rm;
 456   CodeBlob* cb = fr->cb();
 457   assert(cb != NULL, "no codeblob");
 458 
 459   // Any reg might be saved by a safepoint handler (see generate_handler_blob).
 460   const int max_saved_on_entry_reg_count = ConcreteRegisterImpl::number_of_registers;
 461   assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
 462          "already updated this map; do not 'update' it twice!" );
 463   debug_only(reg_map->_update_for_id = fr->id());
 464 
 465   // Check if caller must update oop argument
 466   assert((reg_map->include_argument_oops() ||
 467           !cb->caller_must_gc_arguments(reg_map->thread())),
 468          "include_argument_oops should already be set");
 469 
 470   int nof_callee = 0;
 471   oop*        locs[2*max_saved_on_entry_reg_count+1];
 472   VMReg regs[2*max_saved_on_entry_reg_count+1];
 473   // ("+1" because max_saved_on_entry_reg_count might be zero)
 474 
 475   // Scan through oopmap and find location of all callee-saved registers
 476   // (we do not do update in place, since info could be overwritten)
 477 
 478   address pc = fr->pc();
 479 
 480   OopMap* map  = cb->oop_map_for_return_address(pc);
 481 
 482   assert(map != NULL, " no ptr map found");
 483 
 484   OopMapValue omv;
 485   for(OopMapStream oms(map,OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
 486     omv = oms.current();
 487     assert(nof_callee < 2*max_saved_on_entry_reg_count, "overflow");
 488     regs[nof_callee] = omv.content_reg();
 489     locs[nof_callee] = fr->oopmapreg_to_location(omv.reg(),reg_map);
 490     nof_callee++;
 491   }
 492 
 493   // Check that runtime stubs save all callee-saved registers
 494 #ifdef COMPILER2
 495   assert(cb->is_compiled_by_c1() || !cb->is_runtime_stub() ||
 496          (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
 497          "must save all");
 498 #endif // COMPILER2
 499 
 500   // Copy found callee-saved register to reg_map
 501   for(int i = 0; i < nof_callee; i++) {
 502     reg_map->set_location(regs[i], (address)locs[i]);
 503   }
 504 }
 505 
 506 //=============================================================================
 507 // Non-Product code
 508 
 509 #ifndef PRODUCT
 510 
 511 bool OopMap::has_derived_pointer() const {
 512 #ifndef TIERED
 513   COMPILER1_PRESENT(return false);
 514 #endif // !TIERED
 515 #ifdef COMPILER2
 516   OopMapStream oms((OopMap*)this,OopMapValue::derived_oop_value);
 517   return oms.is_done();
 518 #else
 519   return false;
 520 #endif // COMPILER2
 521 }
 522 
 523 #endif //PRODUCT
 524 
 525 // Printing code is present in product build for -XX:+PrintAssembly.
 526 
 527 static
 528 void print_register_type(OopMapValue::oop_types x, VMReg optional,
 529                          outputStream* st) {
 530   switch( x ) {
 531   case OopMapValue::oop_value:
 532     st->print("Oop");
 533     break;
 534   case OopMapValue::value_value:
 535     st->print("Value" );
 536     break;
 537   case OopMapValue::narrowoop_value:
 538     tty->print("NarrowOop" );
 539     break;
 540   case OopMapValue::callee_saved_value:
 541     st->print("Callers_" );
 542     optional->print_on(st);
 543     break;
 544   case OopMapValue::derived_oop_value:
 545     st->print("Derived_oop_" );
 546     optional->print_on(st);
 547     break;
 548   default:
 549     ShouldNotReachHere();
 550   }
 551 }
 552 
 553 
 554 void OopMapValue::print_on(outputStream* st) const {
 555   reg()->print_on(st);
 556   st->print("=");
 557   print_register_type(type(),content_reg(),st);
 558   st->print(" ");
 559 }
 560 
 561 
 562 void OopMap::print_on(outputStream* st) const {
 563   OopMapValue omv;
 564   st->print("OopMap{");
 565   for(OopMapStream oms((OopMap*)this); !oms.is_done(); oms.next()) {
 566     omv = oms.current();
 567     omv.print_on(st);
 568   }
 569   st->print("off=%d}", (int) offset());
 570 }
 571 
 572 
 573 void OopMapSet::print_on(outputStream* st) const {
 574   int i, len = om_count();
 575 
 576   st->print_cr("OopMapSet contains %d OopMaps\n",len);
 577 
 578   for( i = 0; i < len; i++) {
 579     OopMap* m = at(i);
 580     st->print_cr("#%d ",i);
 581     m->print_on(st);
 582     st->cr();
 583   }
 584 }
 585 
 586 
 587 
 588 //------------------------------DerivedPointerTable---------------------------
 589 
 590 #ifdef COMPILER2
 591 
 592 class DerivedPointerEntry : public CHeapObj {
 593  private:
 594   oop*     _location; // Location of derived pointer (also pointing to the base)
 595   intptr_t _offset;   // Offset from base pointer
 596  public:
 597   DerivedPointerEntry(oop* location, intptr_t offset) { _location = location; _offset = offset; }
 598   oop* location()    { return _location; }
 599   intptr_t  offset() { return _offset; }
 600 };
 601 
 602 
 603 GrowableArray<DerivedPointerEntry*>* DerivedPointerTable::_list = NULL;
 604 bool DerivedPointerTable::_active = false;
 605 
 606 
 607 void DerivedPointerTable::clear() {
 608   // The first time, we create the list.  Otherwise it should be
 609   // empty.  If not, then we have probably forgotton to call
 610   // update_pointers after last GC/Scavenge.
 611   assert (!_active, "should not be active");
 612   assert(_list == NULL || _list->length() == 0, "table not empty");
 613   if (_list == NULL) {
 614     _list = new (ResourceObj::C_HEAP) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap
 615   }
 616   _active = true;
 617 }
 618 
 619 
 620 // Returns value of location as an int
 621 intptr_t value_of_loc(oop *pointer) { return (intptr_t)(*pointer); }
 622 
 623 
 624 void DerivedPointerTable::add(oop *derived_loc, oop *base_loc) {
 625   assert(Universe::heap()->is_in_or_null(*base_loc), "not an oop");
 626   assert(derived_loc != base_loc, "Base and derived in same location");
 627   if (_active) {
 628     assert(*derived_loc != (oop)base_loc, "location already added");
 629     assert(_list != NULL, "list must exist");
 630     intptr_t offset = value_of_loc(derived_loc) - value_of_loc(base_loc);
 631     assert(offset >= -1000000, "wrong derived pointer info");
 632 
 633     if (TraceDerivedPointers) {
 634       tty->print_cr(
 635         "Add derived pointer@" INTPTR_FORMAT
 636         " - Derived: " INTPTR_FORMAT
 637         " Base: " INTPTR_FORMAT " (@" INTPTR_FORMAT ") (Offset: %d)",
 638         derived_loc, (address)*derived_loc, (address)*base_loc, base_loc, offset
 639       );
 640     }
 641     // Set derived oop location to point to base.
 642     *derived_loc = (oop)base_loc;
 643     assert_lock_strong(DerivedPointerTableGC_lock);
 644     DerivedPointerEntry *entry = new DerivedPointerEntry(derived_loc, offset);
 645     _list->append(entry);
 646   }
 647 }
 648 
 649 
 650 void DerivedPointerTable::update_pointers() {
 651   assert(_list != NULL, "list must exist");
 652   for(int i = 0; i < _list->length(); i++) {
 653     DerivedPointerEntry* entry = _list->at(i);
 654     oop* derived_loc = entry->location();
 655     intptr_t offset  = entry->offset();
 656     // The derived oop was setup to point to location of base
 657     oop  base        = **(oop**)derived_loc;
 658     assert(Universe::heap()->is_in_or_null(base), "must be an oop");
 659 
 660     *derived_loc = (oop)(((address)base) + offset);
 661     assert(value_of_loc(derived_loc) - value_of_loc(&base) == offset, "sanity check");
 662 
 663     if (TraceDerivedPointers) {
 664       tty->print_cr("Updating derived pointer@" INTPTR_FORMAT
 665                     " - Derived: " INTPTR_FORMAT "  Base: " INTPTR_FORMAT " (Offset: %d)",
 666           derived_loc, (address)*derived_loc, (address)base, offset);
 667     }
 668 
 669     // Delete entry
 670     delete entry;
 671     _list->at_put(i, NULL);
 672   }
 673   // Clear list, so it is ready for next traversal (this is an invariant)
 674   if (TraceDerivedPointers && !_list->is_empty()) {
 675     tty->print_cr("--------------------------");
 676   }
 677   _list->clear();
 678   _active = false;
 679 }
 680 
 681 #endif // COMPILER2