void BranchTable::append(address inst_addr, address caller_addr, address callee_addr, jint old_inst) { TTY_TRACE_IF_VERBOSE(("entering append\n")); GUARANTEE(inst_addr >= (address) _compiler_area_start && inst_addr <= (address) _compiler_area_top, "inst_addr sansity\n"); GUARANTEE(caller_addr, "sanity check"); GUARANTEE(callee_addr, "sanity check"); GUARANTEE(old_inst, "sanity check"); /*remove old element*/ if (_b_items[_item_index].inst_addr() != 0) { *(int*)(_b_items[_item_index].inst_addr()) = _b_items[_item_index].old_inst(); OsMisc_flush_icache(_b_items[_item_index].inst_addr(), 4); TTY_TRACE_IF_VERBOSE(("cover an old branch item\n")); } /*new value*/ _b_items[_item_index].set_inst_addr(inst_addr); _b_items[_item_index].set_caller_addr(caller_addr); _b_items[_item_index].set_callee_addr(callee_addr); _b_items[_item_index].set_old_inst(old_inst); TTY_TRACE_IF_VERBOSE(("inst addr = 0x%x, caller addr = 0x%x\n", *(int*) inst_addr, (int)caller_addr)); address target = callee_addr + CompiledMethodDesc::entry_offset(); int value; value =( target - (inst_addr + 8)) >> 2;/*assumption: log(target)<24*/ *(int*)(inst_addr) = (0xE << 28 | 0xA << 24 | (value & ((1<<24) - 1))); #if AZZERT GUARANTEE(*(juint*)(inst_addr) >> 24 ==0xEA, "sanity"); #endif OsMisc_flush_icache(inst_addr, 4); ++_item_index; _item_index &= BRANCH_TABLE_LENGTH - 1; TTY_TRACE_IF_VERBOSE(("leaving append\n")); }
void BranchTable::remove_only(address cm) { for (int i = 0; i < BRANCH_TABLE_LENGTH; i++) { if (_b_items[i].inst_addr() != 0 && _b_items[i].callee_addr() == cm) { *(int*)(_b_items[i].inst_addr()) = _b_items[i].old_inst(); OsMisc_flush_icache(_b_items[i].inst_addr(), 4); jvm_memset(&_b_items[i], 0, sizeof(BranchItem)); } } }
void BranchTable::remove() { TTY_TRACE_IF_VERBOSE(("entering remove\n")); for (int i = 0; i < BRANCH_TABLE_LENGTH; i++) { if (_b_items[i].inst_addr() != 0) { const CompiledMethodDesc* callee = (CompiledMethodDesc*)_b_items[i].callee_addr(); const CompiledMethodDesc* caller = (CompiledMethodDesc*)_b_items[i].caller_addr(); const int callee_index = callee->get_cache_index(); const int caller_index = caller->get_cache_index(); GUARANTEE(callee_index >= 0, "sanity"); GUARANTEE(caller_index >= 0, "sanity"); if (callee_index > CompiledMethodCache::get_upb() || caller_index > CompiledMethodCache::get_upb() || CompiledMethodCache::get_item(callee_index) != callee || CompiledMethodCache::get_item(caller_index) != caller)//means removed { GUARANTEE(_b_items[i].inst_addr() >= (address) _compiler_area_start && _b_items[i].inst_addr() <= (address) _compiler_area_top, "sansity\n"); { TTY_TRACE_IF_VERBOSE(("static removed\n")); TTY_TRACE_IF_VERBOSE(("remove: inst_addr = 0x%x, index = %d\n", (int) _b_items[i].inst_addr(), i)); GUARANTEE(*(juint*)(_b_items[i].inst_addr()) >> 24 ==0xEA, "sanity"); *(int*)(_b_items[i].inst_addr()) = _b_items[i].old_inst(); OsMisc_flush_icache(_b_items[i].inst_addr(), 4); } jvm_memset(&_b_items[i], 0, sizeof(BranchItem)); TTY_TRACE_IF_VERBOSE(("removed index %d\n", i)); } else { GUARANTEE(_b_items[i].inst_addr() >= (address) _compiler_area_start && _b_items[i].inst_addr() <= (address) _compiler_area_top, "sansity\n"); address old_caller_addr = _b_items[i].caller_addr(); address old_callee_addr = _b_items[i].callee_addr(); jint caller_shift = (int) ((MethodDesc*) old_caller_addr)->_klass; if ( caller_shift!= 0) { _b_items[i].set_caller_addr(old_caller_addr + caller_shift); TTY_TRACE_IF_VERBOSE(("adjusted caller\n")); } jint callee_shift = (int) ((MethodDesc*) old_callee_addr)->_klass; if ( callee_shift != 0) { _b_items[i].set_callee_addr(old_callee_addr + callee_shift); TTY_TRACE_IF_VERBOSE(("adjusted callee\n")); } { int offset = callee_shift - caller_shift; TTY_TRACE_IF_VERBOSE(("adjust: inst_addr = 0x%x, index = %d\n", (int) _b_items[i].inst_addr(), i)); GUARANTEE(*(juint*)(_b_items[i].inst_addr()) >> 24 ==0xEA, "sanity"); if (offset != 0) { TTY_TRACE_IF_VERBOSE(("adjusted index %d\n", i)); int* inst_addr = (int*) (_b_items[i].inst_addr()); int current_target = *inst_addr & ((1<<24) - 1); current_target <<= 8; /*lsl*/ current_target >>= 6; /*asr*/ current_target += offset; current_target >>=2; current_target &= ((1<<24) - 1); *inst_addr &= ~((1<<24) - 1); *inst_addr |= current_target; TTY_TRACE_IF_VERBOSE(("static adjusted\n")); OsMisc_flush_icache((address) inst_addr, 4); } _b_items[i].set_inst_addr(_b_items[i].inst_addr() + caller_shift); TTY_TRACE_IF_VERBOSE(("adjusted index %d\n", i)); } }
void CompiledMethod::flush_icache() { // Eventually, we can get rid of the relocation OsMisc_flush_icache(entry(), size()); }