void CodeSection::relocate(address at, RelocationHolder const& spec, int format) { Relocation* reloc = spec.reloc(); relocInfo::relocType rtype = (relocInfo::relocType) reloc->type(); if (rtype == relocInfo::none) return; // The assertion below has been adjusted, to also work for // relocation for fixup. Sometimes we want to put relocation // information for the next instruction, since it will be patched // with a call. assert(start() <= at && at <= end()+1, "cannot relocate data outside code boundaries"); if (!has_locs()) { // no space for relocation information provided => code cannot be // relocated. Make sure that relocate is only called with rtypes // that can be ignored for this kind of code. assert(rtype == relocInfo::none || rtype == relocInfo::runtime_call_type || rtype == relocInfo::internal_word_type|| rtype == relocInfo::section_word_type || rtype == relocInfo::external_word_type, "code needs relocation information"); // leave behind an indication that we attempted a relocation DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress); return; } // Advance the point, noting the offset we'll have to record. csize_t offset = at - locs_point(); set_locs_point(at); // Test for a couple of overflow conditions; maybe expand the buffer. relocInfo* end = locs_end(); relocInfo* req = end + relocInfo::length_limit; // Check for (potential) overflow if (req >= locs_limit() || offset >= relocInfo::offset_limit()) { req += (uint)offset / (uint)relocInfo::offset_limit(); if (req >= locs_limit()) { // Allocate or reallocate. expand_locs(locs_count() + (req - end)); // reload pointer end = locs_end(); } } // If the offset is giant, emit filler relocs, of type 'none', but // each carrying the largest possible offset, to advance the locs_point. while (offset >= relocInfo::offset_limit()) { assert(end < locs_limit(), "adjust previous paragraph of code"); *end++ = filler_relocInfo(); offset -= filler_relocInfo().addr_offset(); } // If it's a simple reloc with no data, we'll just write (rtype | offset). (*end) = relocInfo(rtype, offset, format); // If it has data, insert the prefix, as (data_prefix_tag | data1), data2. end->initialize(this, reloc); }
// Verify that there is enough space remaining for one instruction void force_space_in_buffer(int inst_size, int stubs_size, int const_size, int locs_size) { if ( allow_resizing() && ( ((address) code_end() + inst_size >= (address) code_limit()) || ((address) stub_end() + stubs_size >= (address) stub_limit()) || ((address)ctable_end() + const_size >= (address)ctable_limit()) || ((address) locs_end() + locs_size >= (address) locs_limit())) ) resize(); }
int locs_capacity() const { return (char*)locs_limit() - (char*)locs_start(); }