void ComparingStub::init(nmethod* nm) { CountCodePattern* patt = CountStub::pattern[Comparing]; int32* p = (int32*)insts(); set_recompile_addr(Memory->code->trapdoors->Recompile_stub_td()); set_count_addr(patt, (int32)&sendCounts[id()]); assert(isSetHi(p + patt->limit_sethi_offset), "wrong pattern"); fint limit = recompileLimit(nm->level()); setSetHiImm(p + patt->limit_sethi_offset, limit); }
void ComparingStub::init(nmethod* nm) { CountCodePattern* patt = CountStub::pattern[Comparing]; set_recompile_addr((pc_t)Recompile_stub); set_count_addr(patt, (int32)&sendCounts[id()]); int32* p = (int32*)(int32(insts()) + patt->limit_offset); assert(*p == patt->initial_limit, "???"); fint limit = recompileLimit(nm->level()); *p = limit; }
void nmethod::flushPartially() { # ifdef SIC_COMPILER oldCount = min(recompileLimit(level()), invocationCount()); # else oldCount = invocationCount(); # endif useCount[id] = 0; removeFromCodeTable(); diLink.remove(); save_unlinked_frame_chain(); // protect from accidental flushing if (!UsePICRecompilation) { flush(); // also flush the inline caches } assert(frame_chain != NoFrameChain, "frames should be chained now"); }
void CodeGen::checkRecompilation() { a.Comment("checkRecompilation"); // di recompilation doesn't work right now - see recompile.c if (diLink) return; a.Comment("test for recompilation"); int32 countID = theCompiler->countID; void* counter = &useCount[countID]; a.leal(no_reg, int32(counter), VMAddressOperand, Temp2); a.movl(Temp2, 0, NumberOperand, Temp1); a.incl(Temp1); a.movl(Temp1, Temp2, 0, NumberOperand); fint limit = recompileLimit(theCompiler->level()); // compare to limit a.cmpl(limit, NumberOperand, Temp1); Label ok; a.jne(&ok); // (no frame yet) // Pass a link to caller's sendDesc in LinkReg. // Pass a link to callee (i.e. this code being generated) in RecompileLinkReg // pass original return pc in normal place, push extra return pc on stack // call recompiler int32 fnaddr = diLink ? (int32)DIRecompile_stub : (int32)Recompile_stub; a.call(fnaddr, PVMAddressOperand); a.hlt(); // we don't return here from Recompile_stub. Recompile_stub jumps to new method if // we do on-stack replacement. if we don't do on-stack replacement, it returns directly // to the verified entry point in the nmethod. -mabdelmalek 12/5/2002 ok.define(); }
void CodeGen::checkRecompilation() { // test for recompilation // sethi &counter, t3 // load [t3 + lo%(&counter)], t4 // add t4, 1, t4 // cmp t4, recompileLimit // bne ok // store t4, [t3 + lo%(&counter)] // <jumpTo recompiler> // nop // ok: // di recompilation doesn't work right now - see recompile.c if (diLink) return; a.Comment("test for recompilation"); int32 countID = theCompiler->countID; void* counter = &useCount[countID]; a.SetHiA(counter, Temp3); a.LoadA(Temp3, counter, Temp2); a.AddI(Temp2, 1, Temp2); fint limit = recompileLimit(theCompiler->level()); if (limit < maxImmediate) { a.SubCCI(Temp2, limit, G0); } else { a.SetHiI2(limit, Temp1); // limit is multiple of 1024 a.SubCCR(Temp2, Temp1, G0); } Label* ok = a.BneForward(false); // call recompiler void* fnaddr = diLink ? Memory->code->trapdoors->DIRecompile_stub_td() : Memory->code->trapdoors-> Recompile_stub_td(); Location linkReg = diLink ? DIRecompileLinkReg : RecompileLinkReg; jumpTo(fnaddr, linkReg, linkReg); // The store below is always executed so that we will call the recompiler // exactly once (even if it cannot recompile for some reason). ok->define(); assert(Temp3 != linkReg, "counter addr reg will be trashed by jump"); a.StoreA(Temp3, counter, Temp2); }
void SICGenHelper::checkRecompilation(fint countID) { // test for recompilation // sethi &counter, t3 // load [t3 + lo%(&counter)], t4 // add t4, 1, t4 // cmp t4, recompileLimit // bne ok // store t4, [t3 + lo%(&counter)] // <jumpTo recompiler> // nop // ok: // di recompilation doesn't work right now - see recompile.c if (theSIC->diLink) return; Assembler* ass = theAssembler; ass->Comment("test for recompilation"); void* counter = &useCount[countID]; ass->SetHiA(counter, Temp3); ass->LoadA(Temp3, counter, Temp2); ass->AddI(Temp2, 1, Temp2); fint limit = recompileLimit(0); if (limit < maxImmediate) { ass->SubCCI(Temp2, limit, G0); } else { ass->SetHiI2(limit, Temp1); // limit is multiple of 1024 ass->SubCCR(Temp2, Temp1, G0); } Label* ok = ass->BneForward(false); // call recompiler void* fnaddr = first_inst_addr( theSIC->diLink ? Memory->zone->DIRecompile_stub_td() : Memory->zone-> Recompile_stub_td() ); Location linkReg = theSIC->diLink ? DIRecompileLinkReg : RecompileLinkReg; jumpTo(fnaddr, linkReg, linkReg); // The store below is always executed so that we will call the recompiler // exactly once (even if it cannot recompile for some reason). ok->define(); assert(Temp3 != linkReg, "counter addr reg will be trashed by jump"); ass->StoreA(Temp3, counter, Temp2); }
bool nmethod::shouldNotRecompile() { # ifdef SIC_COMPILER if (compiler() == NIC) return false; if (level() == MaxRecompilationLevels - 1) return true; // no optimizable sends if (isYoung()) { if (invocationCount() > agingLimit() && flags.trapCount < MapLoadTrapLimit) { // isn't really young anymore (but didn't trigger counter because it // has several callers) makeOld(); } else if (nsends() > max(recompileLimit(0), 4 * agingLimit())) { // does a lot of sends - give it a chance anyway } else { // don't recompile yet - too young // but mark it for later recompilation makeToBeRecompiled(); return true; } } # endif return false; }