scope.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.75 $ */
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 // Scopes represent the source-level scopes compiled by the compiler.
00028 // Compilation starts with a method or a block. All subsequently in-
00029 // lined methods/blocks are described via InlinedScopes. If and only
00030 // if compilation starts with a block, there are parent scopes described
00031 // via OutlinedScopes. OutlinedScopes represent scopes outside the current
00032 // compilation; i.e., at runtime, OutlinedScopes will be in different frames
00033 // than all InlinedScopes (which are part of the same frame).  Two OutlinedScopes
00034 // may or may not be in different frames depending on previous inlining (a real stack
00035 // frame may consist of several virtual frames / OutlinedScopes).  Thus the scopes
00036 // up to the OutlinedScope representing the method enclosing the block method
00037 // may be in one or several stack frames.
00038 
00039 class Scope;
00040 class   InlinedScope;
00041 class     MethodScope;
00042 class     BlockScope;
00043 class   OutlinedScope;
00044 class     OutlinedMethodScope;
00045 class     OutlinedBlockScope;
00046 
00047 
00048 // SendInfo holds various data about a send before/while it is being
00049 // inlined
00050 
00051 class SendInfo: public PrintableResourceObj {
00052  public:
00053   InlinedScope* senderScope;
00054   Expr* rcvr;
00055   LookupKey* key;
00056   symbolOop sel;
00057   PReg* resReg;                 // register where result should end up
00058   bool needRealSend;            // need a real (non-inlined) send
00059   bool counting;                // count # sends? (for non-inlined send)
00060   int nsends;                   // estimated # of invocations (< 0 == unknown)
00061   bool predicted;               // was receiver type-predicted?
00062   bool uninlinable;             // was send considered uninlinable?
00063   bool receiverStatic;          // receiver type is statically known
00064   bool inPrimFailure;           // sent from within prim. failure block
00065 
00066  protected:
00067   void init();
00068 
00069  public:
00070   SendInfo(InlinedScope* sen, Expr* r, symbolOop s) {
00071     senderScope = sen; rcvr = r; sel = s; key = NULL;
00072     init();
00073   }
00074 
00075   SendInfo(InlinedScope* sen, LookupKey* lkup, Expr* r);
00076   void computeNSends(RScope* rscope, int bci);
00077    
00078   void print();
00079 };
00080 
00081 
00082 // Scope definitions
00083 
00084 class Scope : public PrintableResourceObj {
00085  private:
00086   static smi    _currentScopeID;                        // for scope descs
00087 
00088  public:
00089   // scopes are numbered starting at 0
00090   static void   initialize()                            { _currentScopeID = 0; }
00091   smi           currentScopeID()                        { return _currentScopeID++; }
00092   virtual smi   scopeID() const                         = 0;
00093     
00094   // test functions
00095   virtual bool  isInlinedScope() const                  { return false; }
00096   virtual bool  isMethodScope() const                   { return false; }
00097   virtual bool  isBlockScope() const                    { return false; }
00098   virtual bool  isOutlinedScope() const                 { return false; }
00099   virtual bool  isOutlinedMethodScope() const           { return false; }   
00100   virtual bool  isOutlinedBlockScope() const            { return false; }
00101 
00102   virtual klassOop      selfKlass() const               = 0;
00103   virtual symbolOop     selector() const                = 0;
00104   virtual methodOop     method() const                  = 0;
00105   virtual Scope*        parent() const                  = 0;    // lexically enclosing scope or NULL (if MethodScope)
00106   virtual InlinedScope* sender() const                  = 0;    // caller scope
00107   virtual klassOop      methodHolder() const            = 0;    // for super sends
00108 
00109   virtual bool          allocatesInterpretedContext() const = 0;// true if the scope allocates its own context in the interpreter
00110   virtual bool          allocatesCompiledContext() const = 0;   // true if the scope allocates a context in the compiled code
00111   virtual bool          expectsContext() const          = 0;    // true if the scope has an incoming context in the interpreter
00112   bool                  needsContextZapping() const     { return (parent() == NULL) && allocatesCompiledContext(); }
00113   
00114   virtual Scope*        home() const                    = 0;    // the home scope
00115   bool                  isTop() const                   { return sender() == NULL; }
00116   bool                  isInlined() const               { return sender() != NULL; }
00117   virtual bool          isSenderOf(InlinedScope* s) const { return false; } // isSenderOf = this is a proper caller of s 
00118   bool                  isSenderOrSame(InlinedScope* s) { return (Scope*)s == this || isSenderOf(s); }
00119     
00120   virtual bool isRecursiveCall(methodOop method, klassOop rcvrKlass, int n) = 0;
00121   virtual void          genCode()                       { ShouldNotCallThis(); }
00122 };
00123 
00124 
00125 class InlinedScope: public Scope {
00126  protected:
00127   int           _scopeID;
00128   InlinedScope* _sender;                                // NULL for top scope
00129   int           _senderBCI;                             // call position in sender (if inlined)
00130   ScopeInfo     _scopeInfo;                             // for debugging information (see scopeDescRecoder.hpp)
00131   LookupKey*    _key;
00132   klassOop      _methodHolder;                          // != receiver klass only for methods invoked by super sends
00133   methodOop     _method;
00134   int           _nofSends;                              // no. of non-inlined sends, cumulative (incl. subScopes)
00135   int           _nofInterruptPoints;                    // no. of interrupt points, cumulative (incl. subScopes)
00136                                                         // (_nofInterruptPoints == 0 => needs no debug info)
00137   bool          _primFailure;                           // true if in a primitive call failure branch
00138   bool          _endsDead;                              // true if method ends with dead code
00139   Expr*         _self;                                  // the receiver
00140   NodeBuilder   _gen;                                   // the generator of the intermediate representation
00141 
00142   PReg*                         _context;               // context (either passed in or created here), if any
00143   GrowableArray<Expr*>*         _arguments;             // the arguments
00144   GrowableArray<Expr*>*         _temporaries;           // the (originally) stack-allocated temporaries
00145   GrowableArray<Expr*>*         _floatTemporaries;      // the (originally) stack-allocated float temporaries
00146   GrowableArray<Expr*>*         _contextTemporaries;    // the (originally) heap-allocated temporaries
00147   GrowableArray<Expr*>*         _exprStackElems;        // the expression stack elems for debugging (indexed by bci)
00148   GrowableArray<InlinedScope*>* _subScopes;             // the inlined scopes
00149   GrowableArray<CompiledLoop*>* _loops;                 // loops contained in this scope
00150   GrowableArray<NonTrivialNode*>* _typeTests;           // type test-like nodes contained in this scope
00151 
00152   GrowableArray<PReg*>*         _pregsBegSorted;        // the scope's PRegs sorted with begBCI (used for regAlloc)
00153   GrowableArray<PReg*>*         _pregsEndSorted;        // the scope's PRegs sorted with endBCI (used for regAlloc)
00154 
00155   // float temporaries
00156   int                           _firstFloatIndex;       // the (stack) float temporary index for the first float
00157 
00158   // for node builders
00159   MergeNode*                    _returnPoint;           // starting point for shared return code
00160   MergeNode*                    _NLReturnPoint;         // starting point for shared non-local return code
00161   MergeNode*                    _nlrTestPoint;          // where NLRs coming from callees will jump to (or NULL)
00162   ContextInitNode*              _contextInitializer;    // node initializing context (if any)
00163   bool                          _hasBeenGenerated;      // true iff genCode() was called
00164   
00165  public:
00166   // for node builders
00167   MergeNode*                    returnPoint()           { return _returnPoint; }
00168   MergeNode*                    nlrPoint()              { return _NLReturnPoint; }
00169   MergeNode*                    nlrTestPoint();         // returns a lazily generated nlrTestPoint
00170   ContextInitNode*              contextInitializer()    { return _contextInitializer; }
00171   bool                          has_nlrTestPoint()      { return _nlrTestPoint != NULL; }
00172   void                          set_contextInitializer(ContextInitNode* n) { _contextInitializer = n; }
00173 
00174  public:
00175   RScope*       rscope;                                 // equiv. scope in recompilee (if any) - used for type feedback
00176   bool          predicted;                              // was receiver type-predicted?
00177   int           depth;                                  // call nesting level (top = 0)
00178   int           loopDepth;                              // loop nesting level (top = 0)
00179   Expr*         result;                                 // result of normal return (NULL if none)
00180   Expr*         nlrResult;                              // NLR result (non-NULL only for blocks)
00181   PReg*         resultPR;                               // pseudo register containing result
00182 
00183 protected:
00184   InlinedScope();
00185   void initialize(methodOop method, klassOop methodHolder, InlinedScope* sender, RScope* rs, SendInfo* info);
00186 
00187 public:
00188   int           scopeID() const                         { return _scopeID; }
00189   InlinedScope* sender() const                          { return _sender; }
00190   int           senderBCI() const                       { return _senderBCI; }
00191   ScopeInfo     scopeInfo() const                       { return _scopeInfo; }
00192   virtual int   bci() const                             { return gen()->bci(); }
00193   bool          isInlinedScope() const                  { return true; }
00194   int           nofArguments() const                    { return _arguments->length(); }
00195   bool          hasTemporaries() const                  { return _temporaries != NULL; }
00196   int           nofTemporaries() const                  { return _temporaries->length(); }
00197   bool          hasFloatTemporaries() const             { return _floatTemporaries != NULL; }
00198   int           nofFloatTemporaries() const             { return _floatTemporaries->length(); }
00199   int           firstFloatIndex() const                 { assert(_firstFloatIndex >= 0, "not yet computed"); return _firstFloatIndex; }
00200   bool          allocatesInterpretedContext() const     { return _method->allocatesInterpretedContext(); }
00201   bool          allocatesCompiledContext() const;
00202   bool          expectsContext() const                  { return _method->expectsContext(); }
00203   bool          isSenderOf(InlinedScope* s) const;
00204 
00205   GrowableArray<Expr*>* contextTemporaries() const      { return _contextTemporaries; }
00206   int           nofBytes() const                        { return _method->end_bci() - 1; }
00207   int           nofSends() const                        { return _nofSends; }
00208   bool          containsNLR()  const                    { return _method->containsNLR(); }
00209   bool          primFailure() const                     { return _primFailure; }
00210   Expr*         self() const                            { return _self; }
00211   void          set_self(Expr* e);
00212   NodeBuilder*  gen() const                             { return (NodeBuilder*const)&_gen; }
00213 
00214   GrowableArray<Expr*>* exprStackElems() const          { return _exprStackElems; }     
00215   void          addSubScope(InlinedScope* s);
00216 
00217   klassOop      selfKlass() const                       { return _key->klass(); }
00218   LookupKey*    key() const                             { return _key; }
00219   klassOop      methodHolder() const                    { return _methodHolder; }
00220   methodOop     method() const                          { return _method; }
00221   symbolOop     selector() const                        { return _key->selector(); }
00222   bool          isLite() const;
00223   Expr*         argument(int no) const                  { return _arguments->at(no); }
00224   Expr*         temporary(int no) const                 { return _temporaries->at(no); }
00225   Expr*         floatTemporary(int no) const            { return _floatTemporaries->at(no); }
00226   void          set_temporary(int no, Expr* t)          { _temporaries->at_put(no, t); }
00227   Expr*         contextTemporary(int no) const          { return _contextTemporaries->at(no); }
00228   PReg*         context() const                         { return _context; }
00229   void          setContext(PReg* ctx)                   { _context = ctx; }
00230   ExprStack*    exprStack() const                       { return gen()->exprStack(); }
00231   Node*         current() const                         { return gen()->current(); }
00232   virtual bool  is_self_initialized() const             { return true; }
00233   virtual void  set_self_initialized()                  { ShouldNotCallThis(); }
00234   bool          hasBeenGenerated() const                { return _hasBeenGenerated; }
00235 
00236   void          createTemporaries(int nofTemps);
00237   void          createFloatTemporaries(int nofFloats);
00238   void          createContextTemporaries(int nofTemps);
00239   void          contextTemporariesAtPut(int no, Expr* e);
00240   int           homeContext() const;                    // the home context level
00241   InlinedScope* find_scope(int context, int& nofIndirections, OutlinedScope*& out);     // find enclosing scope
00242   void          addResult(Expr* e);
00243     
00244   void          genCode();
00245   void          addSend(GrowableArray<PReg*>* exprStack, bool isSend);
00246   GrowableArray<NonTrivialNode*>* typeTests() const     { return _typeTests; }
00247   GrowableArray<CompiledLoop*>* loops() const           { return _loops; }
00248   void          addTypeTest(NonTrivialNode* t);
00249   CompiledLoop* addLoop();
00250 
00251   void          setExprForBCI(int bci, Expr* expr);
00252   void          set2ndExprForBCI(int bci, Expr* expr);
00253    
00254   virtual void  collectContextInfo(GrowableArray<InlinedScope*>* scopeList);
00255   virtual void  generateDebugInfo();
00256           void  generateDebugInfoForNonInlinedBlocks();
00257   void          optimizeLoops();
00258   void          subScopesDo(Closure<InlinedScope*>* c);         // apply f to receiver and all subscopes
00259     
00260  protected:
00261   void          initializeArguments();
00262   virtual void  initializeSelf() {}
00263   virtual void  prologue();
00264   virtual void  epilogue();
00265 
00266  public:
00267   int           descOffset();
00268 
00269  protected:
00270   // int calleeSize(RScope* rs);
00271   void          markLocalsDebugVisible(GrowableArray<PReg*>* exprStack);
00272 
00273  public:
00274   // for global register allocation
00275   void          addToPRegsBegSorted(PReg* r);
00276   void          addToPRegsEndSorted(PReg* r);
00277   void          allocatePRegs(IntFreeList* f);
00278   int           allocateFloatTemporaries(int firstFloatIndex);  // returns the number of float temps allocated for
00279                                                                 // this and all subscopes; sets _firstFloatIndex
00280  public:
00281   void print();
00282   void printTree();
00283 
00284   // see Compiler::number_of_noninlined_blocks
00285   int  number_of_noninlined_blocks();
00286   // see Compiler::copy_noninlined_block_info
00287   void copy_noninlined_block_info(nmethod* nm);
00288     
00289   friend class OutlinedScope;
00290 };
00291   
00292 
00293 class MethodScope: public InlinedScope {         // ordinary methods
00294  protected:
00295   MethodScope();
00296   void initialize(methodOop method, klassOop methodHolder, InlinedScope* sen, RScope* rs, SendInfo* info);
00297  public:
00298   static MethodScope* new_MethodScope(methodOop method, klassOop methodHolder, InlinedScope* sen, RScope* rs, SendInfo* info);
00299 
00300   bool          isMethodScope() const           { return true; }
00301   Scope*        parent() const                  { return NULL; }
00302   Scope*        home() const                    { return (Scope*)this; }
00303 
00304   bool          isRecursiveCall(methodOop method, klassOop rcvrKlass, int n);
00305 
00306   void          generateDebugInfo();
00307 
00308 // debugging
00309   void          print_short();
00310   void          print();
00311 };
00312 
00313 
00314 class BlockScope: public InlinedScope {         // block methods
00315  protected:
00316   Scope* _parent;                               // lexically enclosing scope
00317   bool  _self_is_initialized;                   // true if self has been loaded
00318   void initialize(methodOop method, klassOop methodHolder, Scope* p, InlinedScope* s, RScope* rs, SendInfo* info);
00319   void initializeSelf();
00320   BlockScope();
00321 
00322  public:
00323   static BlockScope* new_BlockScope(methodOop method, klassOop methodHolder, Scope* p, InlinedScope* s, RScope* rs, 
00324                                     SendInfo* info);
00325     
00326   bool          isBlockScope() const            { return true; }
00327   bool  is_self_initialized() const             { return _self_is_initialized; }
00328   void  set_self_initialized()                  { _self_is_initialized = true; }
00329     
00330   Scope*        parent() const                  { return _parent; }
00331   Scope*        home() const                    { return _parent->home(); }
00332   klassOop      selfKlass() const               { return _parent->selfKlass(); }
00333   bool          isRecursiveCall(methodOop method, klassOop rcvrKlass, int n);
00334 
00335   void          generateDebugInfo();
00336     
00337 // debugging
00338   void          print_short();
00339   void          print();
00340 };
00341   
00342 
00343 class OutlinedScope: public Scope {             // abstract; a scope outside of the current compilation
00344  protected:
00345   nmethod*      _nm;                            // nmethod containing this scope
00346   ScopeDesc*    _scope;
00347 
00348  public:
00349   OutlinedScope(nmethod* nm, ScopeDesc* scope);
00350   bool          isOutlinedScope() const         { return true; }
00351   symbolOop     selector() const                { return _scope->selector(); }
00352   Expr*         receiverExpr(PReg* p) const;
00353   methodOop     method() const;
00354   nmethod*      nm() const                      { return _nm; }
00355   InlinedScope* sender() const                  { return NULL; }
00356   ScopeDesc*    scope() const                   { return _scope; }
00357   bool          allocatesInterpretedContext() const { return method()->allocatesInterpretedContext(); }
00358   bool          allocatesCompiledContext() const { return _scope->allocates_compiled_context(); }
00359   bool          expectsContext() const          { return method()->expectsContext(); }
00360   
00361   // debugging
00362   void          print_short(char* name);
00363   void          print(char* name);
00364 };
00365 
00366 OutlinedScope* new_OutlinedScope(nmethod* nm, ScopeDesc* sc);
00367 
00368 
00369 class OutlinedMethodScope: public OutlinedScope {
00370  public:
00371   OutlinedMethodScope(nmethod* nm, ScopeDesc* s) : OutlinedScope(nm, s) {}
00372     
00373   bool isOutlinedMethodScope() const            { return true; }
00374   bool isRecursiveCall(methodOop method, klassOop rcvrKlass, int n) { ShouldNotCallThis(); return false; }
00375   klassOop      selfKlass() const               { return _scope->selfKlass(); }
00376   smi           scopeID() const                 { return _scope->scopeID(); }
00377   Scope*        parent() const                  { return NULL; }
00378   Scope*        home() const                    { return (Scope*)this; }
00379   klassOop      methodHolder() const;
00380 
00381 // debugging
00382   void          print_short();
00383   void          print();
00384 };
00385   
00386   
00387 class OutlinedBlockScope: public OutlinedScope {
00388  protected:
00389   OutlinedScope* _parent;                       // parent or NULL (if non-LIFO)
00390 
00391  public:
00392   OutlinedBlockScope(nmethod* nm, ScopeDesc* sen);
00393     
00394   bool isOutlinedBlockScope() const             { return true; }   
00395   bool isRecursiveCall(methodOop method, klassOop rcvrKlass, int n) { ShouldNotCallThis(); return false; }
00396   Scope*        parent() const                  { return _parent; }
00397   Scope*        home() const                    { return _parent ? _parent->home() : NULL; }
00398   klassOop      selfKlass() const               { return _parent->selfKlass(); }
00399   smi           scopeID() const                 { return _scope->scopeID(); }
00400   klassOop      methodHolder() const            { return _parent->methodHolder(); }
00401 
00402 // debugging
00403   void          print_short();
00404   void          print();
00405 };
00406 
00407 
00408 # endif

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