void CompiledIC::set_cached_oop(oop cache) {
  assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");  
  assert (!is_optimized(), "an optimized virtual call does not have a cached oop");
  assert (cache == NULL || cache != badOop, "invalid oop");  

  if (TraceCompiledIC) {
    tty->print("  ");
    print_compiled_ic();
    tty->print_cr(" changing oop to " INTPTR_FORMAT, cache);
  }

  if (cache == NULL)  cache = (oop)Universe::non_oop_word();
  
  *_oop_addr = cache;
  // fix up the relocations
  RelocIterator iter = _oops;
  while (iter.next()) {
    if (iter.type() == relocInfo::oop_type) {
      oop_Relocation* r = iter.oop_reloc();
      if (r->oop_addr() == _oop_addr)
	r->fix_oop_relocation();
    }
  }
  return;
}
relocInfo* RelocIterator::create_index(CodeBuffer* src_cb, relocInfo* dest_begin, relocInfo* dest_end) {
  if (!UseRelocIndex)  return dest_begin;
  address relocation_begin = (address)dest_begin;
  address relocation_end   = (address)dest_end;
  int     total_size       = relocation_end - relocation_begin;
  int     locs_size        = src_cb->locs_size();
  int     index_size       = total_size - locs_size - BytesPerInt;	// find out how much space is left
  int     ncards           = index_size / sizeof(RelocIndexEntry);
  assert(total_size == locs_size + index_size + BytesPerInt, "checkin'");
  assert(index_size >= 0 && index_size % sizeof(RelocIndexEntry) == 0, "checkin'");
  jint*   index_size_addr  = (jint*)relocation_end - 1;

  assert(sizeof(jint) == BytesPerInt, "change this code");

  *index_size_addr = index_size;
  if (index_size != 0) {
    assert(index_size > 0, "checkin'");

    RelocIndexEntry* index = (RelocIndexEntry *)(relocation_begin + locs_size); 
    assert(index == (RelocIndexEntry*)index_size_addr - ncards, "checkin'");

    // walk over the relocations, and fill in index entries as we go
    RelocIterator iter;
    const address    initial_addr    = NULL;
    relocInfo* const src             = src_cb->locs_start();
    relocInfo* const initial_current = src - 1;  // biased by -1 like elsewhere

    iter._code    = NULL;
    iter._addr    = initial_addr;
    iter._limit   = (address)(ncards * indexCardSize);
    iter._current = initial_current;
    iter._end     = (relocInfo*)( (address)src + locs_size );
    iter._is_copy = true;

    int i = 0;
    address next_card_addr = (address)indexCardSize;
    int addr_offset = 0;
    int reloc_offset = 0;
    while (true) {
      // Checkpoint the iterator before advancing it.
      addr_offset  = iter._addr    - initial_addr;
      reloc_offset = iter._current - initial_current;
      if (!iter.next())  break;
      while (iter.addr() >= next_card_addr) {
	index[i].addr_offset  = addr_offset;
	index[i].reloc_offset = reloc_offset;
	i++;
	next_card_addr += indexCardSize;
      }
    }
    while (i < ncards) {
      index[i].addr_offset  = addr_offset;
      index[i].reloc_offset = reloc_offset;
      i++;
    }
  }
  return dest_begin;		// relocs go at the front, index at the back
}
RelocIterator virtual_call_Relocation::parse_ic(CodeBlob* &code, address &ic_call, address &first_oop, 
                                                oop* &oop_addr, bool *is_optimized) {
#ifndef CORE  
  assert(ic_call != NULL, "ic_call address must be set");
  assert(ic_call != NULL || first_oop != NULL, "must supply a non-null input");
  if (code == NULL) {
    if (ic_call != NULL) {
      code = CodeCache::find_blob(ic_call);
    } else if (first_oop != NULL) {
      code = CodeCache::find_blob(first_oop);
    }
    assert(code != NULL, "address to parse must be in CodeBlob");
  }
  assert(ic_call   == NULL || code->contains(ic_call),   "must be in CodeBlob");
  assert(first_oop == NULL || code->contains(first_oop), "must be in CodeBlob");
  
  address oop_limit = NULL;

  if (ic_call != NULL) {
    // search for the ic_call at the given address
    RelocIterator iter(code, ic_call, ic_call+1);
    bool ret = iter.next();
    assert(ret == true, "relocInfo must exist at this address");    
    assert(iter.addr() == ic_call, "must find ic_call");
    if (iter.type() == relocInfo::virtual_call_type) {      
      virtual_call_Relocation* r = iter.virtual_call_reloc();
      first_oop = r->first_oop();
      oop_limit = r->oop_limit();
      *is_optimized = false;
    } else {
      assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
      *is_optimized = true;
      oop_addr = NULL;
      first_oop = NULL;
      return iter;
    }
  }   

  // search for the first_oop, to get its oop_addr
  RelocIterator all_oops(code, first_oop);
  RelocIterator iter = all_oops;
  iter.set_limit(first_oop+1);
  bool found_oop = false;
  while (iter.next()) {
    if (iter.type() == relocInfo::oop_type) {
      assert(iter.addr() == first_oop, "must find first_oop");
      oop_addr = iter.oop_reloc()->oop_addr();
      found_oop = true;
      break;
    }
  }
  assert(found_oop, "must find first_oop");

  bool did_reset = false;
  while (ic_call == NULL) {
    // search forward for the ic_call matching the given first_oop
    while (iter.next()) {
      if (iter.type() == relocInfo::virtual_call_type) {
	virtual_call_Relocation* r = iter.virtual_call_reloc();
	if (r->first_oop() == first_oop) {
	  ic_call   = r->addr();
	  oop_limit = r->oop_limit();
	  break;
	}
      }
    }
    guarantee(!did_reset, "cannot find ic_call");
    iter = RelocIterator(code);	// search the whole CodeBlob
    did_reset = true;
  }

  assert(oop_limit != NULL && first_oop != NULL && ic_call != NULL, "");
  all_oops.set_limit(oop_limit);
  return all_oops;
#else
  RelocIterator iter((CodeBuffer*) NULL);
  return iter;
#endif // !CORE
}