00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025 # ifdef DELTA_COMPILER
00026 # include "incls/_PRegMapping.cpp.incl"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 int PRegMapping::index(PReg* preg) {
00046 assert(preg != NULL, "no preg specified");
00047
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
00052 i = size();
00053 while (i-- > 0 && _pregs->at(i) != preg) ;
00054
00055
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
00070 preg->_map_index_cash = i;
00071 }
00072
00073
00074 int PRegMapping::freeSlot() {
00075
00076 int i = size();
00077 while (i-- > 0 && used(i)) ;
00078
00079 if (i < 0) {
00080
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
00093
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
00113 int i = spillablePRegIndex();
00114 if (i < 0) fatal("too many temporaries or locked pregs: out of spillable registers");
00115
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
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
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
00152 int hintLoc = _locs->registerAsLocation(hint);
00153 if (_locs->nofUses(hintLoc) == 0) {
00154
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
00171
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
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
00308
00309
00310
00311
00312
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
00329 kill(preg);
00330 }
00331 }
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 Register PRegMapping::def(PReg* preg, Register hint) {
00343
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
00366
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
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
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);
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
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
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
00478 _locs->release(regLoc(i));
00479 _regLocs->at_put(i, _locs->noLocation);
00480 if (!hasStkLoc(i)) {
00481
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
00495 _locs->release(regLoc(i));
00496 _regLocs->at_put(i, _locs->noLocation);
00497 if (!hasStkLoc(i)) {
00498
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
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
00535
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
00544 _locs->release(rloc);
00545 _regLocs->at_put(i, _locs->noLocation);
00546 } else if (_locs->nofUses(sloc) > 1) {
00547
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
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
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
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
00597
00598 if (hasRegLoc(i) && regLoc(i) == with->regLoc(j)) {
00599
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
00606 if (hasRegLoc(i)) {
00607 assert(regLoc(i) != with->regLoc(j), "error in program logic");
00608 _locs->release(regLoc(i));
00609 }
00610 } else {
00611
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
00619 if (hasRegLoc(i)) _locs->release(regLoc(i));
00620 if (hasStkLoc(i)) _locs->release(stkLoc(i));
00621 }
00622
00623 src.push(i);
00624 dst.push(j);
00625 }
00626 }
00627 }
00628 }
00629
00630
00631 while (src.nonEmpty()) {
00632 int i = src.pop();
00633 int j = dst.pop();
00634 if (hasRegLoc(i) && regLoc(i) == with->regLoc(j)) {
00635
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
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
00650 if (with->hasRegLoc(j)) {
00651 Register reg = with->_locs->locationAsRegister(with->regLoc(j));
00652 _assm->popl(reg);
00653 if (with->hasStkLoc(j)) {
00654
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
00662 if (with->hasRegLoc(j)) _locs->allocate(with->regLoc(j));
00663 if (with->hasStkLoc(j)) _locs->allocate(with->stkLoc(j));
00664 }
00665
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
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
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
00775
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
00783 int i = 0;
00784 while ((both_mask & (1 << i)) == 0) i++;
00785 #ifdef ASSERT
00786
00787 { Register reg = Register(i, ' ');
00788 int this_rloc = _locs->registerAsLocation(reg);
00789 int with_rloc = with->_locs->registerAsLocation(reg);
00790
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
00801 int i = 0;
00802 while ((both_mask & (1 << i)) == 0) i++;
00803 #ifdef ASSERT
00804
00805 { Register reg = Register(i, ' ');
00806 int this_rloc = _locs->registerAsLocation(reg);
00807 int with_rloc = with->_locs->registerAsLocation(reg);
00808
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
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
00830
00831
00832 destroy();
00833 }
00834 }
00835
00836
00837 void PRegMapping::makeConformant(PRegMapping* with) {
00838
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
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
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
00916
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
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
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
00990 if (rloc >= 0) totalUses++;
00991 if (sloc >= 0) totalUses++;
00992 }
00993 }
00994
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
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
01009 if (_locs->nofTotalUses() != totalUses) fatal("inconsistent totalUses");
01010 }
01011
01012
01013
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
01051 return p != NULL;
01052 }
01053
01054
01055
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
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
01076 if (mapping->onStack(preg)) {
01077
01078 mapping->killRegister(preg);
01079 _regLoc = mapping->allocateTemporary(reg);
01080 } else {
01081
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