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

nmethod.h

This is the verbatim text of the nmethod.h include file.
/* Sun-$Revision: 23.8 $ */

/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
   See the LICENSE file for license information. */


# pragma interface

# if  defined(FAST_COMPILER) || defined(SIC_COMPILER)

// nmethods (native methods) are the compiled code versions of Self
// methods.  

struct nmFlags {
  // metrowerks requires int types for bitfields to pack!
  
  /* bool        */          int isZombie:             1;  // can be discarded if not on stack
  /* bool        */          int isDI:                 1;  // affected by DI
  /* bool        */          int isInvalid:            1;  // nmethod is invalid (needs programming conv.)
  /* bool        */          int isDebug:              1;  // version compiled for debugging
  /* nm_compiler */          int compiler:             2;  // compiler which generated this nmethod
  /* bool        */          int flushed:              1;  // to catch flushing errors
  /* bool        */          int isUncommonRecompiled: 1;  // recompiled because of uncommon trap?  (SIC)
  /* bool        */          int isYoung:              1;  // "young"? (recently recompiled)
  /* bool        */          int isToBeRecompiled:     1;  // to be recompiled as soon as it matures
  /* bool        */          int isImpureNIC:          1;  // if NIC method, something is inlined
  /* fint        */          int filler:               1;  
  /* uint16      */ unsigned int level:                4;  // optimization level
  /* uint16      */ unsigned int version:              8;  // version number (0 = first version)
  /* uint16      */ unsigned int trapCount:            8;  // number of map-load traps encountered

  void clear() { assert(sizeof(nmFlags) == 4, "oops"); *(int32*)this = 0; }
};


nmethod* constructDoItMethod(oop receiver, oop method);

# define NMETHOD_FROM(fieldName, p)                                           \
    ((nmethod*)((char*)p - (char*)&((nmethod*)NULL)->fieldName))

class nmethod : public OopNCode {
 public:
  int32 depsLen;
  nmethodScopes* scopes;
  
 protected:
  nmln* depsAddr;
  VTBL_AND_SETTER(nmethod,);
 public:
  NMethodLookupKey key; // key for code table searching
  
  codeTableEntry *codeTableLink; // links codeTableEntries for this nmethod
  nmln  linkedSends;    // links all nmethods that are i-c to me
  nmln  diLink;         // links the nmethod that DI forwards to me
  nmln  zoneLink;       // used by the zone to link replacement candidates
  int32 id;             // for LRU and recompiles; every nmethod has unique ID
  int32 oldCount;       // previous value of usage counter
  nmFlags flags;        // various flags
  uint16 verifiedOffset;// offset of entry point for known map
  uint16 diCheckOffset; // offset of entry point for DI checks
  uint16 frameCreationOffset; // offset of entry point where activation frame
                             // has been established.
 protected:
  uint16 frame_size;    // size of stack frame (in words)
 public:
  frame* frame_chain;   // beginning link of frames that are running me
  
 protected:
  nmethod(AbstractCompiler* c, bool generateDebugCode = false);
  void get_platform_specific_data(AbstractCompiler* c);

  void* operator new(size_t size);
  void deallocate()     { flush(); }
 public:
  friend nmethod* new_nmethod(AbstractCompiler* c,
                              bool generateDebugCode = false);
  
  char* insts()                 { return (char*)(this + 1); }
  char* verifiedEntryPoint()    { return insts() + verifiedOffset; }
  char* diCheckEntryPoint()     { return insts() + diCheckOffset; }
  char* entryPointFor(sendDesc *sd);

  PcDesc* pcs()         { return (PcDesc*) scopes->pcs();}
  PcDesc* pcsEnd()      { return (PcDesc*) scopes->pcsEnd();}

  nmln*   deps()        { return depsAddr;}
  nmln*   depsEnd()     { return (nmln*) ((char*) deps() + depsLen);}

  fint    size()        { return (char*)locsEnd() - (char*)this; }

  void removeFromCodeTable();

  nmethod** dBackLinkAddr() { return (nmethod**)deps()   - 1; }

  bool  isNMethod()     { return vtbl_value() == static_vtbl_value(); }
  bool  isUncommon()    { return false; }
  bool  isZombie()      { return flags.isZombie; }
  void  makeZombie(bool unlink = true);
  bool  isDI()          { return flags.isDI; }
  bool  isInvalid()     { return flags.isInvalid; }
  bool  isValid()       { return !isInvalid(); }
  fint  compiler()      {
    switch (flags.compiler) {
     case nm_nic: return NIC;
     case nm_sic: return SIC;
     default: fatal("invalid compiler"); return 0;
    }
  }
  bool  isDebug()               { return flags.isDebug; }
  bool  isUncommonRecompiled()  { return flags.isUncommonRecompiled; }
  bool  isYoung()               { return flags.isYoung; }
  bool  isImpureNIC()           { return flags.isImpureNIC; }
  bool  reusable()              { return compiler()==NIC && !isImpureNIC(); }
  void  makeYoung();
  void  makeVeryYoung();
  void  makeOld();
  fint  agingLimit();          // # invocations before isYoung is cleared

  bool  isToBeRecompiled()      { return flags.isToBeRecompiled; }
  void  makeToBeRecompiled()    { flags.isToBeRecompiled = 1; }
  void  makeImpureNIC()         { flags.isImpureNIC= 1; }
  bool  needToRecompileFor(sendDesc *s) {
    return compiler() == NIC  &&  s->isOptimized(); }
  void  setCompiler(fint c) {
    switch (c) {
     case NIC: flags.compiler = nm_nic; break;
     case SIC: flags.compiler = nm_sic; break;
     default: fatal("invalid compiler"); break;
    }
  }
  bool shouldRecompile();    // these names are crummy (one is not the inverse
  bool shouldNotRecompile(); // of the other)
  bool mustNotRecompile();
  fint level();
# ifdef UNUSED
  void setLevel(fint newLevel)  { flags.level = newLevel; }
# endif
  fint version()                { return flags.version; }
  void setVersion(fint v);
  fint invocationCount();       // approximation (not all calls have counters)
  fint ncallers();              // # of callers (*not* # of inline caches)
  fint nsends(bool includeAll = false); // # of inlinable sends; if includeAll,
                                // also count non-inlinable sends
  bool isTiny();

  bool is_frame_chain_saved() { return frame_chain == SavedFrameChain; }
  void save_frame_chain()     { frame_chain= SavedFrameChain; }
  void clear_frame_chain()    { frame_chain= NULL; }
  void unlink_saved_frame_chain() {
    if (frame_chain == SavedFrameChain) frame_chain= NoFrameChain; }
  void save_unlinked_frame_chain() {
    if (frame_chain == NoFrameChain) frame_chain= SavedFrameChain; }

  bool  encompasses(void* p);
  int32 frameSize()             { return frame_size; }
  
  // for zone LRU management
  int32 lastUsed()      { return LRUtable[id].lastUsed; }
  bool  isUsed()        {
    return frame_chain != NoFrameChain
        || !LRUflag[id]
        || useCount[id] != oldCount; }
  
  virtual void moveTo_inner(NCodeBase* to, int32 delta, int32 size);
  void  shift_target(nmln* l, int32 delta);
  NCodeBase* unlink_me(nmln* l);
  void  forwardLinkedSend(nmln* l, nmethod* to) {
    l->asSendDesc()->rebind(to); }

  void  addDeps(dependencyList *deps); // changes deps
  void  moveDeps(nmln* newDeps, int32 delta);
  void  moveScopes(nmethodScopes* scopes);
  void  remove_me_from_inline_cache();
  void  forwardLinkedSends(nmethod* to);
  
  void  unlink();               // unlink from codeTable, deps etc.
  void  flush();
  void  flushPartially(); // used during recompilation
  void  invalidate();
#ifdef UNUSED
  int32 flushPICs();
  int32 unlinkDI(nmln*& savedDIChildren);
#endif
  void  relinkDI(int32 n, nmln*& savedDIChildren);
  
 protected:
  void  check_store();
 public:
  bool  code_oops_do(oopsDoFn f);
  bool  scavenge_contents();
  void  gc_mark_contents();
  bool  gc_unmark_contents();
  bool  switch_pointers(oop from, oop to,
                        nmethodBList* nmethods_to_invalidate);
  void  relocate();
  void  verify();
  
  // programming and debugging
  PcDesc*    containingPcDesc(char* pc);
  PcDesc*    containingPcDescOrNULL(char* pc);
 public:

  ScopeDesc* containingScopeDesc(char* pc);
  ScopeDesc* correspondingScopeDesc(ScopeDesc* s);
#ifdef DEBUG
  PcDesc*    correspondingPC(ScopeDesc* sd, int32 bci);
#endif
  sendDesc*  sendDescFor(compiled_vframe* vf, bool wantIntrCheck);
  Map*       blockMapFor(blockOop bl);

  addrDesc*  addrDesc_at(char* p); // slow - for debugging

  // Returns true if activation frame has been established. 
  bool       has_frame_at(char* pc);

  // Returns true if pc is not in prologue or epilogue code.
  bool       in_self_code_at(char* pc);
  
  oop   method()   { return scopes->root()->method(); }

# ifdef UNUSED
  bool  isMethod() { return scopes->root()->isMethodScope(); }
# endif
  bool  isAccess() { return scopes->root()->isAccessScope(); }
  
  void  print();
  void  printCode();
# ifdef DEBUG
  void  printLocs();
  void  printDeps();
  void  printPcs();
# endif
  
  friend bool           isNMethod(void* p);
  friend nmethod*       nmethodContaining(char* pc, char* likelyEntryPoint);
  friend nmethod*       findNMethod(void* start);
  friend nmethod*       findNMethod_maybe(void* start);
  
  friend nmethod* nmethod_from_insts(char* insts) {     // for efficiency
    nmethod* nm = (nmethod*) insts - 1;
    if (::isNMethod(nm)) return nm; else return findNMethod(nm);
  }
# include "_nmethod_pd.h.incl"
};

# else // defined(FAST_COMPILER) || defined(SIC_COMPILER)

struct nmethod {
  void invalidate() {}
};

# endif

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