void Countdown::select_timeout(Handler * s, int timeout) { iterator & pos = s->m_iter_timo; if (timeout < 0) // remove { if (isRegister(pos)) { m_falls[pos->fallidx].erase(pos); pos = null_iter(); } return; } size_t newidx = find_fall_idx(timeout); timeout += m_falls[newidx].m_elasped; if (!isRegister(pos)) // not register, first time pos = m_falls[newidx].insert(Timeout((int)newidx, s, timeout)); else { if (size_t(pos->fallidx) != newidx) { m_falls[newidx].splice(m_falls[pos->fallidx].m_list, pos); pos->fallidx = (int)newidx; } pos->count = timeout; } DUMP_SELECT(); }
void CodeGen::move(Location dest, Location src, Location tempReg, bool setcc) { Location b; int32 d; OperandType t; if (dest == src) { if (setcc) { reg_disp_type_of_loc(&b, &d, &t, src); a.testl(AllBits, NumberOperand, b, d, t); } } else if (isRegister(dest)) { reg_disp_type_of_loc(&b, &d, &t, src); a.movl(b,d, t, dest); if (setcc) a.testl(dest, dest); } else if (isRegister(src)) { reg_disp_type_of_loc(&b, &d, &t, dest); if (setcc) a.testl(src, src); a.movl(src, b,d, t); } else if (!isRegister(tempReg)) { reg_disp_type_of_loc(&b, &d, &t, src); a.pushl(b, d, t); reg_disp_type_of_loc(&b, &d, &t, dest); a.popl(b, d, t); if (setcc) a.testl(AllBits, NumberOperand, b, d, t); } else { reg_disp_type_of_loc(&b, &d, &t, src); a.movl(b, d, t, tempReg); reg_disp_type_of_loc(&b, &d, &t, dest); if (setcc) a.testl(tempReg, tempReg); a.movl(tempReg, b, d, t); } }
void CodeGen::loadOop(Location dest, Location src, slotDesc* s) { a.Comment("loadOop1"); int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; Location t = isRegister(src) ? src : dest != Temp1 ? Temp1 : Temp2; Location tt = isRegister(dest) ? dest : src != Temp1 ? Temp1 : Temp2; move(t, src); a.movl(t, offset, NumberOperand, tt); move(dest, tt); }
void AbstractArrayAtNode::gen() { BasicNode::gen(); Label* argFail = NULL; // if arg isn't a smi Label* indexFail = NULL; // if arg is out of bounds Assembler* a = theAssembler; Location arr = genHelper->moveToReg(_src, Temp2); Location index = genHelper->moveToReg(arg, Temp1); Location size = Temp3; // load array size now (avoids load interlock for range check) a->LoadI(arr, sizeOffset, size); if (!intArg) { // CP may have propagated a constant into arg intArg = arg->isConstPReg() && ((ConstPReg*)arg)->constant->is_smi(); } if (!intArg) { // test arg for smiOop if (SICCountTypeTests) { a->startTypeTest(1, false, true); a->doOneTypeTest(); } if (SICCountIntTagTests) a->markTagTest(1); a->AndCCI(index, Tag_Mask, G0); argFail = argFail->unify(a->BneForward(false)); if (SICCountTypeTests) a->endTypeTest(); } argFail = argFail->unify(testArg2()); a->SubCCR(index, size, G0); indexFail = a->BgeuForward(false); Location res = isRegister(_dest->loc) ? _dest->loc : Temp1; bool needDestStore = genAccess(arr, index, res); if (needDestStore && !isRegister(_dest->loc)) { genHelper->moveRegToLoc(res, _dest->loc); } Label* done = a->BraForward(true); MergeNode* failMerge = (MergeNode*)next1(); if (argFail) { argFail->define(); if (error) { Location err = isRegister(error->loc) ? error->loc : Temp1; genHelper->loadImmediateOop(VMString[BADTYPEERROR], err); if (err != error->loc) genHelper->moveRegToLoc(err, error->loc); } if (failMerge) // test added by dmu 4/27/96 failMerge->l = failMerge->l->unify(a->BraForward(true)); } indexFail->define(); if (error) { Location err = isRegister(error->loc) ? error->loc : Temp1; genHelper->loadImmediateOop(VMString[BADINDEXERROR], err); if (err != error->loc) genHelper->moveRegToLoc(err, error->loc); } if (failMerge) // test added by dmu 4/27/96 failMerge->l = failMerge->l->unify(a->BraForward(true)); done->define(); }
void CodeGen::assignment(Location receiver, slotDesc* s, Location val) { // this one called for impl self, arg on stack a.Comment("Begin Simple Assignment"); assert(!isRegister(receiver) && !isRegister(val), "called from genReceiverDataAccess, rcvr is self, val is arg or local, check this so I can use Temp[12]"); move(Temp2, receiver); int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; a.leal(Temp2, offset, NumberOperand, Temp2); // store object data slot contents move(Temp1, val); a.movl(Temp1, Temp2, 0, NumberOperand); // store object data slot contents recordStore(Temp2); // NB: recordStore will clobber Temp2 till I put in ByteMapBaseReg a.Comment("End Simple Assignment"); }
void LoadIntNode::gen() { BasicNode::gen(); if (isRegister(_dest->loc) && isImmediate(smiOop(value))) { theAssembler->OrI(G0, value, _dest->loc); // common case } else if (isRegister(_dest->loc)) { theAssembler->SetHiI(value, _dest->loc); theAssembler->AddI(_dest->loc, value, _dest->loc); } else { theAssembler->SetHiI(value, Temp1); theAssembler->AddI(Temp1, value, Temp1); theAssembler->StoreI(SP, spOffset(_dest->loc), Temp1); } }
RegisterString registerMaskBit(Location l, fint stackLocs, fint nonRegisterArgs) { if (isRegister(l)) { if (l >= I0 && l < I0 + NumInRegisters) { // an in register return nthBit(l - I0 + NumLocalRegisters); } else { assert(l >= L0 && l < L0 + NumLocalRegisters, "unexpected register"); return nthBit(l - L0); } } else if (isStackRegister(l)) { l = Location(l - StackLocations); if (l < BitsPerWord - (NumInRegisters + NumLocalRegisters)) { return nthBit(l + NumInRegisters + NumLocalRegisters); } } else if (isExtraArgRegister(l)) { fint which = ExtraArgLocations - l; assert(which <= nonRegisterArgs, "nonRegisterArgs too small"); which = stackLocs + (nonRegisterArgs - which); // translate into stack temp assert(which >= 0, "should be non-negative"); if (which < BitsPerWord - (NumInRegisters + NumLocalRegisters)) { return nthBit(which + NumInRegisters + NumLocalRegisters); } } return 0; }
void CodeGen::loadOop(Location dest, Location src_register, slotDesc* s) { Location t = isRegister(dest) ? dest : Temp1; int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; a.LoadI(src_register, offset, t); if (dest != t) move(dest, t); }
void CodeGen::assignment(Location receiver, realSlotRef* path, Location val, bool isMem) { // <move arg, t> // <loadPath rr, path, receiver> // store receiver/rr, offset - Mem_Tag, arg/t // <check_store> a.Comment("Begin Assignment"); Location t; if (isRegister(val) && val != CReceiverReg) { t = val; } else { t = Temp1; move(t, val); // load argument } assert(t != Temp2, "register conflict"); int32 offset = smiOop(path->desc->data)->byte_count() - Mem_Tag; if (path->holder->is_object_or_map()) { Location t1 = loadPath(CReceiverReg, path->holder, receiver, Temp1); a.StoreI(t1, offset, t); // store object data slot contents if (isMem) { a.AddI(t1, offset, Temp1); // compute store address recordStore(Temp1); } } else { fatal("don't support vframe lookups yet"); } a.Comment("End Assignment"); }
void ArithRCNode::gen() { BasicNode::gen(); Location src = genHelper->moveToReg(_src, Temp1); Location dest = isRegister(_dest->loc) ? _dest->loc : Temp2; switch (op) { case AddArithOp: theAssembler->AddI(src, oper, dest); break; case SubArithOp: theAssembler->SubI(src, oper, dest); break; case AndArithOp: theAssembler->AndI(src, oper, dest); break; case OrArithOp: theAssembler->OrI (src, oper, dest); break; case XOrArithOp: theAssembler->XorI(src, oper, dest); break; case ArithmeticLeftShiftArithOp: case LogicalLeftShiftArithOp: theAssembler->SllI(src, oper, dest); break; case ArithmeticRightShiftArithOp: theAssembler->SraI(src, oper, dest); break; case LogicalRightShiftArithOp: theAssembler->SrlI(src, oper, dest); break; case AddCCArithOp: theAssembler->AddCCI(src, oper, dest); break; case SubCCArithOp: theAssembler->SubCCI(src, oper, dest); break; case AndCCArithOp: theAssembler->AndCCI(src, oper, dest); break; case OrCCArithOp: theAssembler->OrCCI (src, oper, dest); break; default: ShouldNotReachHere(); // unexpected arith type } if (dest != _dest->loc) { theAssembler->StoreI(SP, spOffset(_dest->loc), dest); } }
void CodeGen::loadImmediate(Location dest, int32 value) { // *if p is 0... // <move g0, dest> // *else... // *if p is small... // or g0, value, t/dest // *else... // sethi value, t/dest // add t/dest, value, t/dest // *end // <move t, dest> // *end Location t; if (isRegister(dest)) { t = dest; } else { t = Temp1; } if (value == 0) { t = G0; } else if (value < maxImmediate && value > -maxImmediate) { a.OrI(G0, value, t); } else { if (value & LOWMASK) { a.SetHiI(value, t); // load high part of value a.AddI(t, value, t); // add low part if nonzero } else { a.SetHiI2(value, t); // low 10 bits are zero } } move(dest, t); }
void CodeGen::zapBlock(Location block, bool memoized) { // <move block, t> // *if memoized // subcc block/t, 0, g0 // bne,a _done // do work in delay slot // *end // store block/t, scopeOffset, G0 // _done: ... Location t; a.Comment("zap block"); if (isRegister(block)) { t = block; } else { t = NLRTempReg; move(t, block); } Label* done; if (memoized) { a.SubCCI(t, 0, G0); // was block generated? done = a.BneForward(true); // branch and zap if yes } a.StoreI(t, scope_offset(), G0); // zap the block if (memoized) done->define(); }
void CodeGen::recordStore(Location dst) { // NB: when fixed to use register revisit call sites a.Comment("recordStore"); assert(isRegister(dst), "receiver to check_store must be in a register"); a.shrl(card_shift, NumberOperand, dst); // shift target addr a.addl(no_reg, (int32)&byte_map_base, VMAddressOperand, dst); // add start of map to dst a.movb(0, dst, 0, VMAddressOperand); }
void CodeGen::checkOop(Label& general, oop what, Location reg) { // test for inline cache hit (selector, delegatee) assert(Temp1 != PerformSelectorLoc && Temp1 != PerformDelegateeLoc && isRegister(PerformSelectorLoc) && isRegister(PerformDelegateeLoc), "wrong register setup"); loadOop(Temp1, what); // load hard-wired value a.SubCCR(reg, Temp1, G0); // compare against actual value if (general.isDefined()) { a.Bne(&general, false); // reuse miss handler a.Nop(); } else { Label* hit = a.BeqForward(false); general.define(); jumpTo(Memory->code->trapdoors->SendMessage_stub_td(), Temp1, G0); a.Nop(); hit->define(); } }
void CodeGen::loadSaved(Location dest, Location src, Location frames_bp, compiled_vframe* src_vf) { a.Comment("loadSaved"); // Load location from a frame on the stack; sp is that frame's // block home (BP on Intel) and frameSz its size. assert(isRegister(frames_bp), "???"); fint frameSz = src_vf->code->frameSize(); Location r; int32 d; OperandType t; reg_disp_type_of_loc(&r, &d, &t, src); assert(t == NumberOperand, "???"); Location tr = isRegister(dest) ? dest : Temp1; // I don't think the following untested case would ever happen, but put the code in anyway. -- dmu 5/06 # if GENERATE_DEBUGGING_AIDS if (r != ebp && CheckAssertions) warning("untested loadSaved from outgoing arg"); # endif a.movl(frames_bp, d - (r == ebp ? 0 : (frameSz - linkage_area_size) * oopSize), NumberOperand, tr); move(dest, tr); }
void CodeGen::recordStore(Location dst) { // srl dst, card_shift, dst // stb g0, [dst + byte_map_base] a.Comment("recordStore"); assert(isRegister(dst), "receiver to check_store must be in a register"); a.SrlI(dst, card_shift, dst); // shift target addr a.StoreBR(dst, ByteMapBaseReg, G0); // set byte in map }
void LongRegisterString::deallocate(Location l) { if (isRegister(l)) { bv->remove(l); } else { assert(isStackRegister(l), "should be stack reg"); fint i = tempToIndex(l); bv->remove(i); } }
Location CodeGen::flushToStack(Location reg, RegisterState*) { // flush register to its corresponding location on the stack if (isRegister(reg)) { Location breg; fint offset = getOffset(reg, breg); assert(breg == SP, "should be SP-relative"); a.StoreI(SP, offset, reg); // flush reg to stack } return reg; // just the same on SPARC, different when we have a machine where there is no fixed mapping }
void LongRegisterString::doAllocate(Location l) { if (isRegister(l)) { bv->add(l); } else { assert(isStackRegister(l), "should be stack reg"); fint i = tempToIndex(l); if (i >= bv->length) grow(i); bv->add(i); } }
void CodeGen::storeSaved(Location dst, Location frames_bp, compiled_vframe* dst_vf, Location src) { a.Comment("storeSaved"); assert(isRegister(frames_bp), "???"); fint frameSz = dst_vf->code->frameSize(); Location r; int32 d; OperandType t; reg_disp_type_of_loc(&r, &d, &t, dst); assert(t == NumberOperand, "???"); Location tr = isRegister(src) ? src : isRegister(dst) ? dst : frames_bp == Temp1 ? Temp2 : Temp1; if (tr == src) a.Untested("storeSaved1"); move(tr, src); // I don't think the following untested case would ever happen, but put the code in anyway. -- dmu 5/06 # if GENERATE_DEBUGGING_AIDS if (r != ebp && CheckAssertions) warning("untested loadSaved from outgoing arg"); # endif a.movl(tr, frames_bp, r == ebp ? d : d - (frameSz - linkage_area_size) * oopSize, NumberOperand); }
inline Location CodeGen::moveToReg(Location what, Location reg) { Location t; if (isRegister(what)) { t = what; } else { t = reg; move(t, what); } return t; }
void SICGenHelper::loadImmediateOop(oop p, Location dest, bool isInt) { assert(isRegister(dest), "must be a register"); if (p == 0) { a->OrR(G0, G0, dest); } else if ((isInt || !p->is_mem()) && isImmediate(smiOop(p))) { a->OrI(G0, (int)p, dest); } else { a->SetHiO(p, dest); // load high part of value a->AddO(dest, p, dest); // add low part } }
int32 fpOffset(Location reg, fint frameSize) { // return offset (in bytes) off of fp if (isRegister(reg)) { assert(reg >= I0 && reg < I0 + NumInRegisters || reg >= L0 && reg < L0 + NumLocalRegisters, "can't access this register"); return ((first_register_offset - StackFromRegister[reg]) - frameSize) * oopSize; } return fpOffset_abstract(reg, frameSize); }
/** * This function returns the type of the addressing * 0 - number , 1 - label, 2- last operand, 3- register * str - the string. */ int checkAddresingType(string str) { if(str[0] == '#') return 0; if(str[0] == '$' && str[1] == '$') return 2; if(isRegister(str)) return 3; addToQueue(str, IC); return 1; }
void CodeGen::assignment(Location receiver, slotDesc* s, Location val) { // <move arg, t> // store [receiver/rr, offset - Mem_Tag], t // <check_store> assert( isRegister(receiver), "receiver must be a register"); a.Comment("Begin Simple Assignment"); Location t; if (isRegister(val) && val != CReceiverReg) { t = val; } else { t = Temp1; move(t, val); // load argument } int32 offset = smiOop(s->data)->byte_count() - Mem_Tag; a.StoreI(receiver, offset, t); // store object data slot contents a.AddI(receiver, offset, Temp1); // compute store address recordStore(Temp1); a.Comment("End Simple Assignment"); }
void RegisterState::allocatePermanent(Location r) { if (isRegister(r)) { ::allocateRegister(permanent, r); } else if (is_StackLocation(r)) { setNth(stackPerms[whichMask(r)], whichBit(r)); } else { // extra incoming arg etc -- ignore } allocate(r); }
void CodeGen::moveComplicated(Location dest, Location src, bool delay) { Unused(delay); assert(!(isRegister(src) && isRegister(dest)), "shouldn't call this"); Location t; if (isRegister(dest)) { t = dest; } else if (isRegister(src)) { t = src; } else { assert(! delay, "cannot fit move in delay slot"); t = Temp1; } if (isRegister(src)) { // already in register } else { Location base; fint offset = getOffset(src, base); a.LoadI(base, offset, t); } if (isRegister(dest)) { // already in register } else { Location base; fint offset = getOffset(dest, base); a.StoreI(base, offset, t); } }
bool LongRegisterString::isAllocated(Location l) { if (isRegister(l)) { return bv->includes(l); } else { assert(isStackRegister(l), "should be stack reg"); fint i = tempToIndex(l); if (i < bv->length) { return bv->includes(i); } else { return false; } } }
void StoreOffsetNode::gen() { BasicNode::gen(); Location b = genHelper->moveToReg(base, Temp1); Location t = Temp2; if (_src->isConstPReg()) { // store constant ConstPReg* value = (ConstPReg*)_src; oop p = value->constant; // don't need to check-store if oop is old - old objs will never become // new again needCheckStore = needCheckStore && p->is_new(); // ints/floats aren't new if (p == 0) { theAssembler->StoreI(b, offset, G0); } else { assert(b != t, "must be different"); t = genHelper->loadImmediateOop(value, t, false); theAssembler->StoreI(b, offset, t); } } else { if (isRegister(_src->loc)) { theAssembler->StoreI(b, offset, _src->loc); } else { theAssembler->LoadI(SP, spOffset(_src->loc), t); theAssembler->StoreI(b, offset, t); } } if (needCheckStore) { // do a check-store assert(isRegister(b), "base reg of check_store must be in a register"); if (offset > card_size || !AllowOffsetCheckStores) { // use slow check-store sequence // (marked card may be off by one, but not more) theAssembler->AddI(b, offset, Temp1); b = Temp1; } theAssembler->SrlI(b, card_shift, Temp1); // shift target addr theAssembler->StoreBR(Temp1, ByteMapBaseReg, G0); // set byte in map } }
void BlockCloneNode::genCall() { Location dest = block()->loc; genHelper->loadImmediateOop(block()->block, CReceiverReg); // load block Oop theAssembler->CallP(first_inst_addr(blockClone->fn())); theAssembler->OrR(SP, G0, Arg1); // load home frame assert(!blockClone->canScavenge() && !blockClone->needsNLRCode(), "need to rewrite this"); genHelper->moveRegToLoc(ResultReg, dest); if (block()->uplevelR && isRegister(dest)) { // flush to stack theAssembler->StoreI(SP, spOffset(dest), dest); } }