relocInfo_s390.cpp revision 12314:17a959a33da5
1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2016 SAP SE. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26#include "precompiled.hpp" 27#include "asm/assembler.inline.hpp" 28#include "code/relocInfo.hpp" 29#include "nativeInst_s390.hpp" 30#include "oops/oop.inline.hpp" 31#include "runtime/safepoint.hpp" 32 33void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { 34 // we don't support splitting of relocations, so o must be zero: 35 assert(o == 0, "tried to split relocations"); 36 if (!verify_only) { 37 switch (format()) { 38 case relocInfo::uncompressed_format: 39 nativeMovConstReg_at(addr())->set_data_plain(((intptr_t)x) + o, code()); 40 break; 41 case relocInfo::compressed_format: 42 if (type() == relocInfo::metadata_type) 43 nativeMovConstReg_at(addr())->set_narrow_klass(((intptr_t)x) + o); 44 else if (type() == relocInfo::oop_type) 45 nativeMovConstReg_at(addr())->set_narrow_oop(((intptr_t)x) + o); 46 else 47 guarantee(false, "bad relocInfo type for relocInfo::narrow_oop_format"); 48 break; 49 case relocInfo::pcrel_addr_format: // patch target location 50 nativeMovConstReg_at(addr())->set_pcrel_addr(((intptr_t)x) + o, code()); 51 break; 52 case relocInfo::pcrel_data_format: // patch data at target location 53 nativeMovConstReg_at(addr())->set_pcrel_data(((intptr_t)x) + o, code()); 54 break; 55 default: 56 assert(false, "not a valid relocInfo format"); 57 break; 58 } 59 } else { 60 // TODO: Reading of narrow oops out of code stream is not implemented 61 // (see nativeMovConstReg::data()). Implement this if you want to verify. 62 // assert(x == (address) nativeMovConstReg_at(addr())->data(), "Instructions must match"); 63 switch (format()) { 64 case relocInfo::uncompressed_format: 65 break; 66 case relocInfo::compressed_format: 67 break; 68 case relocInfo::pcrel_addr_format: 69 break; 70 case relocInfo::pcrel_data_format: 71 break; 72 default: 73 assert(false, "not a valid relocInfo format"); 74 break; 75 } 76 } 77} 78 79address Relocation::pd_call_destination(address orig_addr) { 80 address inst_addr = addr(); 81 82 if (NativeFarCall::is_far_call_at(inst_addr)) { 83 if (!ShortenBranches) { 84 if (MacroAssembler::is_call_far_pcrelative(inst_addr)) { 85 address a1 = MacroAssembler::get_target_addr_pcrel(orig_addr+MacroAssembler::nop_size()); 86#ifdef ASSERT 87 address a2 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size()); 88 address a3 = nativeFarCall_at(orig_addr)->destination(); 89 address a4 = nativeFarCall_at(inst_addr)->destination(); 90 if ((a1 != a3) || (a2 != a4)) { 91 unsigned int range = 128; 92 Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?"); 93 Assembler::dump_code_range(tty, orig_addr, range, "pc-relative call w/o ShortenBranches?"); 94 assert(false, "pc-relative call w/o ShortenBranches?"); 95 } 96#endif 97 return a1; 98 } 99 return (address)(-1); 100 } 101 NativeFarCall* call; 102 if (orig_addr == NULL) { 103 call = nativeFarCall_at(inst_addr); 104 } else { 105 // must access location (in CP) where destination is stored in unmoved code, because load from CP is pc-relative 106 call = nativeFarCall_at(orig_addr); 107 } 108 return call->destination(); 109 } 110 111 if (NativeCall::is_call_at(inst_addr)) { 112 NativeCall* call = nativeCall_at(inst_addr); 113 if (call->is_pcrelative()) { 114 intptr_t off = inst_addr - orig_addr; 115 return (address) (call->destination()-off); 116 } 117 } 118 119 return (address) nativeMovConstReg_at(inst_addr)->data(); 120} 121 122void Relocation::pd_set_call_destination(address x) { 123 address inst_addr = addr(); 124 125 if (NativeFarCall::is_far_call_at(inst_addr)) { 126 if (!ShortenBranches) { 127 if (MacroAssembler::is_call_far_pcrelative(inst_addr)) { 128 address a1 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size()); 129#ifdef ASSERT 130 address a3 = nativeFarCall_at(inst_addr)->destination(); 131 if (a1 != a3) { 132 unsigned int range = 128; 133 Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?"); 134 assert(false, "pc-relative call w/o ShortenBranches?"); 135 } 136#endif 137 nativeFarCall_at(inst_addr)->set_destination(x, 0); 138 return; 139 } 140 assert(x == (address)-1, "consistency check"); 141 return; 142 } 143 int toc_offset = -1; 144 if (type() == relocInfo::runtime_call_w_cp_type) { 145 toc_offset = ((runtime_call_w_cp_Relocation *)this)->get_constant_pool_offset(); 146 } 147 if (toc_offset>=0) { 148 NativeFarCall* call = nativeFarCall_at(inst_addr); 149 call->set_destination(x, toc_offset); 150 return; 151 } 152 } 153 154 if (NativeCall::is_call_at(inst_addr)) { 155 NativeCall* call = nativeCall_at(inst_addr); 156 if (call->is_pcrelative()) { 157 call->set_destination_mt_safe(x); 158 return; 159 } 160 } 161 162 // constant is absolute, must use x 163 nativeMovConstReg_at(inst_addr)->set_data(((intptr_t)x)); 164} 165 166 167// store the new target address into an oop_Relocation cell, if any 168// return indication if update happened. 169bool relocInfo::update_oop_pool(address begin, address end, address newTarget, CodeBlob* cb) { 170 171 // Try to find the CodeBlob, if not given by caller 172 if (cb == NULL) cb = CodeCache::find_blob(begin); 173#ifdef ASSERT 174 else 175 assert(cb == CodeCache::find_blob(begin), "consistency"); 176#endif 177 178 // 'RelocIterator' requires an nmethod 179 nmethod* nm = cb ? cb->as_nmethod_or_null() : NULL; 180 if (nm != NULL) { 181 RelocIterator iter(nm, begin, end); 182 oop* oop_addr = NULL; 183 Metadata** metadata_addr = NULL; 184 while (iter.next()) { 185 if (iter.type() == relocInfo::oop_type) { 186 oop_Relocation *r = iter.oop_reloc(); 187 if (oop_addr == NULL) { 188 oop_addr = r->oop_addr(); 189 *oop_addr = (oop)newTarget; 190 } else { 191 assert(oop_addr == r->oop_addr(), "must be only one set-oop here"); 192 } 193 } 194 if (iter.type() == relocInfo::metadata_type) { 195 metadata_Relocation *r = iter.metadata_reloc(); 196 if (metadata_addr == NULL) { 197 metadata_addr = r->metadata_addr(); 198 *metadata_addr = (Metadata*)newTarget; 199 } else { 200 assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here"); 201 } 202 } 203 } 204 return oop_addr || metadata_addr; 205 } 206 return false; 207} 208 209 210address* Relocation::pd_address_in_code() { 211 ShouldNotReachHere(); 212 return 0; 213} 214 215address Relocation::pd_get_address_from_code() { 216 return (address) (nativeMovConstReg_at(addr())->data()); 217} 218 219void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { 220} 221 222void metadata_Relocation::pd_fix_value(address x) { 223} 224