void inline jump_to_reset() { INT_DISABLE; VIP_REGS[INTENB] = 0; stop_timer_driver(); jump_addr((void *) 0xFFFFFFF0); }
fint sendDesc::ntargets() { char *addr= jump_addr(); if (addr == lookupRoutine()) return 0; if (Memory->code->contains(addr)) return 1; assert(Memory->code->stubs->contains(addr), "what is it?"); NCodeBase *n= findStub(addr); return n->isCountStub() ? 1 : ((CacheStub*)n)->arity(); }
bool sendDesc::isPrimCall() { char *insts= jump_addr(); bool b= !Memory->code->contains(insts) && !Memory->code->stubs->contains(insts) && insts != lookupRoutine(); if (b) { assert(getPrimDescOfFirstInstruction(insts, true), "not a prim call"); } return b; }
// NB: get_method() is not quite equivalent to target(): the former returns // an nmethod even when it is called via a count stub, the latter returns // NULL in this case. // It can also be called on dummy sendDescs representing glue code nmethod* sendDesc::get_method() { char *addr= jump_addr(); if (Memory->code->contains(addr)) return nmethod_from_insts(addr); if (!Memory->code->stubs->contains(addr)) return NULL; NCodeBase *n= findStub(addr); assert(n->isCountStub(), "shouldn't call on PICs"); return ((CountStub*)n)->target(); }
void sendDesc::print() { if (isPrimCall()) { PrimDesc *pd= getPrimDescOfFirstInstruction(jump_addr(), true); lprintf("primitive: %s\n", pd->name()); return; } printIndent(); printLookupType(raw_lookupType()); LookupType l= lookupType(); if (isPerformLookupType(l)) { lprintf(": argc: %ld", arg_count()); } else { lprintf(": selector: "); selector()->print_real_oop(); } if (l & DelegateeStaticBit) { lprintf(": delegatee: "); delegatee()->print_real_oop(); } Indent++; printIndent(); lprintf("addr: %#lx", jump_addr()); if (Memory->code->contains(jump_addr())) { lprintf(" (nmethod %#lx)", nmethod::findNMethod(jump_addr())); } lprintf("; mask: "); printMask(mask()); lprintf("\n"); printIndent(); lprintf("dependency: "); dependency()->print(); lprintf("\n"); if (pic()) { printIndent(); lprintf("PIC: p ((CacheStub*)%#lx)->print()\n", pic()); } if (countStub()) { printIndent(); lprintf("count stub: p ((CountStub*)%#lx)->print()\n", countStub()); } Indent --; }
CacheStub* sendDesc::pic() { char* addr = jump_addr(); if (Memory->code->contains(addr)) { // linked to a nmethod return NULL; } else if (Memory->code->stubs->contains(addr)) { NCodeBase* stub = findStub(addr); return stub->isCacheStub() ? (CacheStub*)stub : NULL; } else { return NULL; } }
CountStub* sendDesc::countStub() { char* addr= jump_addr(); if (Memory->code->contains(addr)) { // linked to a nmethod assert(!Memory->code->stubs->contains(addr), "zones overlap"); return NULL; } else if (Memory->code->stubs->contains(addr)) { NCodeBase* stub = findStub(addr); return stub->isCountStub() ? (CountStub*)stub : NULL; } else { return NULL; } }
bool sendDesc::checkLookupTypeAndEntryPoint() { char *insts= jump_addr(); if (insts == lookupRoutine()) return true; NCodeBase *n= findThing(insts); if (n->isCacheStub()) { return true; // checked in CacheStub::verify } nmethod* nm; if (n->isNMethod()) { nm= (nmethod*)n; } else { assert(n->isCountStub(), "what is it?"); CountStub *cs= (CountStub*)n; nm= cs->target(); insts= cs->jump_addr(); } return checkLookupTypeAndEntryPoint(nm, insts); }
void sendDesc::extend(nmethod* nm, mapOop receiverMapOop, CountStub *cs_from_pic) { char *addr; bool isPerform= isPerformLookupType(raw_lookupType()); if ( PIC && !isPerform && (addr= jump_addr(), addr != lookupRoutine())) { // already has at least one nmethod linked to the send CacheStub* s= pic(); # if GENERATE_DEBUGGING_AIDS if (CheckAssertions) { assert(cs_from_pic==NULL, "discarding countStub?"); if (!s) { // turning monomorphic ic into PIC; PIC will carry dependencies assert(dependency()->notEmpty(), "shouldn't be empty"); // check for duplicate nmethod & rcvr map CountStub *oldcs= countStub(); nmethod *oldnm= oldcs ? oldcs->target() : nmethod::findNMethod(addr); assert( oldnm != nm || receiverMapOop != oldnm->key.receiverMapOop(), "already linked to this nmethod, why rebind?? (maybe I-cache did not get flushed)"); } } # endif s= s->extend(this, nm, receiverMapOop); assert(s, "should have a PIC now"); assert(dependency()->next == dependency()->prev, "more than one link"); } else { // first time we execute this send, or PICs disabled, or perform, or // rebinding after a PIC has been removed, or non-map related misses if (isPerform) NumberOfPerformMisses++; if (!PIC) { CacheStub *s= pic(); // remove existing PIC if (s) s->deallocate(); } rebind(nm, NULL, cs_from_pic); } MachineCache::flush_instruction_cache_for_debugging(); if (VerifyZoneOften) verify(); }
nmethod* sendDesc::target() { char* addr = jump_addr(); return Memory->code->contains(addr) ? nmethod_from_insts(addr) : NULL; }
bool sendDesc::verify() { if (isPrimCall()) return true; LookupType l= lookupType(); bool flag= checkLookupTypeAndEntryPoint(); if (isPerformLookupType(l)) { if (arg_count() < 0 || arg_count() > 100) { error2("sendDesc %#lx arg count %ld is invalid", this, arg_count()); flag = false; } } else { if (! oop(selector())->verify_oop()) { flag = false; } else if (! selector()->is_string()) { error1("sendDesc %#lx selector isn't a string", this); flag = false; } nmethod* nm = target(); if (nm == NULL) { CountStub* cs = countStub(); if (cs) nm = cs->target(); } if (nm == NULL) { CacheStub* cs = pic(); if (cs) { nm= cs->get_method(0); oop sel= nm->key.selector; for (fint i= 1; i < cs->arity(); ++i) if (cs->get_method(i)->key.selector != sel) error2("sendDesc %#lx: selector != PIC case %d selector", this, i); } } if (nm && nm->key.selector != selector()) error1("sendDesc %#lx: selector != target nmethod's selector", this); } if (l & DelegateeStaticBit) { if (! delegatee()->verify_oop()) { flag = false; } else if (baseLookupType(l) == DirectedResendLookupType && ! delegatee()->is_string()) { error1("sendDesc %#lx delegatee isn't a string", this); flag = false; } } if (!dependency()->verify_list_integrity()) { lprintf("\tof sendDesc %#lx\n", this); flag = false; } if (pic()) { if (dependency()->next != dependency()->prev) error1("sendDesc %#lx: more than one elem in dependency chain", this); pic()->verify(); } else { CountStub *cs= countStub(); if (cs == NULL) { if (isCounting() && jump_addr() != lookupRoutine()) error1("sendDesc %#lx: doesn't have countStub but is counting", this); } else { if (!isCounting() && !cs->isAgingStub()) error1("sendDesc %#lx: has countStub but is not counting", this); if (dependency()->next != dependency()->prev) error1("sendDesc %#lx: more than one elem in dependency chain", this); countStub()->verify2(NULL); } } return flag; }
bool sendDesc::wasNeverExecuted() { // the "dirty bit" is used to distinguish sendDescs that are accidentally // empty (because of a flush) from sends that were never executed // (the former are "dirty", the latter clean) return jump_addr() == lookupRoutine() && !isDirty(); }