/* Sun-$Revision: 23.9 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
See the LICENSE file for license information. */
# pragma interface
// These clever little guys are used in many places in nmethods.
// They implement doubly-linked circular lists.
// Someday, we may replace them with singly linked lists, it will save space
// and cost deletion time.
// They always point to themselves--into the middle of maps and nmethods.
// They are used to point from map slotDesc's to all the nmethods that depend
// on the map. Also, the pointer from an nmethod to all the inline cache
// slots that are linked to this nmethod.
// Also each code table bucket is the head of a list of nmethods
// that hash to that bucket.
// Finally, all nmethods containing young objects are linked together on
// another such list for scavenging.
# define nullNMln ((nmln*)NULL)
extern "C" {
void initNmlnCache();
void resetNmlnCache();
}
# define FOR_EACH_NMLN(startExpr, elem, code) \
nmln* CONC(elem,__start__) = (startExpr); \
nmln* elem = CONC(elem,__start__); \
do { code; elem = elem->next;} while (elem != CONC(elem,__start__));
struct nmln {
nmln* next;
nmln* prev;
void init() { next = this; prev = this; }
nmln() { init(); }
bool isEmpty() { return next == this; }
bool notEmpty() { return ! isEmpty(); }
fint length();
bool isMovedEmpty() { return next->next == next; }
void remove() {
// splice me out of my chain
#ifdef GENERATE_ASSERTIONS
if (CheckAssertions && this == (nmln*)catchThisOne) breakpoint();
#endif
if (notEmpty()) { next->prev = prev; prev->next = next; init(); } }
void add(nmln* p) {
// add empty argument nmln after me in my chain
// C++ won't inline this next assertion correctly (augh!)
// assert(this != p, "adding a nmln to itself!");
assert(p->isEmpty(), "adding a nonempty nmln!");
p->next = next;
p->prev = this;
next->prev = p;
next = p; }
void rebind(nmln* p) {
// splice me out of my chain and add to argument's chain
assert(p, "should exist");
if (this != p) {
// splice me out of my chain
next->prev = prev;
prev->next = next;
// add me to argument's chain
next = p->next;
prev = p;
p->next->prev = this;
p->next = this;
} }
void insert() {
// create a new dependency after copying an old one (i.e. cloning a map)
if (isMovedEmpty()) {
// must have been empty
init();
} else {
next->prev = this;
prev->next->next = this;
prev = prev->next;
} }
void relocate() {
// update neighboring dependendencies after being moved
// (i.e. creating an nmethod and after reading a snapshot)
if (isMovedEmpty()) {
// must have been empty
init();
} else {
next->prev = this;
prev->next = this;
} }
void forward(int32 diff) {
// update dependendencies after being forwarded (i.e. scavenging maps)
*this = *((nmln*) ((char*) this - diff));
relocate(); }
void shift(int32 diff) {
// update dependencies before being moved (i.e. nmethod compaction)
if (diff) {
if (isEmpty()) {
// an empty list; shift myself
next = (nmln*) ((char*) next + diff);
prev = (nmln*) ((char*) prev + diff);
} else {
// shift next-door neighbors
prev->next = (nmln*) ((char*) prev->next + diff);
next->prev = (nmln*) ((char*) next->prev + diff);
}
}
}
// update dependendencies before being compacted
void shift(int32 diff, NCodeBase* m);
void init(nmln* p) {
// create a new nmln, and add empty argument nmln to me (create 2-loop)
if (p) {
assert(p->isEmpty(), "should be empty");
// make argument point to me, and me point to argument
next = p;
prev = p;
p->next = this;
p->prev = this;
} else {
// initialize
next = this;
prev = this;
} }
void init_chain();
void flush();
void invalidate();
bool verify_list_integrity();
bool verify_map_deps() { return verify_list_integrity(); }
# if defined(FAST_COMPILER) || defined(SIC_COMPILER)
CacheStub* asCacheStub(); // NULL if not in a cache stub
CountStub* asCountStub(); // NULL if not in a count stub
sendDesc* asSendDesc_or_null(); // NULL if not in a sendDesc
sendDesc* asSendDesc(); // fatal error if not in a sendDesc
sendDesc* callingSendDesc(); // calling sendDesc (possibly transitively)
DIDesc* asDIDesc();
nmethod* asSender(); // sending nmethod
# endif // defined(FAST_COMPILER) || defined(SIC_COMPILER)
inline int32 hash(); // for verify
void print();
};