relocInfo.hpp revision 5976:2b8e28fdf503
1231990Smp/* 259243Sobrien * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 359243Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 459243Sobrien * 559243Sobrien * This code is free software; you can redistribute it and/or modify it 659243Sobrien * under the terms of the GNU General Public License version 2 only, as 759243Sobrien * published by the Free Software Foundation. 859243Sobrien * 959243Sobrien * This code is distributed in the hope that it will be useful, but WITHOUT 1059243Sobrien * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1159243Sobrien * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1259243Sobrien * version 2 for more details (a copy is included in the LICENSE file that 1359243Sobrien * accompanied this code). 1459243Sobrien * 1559243Sobrien * You should have received a copy of the GNU General Public License version 1659243Sobrien * 2 along with this work; if not, write to the Free Software Foundation, 17100616Smp * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1859243Sobrien * 1959243Sobrien * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2059243Sobrien * or visit www.oracle.com if you need additional information or have any 2159243Sobrien * questions. 2259243Sobrien * 2359243Sobrien */ 2459243Sobrien 2559243Sobrien#ifndef SHARE_VM_CODE_RELOCINFO_HPP 2659243Sobrien#define SHARE_VM_CODE_RELOCINFO_HPP 2759243Sobrien 2859243Sobrien#include "memory/allocation.hpp" 2959243Sobrien#include "utilities/top.hpp" 3059243Sobrien 3159243Sobrienclass NativeMovConstReg; 3259243Sobrien 3359243Sobrien// Types in this file: 3459243Sobrien// relocInfo 35231990Smp// One element of an array of halfwords encoding compressed relocations. 3659243Sobrien// Also, the source of relocation types (relocInfo::oop_type, ...). 3759243Sobrien// Relocation 3859243Sobrien// A flyweight object representing a single relocation. 3959243Sobrien// It is fully unpacked from the compressed relocation array. 4059243Sobrien// metadata_Relocation, ... (subclasses of Relocation) 4169408Sache// The location of some type-specific operations (metadata_addr, ...). 4259243Sobrien// Also, the source of relocation specs (metadata_Relocation::spec, ...). 43167465Smp// oop_Relocation, ... (subclasses of Relocation) 44167465Smp// oops in the code stream (strings, class loaders) 4569408Sache// Also, the source of relocation specs (oop_Relocation::spec, ...). 4659243Sobrien// RelocationHolder 4759243Sobrien// A ValueObj type which acts as a union holding a Relocation object. 4859243Sobrien// Represents a relocation spec passed into a CodeBuffer during assembly. 4959243Sobrien// RelocIterator 5059243Sobrien// A StackObj which iterates over the relocations associated with 5159243Sobrien// a range of code addresses. Can be used to operate a copy of code. 5259243Sobrien// BoundRelocation 5359243Sobrien// An _internal_ type shared by packers and unpackers of relocations. 5459243Sobrien// It pastes together a RelocationHolder with some pointers into 5559243Sobrien// code and relocInfo streams. 5659243Sobrien 5759243Sobrien 58145479Smp// Notes on relocType: 59145479Smp// 60145479Smp// These hold enough information to read or write a value embedded in 61145479Smp// the instructions of an CodeBlob. They're used to update: 62145479Smp// 63145479Smp// 1) embedded oops (isOop() == true) 64167465Smp// 2) inline caches (isIC() == true) 6559243Sobrien// 3) runtime calls (isRuntimeCall() == true) 66167465Smp// 4) internal word ref (isInternalWord() == true) 67167465Smp// 5) external word ref (isExternalWord() == true) 68167465Smp// 6959243Sobrien// when objects move (GC) or if code moves (compacting the code heap). 70167465Smp// They are also used to patch the code (if a call site must change) 71167465Smp// 72167465Smp// A relocInfo is represented in 16 bits: 7359243Sobrien// 4 bits indicating the relocation type 74167465Smp// 12 bits indicating the offset from the previous relocInfo address 75167465Smp// 7659243Sobrien// The offsets accumulate along the relocInfo stream to encode the 77167465Smp// address within the CodeBlob, which is named RelocIterator::addr(). 78167465Smp// The address of a particular relocInfo always points to the first 7959243Sobrien// byte of the relevant instruction (and not to any of its subfields 8059243Sobrien// or embedded immediate constants). 8159243Sobrien// 8259243Sobrien// The offset value is scaled appropriately for the target machine. 8359243Sobrien// (See relocInfo_<arch>.hpp for the offset scaling.) 8459243Sobrien// 8559243Sobrien// On some machines, there may also be a "format" field which may provide 86167465Smp// additional information about the format of the instruction stream 87167465Smp// at the corresponding code address. The format value is usually zero. 88167465Smp// Any machine (such as Intel) whose instructions can sometimes contain 8961524Sobrien// more than one relocatable constant needs format codes to distinguish 9061524Sobrien// which operand goes with a given relocation. 9161524Sobrien// 9261524Sobrien// If the target machine needs N format bits, the offset has 12-N bits, 9361524Sobrien// the format is encoded between the offset and the type, and the 9459243Sobrien// relocInfo_<arch>.hpp file has manifest constants for the format codes. 9559243Sobrien// 9659243Sobrien// If the type is "data_prefix_tag" then the offset bits are further encoded, 9759243Sobrien// and in fact represent not a code-stream offset but some inline data. 9859243Sobrien// The data takes the form of a counted sequence of halfwords, which 99167465Smp// precedes the actual relocation record. (Clients never see it directly.) 10059243Sobrien// The interpetation of this extra data depends on the relocation type. 101167465Smp// 102167465Smp// On machines that have 32-bit immediate fields, there is usually 103167465Smp// little need for relocation "prefix" data, because the instruction stream 104145479Smp// is a perfectly reasonable place to store the value. On machines in 105145479Smp// which 32-bit values must be "split" across instructions, the relocation 10659243Sobrien// data is the "true" specification of the value, which is then applied 10759243Sobrien// to some field of the instruction (22 or 13 bits, on SPARC). 10859243Sobrien// 109167465Smp// Whenever the location of the CodeBlob changes, any PC-relative 110167465Smp// relocations, and any internal_word_type relocations, must be reapplied. 11159243Sobrien// After the GC runs, oop_type relocations must be reapplied. 112167465Smp// 11359243Sobrien// 114167465Smp// Here are meanings of the types: 11559243Sobrien// 11659243Sobrien// relocInfo::none -- a filler record 11759243Sobrien// Value: none 11859243Sobrien// Instruction: The corresponding code address is ignored 11959243Sobrien// Data: Any data prefix and format code are ignored 12059243Sobrien// (This means that any relocInfo can be disabled by setting 121231990Smp// its type to none. See relocInfo::remove.) 12259243Sobrien// 12359243Sobrien// relocInfo::oop_type, relocInfo::metadata_type -- a reference to an oop or meta data 12459243Sobrien// Value: an oop, or else the address (handle) of an oop 125167465Smp// Instruction types: memory (load), set (load address) 12659243Sobrien// Data: [] an oop stored in 4 bytes of instruction 127167465Smp// [n] n is the index of an oop in the CodeBlob's oop pool 12859243Sobrien// [[N]n l] and l is a byte offset to be applied to the oop 12959243Sobrien// [Nn Ll] both index and offset may be 32 bits if necessary 130167465Smp// Here is a special hack, used only by the old compiler: 13159243Sobrien// [[N]n 00] the value is the __address__ of the nth oop in the pool 13259243Sobrien// (Note that the offset allows optimal references to class variables.) 13359243Sobrien// 13459243Sobrien// relocInfo::internal_word_type -- an address within the same CodeBlob 13559243Sobrien// relocInfo::section_word_type -- same, but can refer to another section 136167465Smp// Value: an address in the CodeBlob's code or constants section 137167465Smp// Instruction types: memory (load), set (load address) 13859243Sobrien// Data: [] stored in 4 bytes of instruction 139167465Smp// [[L]l] a relative offset (see [About Offsets] below) 14059243Sobrien// In the case of section_word_type, the offset is relative to a section 14159243Sobrien// base address, and the section number (e.g., SECT_INSTS) is encoded 14259243Sobrien// into the low two bits of the offset L. 143167465Smp// 14459243Sobrien// relocInfo::external_word_type -- a fixed address in the runtime system 145167465Smp// Value: an address 14659243Sobrien// Instruction types: memory (load), set (load address) 14759243Sobrien// Data: [] stored in 4 bytes of instruction 14859243Sobrien// [n] the index of a "well-known" stub (usual case on RISC) 14959243Sobrien// [Ll] a 32-bit address 150167465Smp// 15159243Sobrien// relocInfo::runtime_call_type -- a fixed subroutine in the runtime system 15259243Sobrien// Value: an address 15359243Sobrien// Instruction types: PC-relative call (or a PC-relative branch) 15459243Sobrien// Data: [] stored in 4 bytes of instruction 15559243Sobrien// 15659243Sobrien// relocInfo::static_call_type -- a static call 15759243Sobrien// Value: an CodeBlob, a stub, or a fixup routine 15859243Sobrien// Instruction types: a call 15959243Sobrien// Data: [] 16059243Sobrien// The identity of the callee is extracted from debugging information. 16159243Sobrien// //%note reloc_3 162167465Smp// 16359243Sobrien// relocInfo::virtual_call_type -- a virtual call site (which includes an inline 16459243Sobrien// cache) 16559243Sobrien// Value: an CodeBlob, a stub, the interpreter, or a fixup routine 166167465Smp// Instruction types: a call, plus some associated set-oop instructions 16759243Sobrien// Data: [] the associated set-oops are adjacent to the call 16859243Sobrien// [n] n is a relative offset to the first set-oop 16959243Sobrien// [[N]n l] and l is a limit within which the set-oops occur 170167465Smp// [Nn Ll] both n and l may be 32 bits if necessary 17159243Sobrien// The identity of the callee is extracted from debugging information. 17259243Sobrien// 17359243Sobrien// relocInfo::opt_virtual_call_type -- a virtual call site that is statically bound 17459243Sobrien// 17559243Sobrien// Same info as a static_call_type. We use a special type, so the handling of 17659243Sobrien// virtuals and statics are separated. 177231990Smp// 17859243Sobrien// 179167465Smp// The offset n points to the first set-oop. (See [About Offsets] below.) 180167465Smp// In turn, the set-oop instruction specifies or contains an oop cell devoted 181167465Smp// exclusively to the IC call, which can be patched along with the call. 182167465Smp// 18359243Sobrien// The locations of any other set-oops are found by searching the relocation 18459243Sobrien// information starting at the first set-oop, and continuing until all 18559243Sobrien// relocations up through l have been inspected. The value l is another 18659243Sobrien// relative offset. (Both n and l are relative to the call's first byte.) 187167465Smp// 18859243Sobrien// The limit l of the search is exclusive. However, if it points within 18959243Sobrien// the call (e.g., offset zero), it is adjusted to point after the call and 19059243Sobrien// any associated machine-specific delay slot. 19159243Sobrien// 19259243Sobrien// Since the offsets could be as wide as 32-bits, these conventions 193167465Smp// put no restrictions whatever upon code reorganization. 19459243Sobrien// 195167465Smp// The compiler is responsible for ensuring that transition from a clean 19659243Sobrien// state to a monomorphic compiled state is MP-safe. This implies that 19759243Sobrien// the system must respond well to intermediate states where a random 19859243Sobrien// subset of the set-oops has been correctly from the clean state 19959243Sobrien// upon entry to the VEP of the compiled method. In the case of a 20059243Sobrien// machine (Intel) with a single set-oop instruction, the 32-bit 201167465Smp// immediate field must not straddle a unit of memory coherence. 202167465Smp// //%note reloc_3 203167465Smp// 204167465Smp// relocInfo::static_stub_type -- an extra stub for each static_call_type 205167465Smp// Value: none 206167465Smp// Instruction types: a virtual call: { set_oop; jump; } 20759243Sobrien// Data: [[N]n] the offset of the associated static_call reloc 20859243Sobrien// This stub becomes the target of a static call which must be upgraded 209167465Smp// to a virtual call (because the callee is interpreted). 210167465Smp// See [About Offsets] below. 211167465Smp// //%note reloc_2 21259243Sobrien// 21359243Sobrien// For example: 21459243Sobrien// 21559243Sobrien// INSTRUCTIONS RELOC: TYPE PREFIX DATA 21659243Sobrien// ------------ ---- ----------- 21759243Sobrien// sethi %hi(myObject), R oop_type [n(myObject)] 21859243Sobrien// ld [R+%lo(myObject)+fldOffset], R2 oop_type [n(myObject) fldOffset] 21959243Sobrien// add R2, 1, R2 22059243Sobrien// st R2, [R+%lo(myObject)+fldOffset] oop_type [n(myObject) fldOffset] 22159243Sobrien//%note reloc_1 22259243Sobrien// 22359243Sobrien// This uses 4 instruction words, 8 relocation halfwords, 224167465Smp// and an entry (which is sharable) in the CodeBlob's oop pool, 225167465Smp// for a total of 36 bytes. 226167465Smp// 227167465Smp// Note that the compiler is responsible for ensuring the "fldOffset" when 22859243Sobrien// added to "%lo(myObject)" does not overflow the immediate fields of the 229167465Smp// memory instructions. 23059243Sobrien// 23159243Sobrien// 23259243Sobrien// [About Offsets] Relative offsets are supplied to this module as 23359243Sobrien// positive byte offsets, but they may be internally stored scaled 23459243Sobrien// and/or negated, depending on what is most compact for the target 23559243Sobrien// system. Since the object pointed to by the offset typically 23659243Sobrien// precedes the relocation address, it is profitable to store 23759243Sobrien// these negative offsets as positive numbers, but this decision 238100616Smp// is internal to the relocation information abstractions. 239100616Smp// 24059243Sobrien 24159243Sobrienclass Relocation; 24259243Sobrienclass CodeBuffer; 24359243Sobrienclass CodeSection; 24459243Sobrienclass RelocIterator; 24559243Sobrien 24659243Sobrienclass relocInfo VALUE_OBJ_CLASS_SPEC { 24759243Sobrien friend class RelocIterator; 24859243Sobrien public: 24959243Sobrien enum relocType { 25059243Sobrien none = 0, // Used when no relocation should be generated 25159243Sobrien oop_type = 1, // embedded oop 25259243Sobrien virtual_call_type = 2, // a standard inline cache call for a virtual send 25359243Sobrien opt_virtual_call_type = 3, // a virtual call that has been statically bound (i.e., no IC cache) 25459243Sobrien static_call_type = 4, // a static send 25559243Sobrien static_stub_type = 5, // stub-entry for static send (takes care of interpreter case) 25659243Sobrien runtime_call_type = 6, // call to fixed external routine 25759243Sobrien external_word_type = 7, // reference to fixed external address 25859243Sobrien internal_word_type = 8, // reference within the current code blob 25959243Sobrien section_word_type = 9, // internal, but a cross-section reference 260167465Smp poll_type = 10, // polling instruction for safepoints 26159243Sobrien poll_return_type = 11, // polling instruction for safepoints at return 26259243Sobrien metadata_type = 12, // metadata that used to be oops 26359243Sobrien trampoline_stub_type = 13, // stub-entry for trampoline 26459243Sobrien yet_unused_type_1 = 14, // Still unused 265167465Smp data_prefix_tag = 15, // tag for a prefix (carries data arguments) 26659243Sobrien type_mask = 15 // A mask which selects only the above values 26759243Sobrien }; 26859243Sobrien 26959243Sobrien protected: 27059243Sobrien unsigned short _value; 27159243Sobrien 272167465Smp enum RawBitsToken { RAW_BITS }; 27359243Sobrien relocInfo(relocType type, RawBitsToken ignore, int bits) 27459243Sobrien : _value((type << nontype_width) + bits) { } 27559243Sobrien 27659243Sobrien relocInfo(relocType type, RawBitsToken ignore, int off, int f) 27759243Sobrien : _value((type << nontype_width) + (off / (unsigned)offset_unit) + (f << offset_width)) { } 27859243Sobrien 27959243Sobrien public: 28059243Sobrien // constructor 281167465Smp relocInfo(relocType type, int offset, int format = 0) 28259243Sobrien#ifndef ASSERT 28359243Sobrien { 28459243Sobrien (*this) = relocInfo(type, RAW_BITS, offset, format); 28559243Sobrien } 28659243Sobrien#else 28759243Sobrien // Put a bunch of assertions out-of-line. 28859243Sobrien ; 289167465Smp#endif 290100616Smp 29159243Sobrien #define APPLY_TO_RELOCATIONS(visitor) \ 29259243Sobrien visitor(oop) \ 29359243Sobrien visitor(metadata) \ 29459243Sobrien visitor(virtual_call) \ 29559243Sobrien visitor(opt_virtual_call) \ 29659243Sobrien visitor(static_call) \ 297167465Smp visitor(static_stub) \ 29859243Sobrien visitor(runtime_call) \ 29959243Sobrien visitor(external_word) \ 30059243Sobrien visitor(internal_word) \ 301167465Smp visitor(poll) \ 30259243Sobrien visitor(poll_return) \ 30359243Sobrien visitor(section_word) \ 30459243Sobrien visitor(trampoline_stub) \ 30559243Sobrien 30659243Sobrien 307100616Smp public: 30859243Sobrien enum { 309167465Smp value_width = sizeof(unsigned short) * BitsPerByte, 31059243Sobrien type_width = 4, // == log2(type_mask+1) 311167465Smp nontype_width = value_width - type_width, 31259243Sobrien datalen_width = nontype_width-1, 31359243Sobrien datalen_tag = 1 << datalen_width, // or-ed into _value 314167465Smp datalen_limit = 1 << datalen_width, 315167465Smp datalen_mask = (1 << datalen_width)-1 31659243Sobrien }; 317167465Smp 31859243Sobrien // accessors 31959243Sobrien public: 320167465Smp relocType type() const { return (relocType)((unsigned)_value >> nontype_width); } 321167465Smp int format() const { return format_mask==0? 0: format_mask & 32259243Sobrien ((unsigned)_value >> offset_width); } 32359243Sobrien int addr_offset() const { assert(!is_prefix(), "must have offset"); 32459243Sobrien return (_value & offset_mask)*offset_unit; } 32559243Sobrien 32659243Sobrien protected: 327167465Smp const short* data() const { assert(is_datalen(), "must have data"); 328167465Smp return (const short*)(this + 1); } 329167465Smp int datalen() const { assert(is_datalen(), "must have data"); 330167465Smp return (_value & datalen_mask); } 33159243Sobrien int immediate() const { assert(is_immediate(), "must have immed"); 33259243Sobrien return (_value & datalen_mask); } 33359243Sobrien public: 33459243Sobrien static int addr_unit() { return offset_unit; } 33559243Sobrien static int offset_limit() { return (1 << offset_width) * offset_unit; } 336167465Smp 33759243Sobrien void set_type(relocType type); 33859243Sobrien void set_format(int format); 33959243Sobrien 34059243Sobrien void remove() { set_type(none); } 34159243Sobrien 34259243Sobrien protected: 34359243Sobrien bool is_none() const { return type() == none; } 34459243Sobrien bool is_prefix() const { return type() == data_prefix_tag; } 34559243Sobrien bool is_datalen() const { assert(is_prefix(), "must be prefix"); 34659243Sobrien return (_value & datalen_tag) != 0; } 34759243Sobrien bool is_immediate() const { assert(is_prefix(), "must be prefix"); 34859243Sobrien return (_value & datalen_tag) == 0; } 34959243Sobrien 350167465Smp public: 351167465Smp // Occasionally records of type relocInfo::none will appear in the stream. 352167465Smp // We do not bother to filter these out, but clients should ignore them. 353167465Smp // These records serve as "filler" in three ways: 354167465Smp // - to skip large spans of unrelocated code (this is rare) 35559243Sobrien // - to pad out the relocInfo array to the required oop alignment 35669408Sache // - to disable old relocation information which is no longer applicable 357167465Smp 35869408Sache inline friend relocInfo filler_relocInfo(); 359167465Smp 360167465Smp // Every non-prefix relocation may be preceded by at most one prefix, 361167465Smp // which supplies 1 or more halfwords of associated data. Conventionally, 362167465Smp // an int is represented by 0, 1, or 2 halfwords, depending on how 363167465Smp // many bits are required to represent the value. (In addition, 364167465Smp // if the sole halfword is a 10-bit unsigned number, it is made 36559243Sobrien // "immediate" in the prefix header word itself. This optimization 36659243Sobrien // is invisible outside this module.) 367167465Smp 36859243Sobrien inline friend relocInfo prefix_relocInfo(int datalen); 369167465Smp 37059243Sobrien protected: 37159243Sobrien // an immediate relocInfo optimizes a prefix with one 10-bit unsigned value 37259243Sobrien static relocInfo immediate_relocInfo(int data0) { 37359243Sobrien assert(fits_into_immediate(data0), "data0 in limits"); 37459243Sobrien return relocInfo(relocInfo::data_prefix_tag, RAW_BITS, data0); 37559243Sobrien } 37659243Sobrien static bool fits_into_immediate(int data0) { 377167465Smp return (data0 >= 0 && data0 < datalen_limit); 37859243Sobrien } 37959243Sobrien 380145479Smp public: 38159243Sobrien // Support routines for compilers. 38259243Sobrien 38359243Sobrien // This routine takes an infant relocInfo (unprefixed) and 384167465Smp // edits in its prefix, if any. It also updates dest.locs_end. 38559243Sobrien void initialize(CodeSection* dest, Relocation* reloc); 386145479Smp 38759243Sobrien // This routine updates a prefix and returns the limit pointer. 38859243Sobrien // It tries to compress the prefix from 32 to 16 bits, and if 38959243Sobrien // successful returns a reduced "prefix_limit" pointer. 390145479Smp relocInfo* finish_prefix(short* prefix_limit); 39159243Sobrien 39259243Sobrien // bit-packers for the data array: 39359243Sobrien 39459243Sobrien // As it happens, the bytes within the shorts are ordered natively, 395167465Smp // but the shorts within the word are ordered big-endian. 39659243Sobrien // This is an arbitrary choice, made this way mainly to ease debugging. 397145479Smp static int data0_from_int(jint x) { return x >> value_width; } 39859243Sobrien static int data1_from_int(jint x) { return (short)x; } 39959243Sobrien static jint jint_from_data(short* data) { 40059243Sobrien return (data[0] << value_width) + (unsigned short)data[1]; 40159243Sobrien } 40259243Sobrien 40359243Sobrien static jint short_data_at(int n, short* data, int datalen) { 40459243Sobrien return datalen > n ? data[n] : 0; 405167465Smp } 40659243Sobrien 407167465Smp static jint jint_data_at(int n, short* data, int datalen) { 40859243Sobrien return datalen > n+1 ? jint_from_data(&data[n]) : short_data_at(n, data, datalen); 409145479Smp } 41059243Sobrien 41159243Sobrien // Update methods for relocation information 41259243Sobrien // (since code is dynamically patched, we also need to dynamically update the relocation info) 413167465Smp // Both methods takes old_type, so it is able to performe sanity checks on the information removed. 414167465Smp static void change_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type, relocType new_type); 415167465Smp static void remove_reloc_info_for_address(RelocIterator *itr, address pc, relocType old_type); 416167465Smp 41759243Sobrien // Machine dependent stuff 418167465Smp#ifdef TARGET_ARCH_x86 41959243Sobrien# include "relocInfo_x86.hpp" 42059243Sobrien#endif 42159243Sobrien#ifdef TARGET_ARCH_sparc 42259243Sobrien# include "relocInfo_sparc.hpp" 42359243Sobrien#endif 42459243Sobrien#ifdef TARGET_ARCH_zero 42559243Sobrien# include "relocInfo_zero.hpp" 42659243Sobrien#endif 42759243Sobrien#ifdef TARGET_ARCH_arm 42859243Sobrien# include "relocInfo_arm.hpp" 42959243Sobrien#endif 430167465Smp#ifdef TARGET_ARCH_ppc 43159243Sobrien# include "relocInfo_ppc.hpp" 43259243Sobrien#endif 43359243Sobrien 43459243Sobrien 43559243Sobrien protected: 43659243Sobrien // Derived constant, based on format_width which is PD: 43759243Sobrien enum { 43859243Sobrien offset_width = nontype_width - format_width, 43959243Sobrien offset_mask = (1<<offset_width) - 1, 44059243Sobrien format_mask = (1<<format_width) - 1 44159243Sobrien }; 44259243Sobrien public: 44359243Sobrien enum { 44459243Sobrien // Conservatively large estimate of maximum length (in shorts) 44559243Sobrien // of any relocation record. 44659243Sobrien // Extended format is length prefix, data words, and tag/offset suffix. 447100616Smp length_limit = 1 + 1 + (3*BytesPerWord/BytesPerShort) + 1, 44859243Sobrien have_format = format_width > 0 44959243Sobrien }; 45059243Sobrien}; 45159243Sobrien 45259243Sobrien#define FORWARD_DECLARE_EACH_CLASS(name) \ 453167465Smpclass name##_Relocation; 454167465SmpAPPLY_TO_RELOCATIONS(FORWARD_DECLARE_EACH_CLASS) 45559243Sobrien#undef FORWARD_DECLARE_EACH_CLASS 45659243Sobrien 45759243Sobrien 45859243Sobrien 45959243Sobrieninline relocInfo filler_relocInfo() { 46059243Sobrien return relocInfo(relocInfo::none, relocInfo::offset_limit() - relocInfo::offset_unit); 46159243Sobrien} 46259243Sobrien 46359243Sobrieninline relocInfo prefix_relocInfo(int datalen = 0) { 46459243Sobrien assert(relocInfo::fits_into_immediate(datalen), "datalen in limits"); 46559243Sobrien return relocInfo(relocInfo::data_prefix_tag, relocInfo::RAW_BITS, relocInfo::datalen_tag | datalen); 466167465Smp} 46759243Sobrien 46859243Sobrien 46959243Sobrien// Holder for flyweight relocation objects. 47059243Sobrien// Although the flyweight subclasses are of varying sizes, 471167465Smp// the holder is "one size fits all". 47259243Sobrienclass RelocationHolder VALUE_OBJ_CLASS_SPEC { 47359243Sobrien friend class Relocation; 47459243Sobrien friend class CodeSection; 47559243Sobrien 47659243Sobrien private: 47759243Sobrien // this preallocated memory must accommodate all subclasses of Relocation 47859243Sobrien // (this number is assertion-checked in Relocation::operator new) 47959243Sobrien enum { _relocbuf_size = 5 }; 48059243Sobrien void* _relocbuf[ _relocbuf_size ]; 481167465Smp 48259243Sobrien public: 48359243Sobrien Relocation* reloc() const { return (Relocation*) &_relocbuf[0]; } 48459243Sobrien inline relocInfo::relocType type() const; 48559243Sobrien 48659243Sobrien // Add a constant offset to a relocation. Helper for class Address. 48759243Sobrien RelocationHolder plus(int offset) const; 488167465Smp 48959243Sobrien inline RelocationHolder(); // initializes type to none 490145479Smp 491145479Smp inline RelocationHolder(Relocation* r); // make a copy 492145479Smp 493167465Smp static const RelocationHolder none; 494167465Smp}; 49559243Sobrien 49659243Sobrien// A RelocIterator iterates through the relocation information of a CodeBlob. 49759243Sobrien// It is a variable BoundRelocation which is able to take on successive 49859243Sobrien// values as it is advanced through a code stream. 49959243Sobrien// Usage: 50059243Sobrien// RelocIterator iter(nm); 50159243Sobrien// while (iter.next()) { 50259243Sobrien// iter.reloc()->some_operation(); 50359243Sobrien// } 50459243Sobrien// or: 50559243Sobrien// RelocIterator iter(nm); 50659243Sobrien// while (iter.next()) { 50759243Sobrien// switch (iter.type()) { 50859243Sobrien// case relocInfo::oop_type : 50959243Sobrien// case relocInfo::ic_type : 510145479Smp// case relocInfo::prim_type : 51159243Sobrien// case relocInfo::uncommon_type : 512145479Smp// case relocInfo::runtime_call_type : 51359243Sobrien// case relocInfo::internal_word_type: 51459243Sobrien// case relocInfo::external_word_type: 51559243Sobrien// ... 51659243Sobrien// } 51759243Sobrien// } 51859243Sobrien 51959243Sobrienclass RelocIterator : public StackObj { 52059243Sobrien enum { SECT_LIMIT = 3 }; // must be equal to CodeBuffer::SECT_LIMIT, checked in ctor 52159243Sobrien friend class Relocation; 52259243Sobrien friend class relocInfo; // for change_reloc_info_for_address only 52359243Sobrien typedef relocInfo::relocType relocType; 52459243Sobrien 52559243Sobrien private: 52659243Sobrien address _limit; // stop producing relocations after this _addr 52759243Sobrien relocInfo* _current; // the current relocation information 52859243Sobrien relocInfo* _end; // end marker; we're done iterating when _current == _end 52959243Sobrien nmethod* _code; // compiled method containing _addr 53059243Sobrien address _addr; // instruction to which the relocation applies 53159243Sobrien short _databuf; // spare buffer for compressed data 53259243Sobrien short* _data; // pointer to the relocation's data 53359243Sobrien short _datalen; // number of halfwords in _data 53459243Sobrien char _format; // position within the instruction 53559243Sobrien 53659243Sobrien // Base addresses needed to compute targets of section_word_type relocs. 53759243Sobrien address _section_start[SECT_LIMIT]; 53859243Sobrien address _section_end [SECT_LIMIT]; 53959243Sobrien 54059243Sobrien void set_has_current(bool b) { 54159243Sobrien _datalen = !b ? -1 : 0; 54259243Sobrien debug_only(_data = NULL); 54359243Sobrien } 544167465Smp void set_current(relocInfo& ri) { 545167465Smp _current = &ri; 54659243Sobrien set_has_current(true); 54759243Sobrien } 54859243Sobrien 54959243Sobrien RelocationHolder _rh; // where the current relocation is allocated 55059243Sobrien 55159243Sobrien relocInfo* current() const { assert(has_current(), "must have current"); 55259243Sobrien return _current; } 55359243Sobrien 55459243Sobrien void set_limits(address begin, address limit); 55559243Sobrien 55659243Sobrien void advance_over_prefix(); // helper method 55759243Sobrien 55859243Sobrien void initialize_misc(); 55959243Sobrien 56059243Sobrien void initialize(nmethod* nm, address begin, address limit); 56159243Sobrien 56259243Sobrien RelocIterator() { initialize_misc(); } 563167465Smp 56459243Sobrien public: 56559243Sobrien // constructor 566145479Smp RelocIterator(nmethod* nm, address begin = NULL, address limit = NULL); 56759243Sobrien RelocIterator(CodeSection* cb, address begin = NULL, address limit = NULL); 568167465Smp 56959243Sobrien // get next reloc info, return !eos 57059243Sobrien bool next() { 57159243Sobrien _current++; 572167465Smp assert(_current <= _end, "must not overrun relocInfo"); 57359243Sobrien if (_current == _end) { 57459243Sobrien set_has_current(false); 57559243Sobrien return false; 57659243Sobrien } 57759243Sobrien set_has_current(true); 578167465Smp 57959243Sobrien if (_current->is_prefix()) { 58059243Sobrien advance_over_prefix(); 58159243Sobrien assert(!current()->is_prefix(), "only one prefix at a time"); 582167465Smp } 58359243Sobrien 58459243Sobrien _addr += _current->addr_offset(); 58559243Sobrien 58659243Sobrien if (_limit != NULL && _addr >= _limit) { 58759243Sobrien set_has_current(false); 58859243Sobrien return false; 58959243Sobrien } 590167465Smp 59159243Sobrien if (relocInfo::have_format) _format = current()->format(); 59259243Sobrien return true; 59359243Sobrien } 59459243Sobrien 595167465Smp // accessors 59659243Sobrien address limit() const { return _limit; } 59759243Sobrien void set_limit(address x); 59859243Sobrien relocType type() const { return current()->type(); } 599167465Smp int format() const { return (relocInfo::have_format) ? current()->format() : 0; } 60059243Sobrien address addr() const { return _addr; } 601167465Smp nmethod* code() const { return _code; } 602167465Smp short* data() const { return _data; } 603167465Smp int datalen() const { return _datalen; } 604167465Smp bool has_current() const { return _datalen >= 0; } 60559243Sobrien 606167465Smp void set_addr(address addr) { _addr = addr; } 607167465Smp bool addr_in_const() const; 608167465Smp 609167465Smp address section_start(int n) const { 610167465Smp assert(_section_start[n], "must be initialized"); 611167465Smp return _section_start[n]; 612167465Smp } 613167465Smp address section_end(int n) const { 614167465Smp assert(_section_end[n], "must be initialized"); 615167465Smp return _section_end[n]; 616167465Smp } 61759243Sobrien 618167465Smp // The address points to the affected displacement part of the instruction. 619167465Smp // For RISC, this is just the whole instruction. 62059243Sobrien // For Intel, this is an unaligned 32-bit word. 621167465Smp 622167465Smp // type-specific relocation accessors: oop_Relocation* oop_reloc(), etc. 62359243Sobrien #define EACH_TYPE(name) \ 62459243Sobrien inline name##_Relocation* name##_reloc(); 625167465Smp APPLY_TO_RELOCATIONS(EACH_TYPE) 626167465Smp #undef EACH_TYPE 627167465Smp // generic relocation accessor; switches on type to call the above 628167465Smp Relocation* reloc(); 629167465Smp 63059243Sobrien // CodeBlob's have relocation indexes for faster random access: 631167465Smp static int locs_and_index_size(int code_size, int locs_size); 63259243Sobrien // Store an index into [dest_start+dest_count..dest_end). 633167465Smp // At dest_start[0..dest_count] is the actual relocation information. 63459243Sobrien // Everything else up to dest_end is free space for the index. 635180637Skeramida static void create_index(relocInfo* dest_begin, int dest_count, relocInfo* dest_end); 63659243Sobrien 637167465Smp#ifndef PRODUCT 63859243Sobrien public: 639167465Smp void print(); 640145479Smp void print_current(); 641167465Smp#endif 642167465Smp}; 643145479Smp 644167465Smp 645145479Smp// A Relocation is a flyweight object allocated within a RelocationHolder. 646145479Smp// It represents the relocation data of relocation record. 647145479Smp// So, the RelocIterator unpacks relocInfos into Relocations. 648145479Smp 64959243Sobrienclass Relocation VALUE_OBJ_CLASS_SPEC { 65059243Sobrien friend class RelocationHolder; 65159243Sobrien friend class RelocIterator; 65259243Sobrien 65359243Sobrien private: 65459243Sobrien static void guarantee_size(); 65559243Sobrien 65659243Sobrien // When a relocation has been created by a RelocIterator, 65759243Sobrien // this field is non-null. It allows the relocation to know 65859243Sobrien // its context, such as the address to which it applies. 659167465Smp RelocIterator* _binding; 66059243Sobrien 66159243Sobrien protected: 66259243Sobrien RelocIterator* binding() const { 66359243Sobrien assert(_binding != NULL, "must be bound"); 66459243Sobrien return _binding; 66559243Sobrien } 66659243Sobrien void set_binding(RelocIterator* b) { 66759243Sobrien assert(_binding == NULL, "must be unbound"); 66859243Sobrien _binding = b; 669167465Smp assert(_binding != NULL, "must now be bound"); 67059243Sobrien } 67159243Sobrien 672167465Smp Relocation() { 67359243Sobrien _binding = NULL; 674231990Smp } 67559243Sobrien 676167465Smp static RelocationHolder newHolder() { 67759243Sobrien return RelocationHolder(); 67859243Sobrien } 67959243Sobrien 680145479Smp public: 68159243Sobrien void* operator new(size_t size, const RelocationHolder& holder) throw() { 68259243Sobrien if (size > sizeof(holder._relocbuf)) guarantee_size(); 68359243Sobrien assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree"); 684231990Smp return holder.reloc(); 68559243Sobrien } 686167465Smp 687167465Smp // make a generic relocation for a given type (if possible) 688167465Smp static RelocationHolder spec_simple(relocInfo::relocType rtype); 689167465Smp 690167465Smp // here is the type-specific hook which writes relocation data: 691167465Smp virtual void pack_data_to(CodeSection* dest) { } 692167465Smp 693167465Smp // here is the type-specific hook which reads (unpacks) relocation data: 694167465Smp virtual void unpack_data() { 69559243Sobrien assert(datalen()==0 || type()==relocInfo::none, "no data here"); 696145479Smp } 69759243Sobrien 69859243Sobrien static bool is_reloc_index(intptr_t index) { 699231990Smp return 0 < index && index < os::vm_page_size(); 700231990Smp } 701231990Smp 702231990Smp protected: 703231990Smp // Helper functions for pack_data_to() and unpack_data(). 704231990Smp 70569408Sache // Most of the compression logic is confined here. 706167465Smp // (The "immediate data" mechanism of relocInfo works independently 70759243Sobrien // of this stuff, and acts to further compress most 1-word data prefixes.) 70869408Sache 70959243Sobrien // A variable-width int is encoded as a short if it will fit in 16 bits. 710145479Smp // The decoder looks at datalen to decide whether to unpack short or jint. 71159243Sobrien // Most relocation records are quite simple, containing at most two ints. 71259243Sobrien 713167465Smp static bool is_short(jint x) { return x == (short)x; } 71459243Sobrien static short* add_short(short* p, int x) { *p++ = x; return p; } 71559243Sobrien static short* add_jint (short* p, jint x) { 71659243Sobrien *p++ = relocInfo::data0_from_int(x); *p++ = relocInfo::data1_from_int(x); 71759243Sobrien return p; 71859243Sobrien } 719167465Smp static short* add_var_int(short* p, jint x) { // add a variable-width int 72059243Sobrien if (is_short(x)) p = add_short(p, x); 72159243Sobrien else p = add_jint (p, x); 72259243Sobrien return p; 72359243Sobrien } 72459243Sobrien 72559243Sobrien static short* pack_1_int_to(short* p, jint x0) { 72659243Sobrien // Format is one of: [] [x] [Xx] 72759243Sobrien if (x0 != 0) p = add_var_int(p, x0); 72859243Sobrien return p; 72959243Sobrien } 73059243Sobrien int unpack_1_int() { 73159243Sobrien assert(datalen() <= 2, "too much data"); 73259243Sobrien return relocInfo::jint_data_at(0, data(), datalen()); 733167465Smp } 73459243Sobrien 735231990Smp // With two ints, the short form is used only if both ints are short. 73659243Sobrien short* pack_2_ints_to(short* p, jint x0, jint x1) { 73759243Sobrien // Format is one of: [] [x y?] [Xx Y?y] 73859243Sobrien if (x0 == 0 && x1 == 0) { 73959243Sobrien // no halfwords needed to store zeroes 74059243Sobrien } else if (is_short(x0) && is_short(x1)) { 74159243Sobrien // 1-2 halfwords needed to store shorts 74259243Sobrien p = add_short(p, x0); if (x1!=0) p = add_short(p, x1); 74359243Sobrien } else { 74459243Sobrien // 3-4 halfwords needed to store jints 74559243Sobrien p = add_jint(p, x0); p = add_var_int(p, x1); 74659243Sobrien } 74759243Sobrien return p; 74859243Sobrien } 749167465Smp void unpack_2_ints(jint& x0, jint& x1) { 75059243Sobrien int dlen = datalen(); 75159243Sobrien short* dp = data(); 752167465Smp if (dlen <= 2) { 753167465Smp x0 = relocInfo::short_data_at(0, dp, dlen); 75459243Sobrien x1 = relocInfo::short_data_at(1, dp, dlen); 75559243Sobrien } else { 75659243Sobrien assert(dlen <= 4, "too much data"); 75759243Sobrien x0 = relocInfo::jint_data_at(0, dp, dlen); 75859243Sobrien x1 = relocInfo::jint_data_at(2, dp, dlen); 75959243Sobrien } 76059243Sobrien } 76159243Sobrien 762167465Smp protected: 76359243Sobrien // platform-dependent utilities for decoding and patching instructions 76459243Sobrien void pd_set_data_value (address x, intptr_t off, bool verify_only = false); // a set or mem-ref 76559243Sobrien void pd_verify_data_value (address x, intptr_t off) { pd_set_data_value(x, off, true); } 76659243Sobrien address pd_call_destination (address orig_addr = NULL); 767167465Smp void pd_set_call_destination (address x); 76859243Sobrien 76959243Sobrien // this extracts the address of an address in the code stream instead of the reloc data 77059243Sobrien address* pd_address_in_code (); 77159243Sobrien 77259243Sobrien // this extracts an address from the code stream instead of the reloc data 773167465Smp address pd_get_address_from_code (); 774167465Smp 77559243Sobrien // these convert from byte offsets, to scaled offsets, to addresses 77659243Sobrien static jint scaled_offset(address x, address base) { 77759243Sobrien int byte_offset = x - base; 77859243Sobrien int offset = -byte_offset / relocInfo::addr_unit(); 77959243Sobrien assert(address_from_scaled_offset(offset, base) == x, "just checkin'"); 78059243Sobrien return offset; 78159243Sobrien } 78259243Sobrien static jint scaled_offset_null_special(address x, address base) { 783167465Smp // Some relocations treat offset=0 as meaning NULL. 784167465Smp // Handle this extra convention carefully. 78559243Sobrien if (x == NULL) return 0; 786167465Smp assert(x != base, "offset must not be zero"); 78759243Sobrien return scaled_offset(x, base); 78859243Sobrien } 78959243Sobrien static address address_from_scaled_offset(jint offset, address base) { 79059243Sobrien int byte_offset = -( offset * relocInfo::addr_unit() ); 79159243Sobrien return base + byte_offset; 79259243Sobrien } 79359243Sobrien 79459243Sobrien // these convert between indexes and addresses in the runtime system 79559243Sobrien static int32_t runtime_address_to_index(address runtime_address); 79659243Sobrien static address index_to_runtime_address(int32_t index); 79759243Sobrien 79859243Sobrien // helpers for mapping between old and new addresses after a move or resize 79959243Sobrien address old_addr_for(address newa, const CodeBuffer* src, CodeBuffer* dest); 800167465Smp address new_addr_for(address olda, const CodeBuffer* src, CodeBuffer* dest); 80159243Sobrien void normalize_address(address& addr, const CodeSection* dest, bool allow_other_sections = false); 802167465Smp 803167465Smp public: 80459243Sobrien // accessors which only make sense for a bound Relocation 80559243Sobrien address addr() const { return binding()->addr(); } 806195609Smp nmethod* code() const { return binding()->code(); } 80759243Sobrien bool addr_in_const() const { return binding()->addr_in_const(); } 80859243Sobrien protected: 80959243Sobrien short* data() const { return binding()->data(); } 81059243Sobrien int datalen() const { return binding()->datalen(); } 81159243Sobrien int format() const { return binding()->format(); } 81259243Sobrien 81359243Sobrien public: 814167465Smp virtual relocInfo::relocType type() { return relocInfo::none; } 81559243Sobrien 81659243Sobrien // is it a call instruction? 81759243Sobrien virtual bool is_call() { return false; } 818167465Smp 81959243Sobrien // is it a data movement instruction? 820167465Smp virtual bool is_data() { return false; } 821167465Smp 82259243Sobrien // some relocations can compute their own values 82359243Sobrien virtual address value(); 824195609Smp 82559243Sobrien // all relocations are able to reassert their values 82659243Sobrien virtual void set_value(address x); 82759243Sobrien 82859243Sobrien virtual void clear_inline_cache() { } 82959243Sobrien 83059243Sobrien // This method assumes that all virtual/static (inline) caches are cleared (since for static_call_type and 83159243Sobrien // ic_call_type is not always posisition dependent (depending on the state of the cache)). However, this is 832167465Smp // probably a reasonable assumption, since empty caches simplifies code reloacation. 83359243Sobrien virtual void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { } 83459243Sobrien 83559243Sobrien void print(); 83659243Sobrien}; 83759243Sobrien 83859243Sobrien 83959243Sobrien// certain inlines must be deferred until class Relocation is defined: 84059243Sobrien 84159243Sobrieninline RelocationHolder::RelocationHolder() { 842167465Smp // initialize the vtbl, just to keep things type-safe 84359243Sobrien new(*this) Relocation(); 844167465Smp} 845167465Smp 84659243Sobrien 84759243Sobrieninline RelocationHolder::RelocationHolder(Relocation* r) { 848195609Smp // wordwise copy from r (ok if it copies garbage after r) 84959243Sobrien for (int i = 0; i < _relocbuf_size; i++) { 85059243Sobrien _relocbuf[i] = ((void**)r)[i]; 85159243Sobrien } 85259243Sobrien} 85359243Sobrien 85459243Sobrien 85559243SobrienrelocInfo::relocType RelocationHolder::type() const { 856167465Smp return reloc()->type(); 85759243Sobrien} 85859243Sobrien 85959243Sobrien// A DataRelocation always points at a memory or load-constant instruction.. 86059243Sobrien// It is absolute on most machines, and the constant is split on RISCs. 86159243Sobrien// The specific subtypes are oop, external_word, and internal_word. 86259243Sobrien// By convention, the "value" does not include a separately reckoned "offset". 86359243Sobrienclass DataRelocation : public Relocation { 864167465Smp public: 86559243Sobrien bool is_data() { return true; } 866167465Smp 867167465Smp // both target and offset must be computed somehow from relocation data 86859243Sobrien virtual int offset() { return 0; } 86959243Sobrien address value() = 0; 870195609Smp void set_value(address x) { set_value(x, offset()); } 87159243Sobrien void set_value(address x, intptr_t o) { 87259243Sobrien if (addr_in_const()) 87359243Sobrien *(address*)addr() = x; 87459243Sobrien else 87559243Sobrien pd_set_data_value(x, o); 87659243Sobrien } 87759243Sobrien void verify_value(address x) { 878167465Smp if (addr_in_const()) 87959243Sobrien assert(*(address*)addr() == x, "must agree"); 88059243Sobrien else 88159243Sobrien pd_verify_data_value(x, offset()); 88259243Sobrien } 88359243Sobrien 88459243Sobrien // The "o" (displacement) argument is relevant only to split relocations 88559243Sobrien // on RISC machines. In some CPUs (SPARC), the set-hi and set-lo ins'ns 88659243Sobrien // can encode more than 32 bits between them. This allows compilers to 88759243Sobrien // share set-hi instructions between addresses that differ by a small 888167465Smp // offset (e.g., different static variables in the same class). 88959243Sobrien // On such machines, the "x" argument to set_value on all set-lo 890145479Smp // instructions must be the same as the "x" argument for the 89159243Sobrien // corresponding set-hi instructions. The "o" arguments for the 89259243Sobrien // set-hi instructions are ignored, and must not affect the high-half 893167465Smp // immediate constant. The "o" arguments for the set-lo instructions are 894167465Smp // added into the low-half immediate constant, and must not overflow it. 89559243Sobrien}; 89659243Sobrien 897195609Smp// A CallRelocation always points at a call instruction. 89859243Sobrien// It is PC-relative on most machines. 89959243Sobrienclass CallRelocation : public Relocation { 90059243Sobrien public: 90159243Sobrien bool is_call() { return true; } 90259243Sobrien 90359243Sobrien address destination() { return pd_call_destination(); } 90459243Sobrien void set_destination(address x); // pd_set_call_destination 90559243Sobrien 90659243Sobrien void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); 90759243Sobrien address value() { return destination(); } 90859243Sobrien void set_value(address x) { set_destination(x); } 90959243Sobrien}; 91059243Sobrien 91159243Sobrienclass oop_Relocation : public DataRelocation { 91259243Sobrien relocInfo::relocType type() { return relocInfo::oop_type; } 91359243Sobrien 91459243Sobrien public: 91559243Sobrien // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll] 916167465Smp // an oop in the CodeBlob's oop pool 91759243Sobrien static RelocationHolder spec(int oop_index, int offset = 0) { 91859243Sobrien assert(oop_index > 0, "must be a pool-resident oop"); 91983098Smp RelocationHolder rh = newHolder(); 92083098Smp new(rh) oop_Relocation(oop_index, offset); 92183098Smp return rh; 92283098Smp } 92383098Smp // an oop in the instruction stream 92483098Smp static RelocationHolder spec_for_immediate() { 92583098Smp const int oop_index = 0; 92683098Smp const int offset = 0; // if you want an offset, use the oop pool 92783098Smp RelocationHolder rh = newHolder(); 92883098Smp new(rh) oop_Relocation(oop_index, offset); 929167465Smp return rh; 93083098Smp } 931167465Smp 932167465Smp private: 93383098Smp jint _oop_index; // if > 0, index into CodeBlob::oop_at 93483098Smp jint _offset; // byte offset to apply to the oop itself 935195609Smp 93683098Smp oop_Relocation(int oop_index, int offset) { 93783098Smp _oop_index = oop_index; _offset = offset; 93883098Smp } 939100616Smp 940100616Smp friend class RelocIterator; 94183098Smp oop_Relocation() { } 942100616Smp 943100616Smp public: 94483098Smp int oop_index() { return _oop_index; } 94583098Smp int offset() { return _offset; } 946167465Smp 94783098Smp // data is packed in "2_ints" format: [i o] or [Ii Oo] 94883098Smp void pack_data_to(CodeSection* dest); 94983098Smp void unpack_data(); 95059243Sobrien 95159243Sobrien void fix_oop_relocation(); // reasserts oop value 95259243Sobrien 95359243Sobrien void verify_oop_relocation(); 95459243Sobrien 95559243Sobrien address value() { return (address) *oop_addr(); } 956167465Smp 95759243Sobrien bool oop_is_immediate() { return oop_index() == 0; } 95859243Sobrien 95959243Sobrien oop* oop_addr(); // addr or &pool[jint_data] 96059243Sobrien oop oop_value(); // *oop_addr 96159243Sobrien // Note: oop_value transparently converts Universe::non_oop_word to NULL. 962167465Smp}; 96359243Sobrien 96459243Sobrien 96559243Sobrien// copy of oop_Relocation for now but may delete stuff in both/either 966167465Smpclass metadata_Relocation : public DataRelocation { 96759243Sobrien relocInfo::relocType type() { return relocInfo::metadata_type; } 96859243Sobrien 96959243Sobrien public: 970167465Smp // encode in one of these formats: [] [n] [n l] [Nn l] [Nn Ll] 97159243Sobrien // an metadata in the CodeBlob's metadata pool 97259243Sobrien static RelocationHolder spec(int metadata_index, int offset = 0) { 97359243Sobrien assert(metadata_index > 0, "must be a pool-resident metadata"); 97459243Sobrien RelocationHolder rh = newHolder(); 97559243Sobrien new(rh) metadata_Relocation(metadata_index, offset); 97659243Sobrien return rh; 97759243Sobrien } 97859243Sobrien // an metadata in the instruction stream 979167465Smp static RelocationHolder spec_for_immediate() { 98059243Sobrien const int metadata_index = 0; 98159243Sobrien const int offset = 0; // if you want an offset, use the metadata pool 98259243Sobrien RelocationHolder rh = newHolder(); 98359243Sobrien new(rh) metadata_Relocation(metadata_index, offset); 98459243Sobrien return rh; 985167465Smp } 98659243Sobrien 98759243Sobrien private: 98859243Sobrien jint _metadata_index; // if > 0, index into nmethod::metadata_at 98959243Sobrien jint _offset; // byte offset to apply to the metadata itself 99059243Sobrien 99159243Sobrien metadata_Relocation(int metadata_index, int offset) { 99259243Sobrien _metadata_index = metadata_index; _offset = offset; 99359243Sobrien } 994167465Smp 99559243Sobrien friend class RelocIterator; 99659243Sobrien metadata_Relocation() { } 99759243Sobrien 99859243Sobrien // Fixes a Metadata pointer in the code. Most platforms embeds the 999167465Smp // Metadata pointer in the code at compile time so this is empty 100059243Sobrien // for them. 100159243Sobrien void pd_fix_value(address x); 1002167465Smp 100359243Sobrien public: 100459243Sobrien int metadata_index() { return _metadata_index; } 100559243Sobrien int offset() { return _offset; } 100659243Sobrien 100759243Sobrien // data is packed in "2_ints" format: [i o] or [Ii Oo] 100859243Sobrien void pack_data_to(CodeSection* dest); 1009100616Smp void unpack_data(); 1010167465Smp 1011167465Smp void fix_metadata_relocation(); // reasserts metadata value 1012167465Smp 101359243Sobrien void verify_metadata_relocation(); 101459243Sobrien 101559243Sobrien address value() { return (address) *metadata_addr(); } 101659243Sobrien 101759243Sobrien bool metadata_is_immediate() { return metadata_index() == 0; } 101859243Sobrien 101959243Sobrien Metadata** metadata_addr(); // addr or &pool[jint_data] 102059243Sobrien Metadata* metadata_value(); // *metadata_addr 102159243Sobrien // Note: metadata_value transparently converts Universe::non_metadata_word to NULL. 102259243Sobrien}; 102359243Sobrien 102459243Sobrien 102559243Sobrienclass virtual_call_Relocation : public CallRelocation { 102659243Sobrien relocInfo::relocType type() { return relocInfo::virtual_call_type; } 102759243Sobrien 102859243Sobrien public: 102959243Sobrien // "cached_value" points to the first associated set-oop. 103059243Sobrien // The oop_limit helps find the last associated set-oop. 103159243Sobrien // (See comments at the top of this file.) 103259243Sobrien static RelocationHolder spec(address cached_value) { 103359243Sobrien RelocationHolder rh = newHolder(); 103459243Sobrien new(rh) virtual_call_Relocation(cached_value); 103559243Sobrien return rh; 103659243Sobrien } 103759243Sobrien 103859243Sobrien virtual_call_Relocation(address cached_value) { 103959243Sobrien _cached_value = cached_value; 1040167465Smp assert(cached_value != NULL, "first oop address must be specified"); 104159243Sobrien } 104259243Sobrien 1043231990Smp private: 104459243Sobrien address _cached_value; // location of set-value instruction 104559243Sobrien 104659243Sobrien friend class RelocIterator; 1047167465Smp virtual_call_Relocation() { } 104859243Sobrien 104959243Sobrien 105059243Sobrien public: 105159243Sobrien address cached_value(); 105259243Sobrien 105359243Sobrien // data is packed as scaled offsets in "2_ints" format: [f l] or [Ff Ll] 1054100616Smp // oop_limit is set to 0 if the limit falls somewhere within the call. 105559243Sobrien // When unpacking, a zero oop_limit is taken to refer to the end of the call. 105659243Sobrien // (This has the effect of bringing in the call's delay slot on SPARC.) 1057145479Smp void pack_data_to(CodeSection* dest); 1058145479Smp void unpack_data(); 1059145479Smp 1060145479Smp void clear_inline_cache(); 1061145479Smp}; 1062145479Smp 1063145479Smp 1064145479Smpclass opt_virtual_call_Relocation : public CallRelocation { 1065145479Smp relocInfo::relocType type() { return relocInfo::opt_virtual_call_type; } 1066145479Smp 1067145479Smp public: 106859243Sobrien static RelocationHolder spec() { 106959243Sobrien RelocationHolder rh = newHolder(); 107059243Sobrien new(rh) opt_virtual_call_Relocation(); 107159243Sobrien return rh; 107259243Sobrien } 107359243Sobrien 107459243Sobrien private: 107559243Sobrien friend class RelocIterator; 107659243Sobrien opt_virtual_call_Relocation() { } 107759243Sobrien 107859243Sobrien public: 107959243Sobrien void clear_inline_cache(); 108059243Sobrien 108159243Sobrien // find the matching static_stub 108259243Sobrien address static_stub(); 108359243Sobrien}; 108459243Sobrien 108559243Sobrien 108659243Sobrienclass static_call_Relocation : public CallRelocation { 108759243Sobrien relocInfo::relocType type() { return relocInfo::static_call_type; } 108859243Sobrien 108959243Sobrien public: 109059243Sobrien static RelocationHolder spec() { 109159243Sobrien RelocationHolder rh = newHolder(); 109259243Sobrien new(rh) static_call_Relocation(); 109359243Sobrien return rh; 1094167465Smp } 109559243Sobrien 109659243Sobrien private: 109759243Sobrien friend class RelocIterator; 109859243Sobrien static_call_Relocation() { } 109959243Sobrien 110059243Sobrien public: 1101167465Smp void clear_inline_cache(); 110259243Sobrien 110359243Sobrien // find the matching static_stub 1104145479Smp address static_stub(); 110559243Sobrien}; 110659243Sobrien 110759243Sobrienclass static_stub_Relocation : public Relocation { 110859243Sobrien relocInfo::relocType type() { return relocInfo::static_stub_type; } 110959243Sobrien 111059243Sobrien public: 111159243Sobrien static RelocationHolder spec(address static_call) { 111259243Sobrien RelocationHolder rh = newHolder(); 111359243Sobrien new(rh) static_stub_Relocation(static_call); 111459243Sobrien return rh; 111559243Sobrien } 111659243Sobrien 111759243Sobrien private: 111859243Sobrien address _static_call; // location of corresponding static_call 111959243Sobrien 112059243Sobrien static_stub_Relocation(address static_call) { 112159243Sobrien _static_call = static_call; 112259243Sobrien } 112359243Sobrien 112459243Sobrien friend class RelocIterator; 112559243Sobrien static_stub_Relocation() { } 112659243Sobrien 112759243Sobrien public: 112859243Sobrien void clear_inline_cache(); 112959243Sobrien 113059243Sobrien address static_call() { return _static_call; } 113159243Sobrien 113259243Sobrien // data is packed as a scaled offset in "1_int" format: [c] or [Cc] 113359243Sobrien void pack_data_to(CodeSection* dest); 113459243Sobrien void unpack_data(); 113559243Sobrien}; 113659243Sobrien 113759243Sobrienclass runtime_call_Relocation : public CallRelocation { 113859243Sobrien relocInfo::relocType type() { return relocInfo::runtime_call_type; } 113959243Sobrien 114059243Sobrien public: 114159243Sobrien static RelocationHolder spec() { 1142195609Smp RelocationHolder rh = newHolder(); 114359243Sobrien new(rh) runtime_call_Relocation(); 114459243Sobrien return rh; 114559243Sobrien } 114659243Sobrien 114759243Sobrien private: 114859243Sobrien friend class RelocIterator; 114959243Sobrien runtime_call_Relocation() { } 115059243Sobrien 115159243Sobrien public: 115259243Sobrien}; 115359243Sobrien 115459243Sobrien// Trampoline Relocations. 115559243Sobrien// A trampoline allows to encode a small branch in the code, even if there 115659243Sobrien// is the chance that this branch can not reach all possible code locations. 115759243Sobrien// If the relocation finds that a branch is too far for the instruction 115859243Sobrien// in the code, it can patch it to jump to the trampoline where is 115959243Sobrien// sufficient space for a far branch. Needed on PPC. 116059243Sobrienclass trampoline_stub_Relocation : public Relocation { 116159243Sobrien relocInfo::relocType type() { return relocInfo::trampoline_stub_type; } 116259243Sobrien 116359243Sobrien public: 116459243Sobrien static RelocationHolder spec(address static_call) { 1165167465Smp RelocationHolder rh = newHolder(); 116659243Sobrien return (new (rh) trampoline_stub_Relocation(static_call)); 116759243Sobrien } 1168167465Smp 116959243Sobrien private: 117059243Sobrien address _owner; // Address of the NativeCall that owns the trampoline. 117159243Sobrien 117259243Sobrien trampoline_stub_Relocation(address owner) { 1173167465Smp _owner = owner; 117459243Sobrien } 117583098Smp 1176167465Smp friend class RelocIterator; 117759243Sobrien trampoline_stub_Relocation() { } 117883098Smp 117983098Smp public: 118059243Sobrien 118159243Sobrien // Return the address of the NativeCall that owns the trampoline. 118259243Sobrien address owner() { return _owner; } 118359243Sobrien 118459243Sobrien void pack_data_to(CodeSection * dest); 118559243Sobrien void unpack_data(); 118659243Sobrien 118759243Sobrien // Find the trampoline stub for a call. 118859243Sobrien static address get_trampoline_for(address call, nmethod* code); 118959243Sobrien}; 119059243Sobrien 119159243Sobrienclass external_word_Relocation : public DataRelocation { 119259243Sobrien relocInfo::relocType type() { return relocInfo::external_word_type; } 119359243Sobrien 119459243Sobrien public: 119559243Sobrien static RelocationHolder spec(address target) { 119659243Sobrien assert(target != NULL, "must not be null"); 119759243Sobrien RelocationHolder rh = newHolder(); 119859243Sobrien new(rh) external_word_Relocation(target); 119959243Sobrien return rh; 120059243Sobrien } 120159243Sobrien 120259243Sobrien // Use this one where all 32/64 bits of the target live in the code stream. 120359243Sobrien // The target must be an intptr_t, and must be absolute (not relative). 120459243Sobrien static RelocationHolder spec_for_immediate() { 120559243Sobrien RelocationHolder rh = newHolder(); 120659243Sobrien new(rh) external_word_Relocation(NULL); 1207167465Smp return rh; 120859243Sobrien } 120959243Sobrien 1210145479Smp // Some address looking values aren't safe to treat as relocations 121159243Sobrien // and should just be treated as constants. 121259243Sobrien static bool can_be_relocated(address target) { 121359243Sobrien return target != NULL && !is_reloc_index((intptr_t)target); 121459243Sobrien } 121559243Sobrien 121659243Sobrien private: 121759243Sobrien address _target; // address in runtime 1218145479Smp 121959243Sobrien external_word_Relocation(address target) { 122059243Sobrien _target = target; 122159243Sobrien } 122259243Sobrien 122359243Sobrien friend class RelocIterator; 122459243Sobrien external_word_Relocation() { } 122559243Sobrien 122659243Sobrien public: 122759243Sobrien // data is packed as a well-known address in "1_int" format: [a] or [Aa] 122859243Sobrien // The function runtime_address_to_index is used to turn full addresses 122959243Sobrien // to short indexes, if they are pre-registered by the stub mechanism. 123059243Sobrien // If the "a" value is 0 (i.e., _target is NULL), the address is stored 123159243Sobrien // in the code stream. See external_word_Relocation::target(). 123259243Sobrien void pack_data_to(CodeSection* dest); 123359243Sobrien void unpack_data(); 123459243Sobrien 123559243Sobrien void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); 123659243Sobrien address target(); // if _target==NULL, fetch addr from code stream 123759243Sobrien address value() { return target(); } 123859243Sobrien}; 123959243Sobrien 124059243Sobrienclass internal_word_Relocation : public DataRelocation { 124159243Sobrien relocInfo::relocType type() { return relocInfo::internal_word_type; } 124259243Sobrien 124359243Sobrien public: 124459243Sobrien static RelocationHolder spec(address target) { 124559243Sobrien assert(target != NULL, "must not be null"); 124659243Sobrien RelocationHolder rh = newHolder(); 124759243Sobrien new(rh) internal_word_Relocation(target); 124859243Sobrien return rh; 124959243Sobrien } 125059243Sobrien 125159243Sobrien // use this one where all the bits of the target can fit in the code stream: 125259243Sobrien static RelocationHolder spec_for_immediate() { 125359243Sobrien RelocationHolder rh = newHolder(); 125459243Sobrien new(rh) internal_word_Relocation(NULL); 125559243Sobrien return rh; 125659243Sobrien } 125759243Sobrien 125859243Sobrien internal_word_Relocation(address target) { 125959243Sobrien _target = target; 126059243Sobrien _section = -1; // self-relative 126159243Sobrien } 126259243Sobrien 126359243Sobrien protected: 126459243Sobrien address _target; // address in CodeBlob 126559243Sobrien int _section; // section providing base address, if any 126659243Sobrien 126759243Sobrien friend class RelocIterator; 126859243Sobrien internal_word_Relocation() { } 126959243Sobrien 127059243Sobrien // bit-width of LSB field in packed offset, if section >= 0 127159243Sobrien enum { section_width = 2 }; // must equal CodeBuffer::sect_bits 127259243Sobrien 127359243Sobrien public: 127459243Sobrien // data is packed as a scaled offset in "1_int" format: [o] or [Oo] 127559243Sobrien // If the "o" value is 0 (i.e., _target is NULL), the offset is stored 127659243Sobrien // in the code stream. See internal_word_Relocation::target(). 127759243Sobrien // If _section is not -1, it is appended to the low bits of the offset. 1278167465Smp void pack_data_to(CodeSection* dest); 127959243Sobrien void unpack_data(); 128059243Sobrien 128159243Sobrien void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); 1282167465Smp address target(); // if _target==NULL, fetch addr from code stream 1283145479Smp int section() { return _section; } 1284167465Smp address value() { return target(); } 128559243Sobrien}; 1286167465Smp 1287167465Smpclass section_word_Relocation : public internal_word_Relocation { 128859243Sobrien relocInfo::relocType type() { return relocInfo::section_word_type; } 128959243Sobrien 129059243Sobrien public: 129159243Sobrien static RelocationHolder spec(address target, int section) { 129259243Sobrien RelocationHolder rh = newHolder(); 1293167465Smp new(rh) section_word_Relocation(target, section); 1294167465Smp return rh; 129559243Sobrien } 129659243Sobrien 1297167465Smp section_word_Relocation(address target, int section) { 1298167465Smp assert(target != NULL, "must not be null"); 129959243Sobrien assert(section >= 0, "must be a valid section"); 130059243Sobrien _target = target; 130159243Sobrien _section = section; 130259243Sobrien } 130359243Sobrien 130459243Sobrien //void pack_data_to -- inherited 130559243Sobrien void unpack_data(); 1306167465Smp 1307167465Smp private: 130859243Sobrien friend class RelocIterator; 130959243Sobrien section_word_Relocation() { } 131059243Sobrien}; 1311167465Smp 1312167465Smp 131359243Sobrienclass poll_Relocation : public Relocation { 131459243Sobrien bool is_data() { return true; } 131559243Sobrien relocInfo::relocType type() { return relocInfo::poll_type; } 1316167465Smp void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); 1317167465Smp}; 131859243Sobrien 131959243Sobrienclass poll_return_Relocation : public Relocation { 132059243Sobrien bool is_data() { return true; } 132159243Sobrien relocInfo::relocType type() { return relocInfo::poll_return_type; } 132259243Sobrien void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); 132359243Sobrien}; 132459243Sobrien 132559243Sobrien// We know all the xxx_Relocation classes, so now we can define these: 1326145479Smp#define EACH_CASE(name) \ 132759243Sobrieninline name##_Relocation* RelocIterator::name##_reloc() { \ 132859243Sobrien assert(type() == relocInfo::name##_type, "type must agree"); \ 132959243Sobrien /* The purpose of the placed "new" is to re-use the same */ \ 133059243Sobrien /* stack storage for each new iteration. */ \ 1331167465Smp name##_Relocation* r = new(_rh) name##_Relocation(); \ 1332167465Smp r->set_binding(this); \ 133359243Sobrien r->name##_Relocation::unpack_data(); \ 133459243Sobrien return r; \ 1335167465Smp} 1336167465SmpAPPLY_TO_RELOCATIONS(EACH_CASE); 1337167465Smp#undef EACH_CASE 1338167465Smp 133959243Sobrieninline RelocIterator::RelocIterator(nmethod* nm, address begin, address limit) { 134059243Sobrien initialize(nm, begin, limit); 134159243Sobrien} 134259243Sobrien 134359243Sobrien#endif // SHARE_VM_CODE_RELOCINFO_HPP 134459243Sobrien