pregMapping.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.35 $ */
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 # ifdef DELTA_COMPILER
00026 # include "incls/_PRegMapping.cpp.incl"
00027 
00028 
00029 // Implementation of PRegMapping
00030 //
00031 // The mapping is done via a simple dictionary implemented via the _pregs array holding
00032 // the keys (the pregs), and the _reg_map & _stack_map arrays holding the values (the
00033 // location indices). Note: A preg may be mapped to a register (via _reg_map & and a
00034 // stack location at the same time). An unused dictionary entry is marked by a NULL
00035 // _pregs entry. An unused map entry is marked by a number < 0.
00036 //
00037 // Invariant: A particular preg exists only once in the _pregs array; it has at least
00038 //            one and at most two locations (a register and a stack location).
00039 //
00040 // Note: A future implementation might use little "mapping objects" instead if these
00041 //       three arrays that are used right now. Likely to speed up the implementation
00042 //       (at() and at_put() are not cheap compared to indirection ->. See class Entry).
00043 
00044 
00045 int PRegMapping::index(PReg* preg) {
00046   assert(preg != NULL, "no preg specified");
00047   // try cashed index first
00048   int i = preg->_map_index_cash;
00049   assert(0 <= i, "_map_index_cash must always be > 0");
00050   if (i < size() && _pregs->at(i) == preg) return i;
00051   // otherwise search for it
00052   i = size();
00053   while (i-- > 0 && _pregs->at(i) != preg) ;
00054   // (-1 <= i < size() && (i >= 0 => _pregs->at(i) == preg)
00055   // if found, set cash for next time
00056   if (i >= 0) preg->_map_index_cash = i;
00057   return i;
00058 }
00059 
00060 
00061 void PRegMapping::set_entry(int i, PReg* preg, int rloc, int sloc) {
00062   assert(preg != NULL, "no preg specified");
00063   assert(!_locs->isLocation(rloc) || _locs->isRegister(rloc), "should be a register location if at all");
00064   assert(!_locs->isLocation(sloc) || _locs->isArgument(sloc) || _locs->isStackTmp(sloc), "should be a stack location if at all");
00065   assert(_locs->isLocation(rloc) || _locs->isLocation(sloc), "at least one location expected");
00066   _pregs->at_put(i, preg);
00067   _regLocs->at_put(i, rloc);
00068   _stkLocs->at_put(i, sloc);
00069   // set cash for next time
00070   preg->_map_index_cash = i;
00071 }
00072 
00073 
00074 int PRegMapping::freeSlot() {
00075   // search for an unused slot
00076   int i = size();
00077   while (i-- > 0 && used(i)) ;
00078   // (-1 <= i < size()) && (i >= 0 => !used(i))
00079   if (i < 0) {
00080     // no free slot => grow arrays
00081     _pregs->append(NULL);
00082     _regLocs->append(-1);
00083     _stkLocs->append(-1);
00084     i = size() - 1;
00085   }
00086   assert(!used(i), "just checkin'...");
00087   return i;
00088 }
00089 
00090 
00091 int PRegMapping::spillablePRegIndex() {
00092   // Finds a PReg that is mapped to a register location and that is not locked.
00093   // Returns a value < 0 if there's no such PReg.
00094   int uses = 999999999;
00095   int i0 = -1;
00096   int i = size();
00097   while (i-- > 0) {
00098     PReg* preg = _pregs->at(i);
00099     int rloc = regLoc(i);
00100     if (preg != NULL && _locs->isRegister(rloc) && !PRegLocker::locks(preg) &&
00101         _locs->nofUses(rloc) < uses) {
00102       uses = _locs->nofUses(rloc);
00103       i0 = i;
00104     }
00105   }
00106   return i0;
00107 }
00108 
00109 
00110 void PRegMapping::ensureOneFreeRegister() {
00111   if (!_locs->freeRegisters()) {
00112     // no free registers available => find a register to spill
00113     int i = spillablePRegIndex();
00114     if (i < 0) fatal("too many temporaries or locked pregs: out of spillable registers");
00115     // std->print("WARNING: Register spilling - check if this works\n");
00116     spillRegister(regLoc(i));
00117     assert(_locs->freeRegisters(), "at least one register should be available now");
00118     verify();
00119   }
00120 }
00121 
00122 
00123 void PRegMapping::spillRegister(int loc) {
00124   assert(_locs->isRegister(loc), "must be a register");
00125   int spillLoc = _locs->allocateStackTmp();
00126   // remap pregs
00127   int i = size();
00128   while (i-- > 0) {
00129     if (used(i) && regLoc(i) == loc) {
00130       _locs->release(loc);
00131       _regLocs->at_put(i, _locs->noLocation);
00132       if (!hasStkLoc(i)) {
00133         _locs->use(spillLoc);
00134         _stkLocs->at_put(i, spillLoc);
00135       }
00136     }
00137   }
00138   _locs->release(spillLoc);
00139   assert(_locs->nofUses(loc) == 0, "location should not be used anymore");
00140   // generate spill code
00141   Register reg = _locs->locationAsRegister(loc);
00142   _assm->movl(_locs->locationAsAddress(spillLoc), reg);
00143   verify();
00144 }
00145 
00146 
00147 int PRegMapping::allocateTemporary(Register hint) {
00148   ensureOneFreeRegister();
00149   int regLoc = _locs->noLocation;
00150   if (hint != noreg) {
00151     // try to use hint register
00152     int hintLoc = _locs->registerAsLocation(hint);
00153     if (_locs->nofUses(hintLoc) == 0) {
00154       // hintLoc is available
00155       _locs->allocate(hintLoc);
00156       regLoc = hintLoc;
00157     }
00158   }
00159   if (!_locs->isLocation(regLoc)) regLoc = _locs->allocateRegister();
00160   assert(_locs->isLocation(regLoc) && _locs->nofUses(regLoc) == 1, "should be allocated exactly once");
00161   _tmpLocs->push(regLoc);
00162   return regLoc;
00163 }
00164 
00165 
00166 void PRegMapping::releaseTemporary(int regLoc) {
00167   if (_tmpLocs->pop() == regLoc) {
00168     _locs->release(regLoc);
00169   } else {
00170     // temporary not freed in stack-fashioned manner
00171     // (can only happen if there's more than one temporary per function)
00172     Unimplemented();
00173   }
00174 }
00175 
00176 
00177 void PRegMapping::releaseAllTemporaries() {
00178   while (_tmpLocs->nonEmpty()) _locs->release(_tmpLocs->pop());
00179 }
00180 
00181 
00182 void PRegMapping::destroy() {
00183   _pregs   = NULL;
00184 }
00185 
00186 
00187 PRegMapping::PRegMapping(MacroAssembler* assm, int nofArgs, int nofRegs, int nofTemps) {
00188   const int initialSize = 8;
00189   _assm    = assm;
00190   _NLRinProgress = false;
00191   _locs    = new Locations(nofArgs, nofRegs, nofTemps);
00192   _pregs   = new GrowableArray<PReg*>(initialSize);
00193   _regLocs = new GrowableArray<int>(initialSize);
00194   _stkLocs = new GrowableArray<int>(initialSize);
00195   _tmpLocs = new GrowableArray<int>(2);
00196   verify();
00197 }
00198 
00199 
00200 PRegMapping::PRegMapping(PRegMapping* m) {
00201   _assm    = m->_assm;
00202   _NLRinProgress = m->_NLRinProgress;
00203   _locs    = new Locations(m->_locs);
00204   _pregs   = m->_pregs->copy();
00205   _regLocs = m->_regLocs->copy();
00206   _stkLocs = m->_stkLocs->copy();
00207   _tmpLocs = m->_tmpLocs->copy();
00208   releaseAllTemporaries();
00209   verify();
00210 }
00211 
00212 
00213 bool PRegMapping::isInjective() {
00214   int i = size();
00215   while (i-- > 0) {
00216     if (used(i)) {
00217       if (hasRegLoc(i) && _locs->nofUses(regLoc(i)) > 1) return false;
00218       if (hasStkLoc(i) && _locs->nofUses(stkLoc(i)) > 1) return false;
00219     }
00220   }
00221   return true;
00222 }
00223 
00224 
00225 bool PRegMapping::isConformant(PRegMapping* with) {
00226   // checks conformity on the intersection of this and with
00227   if (NLRinProgress() != with->NLRinProgress()) return false;
00228   int j = with->size();
00229   while (j-- > 0) {
00230     if (with->used(j)) {
00231       int i = index(with->_pregs->at(j));
00232       if (i >= 0) {
00233         if (regLoc(i) != with->regLoc(j) || stkLoc(i) != with->stkLoc(j)) return false;
00234       }
00235     }
00236   }
00237   return true;
00238 }
00239 
00240 
00241 void PRegMapping::mapToArgument(PReg* preg, int argNo) {
00242   assert(index(preg) < 0, "preg for argument defined twice");
00243   int loc = _locs->argumentAsLocation(argNo);
00244   _locs->use(loc);
00245   set_entry(freeSlot(), preg, _locs->noLocation, loc);
00246   verify();
00247 }
00248 
00249 
00250 void PRegMapping::mapToTemporary(PReg* preg, int tempNo) {
00251   assert(index(preg) < 0, "preg for argument defined twice");
00252   int loc = _locs->temporaryAsLocation(tempNo);
00253   _locs->allocate(loc);
00254   set_entry(freeSlot(), preg, _locs->noLocation, loc);
00255   verify();
00256 }
00257 
00258 
00259 void PRegMapping::mapToRegister(PReg* preg, Register reg) {
00260   assert(index(preg) < 0, "preg for register defined twice");
00261   int loc = _locs->registerAsLocation(reg);
00262   _locs->allocate(loc);
00263   set_entry(freeSlot(), preg, loc, _locs->noLocation);
00264   verify();
00265 }
00266 
00267 
00268 void PRegMapping::kill(PReg* preg) {
00269   int i = index(preg);
00270   if (i >= 0) {
00271     if (PrintPRegMapping) {
00272       std->print("kill ");
00273       print(i);
00274     }
00275     int rloc = regLoc(i);
00276     int sloc = stkLoc(i);
00277     if (_locs->isLocation(rloc)) _locs->release(rloc);
00278     if (_locs->isLocation(sloc)) _locs->release(sloc);
00279     _pregs->at_put(i, NULL);
00280     verify();
00281   }
00282 }
00283 
00284 
00285 void PRegMapping::killAll(PReg* exception) {
00286   int i = size();
00287   while (i-- > 0) {
00288     if (used(i) && _pregs->at(i) != exception) {
00289       assert(!PRegLocker::locks(_pregs->at(i)), "PReg is locked");
00290       if (PrintPRegMapping) {
00291         std->print("kill ");
00292         print(i);
00293       }
00294       int rloc = regLoc(i);
00295       int sloc = stkLoc(i);
00296       if (_locs->isLocation(rloc)) _locs->release(rloc);
00297       if (_locs->isLocation(sloc)) _locs->release(sloc);
00298       _pregs->at_put(i, NULL);
00299     }
00300   }
00301   verify();
00302 }
00303 
00304 
00305 void PRegMapping::killDeadsAt(Node* node, PReg* exception) {
00306   while (node->isTrivial() || node->isMergeNode()) node = node->next();
00307   // In case of a ReturnNode resultPR & scope context are needed
00308   // -> maybe use a better solution?
00309   //
00310   // if (node->isReturnNode()) {
00311   //   // end of method, only result needed
00312   //   killAll(node->scope()->resultPR);
00313   // }
00314   assert(node->id() >= 0, "should not be a comment");
00315   int i = size();
00316   while (i-- > 0) {
00317     PReg* preg = _pregs->at(i);
00318     if (preg != NULL && preg != exception && (!preg->isLiveAt(node) || preg->isConstPReg())) kill(preg);
00319   }
00320 }
00321 
00322 
00323 void PRegMapping::cleanupContextReferences() {
00324   int i = size();
00325   while (i-- > 0) {
00326     PReg* preg = _pregs->at(i);
00327     if (preg != NULL && preg->loc.isContextLocation()) {
00328       // refers to a context temporary -> kill it
00329       kill(preg);
00330     }
00331   }
00332 }
00333 
00334 
00335 // Note: Right now, if there's a hint register given, def() and use() make sure that the
00336 // preg will be mapped to the hint register; and hint must be unallocated. This is not the
00337 // same behaviour as in Temporary, where the hint register is only used if it is actually
00338 // available. Furthermore, this behaviour seems inconsistent somehow, because if the preg
00339 // is already in the hint register it will be used even though it is not actually available
00340 // (kind of academic subtlety).
00341 
00342 Register PRegMapping::def(PReg* preg, Register hint) {
00343 //  assert(!preg->isSAPReg() || index(preg) < 0, "SAPRegs can be defined only once");
00344   int i = index(preg);
00345   assert(i < 0 || !hasStkLoc(i) || !_locs->isArgument(stkLoc(i)), "cannot assign to parameters");
00346   kill(preg);
00347   int loc;
00348   if (hint == noreg) {
00349     ensureOneFreeRegister();
00350     loc = _locs->allocateRegister();
00351     hint = _locs->locationAsRegister(loc);
00352   } else {
00353     loc = _locs->registerAsLocation(hint);
00354     _locs->allocate(loc);
00355   }
00356   set_entry(freeSlot(), preg, loc, _locs->noLocation);
00357   verify();
00358   return hint;
00359 }
00360 
00361 
00362 Register PRegMapping::use(PReg* preg, Register hint) {
00363   int i = index(preg);
00364   if (i < 0 && preg->loc.isContextLocation()) {
00365     // preg refers to context temporary
00366     // determine context temporary address
00367     PReg* context = theCompiler->contextList->at(preg->loc.contextNo())->context();
00368     PRegLocker lock(context);
00369     Address addr = Address(use(context), Mapping::contextOffset(preg->loc.tempNo()));
00370     // determine a target register
00371     int loc;
00372     if (hint == noreg) {
00373       ensureOneFreeRegister();
00374       loc = _locs->allocateRegister();
00375       hint = _locs->locationAsRegister(loc);
00376     } else {
00377       loc = _locs->registerAsLocation(hint);
00378       _locs->allocate(loc);
00379     }
00380     _assm->movl(hint, addr);
00381     set_entry(freeSlot(), preg, loc, _locs->noLocation);
00382   }
00383   i = index(preg);
00384   assert(i >= 0, "preg must have been defined")
00385   if (hasRegLoc(i)) {
00386     Register old = _locs->locationAsRegister(regLoc(i));
00387     if (hint == noreg || hint == old) {
00388       hint = old;
00389     } else {
00390       int loc = _locs->registerAsLocation(hint);
00391       _locs->release(regLoc(i));
00392       _locs->allocate(loc);
00393       _regLocs->at_put(i, loc);
00394       _assm->movl(hint, old);
00395     }
00396   } else {
00397     // copy into register
00398     assert(hasStkLoc(i), "must have at least one location");
00399     int loc;
00400     if (hint == noreg) {
00401       ensureOneFreeRegister();
00402       loc = _locs->allocateRegister();
00403       hint = _locs->locationAsRegister(loc);
00404     } else {
00405       loc = _locs->registerAsLocation(hint);
00406       _locs->allocate(loc);
00407     }
00408     _regLocs->at_put(i, loc);
00409     _assm->movl(hint, _locs->locationAsAddress(stkLoc(i)));
00410   }
00411   verify();
00412   return hint;
00413 }
00414 
00415 
00416 Register PRegMapping::use(PReg* preg) {
00417   Register reg;
00418   if (preg->isConstPReg() && !isDefined(preg)) {
00419     reg = def(preg);
00420     _assm->movl(reg, ((ConstPReg*)preg)->constant);
00421   } else {
00422     reg = use(preg, noreg);
00423   }
00424   return reg;
00425 }
00426 
00427 
00428 void PRegMapping::move(PReg* dst, PReg* src) {
00429   assert(dst->loc != topOfStack, "parameter passing cannot be handled here");
00430   kill(dst); // remove any previous definition
00431   int i = index(src);
00432   assert(i >= 0, "src must be defined");
00433   int rloc = regLoc(i);
00434   int sloc = stkLoc(i);
00435   if (_locs->isLocation(rloc)) _locs->use(rloc);
00436   if (_locs->isLocation(sloc)) _locs->use(sloc);
00437   set_entry(freeSlot(), dst, rloc, sloc);
00438   verify();
00439 }
00440 
00441 
00442 void PRegMapping::saveRegister(int loc) {
00443   assert(_locs->isRegister(loc), "must be a register");
00444   int spillLoc = _locs->allocateStackTmp();
00445   // remap pregs
00446   int i = size();
00447   while (i-- > 0) {
00448     if (used(i) && regLoc(i) == loc) {
00449       if (!hasStkLoc(i)) {
00450         _locs->use(spillLoc);
00451         _stkLocs->at_put(i, spillLoc);
00452       }
00453     }
00454   }
00455   _locs->release(spillLoc);
00456   // generate spill code
00457   _assm->movl(_locs->locationAsAddress(spillLoc), _locs->locationAsRegister(loc));
00458   verify();
00459 }
00460 
00461 
00462 void PRegMapping::saveRegisters(PReg* exception) {
00463   int i = size();
00464   while (i-- > 0) {
00465     if (used(i) && hasRegLoc(i) && !hasStkLoc(i) && _pregs->at(i) != exception) {
00466       saveRegister(regLoc(i));
00467     }
00468   }
00469   verify();
00470 }
00471 
00472 
00473 void PRegMapping::killRegisters(PReg* exception) {
00474   int i = size();
00475   while (i-- > 0) {
00476     if (used(i) && hasRegLoc(i) && _pregs->at(i) != exception) {
00477       // remove that register from mapping & release it
00478       _locs->release(regLoc(i));
00479       _regLocs->at_put(i, _locs->noLocation);
00480       if (!hasStkLoc(i)) {
00481         // remove entry for preg alltogether
00482         _pregs->at_put(i, NULL);
00483       }
00484     }
00485   }
00486   verify();
00487 }
00488 
00489 
00490 void PRegMapping::killRegister(PReg* preg) {
00491   int i = index(preg);
00492   assert(i >= 0, "preg must have been defined")
00493   if (hasRegLoc(i)) {
00494     // remove that register from mapping & release it
00495     _locs->release(regLoc(i));
00496     _regLocs->at_put(i, _locs->noLocation);
00497     if (!hasStkLoc(i)) {
00498       // remove entry for preg alltogether
00499       _pregs->at_put(i, NULL);
00500     }
00501   }
00502   verify();
00503 }
00504 
00505 
00506 void PRegMapping::acquireNLRRegisters() {
00507   guarantee(!NLRinProgress(), "no NLR must be in progress");
00508   _NLRinProgress = true;
00509   _locs->allocate(_locs->registerAsLocation(NLR_result_reg));
00510   _locs->allocate(_locs->registerAsLocation(NLR_home_reg  ));
00511   _locs->allocate(_locs->registerAsLocation(NLR_homeId_reg));
00512 }
00513 
00514 
00515 void PRegMapping::releaseNLRRegisters() {
00516   guarantee(NLRinProgress(), "NLR must be in progress");
00517   _NLRinProgress = false;
00518   _locs->release(_locs->registerAsLocation(NLR_result_reg));
00519   _locs->release(_locs->registerAsLocation(NLR_home_reg  ));
00520   _locs->release(_locs->registerAsLocation(NLR_homeId_reg));
00521 }
00522 
00523 
00524 void PRegMapping::makeInjective() {
00525   // Note: This routine must not generate any code that modifies CPU flags!
00526   int i = size();
00527   while (i-- > 0) {
00528     if (used(i)) {
00529       int rloc = regLoc(i);
00530       int sloc = stkLoc(i);
00531       assert(_locs->isLocation(rloc) || _locs->isLocation(sloc), "must have at least one location");
00532       if (_locs->isLocation(rloc) && _locs->isLocation(sloc)) {
00533         if (_locs->nofUses(rloc) > 1 && _locs->nofUses(sloc) > 1) {
00534           // preg is mapped to both register and stack location that are shared with other pregs
00535           // => map to a new stack location
00536           int newLoc = _locs->allocateStackTmp();
00537           _assm->movl(_locs->locationAsAddress(newLoc), _locs->locationAsRegister(rloc));
00538           _locs->release(rloc);
00539           _locs->release(sloc);
00540           _regLocs->at_put(i, _locs->noLocation);
00541           _stkLocs->at_put(i, newLoc);
00542         } else if (_locs->nofUses(rloc) > 1) {
00543           // preg mapped to a register that is shared with other pregs => use stack location only
00544           _locs->release(rloc);
00545           _regLocs->at_put(i, _locs->noLocation);
00546         } else if (_locs->nofUses(sloc) > 1) {
00547           // preg mapped to a stack location that is shared with other pregs => use register location only
00548           _locs->release(sloc);
00549           _stkLocs->at_put(i, _locs->noLocation);
00550         }
00551       } else if (_locs->isLocation(rloc)) {
00552         if (_locs->nofUses(rloc) > 1) {
00553           // preg is mapped to a register that shared with other pregs => map to a new stack location
00554           int newLoc = _locs->allocateStackTmp();
00555           _assm->movl(_locs->locationAsAddress(newLoc), _locs->locationAsRegister(rloc));
00556           _locs->release(rloc);
00557           _regLocs->at_put(i, _locs->noLocation);
00558           _stkLocs->at_put(i, newLoc);
00559         }
00560       } else if (_locs->isLocation(sloc)) {
00561         if (_locs->nofUses(sloc) > 1) {
00562           // preg is mapped to a stack location that is shared with other pregs => map to a new stack location
00563           ensureOneFreeRegister();
00564           int tmpLoc = _locs->allocateRegister();
00565           int newLoc = _locs->allocateStackTmp();
00566           Register t = _locs->locationAsRegister(tmpLoc);
00567           _assm->movl(t, _locs->locationAsAddress(sloc));
00568           _assm->movl(_locs->locationAsAddress(newLoc), t);
00569           _locs->release(tmpLoc);
00570           _locs->release(sloc);
00571           _regLocs->at_put(i, _locs->noLocation);
00572           _stkLocs->at_put(i, newLoc);
00573         }
00574       } else {
00575         ShouldNotReachHere();
00576       }
00577     }
00578   }
00579   verify();
00580   assert(isInjective(), "mapping not injective");
00581 }
00582 
00583 
00584 void PRegMapping::old_makeConformant(PRegMapping* with) {
00585   // determine which entries have to be adjusted (save values on the stack)
00586   char* begin_of_code = _assm->pc();
00587   GrowableArray<int> src(4);
00588   GrowableArray<int> dst(4);
00589   int j = with->size();
00590   while (j-- > 0) {
00591     if (with->used(j)) {
00592       int i = index(with->_pregs->at(j));
00593       if (i >= 0) {
00594         assert(_pregs->at(i) == with->_pregs->at(j), "should be the same");
00595         if (regLoc(i) != with->regLoc(j) || stkLoc(i) != with->stkLoc(j)) {
00596           // push value if necessary
00597           // (not necessary if one of the locations is conformant)
00598           if (hasRegLoc(i) && regLoc(i) == with->regLoc(j)) {
00599             // register locations conform => not necessary to save a value
00600             if (hasStkLoc(i)) {
00601               assert(stkLoc(i) != with->stkLoc(j), "error in program logic");
00602               _locs->release(stkLoc(i));
00603             }
00604           } else if (hasStkLoc(i) && stkLoc(i) == with->stkLoc(j)) {
00605             // stack locations conform => not necessary to save a value
00606             if (hasRegLoc(i)) {
00607               assert(regLoc(i) != with->regLoc(j), "error in program logic");
00608               _locs->release(regLoc(i));
00609             }
00610           } else {
00611             // none of the locations conform => push value
00612             if (hasRegLoc(i)) {
00613               _assm->pushl(_locs->locationAsRegister(regLoc(i)));
00614             } else {
00615               assert(hasStkLoc(i), "must have at least one location");
00616               _assm->pushl(_locs->locationAsAddress(stkLoc(i)));
00617             }
00618             // free allocated locations
00619             if (hasRegLoc(i)) _locs->release(regLoc(i));
00620             if (hasStkLoc(i)) _locs->release(stkLoc(i));
00621           }
00622           // mapping differs for this preg => remember entries
00623           src.push(i);
00624           dst.push(j);
00625         }
00626       }
00627     }
00628   }
00629 
00630   // pop values from stack and adjust entries
00631   while (src.nonEmpty()) {
00632     int i = src.pop();
00633     int j = dst.pop();
00634     if (hasRegLoc(i) && regLoc(i) == with->regLoc(j)) {
00635       // register locations conform => must have non-conformant stack location
00636       assert(stkLoc(i) != with->stkLoc(j), "error in program logic");
00637       if (with->hasStkLoc(j)) {
00638         _assm->movl(with->_locs->locationAsAddress(with->stkLoc(j)), _locs->locationAsRegister(regLoc(i)));
00639         _locs->allocate(with->stkLoc(j));
00640       }
00641     } else if (hasStkLoc(i) && stkLoc(i) == with->stkLoc(j)) {
00642       // stack locations conform => must have non-conformant register location
00643       assert(regLoc(i) != with->regLoc(j), "error in program logic");
00644       if (with->hasRegLoc(j)) {
00645         _assm->movl(with->_locs->locationAsRegister(with->regLoc(j)), _locs->locationAsAddress(stkLoc(i)));
00646         _locs->allocate(with->regLoc(j));
00647       }
00648     } else {
00649       // none of the locations conform => pop value
00650       if (with->hasRegLoc(j)) {
00651         Register reg = with->_locs->locationAsRegister(with->regLoc(j));
00652         _assm->popl(reg);
00653         if (with->hasStkLoc(j)) {
00654           // copy register on stack
00655           _assm->movl(with->_locs->locationAsAddress(with->stkLoc(j)), reg);
00656         }
00657       } else {
00658         assert(with->hasStkLoc(j), "must have at least one location");
00659         _assm->popl(with->_locs->locationAsAddress(with->stkLoc(j)));
00660       }
00661       // allocate locations
00662       if (with->hasRegLoc(j)) _locs->allocate(with->regLoc(j));
00663       if (with->hasStkLoc(j)) _locs->allocate(with->stkLoc(j));
00664     }
00665     // adjust mapping
00666     _regLocs->at_put(i, with->regLoc(j));
00667     _stkLocs->at_put(i, with->stkLoc(j));
00668   }
00669   char* end_of_code = _assm->pc();
00670   if (PrintMakeConformantCode && begin_of_code < end_of_code) {
00671     std->print_cr("MakeConformant:");
00672     Disassembler::decode(begin_of_code, end_of_code);
00673     std->cr();
00674   }
00675 
00676   verify();
00677   assert(isConformant(with), "mapping not conformant");
00678 }
00679 
00680 
00681 // Helper class to make mappings conformant
00682 
00683 class ConformanceHelper: public MapConformance {
00684  private:
00685   MacroAssembler* _masm;
00686 
00687  public:
00688   void generate(MacroAssembler* masm, Variable temp1, Variable temp2);
00689   void move(Variable src, Variable dst);
00690   void push(Variable src);
00691   void pop (Variable dst);
00692 };
00693 
00694 
00695 void ConformanceHelper::generate(MacroAssembler* masm, Variable temp1, Variable temp2) {
00696   _masm = masm;
00697   MapConformance::generate(temp1, temp2);
00698   _masm = NULL;
00699 };
00700 
00701 
00702 void ConformanceHelper::move(Variable src, Variable dst) {
00703   Register src_reg = src.in_register() ? Register(src.register_number(), ' ') : noreg;
00704   Register dst_reg = dst.in_register() ? Register(dst.register_number(), ' ') : noreg;
00705   Address  src_adr = src.on_stack() ? Address(ebp, src.stack_offset()) : Address();
00706   Address  dst_adr = dst.on_stack() ? Address(ebp, dst.stack_offset()) : Address();
00707 
00708   if (src.in_register()) {
00709     if (dst.in_register()) {
00710       _masm->movl(dst_reg, src_reg);
00711     } else if (dst.on_stack()) {
00712       _masm->movl(dst_adr, src_reg);
00713     } else {
00714       ShouldNotReachHere();
00715     }
00716   } else if (src.on_stack()) {
00717     if (dst.in_register()) {
00718       _masm->movl(dst_reg, src_adr);
00719     } else {
00720       ShouldNotReachHere();
00721     }
00722   } else {
00723     ShouldNotReachHere();
00724   }
00725 }
00726 
00727 
00728 void ConformanceHelper::push(Variable src) {
00729   if (src.in_register()) {
00730     _masm->pushl(Register(src.register_number(), ' '));
00731   } else if (src.on_stack()) {
00732     _masm->pushl(Address(ebp, src.stack_offset()));
00733   } else {
00734     ShouldNotReachHere();
00735   }
00736 }
00737 
00738 
00739 void ConformanceHelper::pop(Variable dst) {
00740   if (dst.in_register()) {
00741     _masm->popl(Register(dst.register_number(), ' '));
00742   } else if (dst.on_stack()) {
00743     _masm->popl(Address(ebp, dst.stack_offset()));
00744   } else {
00745     ShouldNotReachHere();
00746   }
00747 }
00748 
00749 
00750 void PRegMapping::new_makeConformant(PRegMapping* with) {
00751   // set up ConformanceHelper
00752   bool makeConformant = false;
00753   Variable unused = Variable::unused();
00754   ConformanceHelper chelper;
00755   int j = with->size();
00756   while (j-- > 0) {
00757     if (with->used(j)) {
00758       int i = index(with->_pregs->at(j));
00759       if (i >= 0) {
00760         assert(_pregs->at(i) == with->_pregs->at(j), "should be the same");
00761         if (regLoc(i) != with->regLoc(j) || stkLoc(i) != with->stkLoc(j)) {
00762           Variable src_reg =       hasRegLoc(i) ? Variable::new_register(      _locs->locationAsRegisterNo(      regLoc(i))) : unused;
00763           Variable src_stk =       hasStkLoc(i) ? Variable::new_stack   (      _locs->locationAsByteOffset(      stkLoc(i))) : unused;
00764           Variable dst_reg = with->hasRegLoc(j) ? Variable::new_register(with->_locs->locationAsRegisterNo(with->regLoc(j))) : unused;
00765           Variable dst_stk = with->hasStkLoc(j) ? Variable::new_stack   (with->_locs->locationAsByteOffset(with->stkLoc(j))) : unused;
00766           chelper.append_mapping(src_reg, src_stk, dst_reg, dst_stk);
00767           makeConformant = true;
00768         }
00769       }
00770     }
00771   }
00772 
00773   if (makeConformant) {
00774     // mappings differ -> generate code to make them conformant
00775     // first: find free registers that can be used for "make conformance" code
00776     int this_mask =       _locs->freeRegisterMask();
00777     int with_mask = with->_locs->freeRegisterMask();
00778     int both_mask = this_mask & with_mask;
00779     Variable temp1 = unused;
00780     Variable temp2 = unused;
00781     if (both_mask != 0) {
00782       // free registers in common
00783       int i = 0;
00784       while ((both_mask & (1 << i)) == 0) i++;
00785       #ifdef ASSERT
00786         // make sure register can actually be used in both mappings
00787         { Register reg = Register(i, ' ');
00788           int this_rloc =       _locs->registerAsLocation(reg);
00789           int with_rloc = with->_locs->registerAsLocation(reg);
00790           // allocate & deallocate them - will fail if registers are already in use
00791                 _locs->allocate(this_rloc);       _locs->release(this_rloc);
00792           with->_locs->allocate(with_rloc); with->_locs->release(with_rloc);
00793         }
00794       #endif
00795       temp1 = Variable::new_register(i);
00796       clearNth(both_mask, i);
00797     }
00798 
00799     if (both_mask != 0) {
00800       // free registers in common
00801       int i = 0;
00802       while ((both_mask & (1 << i)) == 0) i++;
00803       #ifdef ASSERT
00804         // make sure register can actually be used in both mappings
00805         { Register reg = Register(i, ' ');
00806           int this_rloc =       _locs->registerAsLocation(reg);
00807           int with_rloc = with->_locs->registerAsLocation(reg);
00808           // allocate & deallocate them - will fail if registers are already in use
00809                 _locs->allocate(this_rloc);       _locs->release(this_rloc);
00810           with->_locs->allocate(with_rloc); with->_locs->release(with_rloc);
00811         }
00812       #endif
00813       temp2 = Variable::new_register(i);
00814       clearNth(both_mask, i);
00815     }
00816     guarantee(temp1 != temp2 || temp1 == unused, "should not be the same");
00817 
00818     // make conformant
00819     char* begin_of_code = _assm->pc();
00820     chelper.generate(_assm, temp1, temp2);
00821     char* end_of_code = _assm->pc();
00822     if (PrintMakeConformantCode) {
00823       chelper.print();
00824       std->print_cr("(using R%d & R%d as temporary registers)", temp1.register_number(), temp2.register_number());
00825       Disassembler::decode(begin_of_code, end_of_code);
00826       std->cr();
00827     }
00828 
00829     // Mapping should not be used anymore now, since it is not representing the
00830     // current situation (one should use the 'with' mapping instead). Destroy it
00831     // to make sure it is not accidentally used.
00832     destroy();
00833   }
00834 }
00835 
00836 
00837 void PRegMapping::makeConformant(PRegMapping* with) {
00838   //guarantee(NLRinProgress() == with->NLRinProgress(), "cannot be made conformant");
00839 
00840   if (PrintPRegMapping && WizardMode) {
00841     std->print("make conformant:\n");
00842     print();
00843     std->print("with ");
00844     with->print();
00845   }
00846 
00847   _locs->extendTo(with->_locs->nofStackTmps());
00848   assert(_locs->nofArguments() == with->_locs->nofArguments(), "must be the same");
00849   assert(_locs->nofRegisters() == with->_locs->nofRegisters(), "must be the same");
00850   assert(_locs->nofStackTmps() >= with->_locs->nofStackTmps(), "must be greater or equal");
00851   assert(with->isInjective(), "'with' mapping not injective");
00852   
00853   // strip mapping so that it contains the same pregs as 'with' mapping
00854   int i = size();
00855   while (i-- > 0) {
00856     if (used(i)) {
00857       int j = with->index(_pregs->at(i));
00858       if (j < 0) {
00859         // entry not found in 'with' mapping -> remove it from this mapping
00860         kill(_pregs->at(i));
00861       }
00862     }
00863   }
00864 
00865   if (UseNewMakeConformant) {
00866     new_makeConformant(with);
00867   } else {
00868     old_makeConformant(with);
00869   }
00870 }
00871 
00872 
00873 void PRegMapping::iterate(PRegClosure* closure) {
00874   for (int i = size(); i-- > 0; ) {
00875     PReg* preg = _pregs->at(i);
00876     if (preg != NULL) {
00877       preg->_map_index_cash = i;
00878       closure->preg_do(preg);
00879     }
00880   }
00881 }
00882 
00883 
00884 Location PRegMapping::locationFor(PReg* preg) {
00885   int i = index(preg);
00886   assert(i >= 0, "preg must be defined");
00887   Location loc = illegalLocation;
00888   if (hasStkLoc(i)) {
00889     loc = Location::stackLocation(_locs->locationAsWordOffset(stkLoc(i)));
00890   } else if (hasRegLoc(i)) {
00891     loc = Location::registerLocation(_locs->locationAsRegister(regLoc(i)).number());
00892   } else {
00893     ShouldNotReachHere();
00894   }
00895   return loc;
00896 }
00897 
00898 
00899 int PRegMapping::nofPRegs() {
00900   int i = size();
00901   int n = 0;
00902   while (i-- > 0) {
00903     if (used(i)) n++;
00904   };
00905   return n;
00906 }
00907 
00908 
00909 int PRegMapping::maxNofStackTmps() {
00910   return _locs->nofStackTmps();
00911 }
00912 
00913 
00914 void PRegMapping::my_print() {
00915   // This is only here for debugging because print() cannot
00916   // be called from within the debugger for some strange reason...
00917   print();
00918 }
00919 
00920 
00921 void PRegMapping::print(int i) {
00922   assert(used(i), "unused slot");
00923   int rloc = regLoc(i);
00924   int sloc = stkLoc(i);
00925   std->print("%s -> ", _pregs->at(i)->name());
00926   if (rloc >= 0) {
00927     std->print(_locs->locationAsRegister(rloc).name());
00928   }
00929   if (sloc >= 0) {
00930     if (rloc >= 0) std->print(", ");
00931     int offs = _locs->locationAsByteOffset(sloc);
00932     std->print("[ebp%s%d]", (offs < 0 ? "" : "+"), offs);
00933   }
00934   std->cr();
00935 }
00936 
00937 
00938 void PRegMapping::print() {
00939   if (WizardMode) _locs->print();
00940   if (nofPRegs() > 0) {
00941     std->print("PReg mapping:\n");
00942     for (int i = 0; i < size(); i++) {
00943       if (used(i)) print(i);
00944     }
00945   } else {
00946     std->print("PReg mapping is empty\n");
00947   }
00948   std->cr();
00949   if (_tmpLocs->length() > 0) {
00950     std->print("Temporaries in use:\n");
00951     for (int i = 0; i < _tmpLocs->length(); i++) {
00952       int loc = _tmpLocs->at(i);
00953       assert(_locs->isRegister(loc), "temporaries must be in registers");
00954       std->print("temp %d -> %d %s\n", i, loc, _locs->locationAsRegister(loc).name());
00955     }
00956     std->cr();
00957   }
00958   if (NLRinProgress()) {
00959     std->print_cr("NLR in progress");
00960     std->cr();
00961   }
00962 }
00963 
00964 
00965 void PRegMapping::verify() {
00966   if (!CompilerDebug) return;
00967   _locs->verify();
00968   int totalUses = 0;
00969   int i = size();
00970   while (i-- > 0) {
00971     if (used(i)) {
00972       // verify mapping for entry i
00973       int rloc = regLoc(i);
00974       int sloc = stkLoc(i);
00975       if (rloc < 0 && sloc < 0) fatal("no location associated with preg");
00976       int rlocUses = 0;
00977       int slocUses = 0;
00978       int j = size();
00979       while (j-- > 0) {
00980         if (used(j)) {
00981           if (i != j && _pregs->at(i) == _pregs->at(j)) fatal("preg found twice in mapping");
00982             if (rloc >= 0 && regLoc(j) == rloc) rlocUses++;
00983             if (sloc >= 0 && stkLoc(j) == sloc) slocUses++;
00984           }
00985       }
00986       // check locations usage counter
00987       if (rloc >= 0 && _locs->nofUses(rloc) != rlocUses) fatal("inconsistent nofUses (register locations)");
00988       if (sloc >= 0 && _locs->nofUses(sloc) != slocUses) fatal("inconsistent nofUses (stack locations)");
00989       // compute total usage
00990       if (rloc >= 0) totalUses++;
00991       if (sloc >= 0) totalUses++;
00992     }
00993   }
00994   // check allocated temporaries
00995   i = _tmpLocs->length();
00996   while (i-- > 0) {
00997     int rloc = _tmpLocs->at(i);
00998     if (_locs->nofUses(rloc) != 1) fatal("inconsistent nofUses (temporaries)");
00999     totalUses++;
01000   }
01001   // check NLR registers if in use
01002   if (NLRinProgress()) {
01003     if (_locs->nofUses(_locs->registerAsLocation(NLR_result_reg)) != 1) fatal("inconsistent nofUses (NLR_result_reg)");
01004     if (_locs->nofUses(_locs->registerAsLocation(NLR_home_reg  )) != 1) fatal("inconsistent nofUses (NLR_home_reg  )");
01005     if (_locs->nofUses(_locs->registerAsLocation(NLR_homeId_reg)) != 1) fatal("inconsistent nofUses (NLR_homeId_reg)");
01006     totalUses += 3;
01007   }
01008   // check total uses
01009   if (_locs->nofTotalUses() != totalUses) fatal("inconsistent totalUses");
01010 }
01011 
01012 
01013 // Implementation of PRegLocker
01014 
01015 PRegLocker* PRegLocker::_top;
01016 
01017 
01018 PRegLocker::PRegLocker(PReg* r0) {
01019   assert(r0 != NULL, "PReg must be defined");
01020   lock(r0, NULL, NULL);
01021 }
01022 
01023 
01024 PRegLocker::PRegLocker(PReg* r0, PReg* r1) {
01025   assert(r0 != NULL && r1 != NULL, "PRegs must be defined");
01026   lock(r0, r1, NULL);
01027 }
01028 
01029 
01030 PRegLocker::PRegLocker(PReg* r0, PReg* r1, PReg* r2) {
01031   assert(r0 != NULL && r1 != NULL && r2 != NULL, "PRegs must be defined");
01032   lock(r0, r1, r2);
01033 }
01034 
01035 
01036 bool PRegLocker::holds(PReg* preg) const {
01037   assert(preg != NULL, "undefined preg");
01038   int i = sizeof(_pregs)/sizeof(PReg*);
01039   while (i-- > 0) {
01040     if (preg == _pregs[i]) return true;
01041   }
01042   return false;
01043 }
01044 
01045 
01046 bool PRegLocker::locks(PReg* preg) {
01047   assert(preg != NULL, "undefined preg");
01048   PRegLocker* p = _top;
01049   while (p != NULL && !p->holds(preg)) p = p->_prev;
01050   // p == NULL || p->holds(preg)
01051   return p != NULL;
01052 }
01053 
01054 
01055 // Implementation of Temporary
01056 
01057 Temporary::Temporary(PRegMapping* mapping, Register hint) {
01058   _mapping = mapping;
01059   _regLoc  = mapping->allocateTemporary(hint);
01060 }
01061 
01062 
01063 Temporary::Temporary(PRegMapping* mapping, PReg* preg) {
01064   // old code - keep around for time comparison purposes
01065   const bool old_code = false;
01066   if (old_code) {
01067     _mapping = mapping;
01068     _regLoc  = mapping->allocateTemporary(noreg);
01069     mapping->assembler()->movl(Temporary::reg(), mapping->use(preg));
01070     return;
01071   }
01072 
01073   _mapping = mapping;
01074   Register reg  = mapping->use(preg);
01075   // preg is guaranteed to be in a register
01076   if (mapping->onStack(preg)) {
01077     // preg is also on stack -> release register location from mapping and use it as copy
01078     mapping->killRegister(preg);
01079     _regLoc = mapping->allocateTemporary(reg);
01080   } else {
01081     // preg is only in register -> need to allocate a new register & copy it explicitly
01082     _regLoc = mapping->allocateTemporary(noreg);
01083     mapping->assembler()->movl(Temporary::reg(), reg);
01084   }
01085 }
01086 
01087 
01088 Temporary::~Temporary() {
01089   _mapping->releaseTemporary(_regLoc);
01090 }
01091 
01092 # endif

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