// 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()); } }
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; }
// 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()); }