locations.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.12 $ */
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/_locations.cpp.incl"
00027 
00028 
00029 // Implementation of Locations
00030 //
00031 // Each entry of _freeList corresponds to a register or stack location. If the location
00032 // is used, the _freeList entry holds the negative reference count for that location. If
00033 // the location is not used, the _freeList entry holds a link (an index) to the next un-
00034 // used location or a sentinel value which indicates the end of the list. There are two
00035 // free lists, one for registers and one for stack locations; the end of a list is indi-
00036 // cated by a sentinel entry.
00037 //
00038 // _freeList->at(i) >= 0: unused, entry is index to next unused entry or sentinel
00039 // _freeList->at(i) <  0: used, entry is negative reference count
00040 
00041 Locations::Locations(int nofArgs, int nofRegs, int nofInitialStackTmps) {
00042   assert(0 <= nofArgs, "illegal number of arguments");
00043   assert(0 <= nofRegs && nofRegs <= maxNofUsableRegisters, "too many registers required");
00044   _nofArguments = nofArgs;
00045   _nofRegisters = nofRegs;
00046   _freeList     = new GrowableArray<int>(nofArgs + nofRegs + nofInitialStackTmps);
00047   int i = 0;
00048   // initialize argument reference counts
00049   while (i < nofArgs) {
00050     _freeList->at_put_grow(i, 0);
00051     i++;
00052   }
00053   // initialize register free list
00054   while (i < nofArgs + nofRegs) {
00055     _freeList->at_put_grow(i, i-1);
00056     i++;
00057   }
00058   _freeList->at_put(nofArgs, sentinel); // end of list
00059   _firstFreeRegister = i-1;
00060   // initialize stackTmps free list
00061   while (i < nofArgs + nofRegs + nofInitialStackTmps) {
00062     _freeList->at_put_grow(i, i-1);
00063     i++;
00064   }
00065   _freeList->at_put(nofArgs + nofRegs, sentinel); // end of list
00066   _firstFreeStackTmp = i-1;
00067   verify();
00068 }
00069 
00070 
00071 Locations::Locations(Locations* l) {
00072   l->verify();
00073   _nofArguments      = l->_nofArguments;
00074   _nofRegisters      = l->_nofRegisters;
00075   _freeList          = l->_freeList->copy();
00076   _firstFreeRegister = l->_firstFreeRegister;
00077   _firstFreeStackTmp = l->_firstFreeStackTmp;
00078   verify();
00079 }
00080 
00081 
00082 void Locations::extendTo(int nofStackTmps) {
00083   while (this->nofStackTmps() < nofStackTmps) {
00084     // grow _freeList
00085     _freeList->append(_firstFreeStackTmp);
00086     _firstFreeStackTmp = _freeList->length() - 1;
00087   }
00088   verify();
00089 }
00090 
00091 
00092 int Locations::allocateRegister() {
00093   int i = _firstFreeRegister;
00094   if (!isRegister(i)) fatal("out of registers");
00095   _firstFreeRegister = _freeList->at(i);
00096   _freeList->at_put(i, -1); // initialize reference count
00097   verify();
00098   return i;
00099 }
00100 
00101 
00102 int Locations::allocateStackTmp() {
00103   int i = _firstFreeStackTmp;
00104   if (!isStackTmp(i)) {
00105     // grow _freeList
00106     _freeList->append(sentinel);
00107     assert(_freeList->length() <= sentinel, "sentinel too small");
00108     i = _freeList->length() - 1;
00109   }
00110   _firstFreeStackTmp = _freeList->at(i);
00111   _freeList->at_put(i, -1); // initialize reference count
00112   verify();
00113   return i;
00114 }
00115 
00116 
00117 void Locations::allocate(int i) {
00118   assert(isLocation(i), "illegal location");
00119   assert(nofUses(i) == 0, "already allocated");
00120   if (isRegister(i)) {
00121     int j = _firstFreeRegister;
00122     if (j == i) {
00123       // remove first entry from free list
00124       _firstFreeRegister = _freeList->at(i);
00125     } else {
00126       // find i in the free list
00127       while (_freeList->at(j) != i) j = _freeList->at(j);
00128       _freeList->at_put(j, _freeList->at(i));
00129     }
00130     _freeList->at_put(i, -1); // initialize reference count
00131   } else if (isStackTmp(i)) {
00132     int j = _firstFreeStackTmp;
00133     if (j == i) {
00134       // remove first entry from free list
00135       _firstFreeStackTmp = _freeList->at(i);
00136     } else {
00137       // find i in the free list
00138       while (_freeList->at(j) != i) j = _freeList->at(j);
00139       _freeList->at_put(j, _freeList->at(i));
00140     }
00141     _freeList->at_put(i, -1); // initialize reference count
00142   } else {
00143     ShouldNotReachHere();
00144   }
00145   verify();
00146 }
00147 
00148 
00149 void Locations::use(int i) {
00150   assert(isLocation(i), "illegal location");
00151   assert(isArgument(i) || nofUses(i) > 0, "not yet allocated");
00152   _freeList->at_put(i, _freeList->at(i) - 1); // adjust reference counter
00153   verify();
00154 }
00155 
00156 
00157 void Locations::release(int i) {
00158   assert(isLocation(i), "illegal location");
00159   assert(nofUses(i) > 0, "not yet allocated");
00160   _freeList->at_put(i, _freeList->at(i) + 1); // adjust reference counter
00161   if (_freeList->at(i) == 0) {
00162     // not used anymore => recycle
00163     if (isRegister(i)) {
00164       // register location
00165       _freeList->at_put(i, _firstFreeRegister);
00166       _firstFreeRegister = i;
00167     } else if (isStackTmp(i)) {
00168       // stack location
00169       _freeList->at_put(i, _firstFreeStackTmp);
00170       _firstFreeStackTmp = i;
00171     }
00172   }
00173   verify();
00174 }
00175 
00176 
00177 int Locations::nofUses(int i) const {
00178   assert(isLocation(i), "illegal location");
00179   int n = _freeList->at(i);
00180   return n < 0 ? -n : 0;
00181 }
00182 
00183 
00184 int Locations::nofTotalUses() const {
00185   int totalUses = 0;
00186   for (int i = locationsBeg(); i < locationsEnd(); i++) totalUses += nofUses(i);
00187   return totalUses;
00188 }
00189 
00190 
00191 int Locations::nofFreeRegisters() const {
00192   int i = _firstFreeRegister;
00193   int n = 0;
00194   while (isRegister(i)) {
00195     i = _freeList->at(i);
00196     n++;
00197   }
00198   return n;
00199 }
00200 
00201 
00202 int Locations::freeRegisterMask() const {
00203   int mask = 0;
00204   for (int i = registersBeg(); i < registersEnd(); i++) {
00205     if (nofUses(i) == 0) mask |= 1 << locationAsRegister(i).number();
00206   }
00207   return mask;
00208 }
00209 
00210 
00211 int Locations::usedRegisterMask() const {
00212   int mask = 0;
00213   for (int i = registersBeg(); i < registersEnd(); i++) {
00214     if (nofUses(i) > 0) mask |= 1 << locationAsRegister(i).number();
00215   }
00216   return mask;
00217 }
00218 
00219 
00220 int Locations::argumentAsLocation(int argNo) const {
00221   assert(0 <= argNo && argNo < nofArguments(), "illegal argument no.");
00222   return argumentsBeg() + argNo;
00223 }
00224 
00225 
00226 int Locations::registerAsLocation(Register reg) const {
00227   assert(maxNofUsableRegisters == 6, "inconsistency - adjust this code");
00228   if (reg == eax) return registersBeg() + 0;
00229   if (reg == ebx) return registersBeg() + 1;
00230   if (reg == ecx) return registersBeg() + 2;
00231   if (reg == edx) return registersBeg() + 3;
00232   if (reg == edi) return registersBeg() + 4;
00233   if (reg == esi) return registersBeg() + 5;
00234   ShouldNotReachHere();
00235   return 0;
00236 }
00237 
00238 
00239 int Locations::temporaryAsLocation(int tempNo) const {
00240   assert(0 <= tempNo, "illegal temporary no.");
00241   return stackTmpsBeg() + tempNo;
00242 }
00243 
00244 
00245 Register Locations::locationAsRegister(int loc) const {
00246   assert(isRegister(loc), "location is not a register");
00247   switch (loc - registersBeg()) {
00248     case  0: return eax;
00249     case  1: return ebx;
00250     case  2: return ecx;
00251     case  3: return edx;
00252     case  4: return edi;
00253     case  5: return esi;
00254     default: fatal("inconsistency - adjust this code");
00255   }
00256   ShouldNotReachHere();
00257   return eax;
00258 }
00259 
00260 
00261 // Stack frame
00262 //
00263 // |    ^   |
00264 // |1st temp| <-- ebp - 1*oopSize (firstTemporaryOffset)
00265 // |ebp save| <-- ebp
00266 // |ret addr|
00267 // |last arg| <-- ebp + 2*oopSize (lastParameterOffset)
00268 // |        |
00269 
00270 int Locations::locationAsWordOffset(int loc) const {
00271   assert(isLocation(loc), "illegal location");
00272   if (isArgument(loc)) {
00273     int lastParameterOffset = 2;
00274     return lastParameterOffset + (nofArguments() - 1 - (loc - argumentsBeg()));
00275   } else if (isStackTmp(loc)) {
00276     const int firstTemporaryOffset = -1;
00277     return firstTemporaryOffset - (loc - stackTmpsBeg());
00278   }
00279   ShouldNotReachHere();
00280   return 0;
00281 }
00282 
00283 
00284 void Locations::print() {
00285   int len = _freeList->length();
00286   int i;
00287   // print used locations
00288   std->print("Locations:\n");
00289   for (i = 0; i < len; i++) {
00290     if (nofUses(i) > 0) {
00291       std->print("%d: %d uses\n", i, nofUses(i));
00292     }
00293   }
00294   std->cr();
00295   // print whole free list
00296   std->print("Free List:\n");
00297   std->print("no. of arguments    : %d\n", _nofArguments);
00298   std->print("no. of registers    : %d\n", _nofRegisters);
00299   std->print("first free register : %d\n", _firstFreeRegister);
00300   std->print("first free stack loc: %d\n", _firstFreeStackTmp);
00301   for (i = 0; i < len; i++) {
00302     std->print("%d: %d\n", i, _freeList->at(i));
00303   }
00304   std->cr();
00305 }
00306 
00307 
00308 void Locations::verify() {
00309   if (!CompilerDebug) return;
00310   int nofFreeRegisters = 0;
00311   int nofFreeStackTmps = 0;
00312   int nofUsedLocations = 0;
00313   int i;
00314   // verify arguments reference counts
00315   i = 0;
00316   while (i < _nofArguments) {
00317     if (_freeList->at(i) > 0) fatal("bug in argument reference counts");
00318     i++;
00319   }
00320   // verify register free list
00321   i = _firstFreeRegister;
00322   while (i != sentinel) {
00323     if (!isRegister(i)) fatal("bug in registers free list");
00324     nofFreeRegisters++;
00325     i = _freeList->at(i);
00326   }
00327   if (nofFreeRegisters > _nofRegisters) fatal("too many free registers");
00328   // verify stack locs free list
00329   i = _firstFreeStackTmp;
00330   while (i != sentinel) {
00331     if (!isStackTmp(i)) fatal("bug in stack locs free list");
00332     nofFreeStackTmps++;
00333     i = _freeList->at(i);
00334   }
00335   if (nofFreeStackTmps > _freeList->length() - _nofRegisters - _nofArguments) fatal("too many free stack locs");
00336   // verify used locations
00337   i = _freeList->length();
00338   while (i-- > _nofArguments) {
00339     if (_freeList->at(i) < 0) nofUsedLocations++;
00340   }
00341   // verify total number
00342   if (_nofArguments + nofFreeRegisters + nofFreeStackTmps + nofUsedLocations != _freeList->length()) fatal("locations data structure is leaking");
00343 }
00344 
00345 
00346 # endif

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