node.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.129 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 
00025 # ifdef DELTA_COMPILER
00026 
00027 // This file defines the intermediate language used by the Compiler.
00028 // For each node a code pattern is generated during code generation.
00029 // Note: offsets in nodes are always in oops!
00030 
00031 class Node;                             // abstract
00032 
00033 class   TrivialNode;                    // abstract; has no defs/uses; most generate no code
00034 class     MergeNode;                    // nop; can have >1 predecessors
00035 class     NopNode;                      // generates no code (place holders etc)
00036 class     CommentNode;                  // for compiler debugging
00037 class     FixedCodeNode;                // fixed code pattern for compiler debugging, instrumentation, etc.
00038 class     LoopHeaderNode;               // loop header (contains type tests moved out of loop)
00039     
00040 class   NonTrivialNode;                 // non-trivial node, may have defs/uses and generate code
00041 
00042 class     PrologueNode;                 // entire method prologue
00043   
00044 class     LoadNode;                     // abstract
00045 class       LoadIntNode;                // load vm constant
00046 class       LoadOffsetNode;             // load slot of some object
00047 class       LoadUplevelNode;            // load up-level accessed variable
00048 
00049 class     StoreNode;
00050 class       AssignNode;                 // general assignment (e.g. into temp)
00051 class       StoreOffsetNode;            // store into slot of object
00052 class       StoreUplevelNode;           // store up-level accessed variable
00053 
00054 class     AbstractReturnNode;
00055 class       ReturnNode;                 // method return 
00056 class       NLRSetupNode;               // setup NLR leaving this compiled method
00057 class       InlinedReturnNode;          // inlined method return (old backend only)
00058 class       NLRContinuationNode;        // continue NLR going through this method
00059 
00060 class     ArithNode;                    // all computations (incl comparisons)
00061 class     AbstractBranchNode;           // nodes with (potentially) >1 sucessors
00062 class       TArithRRNode;               // tagged arithmetic nodes
00063 class       CallNode;                   // abstract
00064 class         SendNode;                 // Delta send
00065 class         PrimNode;                 // primitive call
00066 class           BlockCreateNode;        // inital block clone (possibly memoized)
00067 class             BlockMaterializeNode; // create block (testing for memoization)
00068 class           InterruptCheckNode;     // interrupt check / stack overflow test
00069 class         DLLNode;                  // DLL call
00070 class         ContextCreateNode;        // creates a context and copies arguments
00071 
00072 class       AbstractArrayAtNode;
00073 class         ArrayAtNode;              // _At: primitive
00074 class         AbstractArrayAtPutNode;
00075 class           ArrayAtPutNode;         // _At:Put: primitive
00076 
00077 class       InlinedPrimitiveNode;       // specialized inlined primitives
00078 
00079 class       BranchNode;                 // machine-level conditional branches
00080 class       TypeTestNode;               // type tests (compare klasses, incl int/float)
00081 class       NLRTestNode;                // tests whether NLR has found home method
00082 class     ContextInitNode;              // initialize context fields
00083 class     ContextZapNode;               // zap context (new backend only)
00084 
00085 class     UncommonNode;                 // uncommon branch
00086 
00087 void initNodes();                       // to be called before each compilation
00088 
00089 
00090 // Node definitions
00091 
00092 // Node: abstract superclass, holds common behavior (except prev/next links)
00093 
00094 class PRegMapping;
00095 
00096 class BasicNode: public PrintableResourceObj {
00097  protected:     
00098   BB*           _bb;                    // basic block to which I belong
00099   int16         _id;                    // unique node id for debugging
00100   int16         _num;                   // node number within basic block
00101   InlinedScope* _scope;                 // scope to which we belong
00102   int16         _bci;                   // bci within that scope
00103   PRegMapping*  _mapping;               // the mapping at that node, if any (will be modified during code generation)
00104 
00105  public:        
00106   Label         label;                  // for jumps to this node -- SHOULD BE MOVED TO BB -- fix this
00107   bool          dontEliminate;          // for special cases: must not elim. this node
00108   bool          deleted;                // node has been deleted
00109 
00110   int           id() const              { return this == NULL ? -1 : _id; }
00111   BB*           bb() const              { return _bb; }
00112   int           num() const             { return _num; }
00113   InlinedScope* scope() const           { return _scope; }
00114   int           bci() const             { return _bci; }
00115 
00116   void          setBB(BB* b)            { _bb = b; }
00117   void          setNum(int n)           { _num = n; }
00118   void          setScope(InlinedScope* s);
00119 
00120   static int currentID;                 // current node ID
00121   static int currentCommentID;          // current ID for comment nodes
00122   static ScopeInfo lastScopeInfo;       // for pcDesc generation
00123   static int lastBCI;
00124 
00125   BasicNode();
00126 
00127   virtual bool isPrologueNode() const           { return false; }
00128   virtual bool isAssignNode() const             { return false; }
00129   virtual bool isTArithNode() const             { return false; }
00130   virtual bool isArithNode() const              { return false; }
00131   virtual bool isNLRSetupNode() const           { return false; }
00132   virtual bool isNLRTestNode() const            { return false; }
00133   virtual bool isNLRContinuationNode() const    { return false; }
00134   virtual bool isReturnNode() const             { return false; }
00135   virtual bool isInlinedReturnNode() const      { return false; }
00136   virtual bool isLoopHeaderNode() const         { return false; }
00137   virtual bool isExitNode() const               { return false; }
00138   virtual bool isMergeNode() const              { return false; }
00139   virtual bool isBranchNode() const             { return false; }
00140   virtual bool isBlockCreateNode() const        { return false; }
00141   virtual bool isContextCreateNode() const      { return false; }
00142   virtual bool isContextInitNode() const        { return false; }
00143   virtual bool isContextZapNode() const         { return false; }
00144   virtual bool isCommentNode() const            { return false; }
00145   virtual bool isSendNode() const               { return false; }
00146   virtual bool isCallNode() const               { return false; }
00147   virtual bool isStoreNode() const              { return false; }
00148   virtual bool isDeadEndNode() const            { return false; }
00149   virtual bool isTypeTestNode() const           { return false; }
00150   virtual bool isUncommonNode() const           { return false; }
00151   virtual bool isNopNode() const                { return false; }
00152   virtual bool isCmpNode() const                { return false; }
00153   virtual bool isArraySizeLoad() const          { return false; }
00154   virtual bool isAccessingFloats() const        { return false; }
00155   virtual bool isTrivial() const                = 0;
00156 
00157   protected:
00158   virtual Node* clone(PReg* from, PReg* to) const { SubclassResponsibility(); return NULL; }
00159   void genPcDesc();
00160  public:
00161   // for splitting: rough estimate of space cost of node (in bytes)
00162   virtual int  cost() const                     { return oopSize; }     
00163   virtual bool hasDest() const                  { return false; }
00164   virtual bool canCopyPropagate() const         { return false; }
00165         // canCopyPropagate: can node replace a use with copy-propagated PReg?
00166         // if true, must implement copyPropagate below
00167           bool canCopyPropagate(Node* fromNode) const; // can copy-propagate from fromNode to receiver?
00168   virtual bool copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false) = 0;
00169   virtual bool canCopyPropagateOop() const      { return false; }
00170         // canCopyPropagateOop: can node replace a use with a copy-propagated 
00171         // oop?  if true, must handle ConstPRegs; implies canCopyPropagate
00172   virtual bool isAssignmentLike() const         { return false; }
00173         // isAssignmentLike: node copies src to dest (implies hasSrc/Dest)
00174   virtual bool shouldCopyWhenSplitting() const  { return false; }
00175   virtual bool hasSrc() const                   { return false; }
00176   virtual bool hasConstantSrc() const           { return false; }
00177   virtual oop  constantSrc() const              { ShouldNotCallThis(); return 0; }
00178   virtual bool canChangeDest() const            { assert(hasDest(), "shouldn't call"); return true; }
00179 
00180   virtual bool endsBB() const                   = 0;
00181   virtual bool startsBB() const                 { return false; }
00182 
00183   int loopDepth() const                         { return _bb->loopDepth(); }
00184 
00185   virtual BB* newBB();
00186   virtual void makeUses(BB* bb) { Unused(bb); }
00187   virtual void removeUses(BB* bb) { Unused(bb); }
00188   virtual void eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false) = 0;
00189   virtual bool canBeEliminated() const { return !dontEliminate; }
00190   virtual void computeEscapingBlocks(GrowableArray<BlockPReg*>* lst) { Unused(lst); }
00191   virtual void markAllocated(int* use_count, int* def_count) = 0;
00192   virtual SimpleBitVector trashedMask();
00193   virtual void gen();
00194   virtual void apply(NodeVisitor* v)            { ShouldNotCallThis(); }
00195   virtual Node* likelySuccessor() const = 0;    // most likely code path
00196   virtual Node* uncommonSuccessor() const = 0;  // code path taken only in uncommon situations
00197   void removeUpToMerge();                       // remove all nodes from this to next merge
00198   Node* copy(PReg* from, PReg* to) const;       // make a copy, substituting 'to' wherever 'from' is used
00199   
00200   // for type test / loop optimization
00201   // If a node includes one or more type tests of its argument(s), it should return true for doesTypeTests
00202   // and implement the other four methods in this group.  It can then benefit from type test optimizations
00203   // (e.g., moving a test out of a loop).
00204   virtual bool doesTypeTests()  const { return false; }       // does node perform any type test?
00205   virtual bool hasUnknownCode() const { return false; }       // does handle unknown cases? (with real code, not uncommon branch)
00206   virtual void collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const { ShouldNotCallThis(); }
00207           // return a list of pregs tested and, for each preg, a list of its types
00208   virtual void assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n) {} // assert that the klass of r (used by the reciver) is oneof(klasses)
00209   virtual void assert_in_bounds(PReg* r, LoopHeaderNode* n) {}// assert that r (used by the reciver) is within array bounds
00210 
00211   virtual void print_short();
00212   virtual void print()                  { print_short(); }
00213   virtual char* print_string(char* buf, bool printAddr = true) const = 0;
00214   void printID() const;
00215   virtual void verify() const {}
00216 
00217   // Mappings
00218   //
00219   // Note: make sure, mapping at node is always unchanged, once it is set.
00220 
00221   PRegMapping* mapping() const;
00222   bool hasMapping() const                       { return _mapping != NULL; }
00223   void setMapping(PRegMapping* mapping);
00224 };
00225 
00226 
00227 // Linking code for Nodes
00228 // originally: NodeClassTemplate(Node, BasicNode)
00229 
00230 class Node: public BasicNode {
00231  protected:
00232   Node *_prev, *_next;
00233   Node() { _prev = _next = NULL; }
00234 
00235  public:
00236   virtual bool endsBB() const;
00237   virtual Node* likelySuccessor() const;
00238   virtual Node* uncommonSuccessor() const;
00239   void eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00240   virtual void verify() const;
00241 
00242   friend class NodeFactory;
00243 
00244   // ----------- node linking behavior -----------
00245   virtual bool hasSingleSuccessor() const               { return true; }
00246   virtual bool hasSinglePredecessor() const             { return true; }
00247   virtual int nPredecessors() const                     { return _prev ? 1 : 0; }
00248   virtual int nSuccessors() const                       { return _next ? 1 : 0; }
00249   virtual bool isPredecessor(const Node* n) const       { return _prev == n; }
00250   virtual bool isSuccessor(const Node* n) const         { return _next == n; }
00251   Node* next() const                                    { return _next; }
00252   virtual Node* next1() const                           { return NULL; }
00253   virtual Node* next(int i) const {
00254     if (i == 0) return _next; else { fatal("single next"); return NULL;} }
00255   virtual Node* firstPrev() const                       { return _prev; }
00256   virtual Node* prev(int n) const                       { if (n == 0) return _prev; else fatal("single prev"); return NULL; }
00257 
00258   virtual void setPrev(Node* p)                         { assert(_prev == NULL, "already set"); _prev = p; }
00259   virtual void movePrev(Node* from, Node* to)           { assert(_prev == from, "mismatched prev link"); _prev = to; }
00260 
00261   void setNext(Node* n)                                 { assert(_next == NULL, "already set"); _next = n; }
00262   virtual void setNext1(Node* n)                        { Unused(n); ShouldNotCallThis(); }
00263   virtual void setNext(int i, Node* n)                  { if (i == 0) setNext(n); else fatal("subclass"); }
00264   virtual void moveNext(Node* from, Node* to)           { assert(_next == from, "mismatched next link"); _next = to; }
00265 
00266  protected:
00267   virtual void removeMe();
00268   Node* endOfList() const;
00269 
00270  public:  // really should be private, but C++ has instance- rather than class-based privacy -- don't you love it?
00271   virtual void removePrev(Node* n);
00272 
00273  public:
00274   virtual void removeNext(Node* n);                     // cut the next link between this and n 
00275   Node* append(Node* p)                                 { setNext(p);  p->setPrev(this); return p; }
00276   Node* append1(Node* p)                                { setNext1(p); p->setPrev(this); return p; }
00277   Node* append(int i, Node* p)                          { setNext(i, p);  p->setPrev(this); return p; }
00278   Node* appendEnd(Node* p)                              { return endOfList()->append(p); }
00279 
00280   void insertNext(Node* n) {
00281     assert(hasSingleSuccessor(), ">1 successors");
00282     n->setNext(_next); n->setPrev(this);
00283     _next->movePrev(this, n); _next = n; }
00284   void insertPrev(Node* n) {
00285     assert(n->hasSinglePredecessor(), "where to insert?");
00286     n->setPrev(_prev); n->setNext(this);
00287     _prev->moveNext(this, n); _prev = n; }
00288 
00289   friend class NodeBuilder;
00290 };
00291 
00292 
00293 class TrivialNode: public Node {
00294  public:
00295   bool isTrivial() const                { return true; }
00296   int  cost() const                     { return 0; }
00297   bool copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false) { return false; }
00298   void markAllocated(int* use_count, int* def_count) {}
00299 
00300   // may need to implement several inherited dummy methods here -- most
00301   // will do nothing
00302 
00303   friend class NodeFactory;
00304 };
00305 
00306 
00307 class NonTrivialNode: public Node {
00308  protected:
00309   PReg* _dest;                          // not all nodes actually have src & dest,
00310   PReg* _src;                           // but they're declared here for convenience
00311   Use*  srcUse;                         // and easier code sharing
00312   Def*  destDef;
00313 
00314   NonTrivialNode();
00315 
00316  public:
00317   bool  isTrivial() const               { return false; }
00318   PReg* src() const;
00319   PReg* dest() const;
00320   PReg* dst() const                     { return dest(); }
00321   void  setDest(BB* bb, PReg* d);
00322   virtual bool copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00323   void  makeUses(BB* bb);
00324   void  removeUses(BB* bb);
00325   void  verify() const;
00326 
00327   friend class NodeFactory;
00328 };
00329 
00330 
00331 class PrologueNode : public NonTrivialNode {
00332  protected:
00333   LookupKey*  _key;
00334   const int   _nofArgs;
00335   const int   _nofTemps;
00336 
00337   PrologueNode(LookupKey* key, int nofArgs, int nofTemps) : _nofArgs(nofArgs), _nofTemps(nofTemps) {
00338     _key        = key;
00339   }
00340 
00341  public:
00342   bool isPrologueNode() const           { return true; }
00343   virtual bool canChangeDest() const    { return false; }       // has no dest
00344   Node* clone(PReg* from, PReg* to) const;
00345   void makeUses(BB* bb);
00346   void removeUses(BB* bb) { ShouldNotCallThis(); }
00347   void gen();
00348   void apply(NodeVisitor* v)            { v->aPrologueNode(this); }
00349   bool canBeEliminated() const          { return false; }
00350   void markAllocated(int* use_count, int* def_count) {
00351     Unused(use_count); Unused(def_count); }
00352   char* print_string(char* buf, bool printAddr = true) const;
00353 
00354   friend class NodeFactory;
00355 };
00356 
00357 
00358 class LoadNode: public NonTrivialNode {
00359  protected:
00360   LoadNode(PReg* d)                     { _dest = d; assert(d, "dest is NULL"); }
00361 
00362  public:
00363   bool hasDest() const                  { return true; }
00364   bool canCopyPropagate() const         { return true; }
00365   bool canCopyPropagateOop() const      { return true; }
00366   void makeUses(BB* bb);
00367   void removeUses(BB* bb);
00368   void markAllocated(int* use_count, int* def_count);
00369   void eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00370 
00371   friend class NodeFactory;
00372 };
00373 
00374 
00375 class LoadIntNode: public LoadNode {
00376  protected:
00377   int _value;           // constant (vm-level, not an oop) to be loaded
00378 
00379   LoadIntNode(PReg* dst, int value) : LoadNode(dst) { _value = value; }
00380 
00381  public:
00382   Node* clone(PReg* from, PReg* to) const;
00383   int   value()                         { return _value; }
00384   void  gen();
00385   void  apply(NodeVisitor* v)           { v->aLoadIntNode(this); }
00386   char* print_string(char* buf, bool printAddr = true) const;
00387 
00388   friend class NodeFactory;
00389 };
00390 
00391 
00392 class LoadOffsetNode: public LoadNode {
00393  public:
00394   // _src is base address (e.g. object containing a slot)
00395   int   offset;         // offset in words
00396   bool  isArraySize;    // is this load implementing an array size primitive?
00397 
00398  protected:
00399   LoadOffsetNode(PReg* dst, PReg* b, int offs, bool arr) : LoadNode(dst) {
00400     _src = b; offset = offs; isArraySize = arr; }
00401 
00402  public:
00403   Node* clone(PReg* from, PReg* to) const;
00404   PReg* base() const                    { return _src; }
00405   bool  hasSrc() const                  { return true; }
00406   bool  isArraySizeLoad() const         { return isArraySize; }
00407   void  makeUses(BB* bb);
00408   void  removeUses(BB* bb);
00409   void  markAllocated(int* use_count, int* def_count);
00410   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00411   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00412   void  gen();
00413   void  apply(NodeVisitor* v)           { v->aLoadOffsetNode(this); }
00414   void  verify() const;
00415   char* print_string(char* buf, bool printAddr = true) const;
00416 
00417   friend class NodeFactory;
00418 };
00419 
00420 
00421 class LoadUplevelNode: public LoadNode {
00422  private:
00423   Use*          _context0Use;
00424   PReg*         _context0;              // starting context
00425   int           _nofLevels;             // no. of indirections to follow via context home field
00426   int           _offset;                // offset of temporary in final context
00427   symbolOop     _name;                  // temporary name (for printing)
00428 
00429  protected:
00430   LoadUplevelNode(PReg* dst, PReg* context0, int nofLevels, int offset, symbolOop name);
00431 
00432  public:
00433   PReg* context0() const                { return _context0; }
00434   int   nofLevels() const               { return _nofLevels; }
00435   int   offset() const                  { return _offset; }
00436   Node* clone(PReg* from, PReg* to) const;
00437   void  makeUses(BB* bb);
00438   void  removeUses(BB* bb);
00439   void  markAllocated(int* use_count, int* def_count);
00440   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00441   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00442   void  gen();
00443   void  apply(NodeVisitor* v)           { v->aLoadUplevelNode(this); }
00444   void  verify() const;
00445   char* print_string(char* buf, bool printAddr = true) const;
00446 
00447   friend class NodeFactory;
00448 };
00449 
00450 
00451 class StoreNode: public NonTrivialNode {
00452  protected:
00453   StoreNode(PReg* s)                    { _src = s; assert(_src, "src is NULL"); }
00454 
00455  public:
00456   bool isStoreNode() const              { return true; }
00457   bool canCopyPropagate() const         { return true; }
00458   bool canCopyPropagateOop() const      { return true; }
00459   bool hasSrc() const                   { return true; }
00460   virtual bool needsStoreCheck() const  { return false; }
00461   virtual char* action() const          = NULL;         // for debugging messages
00462   virtual void setStoreCheck(bool ncs)  {}
00463   void assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n);
00464   void makeUses(BB* bb);
00465   void removeUses(BB* bb);
00466   void markAllocated(int* use_count, int* def_count);
00467   void eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00468   void computeEscapingBlocks(GrowableArray<BlockPReg*>* l);
00469 
00470   friend class NodeFactory;
00471 };
00472 
00473 
00474 class StoreOffsetNode: public StoreNode {
00475   // store into data slot, do check-store if necessary
00476   // _src is value being stored, may be a ConstPReg*
00477  private:
00478   PReg* _base;                          // base address (object containing the slot)
00479   Use*  _baseUse;
00480   int   _offset;                        // offset in words
00481   bool  _needsStoreCheck;               // does store need a GC store check?
00482 
00483  protected:
00484   StoreOffsetNode(PReg* s, PReg* b, int o, bool nsc) : StoreNode(s) {
00485     _base = b; assert(b, "base is NULL"); _offset = o; _needsStoreCheck = nsc; }
00486 
00487  public:
00488   PReg* base() const                    { return _base; }
00489   int   offset() const                  { return _offset; }
00490   bool  needsStoreCheck() const         { return _needsStoreCheck; }
00491   bool  hasSrc() const                  { return true; }
00492   void  setStoreCheck(bool ncs)         { _needsStoreCheck = ncs; }
00493   char* action() const                  { return "stored into an object"; }
00494   Node* clone(PReg* from, PReg* to) const;
00495   void  makeUses(BB* bb);
00496   void  removeUses(BB* bb);
00497   void  markAllocated(int* use_count, int* def_count);
00498   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00499   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00500   bool  canBeEliminated() const         { return false; }
00501   void  gen();
00502   void  apply(NodeVisitor* v)           { v->aStoreOffsetNode(this); }
00503   void  verify() const;
00504   char* print_string(char* buf, bool printAddr = true) const;
00505 
00506   friend class NodeFactory;
00507 };
00508 
00509 
00510 class StoreUplevelNode: public StoreNode {
00511   // when node is created, it is not known whether store will be to stack/reg or context
00512   // _src may be a ConstPReg*
00513  private:
00514   Use*          _context0Use;
00515   PReg*         _context0;              // starting context
00516   int           _nofLevels;             // no. of indirections to follow via context home field
00517   int           _offset;                // offset of temporary in final context
00518   bool          _needsStoreCheck;       // generate a store check if true
00519   symbolOop     _name;                  // temporary name (for printing)
00520 
00521  protected:
00522   StoreUplevelNode(PReg* src, PReg* context0, int nofLevels, int offset, symbolOop name, bool needsStoreCheck);
00523 
00524  public:
00525   PReg* context0() const                { return _context0; }
00526   int   nofLevels() const               { return _nofLevels; }
00527   int   offset() const                  { return _offset; }
00528   bool  needsStoreCheck() const         { return _needsStoreCheck; }
00529   void  setStoreCheck(bool ncs)         { _needsStoreCheck = ncs; }
00530   char* action() const                  { return "stored into a context temporary"; }
00531   Node* clone(PReg* from, PReg* to) const;
00532   void  makeUses(BB* bb);
00533   void  removeUses(BB* bb);
00534   void  markAllocated(int* use_count, int* def_count);
00535   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00536   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00537   void  gen();
00538   void  apply(NodeVisitor* v)           { v->aStoreUplevelNode(this); }
00539   void  verify() const;
00540   char* print_string(char* buf, bool printAddr = true) const;
00541 
00542   friend class NodeFactory;
00543 };
00544   
00545 
00546 class AssignNode : public StoreNode {
00547   // _src may be a ConstPReg*
00548  protected:
00549   AssignNode(PReg* s, PReg* d);
00550 
00551  public:
00552   int   cost() const                    { return oopSize/2; }  // assume 50% eliminated
00553   bool  isAccessingFloats() const;
00554   bool  isAssignNode() const            { return true; }
00555   bool  hasDest() const                 { return true; }
00556   bool  hasSrc() const                  { return true; }
00557   bool  hasConstantSrc() const          { return _src->isConstPReg(); }
00558   bool  isAssignmentLike() const        { return true; }
00559   bool  shouldCopyWhenSplitting() const { return true; }
00560   bool  canBeEliminated() const;
00561   oop   constantSrc() const;
00562   char* action() const                  { return _dest->isSAPReg() ? 
00563                                                   "passed as an argument" : "assigned to a local"; }
00564   Node* clone(PReg* from, PReg* to) const;
00565   void  makeUses(BB* bb);
00566   void  removeUses(BB* bb);
00567   void  markAllocated(int* use_count, int* def_count);
00568   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00569   void  gen();
00570   void  apply(NodeVisitor* v)           { v->anAssignNode(this); }
00571   char* print_string(char* buf, bool printAddr = true) const;
00572 
00573  protected:
00574   void  genOop();
00575 
00576   friend class NodeFactory;
00577 };
00578   
00579 
00580 class AbstractReturnNode: public NonTrivialNode {
00581  protected:
00582   AbstractReturnNode(int bci, PReg* src, PReg* dest)    { _bci = bci; _src = src; _dest = dest; }
00583 
00584  public:
00585   bool  canBeEliminated() const         { return false; }
00586   bool  isReturnNode() const            { return true; }
00587   bool  endsBB() const                  { return true; }
00588   bool  canCopyPropagate() const        { return true; }
00589   bool  canCopyPropagateOop() const     { return true; }
00590   bool  hasSrc() const                  { return true; }
00591   bool  isAssignmentLike() const        { return true; }
00592   bool  hasDest() const                 { return true; }
00593   void  makeUses(BB* bb);
00594   void  removeUses(BB* bb);
00595   void  computeEscapingBlocks(GrowableArray<BlockPReg*>* l);
00596   void  markAllocated(int* use_count, int* def_count) { Unused(use_count); Unused(def_count); }
00597 
00598   friend class NodeFactory;
00599 };
00600 
00601 
00602 class InlinedReturnNode: public AbstractReturnNode {
00603   // should replace with AssignNode + ContextZap (if needed)
00604  protected:
00605   InlinedReturnNode(int bci, PReg* src, PReg* dest) : AbstractReturnNode(bci, src, dest) {}
00606 
00607  public:
00608   bool  isInlinedReturnNode() const     { return true; }
00609   bool  endsBB() const                  { return NonTrivialNode::endsBB(); }
00610   bool  isTrivial() const               { return true; }
00611   bool  canBeEliminated() const         { return true; }
00612   bool  shouldCopyWhenSplitting() const { return true; }
00613   int   cost() const                    { return 0; }
00614   Node* clone(PReg* from, PReg* to) const;
00615   void  gen();
00616   void  apply(NodeVisitor* v)           { v->anInlinedReturnNode(this); }
00617   void  verify() const;
00618   char* print_string(char* buf, bool printAddr = true) const;
00619 
00620   friend class NodeFactory;
00621 };
00622 
00623 
00624 // The NLRSetupNode starts an NLR by setting up two of the three special NLR regs
00625 // (home fp and home scope ID); it assumes the NLR result already is in NLRResultReg
00626 // (so that the setup code can be shared).
00627 // next() is the NLRContinuationNode that actually does the NLR.  (Functionality is split
00628 // up because the NLRContinuationNode may be shared with NLRTestNodes.)
00629 
00630 class NLRSetupNode: public AbstractReturnNode {
00631   Use*  resultUse;
00632   Use*  contextUse;                     // needs context to load home FP
00633  protected:
00634   NLRSetupNode(PReg* result, int bci);
00635 
00636  public:
00637   bool  isExitNode() const              { return true; }
00638   bool  isNLRSetupNode() const          { return true; }
00639   // uses hardwired regs, has no src or dest
00640   bool  canCopyPropagate() const        { return false; }
00641   bool  canCopyPropagateOop() const     { return false; }
00642   bool  hasSrc() const                  { return false; }
00643   bool  isAssignmentLike() const        { return false; }
00644   bool  hasDest() const                 { return false; }
00645   bool  canChangeDest() const           { return false; }       // has no dest
00646   Node* clone(PReg* from, PReg* to) const;
00647   void  makeUses(BB* bb);
00648   void  removeUses(BB* bb);
00649   void  gen();
00650   void  apply(NodeVisitor* v)           { v->aNLRSetupNode(this); }
00651   void  verify() const;
00652   char* print_string(char* buf, bool printAddr = true) const;
00653 
00654   friend class NodeFactory;
00655 };
00656 
00657 
00658 class NLRContinuationNode: public AbstractReturnNode {
00659  protected:
00660   NLRContinuationNode(int bci, PReg* src, PReg* dest) : AbstractReturnNode(bci, src, dest) { }
00661 
00662  public:
00663   bool  isExitNode() const              { return true; }
00664   bool  isNLRContinuationNode() const   { return true; }
00665   // uses hardwired regs, has no src or dest
00666   bool  canCopyPropagate() const        { return false; }
00667   bool  canCopyPropagateOop() const     { return false; }
00668   bool  hasSrc() const                  { return false; }
00669   bool  isAssignmentLike() const        { return false; }
00670   bool  hasDest() const                 { return false; }
00671   bool  canChangeDest() const           { return false; }       // has no dest
00672   Node* clone(PReg* from, PReg* to) const;
00673   void  makeUses(BB* bb);
00674   void  removeUses(BB* bb);
00675   void  gen();
00676   void  apply(NodeVisitor* v)           { v->aNLRContinuationNode(this); }
00677   void  verify() const;
00678   char* print_string(char* buf, bool printAddr = true) const;
00679 
00680   friend class NodeFactory;
00681 };
00682 
00683 
00684 // normal method return
00685 class ReturnNode: public AbstractReturnNode {
00686  private:
00687   Use*  resultUse;
00688 
00689  protected:
00690   ReturnNode(PReg* res, int bci);
00691 
00692  public:
00693   Node* clone(PReg* from, PReg* to) const;
00694   bool  isExitNode() const              { return true; }
00695   bool  hasSrc() const                  { return false; }
00696   bool  isAssignmentLike() const        { return false; }
00697   bool  hasDest() const                 { return false; }
00698   void  makeUses(BB* bb);
00699   void  removeUses(BB* bb);
00700   void  markAllocated(int* use_count, int* def_count);
00701   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00702   void  gen();
00703   void  apply(NodeVisitor* v)           { v->aReturnNode(this); }
00704   void  verify() const;
00705   char* print_string(char* buf, bool printAddr = true) const;
00706 
00707   friend class NodeFactory;
00708 };
00709 
00710 
00711 // Linking code for MergeNodes
00712 // originally: MergeNodeClassTemplate(AbstractMergeNode, Node, GrowableArray<Node*>, TrivialNode, 3)
00713 
00714 class AbstractMergeNode: public TrivialNode {
00715  private:
00716   enum { N = 3 };
00717   /* n-way merge */
00718  protected:
00719   GrowableArray<Node*>* _prevs;
00720 
00721  public:
00722   AbstractMergeNode()                   { _prevs = new GrowableArray<Node*>(N); }
00723   AbstractMergeNode(Node* prev1, Node* prev2) {
00724     _prevs = new GrowableArray<Node*>(N);
00725     _prevs->append(prev1); prev1->setNext(this);
00726     _prevs->append(prev2); prev2->setNext(this);
00727   }
00728 
00729   bool hasSinglePredecessor() const     { return _prevs->length() <= 1; }
00730   int nPredecessors() const             { return _prevs->length(); }
00731   Node* firstPrev() const               { return _prevs->isEmpty() ? NULL : _prevs->at(0); }
00732 
00733   void setPrev(Node* p) {
00734     assert(p, "should be something");
00735     assert(!_prevs->contains(p), "shouldn't already be there");
00736     _prevs->append(p);
00737   }
00738 
00739   Node* prev(int n) const               { return _prevs->at(n); }
00740 
00741  protected:
00742   void removeMe();
00743   virtual void removePrev(Node* n) {
00744     /* cut the _prev link between this and n    */
00745     _prevs->remove(n);
00746   }
00747 
00748  public:
00749   void movePrev(Node* from, Node* to);
00750   bool isPredecessor(const Node* n) const;
00751 };
00752 
00753 
00754 class MergeNode : public AbstractMergeNode {
00755  protected:
00756   MergeNode(int bci);
00757   MergeNode(Node* prev1, Node* prev2);
00758   
00759  public:
00760   bool  isLoopStart;                    // does this node start a loop?
00761   bool  isLoopEnd;                      // does this node end a loop? (i.e., first node after loop)
00762   bool  didStartBB;                     // used for debugging / assertion checks
00763   int   cost() const                    { return 0; }
00764   bool  isTrivial() const               { return _prevs->length() <= 1; }
00765   bool  startsBB() const                { return _prevs->length() > 1 || isLoopStart; }
00766   bool  isMergeNode() const             { return true; }
00767   BB*   newBB();
00768   Node* clone(PReg* from, PReg* to) const;
00769   void  gen();
00770   void  apply(NodeVisitor* v)           { v->aMergeNode(this); }
00771   void  verify() const;
00772   char* print_string(char* buf, bool printAddr = true) const;
00773 
00774   friend class NodeFactory;
00775 };
00776     
00777 
00778 class ArithNode : public NonTrivialNode {       // abstract
00779   // NB: ArithNodes are not used for tagged int arithmetic -- see TArithNode
00780  protected:
00781   ArithOpCode   _op;
00782   ConstPReg*    _constResult;   // non-NULL if constant-folded
00783 
00784   ArithNode(ArithOpCode op, PReg* src, PReg* dst) {
00785     _op = op; _src = src; _dest = dst; _constResult = NULL;
00786   }
00787 
00788  public:
00789   bool          canCopyPropagate() const        { return true; }
00790   bool          canCopyPropagateOop() const     { return true; }
00791   bool          hasSrc() const                  { return true; }
00792   bool          hasDest() const                 { return true; }
00793   bool          isAssignmentLike() const        { return _constResult != NULL; }
00794   bool          isArithNode() const             { return true; }
00795   bool          isCmpNode() const               { return _op == tCmpArithOp; }
00796   void          makeUses(BB* bb);
00797   void          removeUses(BB* bb);
00798   void          markAllocated(int* use_count, int* def_count);
00799   void          eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00800   bool          copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00801   ArithOpCode   op() const                      { return _op; }
00802   virtual bool  operIsConst() const = 0;
00803   virtual int   operConst() const = 0;
00804   virtual bool  doCopyPropagate(BB* bb, Use* u, PReg* d, bool repl);
00805   char*         opName() const;
00806 
00807   friend class NodeFactory;
00808 };
00809 
00810 
00811 class ArithRRNode : public ArithNode {  // reg op reg => reg
00812  protected:
00813   PReg* _oper;
00814   Use*  _operUse;
00815 
00816   ArithRRNode(ArithOpCode o, PReg* s, PReg* o2, PReg* d);
00817 
00818  public:
00819   PReg* operand() const                         { return _oper; }
00820   Node* clone(PReg* from, PReg* to) const;
00821   bool  operIsConst() const;
00822   int   operConst() const;
00823   bool  doCopyPropagate(BB* bb, Use* u, PReg* d, bool replace);
00824   void  makeUses(BB* bb);
00825   void  removeUses(BB* bb);
00826   void  markAllocated(int* use_count, int* def_count);
00827   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
00828   void  gen();
00829   void  apply(NodeVisitor* v)                   { v->anArithRRNode(this); }
00830   void  verify() const;
00831   char* print_string(char* buf, bool printAddr = true) const;
00832 
00833   friend class NodeFactory;
00834 };
00835 
00836 
00837 class FloatArithRRNode : public ArithRRNode {  // for untagged float operations
00838   FloatArithRRNode(ArithOpCode o, PReg* s, PReg* o2, PReg* d) : ArithRRNode(o, s, o2, d) { }
00839  public:
00840   bool  isAccessingFloats() const               { return true; }
00841   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00842   void  gen();
00843   void  apply(NodeVisitor* v)                   { v->aFloatArithRRNode(this); }
00844   void  verify() const;
00845   char* print_string(char* buf, bool printAddr = true) const;
00846 
00847   friend class NodeFactory;
00848 };
00849 
00850 
00851 class FloatUnaryArithNode : public ArithNode {  
00852   // unary untagged float operation; src is an untagged float, dest is either another
00853   // untagged float or a floatOop
00854   FloatUnaryArithNode(ArithOpCode op, PReg* src, PReg* dst) : ArithNode(op, src, dst) {}
00855  public:
00856   bool  isAccessingFloats() const               { return true; }
00857   bool  isCmpNode() const                       { return false; }
00858   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00859   bool  operIsConst() const                     { return false; }
00860   int   operConst() const                       { ShouldNotCallThis(); return 0; }
00861   void  gen();
00862   void  apply(NodeVisitor* v)                   { v->aFloatUnaryArithNode(this); }
00863   void  verify() const;
00864   char* print_string(char* buf, bool printAddr = true) const;
00865   friend class NodeFactory;
00866 };
00867 
00868 
00869 class ArithRCNode : public ArithNode {  // reg op const => reg
00870   // used to compare against non-oop constants (e.g. for markOop test)
00871   // DO NOT USE to add a reg and an oop constant -- use ArithRR + ConstPRegs for that
00872  protected:
00873   int   _oper;
00874 
00875   ArithRCNode(ArithOpCode o, PReg* s, int o2, PReg* d)
00876     : ArithNode(o, s, d) { _oper = o2; }
00877 
00878  public:
00879   int   operand() const                         { return _oper; }
00880   Node* clone(PReg* from, PReg* to) const;
00881   void  gen();
00882   void  apply(NodeVisitor* v)                   { v->anArithRCNode(this); }
00883   bool  operIsConst() const                     { return true; }
00884   int   operConst() const                       { return _oper; }
00885   char* print_string(char* buf, bool printAddr = true) const;
00886 
00887   friend class NodeFactory;
00888 };
00889 
00890 // node with >1 successor; supplies linking code (next(i) et al.) and some default behavior
00891 class AbstractBranchNode : public NonTrivialNode {
00892   // next() is the fall-through case, next1() the taken branch
00893  public:
00894   virtual bool  canFail() const = NULL;         // does node have a failure branch?
00895   virtual Node* failureBranch() const           { return next1(); }
00896   bool          endsBB() const                  { return true; }
00897  protected:
00898   AbstractBranchNode()                          { _nxt = new GrowableArray<Node*>(EstimatedSuccessors); }
00899   void          removeFailureIfPossible();
00900   void          verify(bool verifySuccessors) const;
00901 
00902   // ---------- node linking code --------------
00903  private:
00904   enum { EstimatedSuccessors = 2 };             // most nodes have only 2 successors
00905  protected:
00906   GrowableArray<Node*>* _nxt;                   /* elem 0 is next1 */
00907  public:
00908 
00909   Node* next1() const                           { return _nxt->length() ? _nxt->at(0) : NULL; }
00910   bool hasSingleSuccessor() const               { return next1() == NULL; }
00911   int nSuccessors() const                       { return _nxt->length() + (_next ? 1 : 0); }
00912   Node* next() const                            { return _next; }
00913   Node* next(int i) const                       { return i == 0 ? _next : _nxt->at(i-1); }
00914 
00915   void removeMe();
00916   void removeNext(Node* n);
00917 
00918   void setNext1(Node* n) {
00919     assert(_nxt->length() == 0, "already set");
00920     _nxt->append(n);
00921   }
00922 
00923   void setNext(Node* n)                         { NonTrivialNode::setNext(n); }
00924   void setNext(int i, Node* n);
00925   void moveNext(Node* from, Node* to);
00926   bool isSuccessor(const Node* n) const;
00927 };
00928 
00929 class TArithRRNode : public AbstractBranchNode {  
00930   // tagged arithmetic operation; next() is sucess case, next1()
00931   // is failure (leaving ORed operands in Temp1 for tag test)
00932  protected:
00933   ArithOpCode   _op;
00934   PReg*         _oper;
00935   Use*          _operUse;
00936   bool          _arg1IsInt;                     // is _src a smi?
00937   bool          _arg2IsInt;                     // is _oper a smi?
00938   ConstPReg*    _constResult;                   // non-NULL if constant-folded
00939 
00940   TArithRRNode(ArithOpCode o, PReg* s, PReg* o2, PReg* d, bool a1, bool a2);
00941 
00942  public:
00943   ArithOpCode   op() const                      { return _op; }
00944   PReg*         operand() const                 { return _oper; }
00945   bool          arg1IsInt() const               { return _arg1IsInt; }
00946   bool          arg2IsInt() const               { return _arg2IsInt; }
00947   bool          canFail() const                 { return !(_arg1IsInt && _arg2IsInt); }
00948   bool          isTArithNode() const            { return true; }
00949   bool          isAssignmentLike() const        { return _constResult != NULL; }
00950   bool          canCopyPropagate() const        { return true; }
00951   bool          canCopyPropagateOop() const     { return true; }
00952   bool          hasSrc() const                  { return true; }
00953   bool          hasDest() const                 { return true; }
00954 
00955   bool          doesTypeTests()  const          { return true; }
00956   bool          hasUnknownCode() const;
00957   void          collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const;
00958   void          assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n);
00959 
00960   void          makeUses(BB* bb);
00961   void          removeUses(BB* bb);
00962   void          markAllocated(int* use_count, int* def_count);
00963   Node*         clone(PReg* from, PReg* to) const;
00964   bool          copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00965   Node*         likelySuccessor() const;
00966   Node*         uncommonSuccessor() const;
00967   void          gen();
00968   void          apply(NodeVisitor* v)           { v->aTArithRRNode(this); }
00969   void          verify() const;
00970   char*         print_string(char* buf, bool printAddr = true) const;
00971 
00972  protected:
00973   bool          doCopyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
00974 
00975   friend class NodeFactory;
00976 };
00977 
00978 
00979 class CallNode : public AbstractBranchNode {
00980   // next1 is the NLR branch (if there is one)
00981   // dest() is the return value
00982  protected:
00983   CallNode(MergeNode* n, GrowableArray<PReg*>* args, GrowableArray<PReg*>* exprs);
00984   
00985  public:
00986   GrowableArray<PReg*>* exprStack;      // current expr. stack for debugging info (NULL if not needed)
00987   GrowableArray<Use*>*  argUses;        // uses for args and receiver
00988   GrowableArray<PReg*>* uplevelUsed;    // PRegs potentially uplevel-read during this call (NULL if not needed)
00989   GrowableArray<PReg*>* uplevelDefd;    // PRegs potentially uplevel-written during this call (NULL if not needed)
00990   GrowableArray<Use*>*  uplevelUses;    // uses for uplevel-read names
00991   GrowableArray<Def*>*  uplevelDefs;    // defs for uplevel-written names
00992   GrowableArray<PReg*>* args;           // args including receiver (at index 0, followed by first arg), or NULL
00993   int                   nblocks;        // number of possibly live blocks at this point (for uplevel access computation)
00994         
00995   bool hasDest() const                  { return true; }
00996   bool isCallNode() const               { return true; }
00997   bool canChangeDest() const            { return false; }
00998   bool canBeEliminated() const          { return false; }
00999   virtual bool canInvokeDelta() const = NULL;   // can call invoke Delta code?
01000   MergeNode* nlrTestPoint() const;
01001   Node* likelySuccessor() const;
01002   Node* uncommonSuccessor() const;
01003   bool copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
01004   void computeEscapingBlocks(GrowableArray<BlockPReg*>* ll);
01005   void makeUses(BB* bb);
01006   void removeUses(BB* bb);
01007   void markAllocated(int* use_count, int* def_count);
01008   SimpleBitVector trashedMask();
01009   void nlrCode();                       // generate NLR code sequence
01010   void verify() const;
01011 
01012   friend class NodeFactory;
01013 };
01014 
01015 
01016 class SendNode : public CallNode {
01017  protected:
01018   LookupKey* _key;        // lookup key (for selector)
01019   bool       _superSend;  // is it a super send?
01020   SendInfo*  _info;       // to set CompiledIC flags (counting, uninlinable, etc.)
01021 
01022   SendNode(
01023     LookupKey* key,
01024     MergeNode* nlrTestPoint,
01025     GrowableArray<PReg*>* args,
01026     GrowableArray<PReg*>* exprStk,
01027     bool superSend,
01028     SendInfo* info
01029   );
01030 
01031  public:
01032   bool  isSendNode() const              { return true; }
01033   bool  isSuperSend() const             { return _superSend; }
01034   bool  isCounting() const;
01035   bool  isUninlinable() const;
01036   bool  staticReceiver() const;
01037   bool  canInvokeDelta() const          { return true; }
01038   bool  canFail() const                 { return false; }
01039   int   cost() const                    { return oopSize * 5; }   // include IC + some param pushing
01040   PReg* recv() const;
01041   Node* clone(PReg* from, PReg* to) const;
01042   void  computeEscapingBlocks(GrowableArray<BlockPReg*>* ll);
01043   void  gen();
01044   void  apply(NodeVisitor* v)           { v->aSendNode(this); }
01045   char* print_string(char* buf, bool printAddr = true) const;
01046 
01047   friend class NodeFactory;
01048 };
01049 
01050 
01051 class PrimNode: public CallNode {
01052  protected:
01053   primitive_desc*       _pdesc;
01054 
01055   PrimNode(primitive_desc* pdesc, MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack);
01056 
01057  public:
01058   bool                  canBeEliminated() const;
01059   bool                  canInvokeDelta() const;
01060   bool                  canFail() const;
01061   primitive_desc*       pdesc() const           { return _pdesc; }
01062   Node*                 clone(PReg* from, PReg* to) const;
01063   void                  computeEscapingBlocks(GrowableArray<BlockPReg*>* ll);
01064   void                  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01065   void                  gen();
01066   void                  apply(NodeVisitor* v)   { v->aPrimNode(this); }
01067   char*                 print_string(char* buf, bool printAddr = true) const;
01068 
01069   friend class NodeFactory;
01070 };
01071 
01072 
01073 class DLLNode: public CallNode {
01074  protected:
01075   symbolOop     _dll_name;
01076   symbolOop     _function_name;
01077   dll_func      _function;
01078   bool          _async;
01079 
01080   DLLNode(symbolOop dll_name, symbolOop function_name, dll_func function, bool async,
01081           MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack);
01082 
01083  public:
01084   bool          canInvokeDelta() const;
01085   bool          canFail() const                 { return true; }
01086   int           nofArguments() const            { return args == NULL ? 0 : args->length(); }
01087   symbolOop     dll_name() const                { return _dll_name; }
01088   symbolOop     function_name() const           { return _function_name; }
01089   dll_func      function() const                { return _function; }
01090   bool          async() const                   { return _async; }
01091   void          computeEscapingBlocks(GrowableArray<BlockPReg*>* ll);
01092   Node*         clone(PReg* from, PReg* to) const;
01093   void          gen();
01094   void          apply(NodeVisitor* v)           { v->aDLLNode(this); }
01095   char*         print_string(char* buf, bool printAddr = true) const;
01096 
01097   friend class NodeFactory;
01098 };
01099 
01100 
01101 class InterruptCheckNode : public PrimNode {
01102  protected:
01103   static primitive_desc* _intrCheck;
01104 
01105   InterruptCheckNode(GrowableArray<PReg*>* exprs)
01106     : PrimNode(_intrCheck, NULL, NULL, exprs) {}
01107 
01108  public:
01109   Node* clone(PReg* from, PReg* to) const;
01110   void  gen();
01111   void  apply(NodeVisitor* v)           { Unimplemented(); }
01112   char* print_string(char* buf, bool printAddr = true) const;
01113 
01114   friend void node_init();
01115   friend class NodeFactory;
01116 };
01117 
01118 
01119 // a LoopHeaderNode is inserted before every loop; usually it is a no-op
01120 // for optimized integer loops, it does the pre-loop type tests
01121 class LoopHeaderNode : public TrivialNode {
01122  protected:
01123   // info for integer loops
01124   bool  _integerLoop;                                   // integer loop? (if no: inst. vars below are not set)
01125   PReg* _loopVar;                                       // loop variable
01126   PReg* _lowerBound;                                    // lower bound
01127   PReg* _upperBound;                                    // upper bound (or NULL; mutually exclusive with boundArray)
01128   LoadOffsetNode* _upperLoad;                           // loads array size that is the upper bound
01129   GrowableArray<AbstractArrayAtNode*>* _arrayAccesses;  // arrays indexed by loopVar
01130   // info for generic loops; all instance variables below this line are valid only after the loop optimization pass!
01131   GrowableArray<HoistedTypeTest*>* _tests;              // type tests hoisted out of loop
01132   bool _activated;                                      // gen() does nothing until activated
01133   LoopHeaderNode* _enclosingLoop;                       // enclosing loop or NULL
01134   GrowableArray<LoopHeaderNode*>* _nestedLoops;         // nested loops (NULL if none)
01135   int  _nofCalls;                                       // number of non-inlined calls in loop (excluding unlikely code)
01136   GrowableArray<LoopRegCandidate*>* _registerCandidates;// candidates for reg. allocation within loop (best comes first); NULL if none
01137 
01138   LoopHeaderNode();
01139 
01140  public:
01141   bool  isLoopHeaderNode() const                                { return true; }
01142   bool  isActivated() const                                     { return _activated; }
01143   bool  isInnerLoop() const                                     { return _nestedLoops == NULL; }
01144   bool  isIntegerLoop() const                                   { return _integerLoop; }
01145   PReg* loopVar() const                                         { return _loopVar; }
01146   PReg* lowerBound() const                                      { return _lowerBound; }
01147   PReg* upperBound() const                                      { return _upperBound; }
01148   LoadOffsetNode*                       upperLoad() const       { return _upperLoad; }
01149   GrowableArray<AbstractArrayAtNode*>*  arrayAccesses() const   { return _arrayAccesses; }
01150   GrowableArray<HoistedTypeTest*>*      tests() const           { return _tests; }
01151   Node* clone(PReg* from, PReg* to) const                       { ShouldNotCallThis(); return NULL; }
01152   int   nofCallsInLoop() const                                  { return _nofCalls; }
01153   void  set_nofCallsInLoop(int n)                               { _nofCalls = n; }
01154   void  activate(PReg* loopVar, PReg* lowerBound, PReg* upperBound, LoadOffsetNode* upperLoad);
01155   void  activate();                                             // for non-integer loops
01156   void  addArray(AbstractArrayAtNode* n);
01157   LoopHeaderNode* enclosingLoop() const                         { return _enclosingLoop; }
01158   void  set_enclosingLoop(LoopHeaderNode* l);
01159   GrowableArray<LoopHeaderNode*>* nestedLoops() const           { return _nestedLoops; }
01160   void  addNestedLoop(LoopHeaderNode* l);
01161   GrowableArray<LoopRegCandidate*>* registerCandidates() const  { return _registerCandidates; }
01162   void  addRegisterCandidate(LoopRegCandidate* c);
01163   void  gen();
01164   void  apply(NodeVisitor* v)                                   { v->aLoopHeaderNode(this); }
01165   char* print_string(char* buf, bool printAddr = true) const;
01166 
01167   friend class NodeFactory;
01168   friend class CompiledLoop;
01169  protected:
01170    void generateTypeTests(Label& cont, Label& failure);
01171    void generateIntegerLoopTests(Label& cont, Label& failure);
01172    void generateArrayLoopTests(Label& cont, Label& failure);
01173    void generateIntegerLoopTest(PReg* p, Label& cont, Label& failure);
01174    void handleConstantTypeTest(ConstPReg* r, GrowableArray<klassOop>* klasses);
01175 };
01176 
01177 
01178 class BlockCreateNode : public PrimNode {
01179   // Initializes block (closure) location with closure if it's
01180   // not a memoized block; and with 0 otherwise
01181   // src is NULL (but non-NULL for subclass instances)
01182  protected:
01183   PReg*                         _context;       // context or parameter/self that's copied into the block (or NULL)
01184   Use*                          _contextUse;    // use of _context 
01185 
01186   void materialize();                           // generates code to materialize the block
01187   void copyIntoContexts(Register val, Register t1, Register t2);    // helper for above
01188 
01189   BlockCreateNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack);
01190 
01191  public:
01192   bool  isBlockCreateNode() const       { return true; }
01193   // block creation nodes are like assignments if memoized, so don't end BBs here
01194   bool  endsBB() const                  { return !isMemoized() || NonTrivialNode::endsBB(); }
01195   BlockPReg* block() const              { assert(_dest->isBlockPReg(), "must be BlockPReg"); return (BlockPReg*)_dest; }
01196   bool  isMemoized() const              { return block()->isMemoized(); }
01197   bool  hasConstantSrc() const          { return false; }
01198   bool  hasSrc() const                  { return false; }
01199   int   cost() const                    { return 2*oopSize; }    // hope it's memoized 
01200   Node* clone(PReg* from, PReg* to) const;
01201   bool  canBeEliminated() const         { return !dontEliminate; }
01202   void  makeUses(BB* bb);
01203   void  removeUses(BB* bb);
01204   void  markAllocated(int* use_count, int* def_count);
01205   void  gen();
01206   void  apply(NodeVisitor* v)           { v->aBlockCreateNode(this); }
01207   void  verify() const;
01208   char* print_string(char* buf, bool printAddr = true) const;
01209 
01210   friend void node_init();
01211 
01212   friend class NodeFactory;
01213 };
01214 
01215 
01216 class BlockMaterializeNode : public BlockCreateNode {
01217   // Materializes (creates) a block if it has not been materialized yet (no-op if not a memoized block)
01218   // src and dest are the BlockPReg
01219  protected:
01220   BlockMaterializeNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack)
01221     : BlockCreateNode(b, expr_stack) { _src = _dest; }
01222 
01223  public:
01224   bool  endsBB() const                  { return true; }
01225   bool  hasSrc() const                  { return true; }
01226   int   cost() const                    { return 5*oopSize; } // assume blk is memoized
01227   Node* clone(PReg* from, PReg* to) const;
01228   void  makeUses(BB* bb);
01229   void  removeUses(BB* bb);
01230   void  markAllocated(int* use_count, int* def_count);
01231   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01232   void  gen();
01233   void  apply(NodeVisitor* v)           { v->aBlockMaterializeNode(this); }
01234   char* print_string(char* buf, bool printAddr = true) const;
01235 
01236   friend class NodeFactory;
01237 };
01238 
01239 
01240 class ContextCreateNode: public PrimNode {
01241   // src is parent context, dest is register holding created context
01242  protected:
01243   int                           _nofTemps;                      // no. of temps in context
01244   int                           _contextSize;                   // size of compiled context
01245   int                           _contextNo;                     // context number (index into compiler's contextList)
01246   GrowableArray<PReg*>*         _parentContexts;                // context chain above parent context (if any)
01247   GrowableArray<Use*>*          _parentContextUses;             // for _parentContexts
01248 
01249   ContextCreateNode(PReg* parent, PReg* context, int nofTemps, GrowableArray<PReg*>* expr_stack);
01250   ContextCreateNode(PReg* b, const ContextCreateNode* n, GrowableArray<PReg*>* expr_stack); // for cloning
01251 
01252  public:
01253   bool          hasSrc() const                                  { return _src != NULL; }
01254   bool          canChangeDest() const                           { return false; }
01255   bool          canBeEliminated() const                         { return false; }
01256   bool          isContextCreateNode() const                     { return true; }
01257   bool          canFail() const                                 { return false; }
01258   PReg*         context() const                                 { return _dest; }
01259   int           nofTemps() const                                { return _nofTemps; }
01260   int           sizeOfContext() const                           { return _contextSize; }
01261   void          set_sizeOfContext(int s )                       { _contextSize = s; }
01262   int           contextNo() const                               { return _contextNo; }
01263   void          set_contextNo(int s )                           { _contextNo = s; }
01264 
01265   Node*         clone(PReg* from, PReg* to) const;
01266   void          makeUses(BB* bb);
01267   void          removeUses(BB* bb);
01268   void          eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01269   void          markAllocated(int* use_count, int* def_count);
01270   void          gen();
01271   void          apply(NodeVisitor* v)                           { v->aContextCreateNode(this); }
01272   void          verify() const;
01273   char*         print_string(char* buf, bool printAddr = true) const;
01274 
01275   friend void   node_init();
01276 
01277   friend class NodeFactory;
01278 };
01279 
01280 
01281 class ContextInitNode: public NonTrivialNode {
01282   // initializes contents of context; src is context (if _src == NULL context was eliminated)
01283  protected:
01284   GrowableArray<Expr*>*         _initializers;          // arguments/nil to be copied into context
01285   GrowableArray<Def*>*          _contentDefs;
01286   GrowableArray<Use*>*          _initializerUses;
01287   GrowableArray<BlockMaterializeNode*>* _materializedBlocks;    // blocks that must be materialized
01288                                                                 // if this context is created
01289 
01290   ContextInitNode(ContextCreateNode* creator);
01291   ContextInitNode(PReg* b, const ContextInitNode* node);        // for cloning
01292 
01293  public:
01294   bool          hasSrc() const                          { return _src != NULL; }
01295   bool          hasDest() const                         { return false; }
01296   bool          isContextInitNode() const               { return true; }
01297   bool          canCopyPropagate() const                { return true; }
01298   bool          canBeEliminated() const                 { return false; }
01299   bool          wasEliminated() const                   { return _src == NULL; }
01300   GrowableArray<Expr*>* contents() const                { return scope()->contextTemporaries(); }
01301   int           nofTemps() const                        { return _initializers->length(); }
01302   Expr*         contextTemp(int i) const                { return contents()->at(i); }
01303   Expr*         initialValue(int i) const               { return _initializers->at(i); }
01304   void          addBlockMaterializer(BlockMaterializeNode* n);
01305   ContextCreateNode* creator() const;
01306   void          notifyNoContext();
01307   bool          hasNoContext() const                    { return _src == NULL; }
01308 
01309   void          initialize(int no, Expr* expr);         // to copy something into the context right after creation
01310   int           positionOfContextTemp(int i) const;     // position of ith context temp in compiled context 
01311   Node*         clone(PReg* from, PReg* to) const;
01312   void          makeUses(BB* bb);
01313   void          removeUses(BB* bb);
01314   void          eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01315   bool          copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
01316   void          markAllocated(int* use_count, int* def_count);
01317   void          computeEscapingBlocks(GrowableArray<BlockPReg*>* l);
01318   void          gen();
01319   void          apply(NodeVisitor* v)                   { v->aContextInitNode(this); }
01320   void          verify() const;
01321   char*         print_string(char* buf, bool printAddr = true) const;
01322 
01323   friend void   node_init();
01324 
01325   friend class NodeFactory;
01326 };
01327 
01328 
01329 class ContextZapNode: public NonTrivialNode {
01330 // placeholder for context zap code; zapping is only needed if the node isActive().
01331  private:
01332   ContextZapNode(PReg* context)                 { _src = context; assert(_src, "src is NULL"); }
01333   
01334  public:
01335   bool  isActive() const                        { return scope()->needsContextZapping(); }
01336   bool  isContextZapNode() const                { return true; }
01337   bool  hasSrc() const                          { return true; }
01338   bool  shouldCopyWhenSplitting() const         { return true; }
01339   PReg* context() const                         { return _src; }
01340 
01341   Node* clone(PReg* from, PReg* to) const;
01342   void  makeUses(BB* bb);
01343   void  removeUses(BB* bb);
01344   void  markAllocated(int* use_count, int* def_count);
01345   void  gen();
01346   void  apply(NodeVisitor* v)                   { v->aContextZapNode(this); }
01347   void  verify() const;
01348   char* print_string(char* buf, bool printAddr = true) const;
01349 
01350   friend class NodeFactory;
01351 };
01352 
01353 
01354 class NLRTestNode: public AbstractBranchNode {
01355   // placeholder for NLR test code: tests if NLR reached home scope, zaps context (if needed), then
01356   // returns from method (if home scope found) or continues the NLR
01357   // next() is the "continue NLR" branch, next1() the "found home" branch
01358  protected:
01359   NLRTestNode(int bci);
01360 
01361  public:
01362   bool  isNLRTestNode() const                   { return true; }
01363   bool  canChangeDest() const                   { return false; }
01364   bool  canBeEliminated() const                 { return false; }
01365   bool  canFail() const                         { return false; }
01366   void  fixup();                                // connect next() and next1() to sender scopes
01367 
01368   Node* clone(PReg* from, PReg* to) const;
01369   void  makeUses(BB* bb);
01370   void  removeUses(BB* bb);
01371   // void eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01372   void  markAllocated(int* use_count, int* def_count) {};
01373   Node* likelySuccessor() const;
01374   Node* uncommonSuccessor() const;
01375   void  gen();
01376   void  apply(NodeVisitor* v)                   { v->aNLRTestNode(this); }
01377   void  verify() const;
01378   char* print_string(char* buf, bool printAddr = true) const;
01379 
01380   friend class NodeFactory;
01381 };
01382 
01383 
01384 class BranchNode : public AbstractBranchNode {
01385   // next() is the target of an untaken branch, next1() the taken
01386   // conditional branches expect CCs to be set by previous node (backend specific?)
01387   // usually after a node that sets CCs
01388  protected:
01389   BranchOpCode  _op;                            // branch untaken is likely
01390   bool          _taken_is_uncommon;             // true if branch taken is uncommon
01391 
01392   BranchNode(BranchOpCode op, bool taken_is_uncommon) {
01393     _op = op;
01394     _taken_is_uncommon = taken_is_uncommon;
01395   }
01396 
01397  public:
01398   BranchOpCode  op() const                      { return _op; }
01399   bool          isBranchNode() const            { return true; }
01400   bool          canFail() const                 { return false; }
01401   void          eliminateBranch(int op1, int op2, int res);
01402   void          eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01403   void          markAllocated(int* use_count, int* def_count) { Unused(use_count); Unused(def_count); }
01404   Node*         clone(PReg* from, PReg* to) const;
01405   Node*         likelySuccessor() const;
01406   Node*         uncommonSuccessor() const;
01407   void          gen();
01408   void          apply(NodeVisitor* v)           { v->aBranchNode(this); }
01409   char*         print_string(char* buf, bool printAddr = true) const;
01410   void          verify()                        { AbstractBranchNode::verify(false); }  
01411 
01412   friend class NodeFactory;
01413 };
01414 
01415 
01416 class TypeTestNode : public AbstractBranchNode {
01417   // n-way map test; next(i) is the ith class [i=1..n], next() is the
01418   // "otherwise" branch
01419   // _src is the register containing the receiver
01420  protected:
01421   GrowableArray<klassOop>* _classes;    // classes to test for
01422   bool _hasUnknown;                     // can recv be anything? (if false, recv class
01423                                         // guaranteed to be in classes list)
01424 
01425   bool needsKlassLoad() const;          // does test need object's klass?
01426   TypeTestNode(PReg* r, GrowableArray<klassOop>* classes, bool hasUnknown);
01427 
01428  public:
01429   GrowableArray<klassOop>* classes() const      { return _classes; }
01430   bool  hasUnknown() const                      { return _hasUnknown; }
01431   bool  canFail() const                         { return _hasUnknown; }
01432   Node* failureBranch() const                   { return next(); }
01433   void  setUnknown(bool u)                      { _hasUnknown = u; }
01434   bool  isTypeTestNode() const                  { return true; }
01435   bool  hasSrc() const                          { return true; }
01436   bool  canCopyPropagate() const                { return true; }
01437   bool  canCopyPropagateOop() const             { return true; }
01438   int   cost() const                            { return 2 * oopSize * (_classes->length() + needsKlassLoad() ? 1 : 0); }
01439   Node* smiCase() const;                        // the continuation for the smi case, NULL if there is none
01440 
01441   bool  doesTypeTests()  const                  { return true; }
01442   bool  hasUnknownCode() const;                 // is there code (send) for unknown case?
01443   void  collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const;
01444   void  assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n);
01445 
01446   Node* clone(PReg* from, PReg* to) const;
01447   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
01448   void  makeUses(BB* bb);
01449   void  removeUses(BB* bb);
01450   void  markAllocated(int* use_count, int* def_count);
01451   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01452   void  eliminate(BB* bb, PReg* r, ConstPReg* c, klassOop m);
01453   void  eliminateUnnecessary(klassOop m);
01454   Node* likelySuccessor() const;
01455   Node* uncommonSuccessor() const;
01456   void  gen();
01457   void  apply(NodeVisitor* v)                   { v->aTypeTestNode(this); }
01458   void  verify() const;
01459   char* print_string(char* buf, bool printAddr = true) const;
01460 
01461   friend class NodeFactory;
01462 };
01463 
01464 
01465 class AbstractArrayAtNode : public AbstractBranchNode {
01466   // array access: test index type & range, load element
01467   // next() is the success case, next1() the failure
01468  protected:
01469                                 // _src is the array, _dest the result
01470   PReg* _arg;                   // index value
01471   Use*  _argUse;
01472   bool  _intArg;                // need not test for int if true
01473   PReg* _error;                 // where to move the error string
01474   Def*  _errorDef;
01475   bool  _needBoundsCheck;       // need array bounds check?
01476   int   _dataOffset;            // where start of array is (oop offset)
01477   int   _sizeOffset;            // where size of array is (oop offset)
01478 
01479    AbstractArrayAtNode(PReg* r, PReg* idx, bool ia, PReg* res, PReg* err, int dataOffset, int sizeOffset) {
01480      _src = r; _arg = idx; _intArg = ia; _dest = res; _error = err;
01481      _dataOffset = dataOffset; _sizeOffset = sizeOffset;
01482      dontEliminate = true; _needBoundsCheck = true;
01483    }
01484 
01485  public:
01486   bool  hasSrc() const                  { return true; }
01487   bool  hasDest() const                 { return _dest != NULL; }
01488   bool  canFail() const = NULL;
01489   int   cost() const                    { return 20 + (_intArg ? 0 : 12); } // fix this
01490   bool  canCopyPropagate() const        { return true; }
01491   int   sizeOffset() const              { return _sizeOffset; }
01492   bool  copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
01493 
01494   bool  doesTypeTests() const           { return true; }
01495   bool  needsBoundsCheck() const        { return _needBoundsCheck; }
01496   bool  hasUnknownCode() const;
01497   void  collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const;
01498   void  assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n);
01499   void  assert_in_bounds(PReg* r, LoopHeaderNode* n);
01500 
01501   void  makeUses(BB* bb);
01502   void  removeUses(BB* bb);
01503   void  markAllocated(int* use_count, int* def_count);
01504   void  eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01505   Node* likelySuccessor() const;
01506   Node* uncommonSuccessor() const;
01507 
01508   friend class NodeFactory;
01509 };
01510 
01511 
01512 class ArrayAtNode : public AbstractArrayAtNode {
01513  public:
01514   enum AccessType {
01515     byte_at,                            // corresponds to primitiveIndexedByteAt:ifFail:
01516     double_byte_at,                     // corresponds to primitiveIndexedDoubleByteAt:ifFail:
01517     character_at,                       // corresponds to primitiveIndexedDoubleByteCharacterAt:ifFail:
01518     object_at                           // corresponds to primitiveIndexedObjectAt:ifFail:
01519   };
01520 
01521  protected:
01522   AccessType    _access_type;
01523 
01524   ArrayAtNode(
01525     AccessType  access_type,            // specifies the operation
01526     PReg*       array,                  // holds the array
01527     PReg*       index,                  // holds the index
01528     bool        smiIndex,               // true if index is known to be a smi, false otherwise
01529     PReg*       result,                 // where the result is stored
01530     PReg*       error,                  // where the error symbol is stored if the operation fails
01531     int         data_offset,            // data offset in oops relative to array
01532     int         length_offset           // array length offset in oops relative to array
01533   );
01534 
01535  public:
01536   AccessType    access_type() const     { return _access_type; }
01537   PReg*         array() const           { return _src; }
01538   PReg*         index() const           { return _arg; }
01539   PReg*         error() const           { return _error; }
01540   bool          index_is_smi() const    { return _intArg; }
01541   bool          index_needs_bounds_check() const { return _needBoundsCheck; }
01542   bool          canFail() const         { return !index_is_smi() || index_needs_bounds_check(); }
01543   int           data_word_offset() const{ return _dataOffset; }
01544   int           size_word_offset() const{ return _sizeOffset; }
01545   Node*         clone(PReg* from, PReg* to) const;
01546   char*         print_string(char* buf, bool printAddr = true) const;
01547   void          gen();
01548   void          apply(NodeVisitor* v)   { v->anArrayAtNode(this); }
01549 
01550   friend class  NodeFactory;
01551 };
01552 
01553 
01554 class AbstractArrayAtPutNode : public AbstractArrayAtNode {
01555   // array store: test index type & range, store element
01556   // next() is the success case, next1() the failure
01557  protected:
01558   PReg* elem;
01559   Use* elemUse;
01560 
01561    AbstractArrayAtPutNode(PReg* arr, PReg* idx, bool ia, PReg* el, PReg* res, PReg* err, int doff, int soff)
01562     : AbstractArrayAtNode(arr, idx, ia, res, err, doff, soff) { elem = el; }
01563 
01564  public:
01565   bool copyPropagate(BB* bb, Use* u, PReg* d, bool replace = false);
01566   bool canCopyPropagateOop() const      { return true; }
01567   void makeUses(BB* bb);
01568   void removeUses(BB* bb);
01569   void markAllocated(int* use_count, int* def_count);
01570 
01571   friend class NodeFactory;
01572 };
01573  
01574 
01575 class ArrayAtPutNode : public AbstractArrayAtPutNode {
01576  public:
01577   enum AccessType {
01578     byte_at_put,                        // corresponds to primitiveIndexedByteAt:put:ifFail:
01579     double_byte_at_put,                 // corresponds to primitiveIndexedDoubleByteAt:put:ifFail:
01580     object_at_put                       // corresponds to primitiveIndexedObjectAt:put:ifFail:
01581   };
01582   static bool stores_smi_elements(AccessType t) { return t != object_at_put; }
01583 
01584  protected:
01585   AccessType    _access_type;
01586   bool          _needs_store_check;
01587   bool          _smi_element;
01588   bool          _needs_element_range_check;
01589 
01590   ArrayAtPutNode(
01591     AccessType  access_type,            // specifies the operation
01592     PReg*       array,                  // holds the array
01593     PReg*       index,                  // holds the index
01594     bool        smi_index,              // true if index is known to be a smi, false otherwise
01595     PReg*       element,                // holds the element
01596     bool        smi_element,            // true if element is known to be a smi, false otherwise
01597     PReg*       result,                 // where the result is stored
01598     PReg*       error,                  // where the error symbol is stored if the operation fails
01599     int         data_offset,            // data offset in oops relative to array
01600     int         length_offset,          // array length offset in oops relative to array
01601     bool        needs_store_check       // indicates whether a store check is necessary or not
01602   );
01603 
01604  public:
01605   AccessType    access_type() const     { return _access_type; }
01606   PReg*         array() const           { return _src; }
01607   PReg*         index() const           { return _arg; }
01608   PReg*         element() const         { return elem; }
01609   PReg*         error() const           { return _error; }
01610   bool          index_is_smi() const    { return _intArg; }
01611   bool          element_is_smi() const  { return _smi_element; }
01612   bool          index_needs_bounds_check() const { return _needBoundsCheck; }
01613   bool          element_needs_range_check() const { return _needs_element_range_check; }
01614   bool          canFail() const         { return !index_is_smi() || index_needs_bounds_check() ||
01615                                                   (access_type() != object_at_put && (!element_is_smi() || element_needs_range_check())); }
01616   bool          needs_store_check() const { return _needs_store_check; }
01617   int           data_word_offset() const{ return _dataOffset; }
01618   int           size_word_offset() const{ return _sizeOffset; }
01619   Node*         clone(PReg* from, PReg* to) const;
01620 
01621   void          collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const;
01622   void          assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n);
01623 
01624   void          computeEscapingBlocks(GrowableArray<BlockPReg*>* l);
01625   char*         print_string(char* buf, bool printAddr = true) const;
01626   void          gen();
01627   void          apply(NodeVisitor* v)   { v->anArrayAtPutNode(this); }
01628 
01629   friend class NodeFactory;
01630 };
01631 
01632 
01633 class InlinedPrimitiveNode : public AbstractBranchNode {
01634  public:
01635   enum Operation {
01636     obj_klass,                          // corresponds to primitiveClass
01637     obj_hash,                           // corresponds to primitiveHash
01638     proxy_byte_at,                      // corresponds to primitiveProxyByteAt:ifFail:
01639     proxy_byte_at_put,                  // corresponds to primitiveProxyByteAt:put:ifFail:
01640   };
01641 
01642  private:
01643   Operation     _op;
01644   // _src is    _recv;                  // receiver or NULL
01645   PReg*         _arg1;                  // 1st argument or NULL
01646   PReg*         _arg2;                  // 2nd argument or NULL
01647   PReg*         _error;                 // primitive error or NULL if primitive can't fail
01648   Use*          _arg1_use;
01649   Use*          _arg2_use;
01650   Def*          _error_def;
01651   bool          _arg1_is_smi;           // true if 1st argument is known to be a smi
01652   bool          _arg2_is_smi;           // true if 2nd argument is known to be a smi
01653 
01654   InlinedPrimitiveNode(
01655     Operation op,
01656     PReg* result,
01657     PReg* error,
01658     PReg* recv,
01659     PReg* arg1, bool arg1_is_smi,
01660     PReg* arg2, bool arg2_is_smi
01661   );
01662 
01663  public:
01664   Operation     op() const              { return _op; }
01665   PReg*         arg1() const            { return _arg1; }
01666   PReg*         arg2() const            { return _arg2; }
01667   PReg*         error() const           { return _error; }
01668   bool          arg1_is_smi() const     { return _arg1_is_smi; }
01669   bool          arg2_is_smi() const     { return _arg2_is_smi; }
01670   bool          hasSrc() const          { return _src != NULL; }
01671   bool          hasDest() const         { return _dest != NULL; }
01672   bool          canFail() const;
01673   void          makeUses(BB* bb);
01674   void          removeUses(BB* bb);
01675   void          markAllocated(int* use_count, int* def_count);
01676   bool          canBeEliminated() const;
01677   void          eliminate(BB* bb, PReg* r, bool removing = false, bool cp = false);
01678   bool          canCopyPropagate() const        { return false; }
01679   bool          canCopyPropagateOop() const     { return false; }
01680   bool          copyPropagate(BB* bb, Use* u, PReg* d, bool replace);
01681   Node*         likelySuccessor() const;
01682   Node*         uncommonSuccessor() const;
01683   void          gen();
01684   void          apply(NodeVisitor* v)           { v->anInlinedPrimitiveNode(this); }
01685   void          verify() const;
01686   char*         print_string(char* buf, bool printAddr = true) const;
01687   
01688   friend class NodeFactory;
01689 };
01690 
01691 
01692 class UncommonNode : public NonTrivialNode {
01693   GrowableArray<PReg*>* exprStack;
01694  
01695  protected:
01696   UncommonNode(GrowableArray<PReg*>* e, int bci);
01697 
01698  public:
01699   bool  isUncommonNode() const          { return true; }
01700   int   cost() const                    { return 4; } // fix this
01701   bool  isExitNode() const              { return true; }
01702   bool  isEndsBB() const                { return true; }
01703   Node* clone(PReg* from, PReg* to) const;
01704   void  markAllocated(int* use_count, int* def_count) { Unused(use_count); Unused(def_count); }
01705   void  gen();
01706   void  apply(NodeVisitor* v)           { v->anUncommonNode(this); }
01707   void  verify() const;
01708   char* print_string(char* buf, bool printAddr = true) const;
01709 
01710   friend class NodeFactory;
01711 };
01712 
01713 
01714 class FixedCodeNode : public TrivialNode {
01715  public:
01716   enum FixedCodeKind {
01717     dead_end,                           // dead-end marker (for compiler debugging)
01718     inc_counter                         // increment invocation counter
01719   };
01720  protected:
01721   const FixedCodeKind _kind;
01722   FixedCodeNode(FixedCodeKind k) : _kind(k) {}
01723 
01724  public:
01725   bool  isExitNode() const              { return _kind == dead_end; }
01726   bool  isDeadEndNode() const           { return _kind == dead_end; }
01727   FixedCodeKind kind() const            { return _kind; }
01728   Node* clone(PReg* from, PReg* to) const;
01729   void  gen();
01730   void  apply(NodeVisitor* v)           { v->aFixedCodeNode(this); }
01731   char* print_string(char* buf, bool printAddr = true) const;
01732 
01733   friend class NodeFactory;
01734 };
01735 
01736 
01737 class NopNode : public TrivialNode {
01738  protected:
01739   NopNode() {}
01740 
01741  public:
01742   bool  isNopNode() const               { return true; }
01743   Node* clone(PReg* from, PReg* to) const;
01744   void  apply(NodeVisitor* v)           { v->aNopNode(this); }
01745   char* print_string(char* buf, bool printAddr = true) const;
01746 
01747   friend class NodeFactory;
01748 };
01749 
01750 
01751 class CommentNode : public TrivialNode {
01752  protected:
01753   CommentNode(char* s);
01754   
01755  public:
01756   char* comment;
01757   bool  isCommentNode() const           { return true; }
01758   Node* clone(PReg* from, PReg* to) const;
01759   void  apply(NodeVisitor* v)           { v->aCommentNode(this); }
01760   char* print_string(char* buf, bool printAddr = true) const;
01761 
01762   friend class NodeFactory;
01763 };
01764 
01765 
01766 // NodeFactory is used to create new nodes.
01767 
01768 class NodeFactory : AllStatic {
01769  public:
01770   static int cumulCost;                                 // cumulative cost of all nodes generated so far
01771 
01772   static void                   registerNode(Node* n)   { cumulCost += n->cost(); }
01773 
01774   static PrologueNode*          new_PrologueNode        (LookupKey* key, int nofArgs, int nofTemps);
01775 
01776   static LoadOffsetNode*        new_LoadOffsetNode      (PReg* dst, PReg* base, int offs, bool isArray);
01777   static LoadUplevelNode*       new_LoadUplevelNode     (PReg* dst, PReg* context0, int nofLevels, int offset, symbolOop name);
01778   static LoadIntNode*           new_LoadIntNode         (PReg* dst, int value);
01779   
01780   static StoreOffsetNode*       new_StoreOffsetNode     (PReg* src, PReg* base, int offs, bool needStoreCheck);
01781   static StoreUplevelNode*      new_StoreUplevelNode    (PReg* src, PReg* context0, int nofLevels, int offset, symbolOop name, bool needStoreCheck);
01782   static AssignNode*            new_AssignNode          (PReg* src, PReg* dst);
01783 
01784   static ReturnNode*            new_ReturnNode          (PReg* res, int bci);
01785   static InlinedReturnNode*     new_InlinedReturnNode   (int bci, PReg* src, PReg* dst);
01786   static NLRSetupNode*          new_NLRSetupNode        (PReg* result, int bci);
01787   static NLRContinuationNode*   new_NLRContinuationNode (int bci);
01788   static NLRTestNode*           new_NLRTestNode         (int bci);
01789 
01790   static ArithRRNode*           new_ArithRRNode         (PReg* dst, PReg* src, ArithOpCode op, PReg* o2);
01791   static ArithRCNode*           new_ArithRCNode         (PReg* dst, PReg* src, ArithOpCode op, int   o2);
01792   static TArithRRNode*          new_TArithRRNode        (PReg* dst, PReg* src, ArithOpCode op, PReg* o2, bool a1, bool a2);
01793   static FloatArithRRNode*      new_FloatArithRRNode    (PReg* dst, PReg* src, ArithOpCode op, PReg* o2);
01794   static FloatUnaryArithNode*   new_FloatUnaryArithNode (PReg* dst, PReg* src, ArithOpCode op);
01795 
01796   static MergeNode*             new_MergeNode           (Node* prev1, Node* prev2);
01797   static MergeNode*             new_MergeNode           (int bci);
01798 
01799   static SendNode*              new_SendNode            (LookupKey* key, MergeNode* nlrTestPoint,
01800                                                          GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack, 
01801                                                          bool superSend, SendInfo* info);
01802   static PrimNode*              new_PrimNode            (primitive_desc* pdesc, MergeNode* nlrTestPoint,
01803                                                          GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack);
01804   static DLLNode*               new_DLLNode             (symbolOop dll_name, symbolOop function_name, dll_func function, bool async,
01805                                                          MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack);
01806 
01807   static InterruptCheckNode*    new_InterruptCheckNode  (GrowableArray<PReg*>* expr_stack);
01808   static LoopHeaderNode*        new_LoopHeaderNode      ();
01809   
01810   static BlockCreateNode*       new_BlockCreateNode     (BlockPReg* b, GrowableArray<PReg*>* expr_stack);
01811   static BlockMaterializeNode*  new_BlockMaterializeNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack);
01812 
01813   static ContextCreateNode*     new_ContextCreateNode   (PReg* parent, PReg* context, int nofTemps, GrowableArray<PReg*>* expr_stack);
01814   static ContextCreateNode*     new_ContextCreateNode   (PReg* b, const ContextCreateNode* n, GrowableArray<PReg*>* expr_stack);
01815   static ContextInitNode*       new_ContextInitNode     (ContextCreateNode* creator);
01816   static ContextInitNode*       new_ContextInitNode     (PReg* b, const ContextInitNode* n);
01817   static ContextZapNode*        new_ContextZapNode      (PReg* context);
01818 
01819   static BranchNode*            new_BranchNode          (BranchOpCode op, bool taken_is_uncommon = false);
01820 
01821   static TypeTestNode*          new_TypeTestNode        (PReg* recv, GrowableArray<klassOop>* classes, bool hasUnknown);
01822 
01823   static ArrayAtNode*           new_ArrayAtNode         (ArrayAtNode::AccessType access_type, PReg* array, PReg* index, bool smiIndex,
01824                                                          PReg* result, PReg* error, int data_offset, int length_offset);
01825 
01826   static ArrayAtPutNode*        new_ArrayAtPutNode      (ArrayAtPutNode::AccessType access_type, PReg* array, PReg* index, bool smi_index,
01827                                                          PReg* element, bool smi_element, PReg* result, PReg* error, int data_offset, int length_offset,
01828                                                          bool needs_store_check);
01829   
01830   static InlinedPrimitiveNode*  new_InlinedPrimitiveNode(InlinedPrimitiveNode::Operation op, PReg* result, PReg* error = NULL,
01831                                                          PReg* recv = NULL,
01832                                                          PReg* arg1 = NULL, bool arg1_is_smi = false,
01833                                                          PReg* arg2 = NULL, bool arg2_is_smi = false);
01834 
01835   static UncommonNode*          new_UncommonNode        (GrowableArray<PReg*>* exprStack, int bci);
01836   static FixedCodeNode*         new_FixedCodeNode       (FixedCodeNode::FixedCodeKind k);
01837   static NopNode*               new_NopNode             ();
01838   static CommentNode*           new_CommentNode         (char* comment);
01839 };
01840 
01841 #ifdef DEBUG
01842 void printNodes(Node* n);   // print n and its successors
01843 #endif
01844 
01845 # endif

Generated on Mon Oct 9 13:37:18 2006 for Strongtalk VM by  doxygen 1.4.7