void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) { address pc = (address) inst; if (inst->is_call()) { // NOTE: for call without a mov, the offset must fit a 32-bit immediate // see also CompilerToVM.getMaxCallTargetOffset() NativeCall* call = nativeCall_at(pc); call->set_destination((address) foreign_call_destination); _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); } else if (inst->is_mov_literal64()) { NativeMovConstReg* mov = nativeMovConstReg_at(pc); mov->set_data((intptr_t) foreign_call_destination); _instructions->relocate(mov->instruction_address(), runtime_call_Relocation::spec(), Assembler::imm_operand); } else if (inst->is_jump()) { NativeJump* jump = nativeJump_at(pc); jump->set_jump_destination((address) foreign_call_destination); _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec(), Assembler::call32_operand); } else if (inst->is_cond_jump()) { address old_dest = nativeGeneralJump_at(pc)->jump_destination(); address disp = Assembler::locate_operand(pc, Assembler::call32_operand); *(jint*) disp += ((address) foreign_call_destination) - old_dest; _instructions->relocate(pc, runtime_call_Relocation::spec(), Assembler::call32_operand); } else { JVMCI_ERROR("unsupported relocation for foreign call"); } TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); }
// Release the CompiledICHolder* associated with this call site is there is one. void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site) { // This call site might have become stale so inspect it carefully. NativeCall* call = nativeCall_at(call_site->addr()); if (is_icholder_entry(call->destination())) { NativeMovConstReg* value = nativeMovConstReg_at(call_site->cached_value()); InlineCacheBuffer::queue_for_release((CompiledICHolder*)value->data()); } }
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, TRAPS) { address pc = (address) inst; if (inst->is_call()) { NativeCall* call = nativeCall_at(pc); call->set_destination((address) foreign_call_destination); _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); } else if (inst->is_sethi()) { NativeJump* jump = nativeJump_at(pc); jump->set_jump_destination((address) foreign_call_destination); _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); } else { JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)); } TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); }
inline void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) { address pc = (address) inst; if (inst->is_call()) { NativeCall* call = nativeCall_at(pc); call->set_destination((address) foreign_call_destination); _instructions->relocate(call->instruction_address(), runtime_call_Relocation::spec()); } else if (inst->is_sethi()) { NativeJump* jump = nativeJump_at(pc); jump->set_jump_destination((address) foreign_call_destination); _instructions->relocate(jump->instruction_address(), runtime_call_Relocation::spec()); } else { fatal(err_msg("unknown call or jump instruction at %p", pc)); } TRACE_graal_3("relocating (foreign call) at %p", inst); }
void Relocation::pd_set_call_destination(address x) { if (NativeCall::is_call_at(addr())) { NativeCall* call = nativeCall_at(addr()); call->set_destination(x); return; } if (NativeFarCall::is_call_at(addr())) { NativeFarCall* call = nativeFarCall_at(addr()); call->set_destination(x); return; } // Special case: Patchable branch local to the code cache. // This will break badly if the code cache grows larger than a few Mb. NativeGeneralJump* br = nativeGeneralJump_at(addr()); br->set_jump_destination(x); }
void Relocation::pd_set_call_destination(address x) { address inst_loc = addr(); if (NativeFarCall::is_far_call_at(inst_loc)) { NativeFarCall* call = nativeFarCall_at(inst_loc); call->set_destination(x); } else if (NativeJump::is_jump_at(inst_loc)) { NativeJump* jump= nativeJump_at(inst_loc); jump->set_jump_destination(x); } else if (NativeConditionalFarBranch::is_conditional_far_branch_at(inst_loc)) { NativeConditionalFarBranch* branch = NativeConditionalFarBranch_at(inst_loc); branch->set_branch_destination(x); } else { NativeCall* call = nativeCall_at(inst_loc); call->set_destination_mt_safe(x, false); } }
void Relocation::pd_set_call_destination(address x) { address inst_addr = addr(); if (NativeFarCall::is_far_call_at(inst_addr)) { if (!ShortenBranches) { if (MacroAssembler::is_call_far_pcrelative(inst_addr)) { address a1 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size()); #ifdef ASSERT address a3 = nativeFarCall_at(inst_addr)->destination(); if (a1 != a3) { unsigned int range = 128; Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?"); assert(false, "pc-relative call w/o ShortenBranches?"); } #endif nativeFarCall_at(inst_addr)->set_destination(x, 0); return; } assert(x == (address)-1, "consistency check"); return; } int toc_offset = -1; if (type() == relocInfo::runtime_call_w_cp_type) { toc_offset = ((runtime_call_w_cp_Relocation *)this)->get_constant_pool_offset(); } if (toc_offset>=0) { NativeFarCall* call = nativeFarCall_at(inst_addr); call->set_destination(x, toc_offset); return; } } if (NativeCall::is_call_at(inst_addr)) { NativeCall* call = nativeCall_at(inst_addr); if (call->is_pcrelative()) { call->set_destination_mt_safe(x); return; } } // constant is absolute, must use x nativeMovConstReg_at(inst_addr)->set_data(((intptr_t)x)); }
address Relocation::pd_call_destination(address orig_addr) { address inst_addr = addr(); if (NativeFarCall::is_far_call_at(inst_addr)) { if (!ShortenBranches) { if (MacroAssembler::is_call_far_pcrelative(inst_addr)) { address a1 = MacroAssembler::get_target_addr_pcrel(orig_addr+MacroAssembler::nop_size()); #ifdef ASSERT address a2 = MacroAssembler::get_target_addr_pcrel(inst_addr+MacroAssembler::nop_size()); address a3 = nativeFarCall_at(orig_addr)->destination(); address a4 = nativeFarCall_at(inst_addr)->destination(); if ((a1 != a3) || (a2 != a4)) { unsigned int range = 128; Assembler::dump_code_range(tty, inst_addr, range, "pc-relative call w/o ShortenBranches?"); Assembler::dump_code_range(tty, orig_addr, range, "pc-relative call w/o ShortenBranches?"); assert(false, "pc-relative call w/o ShortenBranches?"); } #endif return a1; } return (address)(-1); } NativeFarCall* call; if (orig_addr == NULL) { call = nativeFarCall_at(inst_addr); } else { // must access location (in CP) where destination is stored in unmoved code, because load from CP is pc-relative call = nativeFarCall_at(orig_addr); } return call->destination(); } if (NativeCall::is_call_at(inst_addr)) { NativeCall* call = nativeCall_at(inst_addr); if (call->is_pcrelative()) { intptr_t off = inst_addr - orig_addr; return (address) (call->destination()-off); } } return (address) nativeMovConstReg_at(inst_addr)->data(); }
address Relocation::pd_call_destination(address orig_addr) { intptr_t adj = 0; if (orig_addr != NULL) { // We just moved this call instruction from orig_addr to addr(). // This means its target will appear to have grown by addr() - orig_addr. adj = -( addr() - orig_addr ); } if (NativeCall::is_call_at(addr())) { NativeCall* call = nativeCall_at(addr()); return call->destination() + adj; } if (NativeFarCall::is_call_at(addr())) { NativeFarCall* call = nativeFarCall_at(addr()); return call->destination() + adj; } // Special case: Patchable branch local to the code cache. // This will break badly if the code cache grows larger than a few Mb. NativeGeneralJump* br = nativeGeneralJump_at(addr()); return br->jump_destination() + adj; }
void CodeInstaller::pd_relocate_JavaMethod(Handle hotspot_method, jint pc_offset, TRAPS) { #ifdef ASSERT Method* method = NULL; // we need to check, this might also be an unresolved method if (hotspot_method->is_a(HotSpotResolvedJavaMethodImpl::klass())) { method = getMethodFromHotSpotMethod(hotspot_method()); } #endif switch (_next_call_type) { case INLINE_INVOKE: break; case INVOKEVIRTUAL: case INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc), Assembler::call32_operand); break; } case INVOKESTATIC: { assert(method == NULL || method->is_static(), "cannot call non-static method with invokestatic"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); break; } case INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); break; } default: JVMCI_ERROR("invalid _next_call_type value"); break; } }
// Code for unit testing implementation of NativeCall class void NativeCall::test() { #ifdef ASSERT ResourceMark rm; CodeBuffer cb("test", 100, 100); MacroAssembler* a = new MacroAssembler(&cb); NativeCall *nc; uint idx; int offsets[] = { 0x0, 0xfffffff0, 0x7ffffff0, 0x80000000, 0x20, 0x4000, }; VM_Version::allow_all(); a->call( a->pc(), relocInfo::none ); a->delayed()->nop(); nc = nativeCall_at( cb.insts_begin() ); nc->print(); nc = nativeCall_overwriting_at( nc->next_instruction_address() ); for (idx = 0; idx < ARRAY_SIZE(offsets); idx++) { nc->set_destination( cb.insts_begin() + offsets[idx] ); assert(nc->destination() == (cb.insts_begin() + offsets[idx]), "check unit test"); nc->print(); } nc = nativeCall_before( cb.insts_begin() + 8 ); nc->print(); VM_Version::revert(); #endif }
bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) { // This call site might have become stale so inspect it carefully. NativeCall* call = nativeCall_at(call_site->addr()); return is_icholder_entry(call->destination()); }