preg.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.70 $ */
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 # include "incls/_precompiled.incl"
00025 
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_preg.cpp.incl"
00028 
00029 int PReg::currentNo = 0;
00030 int BlockPReg::_numBlocks = 0;
00031 static GrowableArray<ConstPReg*>* constants = 0;
00032 static PReg* dummyPR;
00033 const int PReg::AvgBBIndexLen = 10;
00034 const int PReg::VeryNegative = -9999;           // fix this -- should be int16, really
00035 
00036 #define BAD_SCOPE  ((InlinedScope*)1)
00037 
00038 
00039 /*
00040 LogicalAddress* PReg::createLogicalAddress() {
00041   if (_logicalAddress == NULL) {
00042     _logicalAddress = theCompiler->scopeDescRecorder()->createLogicalAddress(nameNode());
00043   };
00044   return _logicalAddress;
00045 }
00046 */
00047 
00048 
00049 LogicalAddress* PReg::createLogicalAddress() {
00050   PReg* r = cpReg();
00051   if (r->_logicalAddress == NULL) {
00052     r->_logicalAddress = theCompiler->scopeDescRecorder()->createLogicalAddress(nameNode());
00053   };
00054   return r->_logicalAddress;
00055 }
00056 
00057 
00058 // weights indexed by loop depth
00059 static int udWeight[] = { 1, 8, 8*8, 8*8*8, 8*8*8*8 };
00060 const  int udWeightLen = sizeof(udWeight) / sizeof(int) - 1;
00061 
00062 
00063 void PReg::initPRegs() {
00064   PReg::currentNo = 0; BlockPReg::_numBlocks = 0;
00065   constants = new GrowableArray<ConstPReg*>(50);
00066   dummyPR = new PReg(BAD_SCOPE);
00067 }
00068 
00069 
00070 SAPReg::SAPReg(InlinedScope* s, int st, int en, bool inContext) : PReg(s), _isInContext(inContext) {
00071   creationStartBCI = _begBCI    = st == IllegalBCI ? s->bci() : st;
00072   _endBCI                       = en == IllegalBCI ? s->bci() : en;
00073   _creationScope = s;
00074 }
00075 
00076 
00077 BlockPReg::BlockPReg(InlinedScope* scope, CompileTimeClosure* closure, int beg, int end) : SAPReg(scope, beg, end) {
00078   _closure = closure; assert(closure, "need a closure");
00079   _memoized = _escapes = false;
00080   _escapeNodes = NULL; _uplevelRead = _uplevelWritten = NULL; _contextCopies = NULL;
00081   _numBlocks++;
00082   theCompiler->blockClosures->append(this);
00083   if (MemoizeBlocks) memoize();     
00084 }
00085 
00086 void BlockPReg::addContextCopy(Location* l) {
00087   if (!_contextCopies) _contextCopies = new GrowableArray<Location*>(3);
00088   _contextCopies->append(l);
00089 }
00090 
00091 void PReg::makeIncorrectDU(bool incU, bool incD) {
00092   if (incU) _nuses = VeryNegative;
00093   if (incD) _ndefs = VeryNegative;
00094 }
00095 
00096 
00097 bool PReg::isLocalTo(BB* bb) const {
00098   // is this a preg local to bb? (i.e. can it be allocated to temp regs?)
00099   // treat ConstPRegs as non-local so they don't get allocated prematurely
00100   // (possible performance bug)
00101   return
00102     loc.equals(unAllocated) && !uplevelR() && !debug && !incorrectDU() &&
00103     !isConstPReg() && dus.length() == 1 && dus.first()->bb == bb;
00104 }
00105 
00106 
00107 // check basic conditions for global CP
00108 bool PReg::canCopyPropagate() const {
00109   if (nuses() == 0 || ndefs() != 1) return false;
00110   // don't propagate if register has incorrect def info or does not
00111   // survive calls (i.e. is local to BB)
00112   if (incorrectD() || loc.isTrashedRegister()) return false;
00113   return true;          // looks good
00114 }
00115 
00116 // NB: _uplevelR/W are initialized lazily to reduce memory consumption
00117 void PReg::addUplevelAccessor(BlockPReg* blk, bool read, bool write) {
00118   if (read) {
00119     if (!_uplevelR) _uplevelR = new GrowableArray<BlockPReg*>(5);
00120     if (!_uplevelR->contains(blk)) _uplevelR->append(blk);
00121   } 
00122   if (write) {
00123     if (!_uplevelW) _uplevelW = new GrowableArray<BlockPReg*>(5);
00124     if (!_uplevelW->contains(blk)) _uplevelW->append(blk);
00125   } 
00126 }
00127 
00128 void PReg::removeUplevelAccessor(BlockPReg* blk) {
00129   if (_uplevelR) {
00130     if (_uplevelR->contains(blk)) _uplevelR->remove(blk);
00131     if (_uplevelR->isEmpty()) _uplevelR = NULL;
00132   }
00133   if (_uplevelW) {
00134     if (_uplevelW->contains(blk)) _uplevelW->remove(blk);
00135     if (_uplevelW->isEmpty()) _uplevelW = NULL;
00136   }
00137 }
00138 
00139 void PReg::removeAllUplevelAccessors() {
00140   _uplevelR = _uplevelW = NULL;
00141 }
00142 
00143 ConstPReg* new_ConstPReg(InlinedScope* s, oop c) {
00144   for (int i = 0; i < constants->length(); i++) {
00145     ConstPReg* r = constants->at(i);
00146     if (r->constant == c) {
00147       // needed to ensure high enough scope (otherwise will break assertions)
00148       // but in reality it's not needed since ConstPRegs aren't register-allocated right now
00149       r->extendLiveRange(s);
00150       return r;
00151     }
00152   }
00153   // constant not found, create new ConstPReg*
00154   ConstPReg* r = new ConstPReg(s, c);
00155   constants->append(r);
00156   r->_ndefs = 1;        // fake def
00157   return r;
00158 }
00159 
00160 
00161 ConstPReg* findConstPReg(Node* n, oop c) {
00162   // return const preg for oop or NULL if none exists
00163   for (int i = 0; i < constants->length(); i++) {
00164     ConstPReg* r = constants->at(i);
00165     if (r->constant == c) {
00166       return r->covers(n) ? r : NULL;
00167     }
00168   }
00169   return NULL;                      // constant not found
00170 }
00171 
00172 
00173 bool ConstPReg::needsRegister() const {
00174   // register only pays off if we're used more than once and aren't a
00175   // small immediate constant
00176 //c    return CompilerCSEConstants && weight > 1 && 
00177 //c      (int(constant) > maxImmediate || int(constant) < -maxImmediate);
00178   return false;
00179 }
00180 
00181 
00182 void ConstPReg::allocateTo(Location reg) {
00183   assert(reg.isRegisterLocation(), "should be a register");
00184   loc = reg;
00185   assert(_scope->isInlinedScope(), "expected non-access scope");
00186   //c    ((InlinedScope*)_scope)->allocateConst(this);
00187   Unimplemented();
00188 }
00189 
00190 
00191 inline int computeWeight(InlinedScope* s) {
00192   const int scale = 16; // normal use counts scale, uncommon use is 1
00193   if (s && s->isInlinedScope() && ((InlinedScope*)s)->primFailure()) {
00194     return 1 * udWeight[min(udWeightLen, s->loopDepth)];
00195   } else {
00196     return scale * udWeight[min(udWeightLen, s ? s->loopDepth : 0)];
00197   }
00198 }
00199 
00200 
00201 void PReg::incUses(Use* use) {
00202   _nuses++;
00203   if (use->isSoft()) _nsoftUses++;
00204   InlinedScope* s = use->node->scope();
00205   weight += computeWeight(s);
00206   assert(weight >= _nuses + _ndefs || isConstPReg(), "weight too small");
00207 }     
00208 
00209 
00210 void PReg::decUses(Use* use) {
00211   _nuses--;
00212   if (use->isSoft()) _nsoftUses--;
00213   InlinedScope* s = use->node->scope();
00214   weight -= computeWeight(s);
00215   assert(weight >= _nuses + _ndefs || isConstPReg(), "weight too small");
00216 }
00217 
00218 
00219 void PReg::incDefs(Def* def) {
00220   _ndefs++;
00221   InlinedScope* s = def->node->scope();
00222   weight += computeWeight(s);
00223   assert(weight >= _nuses + _ndefs || isConstPReg(), "weight too small");
00224 }
00225 
00226 
00227 void PReg::decDefs(Def* def) {
00228   _ndefs--;
00229   InlinedScope* s = def->node->scope();
00230   weight -= computeWeight(s);
00231   assert(weight >= _nuses + _ndefs || isConstPReg(), "weight too small");
00232 }
00233 
00234 
00235 void PReg::removeUse(DUInfo* info, Use* use) {
00236   assert(info->reg == this, "wrong reg");
00237   info->uses.remove(use);
00238   decUses(use);
00239 }
00240 
00241 
00242 void PReg::removeUse(BB* bb, Use* use) {
00243   if (use == NULL) return;
00244   for (int i = 0; i < dus.length(); i++) {
00245     PRegBBIndex* index = dus.at(i);
00246     if (index->bb == bb) {
00247       DUInfo* info = bb->duInfo.info->at(index->index);
00248       removeUse(info, use);
00249       return;
00250     }
00251   }
00252   ShouldNotReachHere(); // info not found
00253 }
00254 
00255 
00256 void PReg::removeDef(DUInfo* info, Def* def) {
00257   assert(info->reg == this, "wrong reg");
00258   info->defs.remove(def);
00259   _ndefs--;
00260   InlinedScope* s = def->node->scope();
00261   weight -= computeWeight(s);
00262   assert(weight >= _nuses + _ndefs, "weight too small");
00263 }
00264 
00265 
00266 void PReg::removeDef(BB* bb, Def* def) {
00267   if (def == NULL) return;
00268   for (int i = 0; i < dus.length(); i++) {
00269     PRegBBIndex* index = dus.at(i);
00270     if (index->bb == bb) {
00271       DUInfo* info = bb->duInfo.info->at(index->index);
00272       removeDef(info, def);
00273       return;
00274     }
00275   }
00276   ShouldNotReachHere(); // info not found
00277 }
00278 
00279 
00280 void PReg::addDUHelper(Node* n, SList<DefUse*>* l, DefUse* el) {
00281   int myNum = n->num();
00282   SListElem<DefUse*>* prev = NULL;
00283   for (SListElem<DefUse*>* e = l->head();
00284        e && e->data()->node->num() < myNum;
00285        prev = e, e = e->next()) ;
00286   l->insertAfter(prev, el);
00287 }
00288 
00289 
00290 Use* PReg::addUse(DUInfo* info, NonTrivialNode* n) {
00291   assert(info->reg == this, "wrong reg");
00292   Use* u = new Use(n);
00293   addDUHelper(n, (SList<DefUse*>*)&info->uses, u);
00294   incUses(u);
00295   return u;
00296 }
00297 
00298 
00299 Use* PReg::addUse(BB* bb, NonTrivialNode* n) {
00300   for (int i = 0; i < dus.length(); i++) {
00301     PRegBBIndex* index = dus.at(i);
00302     if (index->bb == bb) {
00303       DUInfo* info = bb->duInfo.info->at(index->index);
00304       return addUse(info, n);
00305     }
00306   }
00307   return bb->addUse(n, this);
00308 }
00309 
00310 
00311 Def* PReg::addDef(DUInfo* info, NonTrivialNode* n) {
00312   assert(info->reg == this, "wrong reg");
00313   Def* d = new Def(n);
00314   addDUHelper(n, (SList<DefUse*>*)&info->defs, d);
00315   incDefs(d);
00316   return d;
00317 }
00318 
00319 
00320 Def* PReg::addDef(BB* bb, NonTrivialNode* n) {
00321   for (int i = 0; i < dus.length(); i++) {
00322     PRegBBIndex* index = dus.at(i);
00323     if (index->bb == bb) {
00324     DUInfo* info = bb->duInfo.info->at(index->index);
00325     return addDef(info, n);
00326     }
00327   }
00328   return bb->addDef(n, this);
00329 }
00330 
00331 void PReg::forAllDefsDo(Closure<Def*>* c) {
00332   ::forAllDefsDo(&dus, c);
00333 }
00334 
00335 void PReg::forAllUsesDo(Closure<Use*>* c) {
00336   ::forAllUsesDo(&dus, c);
00337 }
00338 
00339 void PReg::allocateTo(Location r) {
00340   if (CompilerDebug) cout(PrintRegAlloc)->print("*allocating %s to %s\n", name(), r.name());
00341   assert(loc.equals(unAllocated), "already allocated");
00342   loc = r;
00343 }
00344 
00345 
00346 bool PReg::extendLiveRange(Node* n) {
00347   // the receiver is being copy-propagated to n
00348   // PRegs currently can't be propagated outside their scope
00349   // should fix CP: treat all PRegs like SAPReg so can propagate anywhere?
00350   return extendLiveRange(n->scope(), n->bci());
00351 }
00352 
00353 bool PReg::extendLiveRange(InlinedScope* s, int bci) {
00354   // the receiver is being copy-propagated to n
00355   // PRegs currently can't be propagated outside their scope
00356   // should fix CP: treat all PRegs like SAPReg so can propagate anywhere?
00357   if (s == _scope) {
00358     return true;        // ok, same scope
00359   } else if (_scope->isSenderOf(s)) {
00360     return true;        // scope is caller; already covers n
00361   } else {
00362     return false;
00363   }
00364 }
00365 
00366 
00367 bool SAPReg::extendLiveRange(Node* n) {
00368   // the receiver is being copy-propagated to n; try to extend its live range
00369   return extendLiveRange(n->scope(), n->bci());
00370 }
00371 
00372 bool SAPReg::extendLiveRange(InlinedScope* s, int bci) {
00373   // the receiver is being copy-propagated to scope s at bci; try to extend its live range
00374   assert(_begBCI != IllegalBCI && creationStartBCI != IllegalBCI &&
00375          _endBCI != IllegalBCI, "live range not set");
00376   if (isInContext()) {
00377     // context locations cannot be propagated beyond their scope
00378     // (otherwise the context pointer's live range would have to be extended)
00379     // was bug 5/3/96  -Urs
00380     return PReg::extendLiveRange(s, bci);
00381   }
00382   bool ok = true;
00383   if (s == _scope) {
00384     if (bciLT(bci, _begBCI)) {
00385       // seems like we're propagating backwards!  happens because of the non-source
00386       // order of the byte codes in while loops (condition comes after body), so
00387       // when propagating from code in the condition into code in the body it looks
00388       // like we're going backwards
00389       // can't handle this yet -- Urs 7/95
00390       return false;
00391     }
00392     if (bciGT(bci, _endBCI)) _endBCI = bci;
00393   } else if (s->isSenderOf(_scope)) {
00394     // propagating upwards - promote receiver to higher scope
00395     for (InlinedScope* ss = _scope; ss->sender() != s; ss = ss->sender());
00396     _scope = s;
00397     _begBCI = ss->senderBCI();
00398     _endBCI = bci;
00399   } else if (_scope->isSenderOf(s)) {
00400     // scope is callee; check if already covered
00401     for (InlinedScope* ss = s; ss->sender() != _scope; ss = ss->sender()) ;
00402     int bci = ss->senderBCI();
00403     if (bciLT(bci, _begBCI)) {
00404       // seems like we're propagating backwards!  happens because of the non-source
00405       // order of the byte codes in while loops (condition comes after body), so
00406       // when propagating from code in the condition into code in the body it looks
00407       // like we're going backwards
00408       // can't handle this yet -- Urs 7/95
00409       return false;
00410     }
00411     if (bciGT(bci, _endBCI)) _endBCI = bci;
00412   } else {
00413     // can't propagate between siblings yet
00414     ok = false;
00415   }
00416   assert(bciLE(_begBCI, _endBCI) && _begBCI != IllegalBCI &&
00417          (bciLE(_endBCI, scope()->nofBytes()) || _endBCI == EpilogueBCI), "invalid start/endBCI");
00418   return ok;
00419 }
00420 
00421 
00422 void ConstPReg::extendLiveRange(InlinedScope* s) {
00423   // make sure the constant reg is in a high enough scope
00424   if (_scope->isSenderOrSame(s)) {
00425     // scope is caller of s
00426   } else if (s->isSenderOf(_scope)) {
00427     // s is caller of scope, so promote receiver to s
00428     _scope = s;
00429   } else {
00430     // scope and s are siblings of some sort - go up to common sender
00431     do { s = s->sender(); } while (!s->isSenderOf(_scope));
00432     _scope = s;
00433   }
00434 }
00435 
00436 
00437 bool ConstPReg::covers(Node* n) const {
00438   // does receiver cover node n (is it live at n)?
00439   InlinedScope* s = n->scope();
00440   if (_scope->isSenderOrSame(s)) {
00441     // ok, scope is caller of s
00442     return true;
00443   } 
00444   return false;
00445 }
00446 
00447 
00448 bool ConstPReg::extendLiveRange(Node* n) {
00449   extendLiveRange(n->scope());
00450   return true;
00451 }
00452 
00453 
00454 bool PReg::checkEquivalentDefs() const {
00455   // check if all defs are equivalent, i.e. assign the same preg
00456   if (ndefs() == 1) return true;
00457   PReg* rhs = NULL;
00458   for (int i = 0; i < dus.length(); i++) {
00459     PRegBBIndex* index = dus.at(i);
00460     BB* bb = index->bb;
00461     DUInfo* info = bb->duInfo.info->at(index->index);
00462     for (SListElem<Def*>* e = info->defs.head(); e; e = e->next()) {
00463       NonTrivialNode* n = e->data()->node;
00464       if (!n->isAssignmentLike()) return false;
00465       if (rhs) {
00466         if (rhs != n->src()) return false;
00467       } else {
00468         rhs = n->src();
00469       }
00470     }
00471   }
00472   // yup, rhs is the only preg ever assigned to me
00473   return true;
00474 }
00475 
00476 
00477 bool PReg::canBeEliminated(bool withUses) const {
00478   // can this PReg be eliminated without compromising the debugging info?
00479   assert(_nuses == 0 || withUses, "still has uses");
00480   if (_ndefs + _nuses == 0) return false;       // nothing to eliminate
00481   
00482   // check if reg can be eliminated
00483   if (incorrectDU()) { // don't elim if uses are incorrect (hardwired pregs)
00484     return false;
00485   }
00486   
00487   assert(!_nsoftUses || debug, "nsoftUses should imply debug");
00488 
00489   if (isBlockPReg() && !withUses && !uplevelR()) {
00490     // blocks can always be eliminated - can describe with BlockValueDesc
00491     return true;
00492   }
00493   
00494   if (debug) {
00495     // debug-visible or uplevel-read: eliminate only if run-time value
00496     // can be reconstructed
00497     if (cpInfo) {
00498       // already computed cpInfo, thus can be eliminated 
00499       assert(!cpReg()->loc.isLocalRegister(), "shouldn't be eliminated");
00500       //assert(!cpReg()->loc.isLocalRegister(), "shouldn't be eliminated (was bug 4/27  -Urs)");
00501       return true;
00502     }
00503     if (_ndefs > 1) {
00504       if (isBlockPReg()) {
00505         // ok; we know all defs of a block are equivalent
00506       } else if (isSAPReg() && checkEquivalentDefs()) {
00507         // ok, all defs are the same
00508       } else {
00509         if (!checkEquivalentDefs()) {
00510           if (CompilerDebug) cout(PrintEliminateUnnededNodes)->print("*not eliminating %s: >1 def && debug-visible\n", name());
00511           return false;
00512         }
00513       }
00514     }
00515     PRegBBIndex* index = dus.first();
00516     DUInfo* info = index->bb->duInfo.info->at(index->index);
00517     SListElem<Def*>* e = info->defs.head();
00518     if (!e) {
00519       // info not in first elem - would have to search
00520       if (CompilerDebug) cout(PrintEliminateUnnededNodes)->print("*not eliminating %s: def not in first info\n", name());
00521       return false;
00522     }
00523     NonTrivialNode* defNode = e->data()->node;
00524     PReg* defSrc;
00525     bool ok;
00526     if (defNode->hasConstantSrc()) {
00527       // constant assignment - easy to handle
00528       ok = true;
00529     } else if (defNode->hasSrc() && (defSrc = defNode->src())->isSAPReg() &&
00530                !defSrc->loc.isRegisterLocation()) {
00531       // can substitute defSrc if its lifetime encompasses ours and if
00532       // it is singly-assigned and not a temp reg (last cond. is necessary to
00533       // prevent e.g. result of a send (in eax) to be used as the receiver of
00534       // subsequent scopes that have nsends > 0; fix this if it becomes a
00535       // performance problem)
00536       ok = defSrc->scope()->isSenderOf(_scope);
00537       if (!ok && defSrc->scope() == _scope && isSAPReg()) {
00538         // same scope, ok if defSrc lives long enough
00539         ok = bciGE(((SAPReg*)defSrc)->endBCI(), endBCI());
00540       }
00541       if (!ok) {
00542         // try to extend defSrc's live range to cover ours
00543         ok = defSrc->extendLiveRange(_scope, endBCI());
00544       }
00545     } else {
00546       ok = false;
00547     }
00548     if (!ok) {
00549       if (CompilerDebug) cout(PrintEliminateUnnededNodes)->print("*not eliminating %s: can't recover debug info\n", name());
00550       return false;                 // can't eliminate this PReg
00551     }
00552   }
00553   return true;
00554 }
00555 
00556 
00557 bool BlockPReg::canBeEliminated(bool withUses) const {
00558   if (!PReg::canBeEliminated(withUses)) return false;
00559   if (!_escapes) return true;
00560   if (uplevelR()) return false;
00561   
00562   // escaping, unused block; can be eliminated
00563   // also, the block doesn't escape anymore
00564   // _escapes = false;
00565   assert(nuses() == 0, "still has uses");
00566   return true;
00567 }
00568 
00569 
00570 // eliminate all nodes defining me (if possible)
00571 void PReg::eliminate(bool withUses) {
00572   if (!canBeEliminated(withUses)) return;
00573   for (int i = 0; i < dus.length(); i++) {
00574     PRegBBIndex* index = dus.at(i);
00575     BB* bb = index->bb;
00576     DUInfo* info = bb->duInfo.info->at(index->index);
00577     eliminateDefs(info, bb, withUses);
00578     if (withUses) eliminateUses(info, bb);
00579   }
00580 }
00581 
00582 void PReg::eliminateUses(DUInfo* info, BB* bb) {
00583   // eliminate all use nodes in info
00584   SListElem<Use*>* ue = info->uses.head();
00585   while (ue) {
00586 #ifdef ASSERT
00587     int oldlen = info->uses.length();     // for debugging
00588 #endif
00589     Node* n = ue->data()->node;
00590     if (CompilerDebug) {
00591       char buf[1024];
00592       cout(PrintEliminateUnnededNodes)->print("*%seliminating node N%ld: %s\n", 
00593         n->canBeEliminated() ? "" : "not ", n->id(), n->print_string(buf)); 
00594     }
00595     assert(n->canBeEliminated(), "must be able to eliminate this");
00596     n->eliminate(bb, this);
00597     assert(info->uses.length() < oldlen, "didn't remove use");
00598     ue = info->uses.head();
00599   }
00600 }
00601 
00602 void PReg::eliminateDefs(DUInfo* info, BB* bb, bool removing) {
00603   // eliminate all defining nodes in info
00604   SListElem<Def*>* e = info->defs.head();
00605   while (e) {
00606 #ifdef ASSERT
00607     int oldlen = info->defs.length();     // for debugging
00608 #endif
00609     NonTrivialNode* n = e->data()->node;
00610     if (n->canBeEliminated()) {
00611       updateCPInfo(n);
00612       n->eliminate(bb, this);
00613       assert(info->defs.length() < oldlen, "didn't remove def");
00614         e = info->defs.head();      // simple, but may rescan some uneliminatable nodes
00615     } else {
00616       if (CompilerDebug) {
00617         char buf[1024];
00618         cout(PrintEliminateUnnededNodes)->print("*not eliminating node N%ld: %s\n", n->id(), n->print_string(buf)); 
00619       }
00620       assert(!removing, "cannot eliminate this?");
00621       e = e->next();
00622     }
00623   }
00624 }
00625 
00626 void BlockPReg::eliminate(bool withUses) {
00627   PReg::eliminate(withUses);
00628   if (nuses() == 0) {
00629     // the block has been eliminated; remove the uplevel accesses
00630     // (needed to enable eliminating the accessed contexts)
00631     if (_uplevelRead) {
00632       for (int i = _uplevelRead->length() - 1; i >= 0; i--) _uplevelRead->at(i)->removeUplevelAccessor(this);
00633     }
00634     if (_uplevelWritten) {
00635       for (int i = _uplevelWritten->length() - 1; i >= 0; i--) _uplevelWritten->at(i)->removeUplevelAccessor(this);
00636     }
00637   }
00638 }
00639 
00640 void PReg::updateCPInfo(NonTrivialNode* n) {
00641   // update/compute cpInfo to keep track of copy-propagation effects for debugging info
00642   if (cpInfo) {
00643     if (debug) {
00644       // canBeEliminated assures that all defs are equivalent
00645 #ifdef ASSERT
00646       CPInfo* cpi = new_CPInfo(n);
00647       assert(cpi && cpi->r->cpReg() == cpReg(), "can't handle this");
00648 #endif
00649     } else {
00650       // can't really handle CP w/multiple defs; make sure we don't use
00651       // bad information
00652       cpInfo->r = dummyPR;
00653     }
00654   } else {
00655     cpInfo = new_CPInfo(n);
00656     assert(!debug || cpInfo || isBlockPReg(), "couldn't create info");
00657     if (cpInfo) {
00658       PReg* r = cpInfo->r;
00659       // if we're eliminating a debug-visible PReg, the replacement
00660       // must be debug-visible, too (so that it isn't allocated to
00661       // a temp reg)
00662       r->debug |= debug;
00663       if (r->cpRegs == NULL) r->cpRegs = new GrowableArray<PReg*>(5);
00664       r->cpRegs->append(this);
00665     }
00666   }
00667 }
00668  
00669 
00670 // for efficiency, node n in isLiveAt() must be "plausible", i.e. in a
00671 // scope somewhere below the receiver's scope
00672 // otherwise, use slow_isLiveAt
00673 
00674 bool PReg::slow_isLiveAt(Node* n) const {
00675   if (_scope->isSenderOrSame(n->scope())) {
00676     return isLiveAt(n);
00677   } else {
00678     return false;
00679   }
00680 }
00681 
00682 
00683 bool PReg::isLiveAt(Node* n) const {
00684   // pregs are live in the entire scope (according to Urs, 2/24/96)
00685   if (!_scope->isSenderOrSame(n->scope())) return false; // cannot be live anymore if s is outside subscopes of _scope
00686   assert(PrologueBCI == begBCI() && endBCI() == EpilogueBCI, "must be live in the entire scope");
00687   return true;
00688 }
00689 
00690 
00691 InlinedScope* findAncestor(InlinedScope* s1, int& bci1, InlinedScope* s2, int& bci2) {
00692   // find closest common ancestor of s1 and s2, and the
00693   // respective sender bcis in that scope
00694   if (s1->depth > s2->depth) {
00695     while (s1->depth > s2->depth) {
00696       bci1 = s1->senderBCI(); s1 = s1->sender();
00697     }
00698   } else {
00699     while (s2->depth > s1->depth) {
00700       bci2 = s2->senderBCI(); s2 = s2->sender();
00701     }
00702   }
00703   assert(s1->depth == s2->depth, "just checkin'...");
00704   while (s1 != s2) {
00705     bci1 = s1->senderBCI(); s1 = s1->sender();
00706     bci2 = s2->senderBCI(); s2 = s2->sender();
00707   }
00708   assert(s1->isInlinedScope(), "oops");
00709   return (InlinedScope*)s1;
00710 }
00711 
00712 
00713 bool SAPReg::isLiveAt(Node* n) const {
00714   // is receiver live at Node n?  (may give conservative answer; i.e., it's ok to
00715   // return true even if the receiver is provably dead)
00716   // check if receiver is live in source-level terms; if that says
00717   // dead it really means dead
00718   InlinedScope* s = n->scope();
00719   bool live = basic_isLiveAt(s, n->bci());
00720   if (!live || !loc.isTemporaryRegister()) return live;
00721   fatal("cannot handle temp registers");
00722   return false;
00723 }
00724 
00725 
00726 bool SAPReg::basic_isLiveAt(InlinedScope* s, int bci) const {
00727   int id = this->id();
00728   if (!_scope->isSenderOrSame(s)) return false; // cannot be live anymore if s is outside subscopes of _scope
00729   assert(bciLE(bci, s->nofBytes()) || bci == EpilogueBCI, "bci too high");
00730   assert(_scope->isSenderOrSame(s), "s is not below my scope");
00731 
00732   // find closest common ancestor of s and creationScope, and the
00733   // respective bcis in that scope
00734   int bs = bci;
00735   int bc = creationStartBCI;
00736   InlinedScope* ss = findAncestor(s, bs, creationScope(), bc);
00737   if (!_scope->isSenderOrSame(ss)) fatal("bad scope arg in basic_isLiveAt");
00738 
00739   // Attention: Originally, the live range of a PReg excluded its defining node.
00740   // The new backend however requires them to be live at the beginning as well.
00741   // The problem comes from situations where a PReg is used over a sequence of
00742   // nodes that all belong to the same bci. In general this has been solved in
00743   // the backend by killing PRegs only at bci boundaries. However, with inlining
00744   // turned on, this became more difficult: resultPRs are defined and used over
00745   // bci boundaries (from callee to caller), but when actually testing for liveness,
00746   // the test sees only the range in the caller, which is all in the same bci.
00747   // By extending the live range so that it includes its definition this is not
00748   // a problem anymore.
00749   //
00750   // Note: the isLiveAt methods are only used by the new backend (gri 3/27/96).
00751   if (ss == _scope) {
00752     // live range = [startBCI, endBCI]                  // originally: ]startBCI, endBCI]
00753     assert(_begBCI == bc ||
00754            ss == creationScope() && creationStartBCI == bc, "oops");
00755     return bciLE(_begBCI, bs) && bciLE(bs, _endBCI);    // originally: bciLT(_begBCI, bs) && bciLE(bs, _endBCI);
00756   } else {
00757     // live range = [bc, end of scope]                  // originally: ]bc, end of scope]
00758     return bciLE(bc, bs);                               // originally: bciLT(bc, bs);
00759   }
00760 }
00761 
00762 
00763 bool PReg::isCPEquivalent(PReg* r) const {
00764   // is receiver in same register as argument?
00765   if (this == r) return true;
00766   // try receiver's CP info
00767   for (CPInfo* i = cpInfo; i && i->r; i = i->r->cpInfo) {
00768     if (i->r == r) return true;
00769   }
00770   // now try the other way
00771   for (i = r->cpInfo; i && i->r; i = i->r->cpInfo) {
00772     if (i->r == this) return true;
00773   }
00774   return false;
00775 }
00776   
00777 
00778 // all the nameNode() functions translate the PReg info into debugging info for
00779 // the scopeDescRecorder
00780 
00781 NameNode* PReg::locNameNode(bool mustBeLegal) const {
00782   assert(!loc.isTemporaryRegister() || !mustBeLegal, "shouldn't be in temp reg");
00783   if (loc.isTemporaryRegister() && !debug) {
00784     return new IllegalName;
00785   } else {
00786     // debug-visible PRegs may have temp regs if they're only visible 
00787     // from uncommon branches
00788     return new LocationName(loc);
00789   }
00790 }
00791 
00792 
00793 InlinedScope* BlockPReg::parent() const {
00794   return _closure->parent_scope();
00795 }
00796 
00797   
00798 NameNode* BlockPReg::locNameNode(bool mustBeLegal) const {
00799   Unused(mustBeLegal);
00800   assert(!loc.isTemporaryRegister(), "shouldn't be in temp reg");    
00801   // for now, always use MemoizedName to describe block (even if always created)
00802   // makes debugging info easier to read (can see which locs must be blocks)
00803   return new MemoizedName(loc, closure()->method(), closure()->parent_scope()->scopeInfo());
00804 }
00805   
00806 
00807 NameNode* PReg::nameNode(bool mustBeLegal) const {
00808   PReg* r = cpReg();
00809   if (!(r->loc.equals(unAllocated))) {
00810     return r->locNameNode(mustBeLegal);
00811   } else if (r->isConstPReg()) {
00812     return r->nameNode(mustBeLegal);
00813   } else if (r->isBlockPReg()) {
00814     CompileTimeClosure* c = ((BlockPReg*) r)->closure();
00815     return new BlockValueName(c->method(), c->parent_scope()->scopeInfo());
00816   } else {
00817     // hack: initial nilling of locals isn't represented yet
00818     // fix this -- should at least check if it's a local
00819     // also, when entire scopes are removed (e.g. when deleting branches of
00820     // a type test) the scope should be marked so its debugging info isn't written
00821     // currently, the contents of such scopes would break several assertions
00822     return newValueName(nilObj);
00823 #ifdef how_it_should_be
00824     assert(!debug, "couldn't recover debug info");
00825     return new IllegalName;
00826 #endif
00827   }
00828 }
00829 
00830 NameNode* ConstPReg::nameNode(bool mustBeLegal) const {
00831   return newValueName(constant);
00832 }
00833 
00834 NameNode* NoPReg::nameNode(bool mustBeLegal) const {
00835   return new IllegalName;
00836 }
00837 
00838 
00839 PReg* PReg::cpReg() const {
00840   // assert(!cpInfo || loc.equals(unAllocated), "allocated regs shouldn't have cpInfo");
00841   // NB: the above assertion looks tempting but can be wrong: some unused PRegs may still
00842   // retain their definition because the defining node cannot be eliminated (because it might fail
00843   // or have other side effects)
00844   // e.g.: result of ArrayAt operation
00845   if (cpInfo == NULL) {
00846     return (PReg*)this;
00847   } else {
00848     PReg* r;
00849     for (CPInfo* i = cpInfo; i; r = i->r, i = r->cpInfo) ;
00850     return r == dummyPR ? (PReg*)this : r;
00851   }
00852 }
00853 
00854 
00855 void BlockPReg::memoize() {
00856   _memoized = true;
00857 }
00858 
00859 
00860 void BlockPReg::markEscaped() {
00861   if (!_escapes) {
00862     _escapes = true;
00863     if (CompilerDebug) cout(PrintExposed)->print("*exposing %s\n", name());
00864     if (MemoizeBlocks) memoize();
00865   }
00866 }
00867 
00868   
00869 void BlockPReg::markEscaped(Node* n) {
00870   markEscaped();
00871   if (_escapeNodes == NULL) _escapeNodes = new GrowableArray<Node*>(5);
00872   if (! _escapeNodes->contains(n)) _escapeNodes->append(n);
00873 }
00874 
00875 
00876 // A helper class for BlockPRegs to compute their uplevel accesses
00877 // Note: Uplevel accesses in all branches are taken into account,
00878 // even if it is known at compile-time that a branch of an ifTrue/ifFalse
00879 // is never generated due to a constant condition (the same holds of course
00880 // for whileTrue/whileFalse and failure blocks of primitive calls).
00881 // -> conservative computation of uplevel accesses
00882 class UplevelComputer: public SpecializedMethodClosure {
00883  public:
00884   BlockPReg* r;                         // the block whose accesses we're computing
00885   InlinedScope* scope;                  // r's scope (i.e., scope creating the block)
00886   GrowableArray<PReg*>* read;           // list of rscope's temps read by r
00887   GrowableArray<PReg*>* written;        // same for written temps 
00888   int nestingLevel;                     // nesting level (0 = block itself, 1 = block within block, etc)
00889   int enclosingDepth;                   // depth to which we're nested within outer method
00890   GrowableArray<Scope*>* enclosingScopes; // 0 = scope immediately enclosing block (= this->scope), etc.
00891   methodOop method;                     // the method currently being scanned for uplevel-accesses; either
00892                                         // r's block method or a nested block method
00893 
00894   UplevelComputer(BlockPReg* reg) {
00895     r = reg; scope = r->scope();
00896     read    = new GrowableArray<PReg*>(10);
00897     written = new GrowableArray<PReg*>(10);
00898     nestingLevel = 0;
00899     method = r->closure()->method();
00900     enclosingDepth = 0;
00901     enclosingScopes = new GrowableArray<Scope*>(5);
00902     for (Scope* s = scope; s != NULL; s = s->parent(), enclosingDepth++) enclosingScopes->push(s);
00903   }
00904 
00905 
00906   void record_temporary (bool reading, int no, int ctx) {
00907     // distance is the lexical nesting distance in source-level terms (i.e., regardless of what the interpreter
00908     // does or whether the intermediate scopes have contexts or not) between r's scope and the scope 
00909     // resolving the access; e.g., 1 --> the scope creating r
00910     int distance = method->lexicalDistance(ctx) - nestingLevel;
00911     if (distance < 1) return;                           // access is resolved in some nested block
00912     Scope* s = enclosingScopes->at(distance - 1);       // -1 because 0th element is enclosing scope, i.e., at distance 1
00913     if (s->isInlinedScope()) {
00914       // temporary is defined in this nmethod
00915       InlinedScope* target = (InlinedScope*)s;
00916       assert(target->allocatesInterpretedContext(), "find_scope returned bad scope");
00917       PReg* reg = target->contextTemporary(no)->preg();
00918       if (CompilerDebug) {
00919         cout(PrintExposed)->print("*adding %s to uplevel-%s of block %s\n", reg->name(), reading ? "read" : "written", r->name());
00920       }
00921       GrowableArray<PReg*>* list = reading ? read : written;
00922       list->append(reg);
00923     } else {
00924       // uplevel access goes to another nmethod 
00925     }
00926   }
00927 
00928   void push_temporary (int no, int context)             { record_temporary(true, no, context); }
00929   void store_temporary(int no, int context)             { record_temporary(false, no, context); }
00930   void allocate_closure(AllocationType type, int nofArgs, methodOop meth) {
00931     // recursively search nested blocks
00932     nestingLevel++;
00933     methodOop savedMethod = method;
00934     method = meth;
00935     MethodIterator iter(meth, this);
00936     method = savedMethod;
00937     nestingLevel--;
00938   }
00939  };
00940 
00941 
00942 void BlockPReg::computeUplevelAccesses() {
00943   // compute _uplevelRead/_uplevelWritten
00944   assert(escapes(), "should escape");
00945   if (_uplevelRead) return;     // already computed
00946   UplevelComputer c(this);
00947   MethodIterator iter(_closure->method(), &c);
00948   assert(! _uplevelWritten, "shouldn't be there");
00949   _uplevelRead    = c.read;
00950   _uplevelWritten = c.written;
00951   for (int i = _uplevelRead->length() - 1; i >= 0; i--) _uplevelRead   ->at(i)->addUplevelAccessor(this, true, false);
00952   for (i = _uplevelWritten->length() - 1;  i >= 0; i--) _uplevelWritten->at(i)->addUplevelAccessor(this, false, true);
00953 }
00954 
00955 
00956 char* PReg::safeName() const {
00957   if (this == NULL) {
00958     return "(null)";     // for safer debugging
00959   } else {
00960     return name();
00961   }
00962 }
00963 
00964 char* PReg::name() const {
00965   char* n = NEW_RESOURCE_ARRAY(char, 25);
00966   if (loc.equals(unAllocated)) {
00967     sprintf(n, "%s%d%s%s%s", prefix(), id(),
00968             uplevelR() || uplevelW() ? "^" : "",
00969             uplevelR() ? "R" : "", uplevelW() ? "W" : "");
00970   } else {
00971     sprintf(n, "%s%d(%s)%s%s%s", prefix(), id(), loc.name(),
00972             uplevelR() || uplevelW() ? "^" : "",
00973             uplevelR() ? "R" : "", uplevelW() ? "W" : "");
00974   }
00975   return n;
00976 }
00977 
00978 
00979 void PReg::print() {
00980   lprintf("%s: ", name()); printDefsAndUses(&dus); lprintf("\n");
00981 }
00982 
00983 
00984 void BlockPReg::print() {
00985   print_short(); lprintf(": "); 
00986   printDefsAndUses(&dus);
00987   if (_uplevelRead) { lprintf("; uplevel-read: "); _uplevelRead->print(); }
00988   if (_uplevelWritten) { lprintf("; uplevel-written: "); _uplevelWritten->print(); }
00989   if (_escapeNodes) { 
00990     lprintf("; escapes at: "); 
00991     for (int i = 0; i < _escapeNodes->length(); i++) lprintf("N%d ", _escapeNodes->at(i)->id()); 
00992   }
00993   lprintf("\n");
00994 }
00995 
00996 
00997 char* BlockPReg::name() const {
00998   char* n = NEW_RESOURCE_ARRAY(char, 25);
00999   sprintf(n, "%s <%#lx>%s", PReg::name(), PrintHexAddresses ? this : 0, _memoized ? "#" : "");
01000   return n;
01001 }
01002 
01003 
01004 char* ConstPReg::name() const {
01005   char* n = NEW_RESOURCE_ARRAY(char, 25);
01006   sprintf(n, "%s <%#lx>", PReg::name(), constant);
01007   return n;
01008 }
01009 
01010 
01011 #ifdef not_yet_used
01012   char* SplitPReg::name() const {
01013     char* n = NEW_RESOURCE_ARRAY(char, 25);
01014 //c    char buf[MaxSplitDepth+1];
01015 //c    sprintf(n, "%s <%s>", PReg::name(), sig->prefix(buf));
01016     sprintf(n, "%s", PReg::name());
01017     return n;
01018   }
01019 #endif
01020 
01021 
01022 bool PReg::verify() const {
01023   bool ok = true;
01024   if (_id < 0 || _id >= currentNo) {
01025     ok = false;
01026     error("PReg %#lx %s: invalid ID %ld", this, name(), _id);
01027   }
01028   int uses = 0, defs = 0;
01029   for (int i = 0; i < dus.length(); i++) {
01030     PRegBBIndex* index = dus.at(i);
01031     DUInfo* info = index->bb->duInfo.info->at(index->index);
01032     defs += info->defs.length();
01033     uses += info->uses.length();
01034   }
01035   if (defs != _ndefs && !incorrectD() && !isConstPReg()) {
01036     // ConstPRegs have fake def
01037     ok = false;
01038     error("PReg %#lx %s: wrong def count (%ld instead of %ld)",
01039           this, name(), _ndefs, defs);
01040   }
01041   if (uses != _nuses && !incorrectU()) {
01042     ok = false;
01043     error("PReg %#lx %s: wrong use count (%ld instead of %ld)",
01044           this, name(), _nuses, uses);
01045   }
01046   if (!incorrectD() && _ndefs == 0 && _nuses > 0) {
01047     ok = false;
01048     error("PReg %#lx %s: used but not defined", this, name());
01049   }
01050 # ifdef fixthis  // fix this - may still be needed
01051   if (debug && !incorrectDU() && isTrashedReg(loc)) {
01052     ok = false;
01053     error("PReg %#lx %s: debug-visible but allocated to temp reg", this, name());
01054   }
01055 # endif
01056   return ok;
01057 }
01058 
01059 
01060 bool SAPReg::verify() const {
01061   bool ok = PReg::verify();
01062   if (ok) {
01063     if (_begBCI == IllegalBCI) {
01064       if (creationStartBCI != IllegalBCI || _endBCI != IllegalBCI) {
01065         ok = false;
01066         error("SAPReg %#lx %s: live range only partially set", this, name());
01067       }
01068     } else if (_scope->isInlinedScope()) {
01069       int ncodes = scope()->nofBytes();
01070       if (creationStartBCI < PrologueBCI ||
01071           creationStartBCI > creationScope()->nofBytes()) {
01072         ok = false;
01073         error("SAPReg %#lx %s: invalid creationStartBCI %ld", this, name(), creationStartBCI);
01074       }
01075       if (_begBCI < PrologueBCI || _begBCI > ncodes) {
01076         ok = false;
01077         error("SAPReg %#lx %s: invalid startBCI %ld", this, name(), _begBCI);
01078       }
01079       if (_endBCI < PrologueBCI || _endBCI > ncodes && _endBCI != EpilogueBCI) {
01080         ok = false;
01081         error("SAPReg %#lx %s: invalid endBCI %ld", this, name(), _endBCI);
01082       }
01083     }
01084   }
01085   return ok;
01086 }
01087 
01088 
01089 bool BlockPReg::verify() const {
01090   bool ok = SAPReg::verify() && _closure->verify();
01091   // check uplevel-accessed vars: if they are blocks, they must be exposed
01092   if (_uplevelRead) {
01093     for (int i = 0; i < _uplevelRead->length(); i++) {
01094       if (_uplevelRead->at(i)->isBlockPReg()) {
01095         BlockPReg* blk = (BlockPReg*)_uplevelRead->at(i);
01096         if (!blk->escapes()) {
01097           error("BlockPReg %#lx is uplevel-accessed by escaping BlockPReg %#lx but isn't marked escaping itself",
01098                  blk, this);
01099           ok = false;
01100         }
01101       }
01102     }
01103     for (i = 0; i < _uplevelWritten->length(); i++) {
01104       if (_uplevelWritten->at(i)->isBlockPReg()) {
01105         BlockPReg* blk = (BlockPReg*)_uplevelRead->at(i);
01106         error("BlockPReg %#lx is uplevel-written by escaping BlockPReg %#lx, but BlockPRegs should never be assigned",
01107                blk, this);
01108         ok = false;
01109       }
01110     }
01111   }
01112   return ok;
01113 }
01114 
01115 
01116 bool NoPReg::verify() const { 
01117   if (_nuses != 0) {
01118     error("NoPReg %#lx: has uses", this);
01119     return false;
01120   } else {
01121     return true;
01122   } 
01123 }
01124 
01125 
01126 bool ConstPReg::verify() const {
01127   bool ok = PReg::verify() && constant->is_klass() || constant->verify();
01128   /*
01129   if (int(constant) < maxImmediate && int(constant) > -maxImmediate
01130     && loc != UnAllocated) {
01131     error("ConstPReg %#lx: could use load immediate to load oop %#lx",
01132            this, constant);
01133     ok = false;
01134   }
01135   */
01136   if (!(loc.equals(unAllocated)) && !loc.isRegisterLocation()) {
01137     error("ConstPReg %#lx: was allocated to stack", this);
01138     ok = false;
01139   }
01140   if (!(loc.equals(unAllocated)) && loc.isTrashedRegister()) {
01141     error("ConstPReg %#lx: was allocated to trashed reg", this);
01142     ok = false;
01143   }
01144   return ok;
01145 }
01146 
01147 
01148 # endif

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