void FSelfScope::initialize() { assert( isTop(), "can't inline yet"); // preallocate receiver, incoming args, locals self = receiver = IReceiverReg; allocs->allocatePermanent(receiver); { // Allocate space for arguments and count argument slots. nargs = 0; FOR_EACH_SLOTDESC_N(method()->map(), s, i) { args->append(UnAllocated); if (s->is_arg_slot()) { oop ind= s->data; assert_smi(ind, "bad index"); fint argIndex= smiOop(ind)->value(); allocs->allocatePermanent(IArgLocation(argIndex)); args->nthPut(i, IArgLocation(argIndex)); nargs++; } } }
oop frame::get_lookup_arg(fint index) { frame* f = sendee(); fint offset = spOffset(IArgLocation(index), f->frame_size()) / oopSize; return callees_sp()->as_oops()[offset]; }
void CodeGen::prologue(bool isAccessMethod, fint nargs ) { // *if not DI child // <smi/float/memOop prologue> // _verified: (entry point from PICs) // if necessary <check selector> // if necessary <check delegatee> // *endif DI // _diCheck: (entry point after recompile) // <verify assignable parents> // *if using recompilation // <checkRecompilation> // *endif // *if haveStackFrame // save sp, -frameSize*oopSize, sp // *endif // <flush register windows if neceessary> // <clear stack temporaries and excess argument locations // CAUTION: use only Temp1/4 for temps in prologue; other temps // may contain lookup parameters. assert(Temp1 != PerformSelectorLoc && Temp1 != PerformDelegateeLoc, "will trash lookup parameters"); assert(Temp2 != PerformSelectorLoc && Temp2 != PerformDelegateeLoc, "will trash lookup parameters"); fint assignableParents = L->adeps->length(); MethodKind kind = isAccessMethod ? MethodKind(-1) : theCompiler->method()->kind(); _incoming_arg_count = nargs; // for eventual putting into nmethod if (diLink == 0) { if (!L->isReceiverStatic()) { // test receiver map # if GENERATE_DEBUGGING_AIDS if (CheckAssertions) switch (L->lookupType()) { case NormalLookupType: break; case StaticNormalLookupType: case ImplicitSelfLookupType: case ResendLookupType: case DirectedResendLookupType: fatal("shouldn't miss"); break; default: break; } # endif Map* m = L->receiverMap(); bool imm = m == Memory->smi_map || m == Memory->float_map; if (SICCountTypeTests) { a.startTypeTest(1, true, imm); a.doOneTypeTest(); } if (m == Memory->smi_map) { smiOop_prologue(Memory->code->trapdoors->SendMessage_stub_td()); } else if (m == Memory->float_map) { floatOop_prologue(Memory->code->trapdoors->SendMessage_stub_td()); } else { memOop_prologue(Memory->code->trapdoors->SendMessage_stub_td()); } } verifiedOffset = a.offset(); if (SICCountTypeTests) a.endTypeTest(); Label generalMiss(a.printing, NULL); a.Comment("verified entry point:"); if (L->isPerform()) { a.Comment("check selector"); checkOop(generalMiss, L->selector(), PerformSelectorLoc); } if (needsDelegatee(L->lookupType()) && !L->isDelegateeStatic()) { a.Comment("check delegatee"); checkOop(generalMiss, L->delegatee(), PerformDelegateeLoc); } } else { // don't check receiver map, selector, delegatee if a DI cache miss assert(assignableParents > 0, "should have some di parents to check"); } diCheckOffset = a.offset(); a.Comment("DI entry point:"); if (assignableParents > 0) { a.Comment("verify state of assignable parents"); fint count = 0; for (fint i = 0; i < assignableParents; i ++) { objectLookupTarget* target = L->adeps->start()[i]; Location t = loadPath(Temp2, target, ReceiverReg, Temp1); count = verifyParents(target, t, count); } } bool recomp = needRecompileCode(theCompiler->level()); if (recomp) checkRecompilation(); if (haveStackFrame) { prologueAddr = a.addr(); a.SaveI(SP, -1, SP); // correct frame size is patched in later frameCreationOffset = a.offset(); } else { prologueAddr = NULL; } if (GenerateCountCode) { int32* counter; if (assignableParents != 0) { counter = &NumberOfDIMethodCalls; } else if (isAccessMethod) { counter = &NumberOfAccessMethodCalls; } else if (kind == BlockMethodType) { counter = &NumberOfBlockMethodCalls; } else { counter = &NumberOfMethodCalls; } genCountCode(counter); } if (!isAccessMethod) { if (!recomp && GenerateLRUCode) { // this code is rarely generated in practice (recomp is usually true) a.Comment("reset unused bit"); void* unused_addr = &LRUflag[Memory->code->nextNMethodID()]; a.SetHiA(unused_addr, Temp2); a.StoreA(Temp2, unused_addr, G0); } // don't keep uplevel-accessed names in regs // (for now, just flush everything) if (nargs > NumIArgRegisters) nargs = NumIArgRegisters; a.Comment("flush incoming args to stack"); for (fint i = 0; i < nargs; i++) { flushToStack(IArgLocation(i), NULL); } flushToStack(IReceiverReg, NULL); // flush receiver to stack switch (kind) { case BlockMethodType: if (theCompiler->needRegWindowFlushes) flushRegisterWindows(); break; case OuterMethodType: if (needToFlushRegWindow) { // we inlined the receiver block if (theCompiler->needRegWindowFlushes) flushRegisterWindows(); } else { // receiver is parent, do nothing } break; default: fatal1("unknown kind: %ld", kind); break; } } a.Comment("End Prologue"); }
Location frame::location_of_interpreter_of_block_scope(void* entry_point) { return entry_point == first_inst_addr(interpret) ? Location(IArgLocation(0)) : IllegalLocation; }