Main Page   Class Hierarchy   Compound List   File List   Header Files   Compound Members   File Members  

nmln.h

This is the verbatim text of the nmln.h include file.
/* 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();
};



Generated at Tue Jun 27 12:15:16 2000 for SelfVM by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999