node.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.155 $ */
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/_node.cpp.incl"
00028 
00029 int BasicNode::currentID;
00030 int BasicNode::currentCommentID;
00031 int BasicNode::lastBCI;
00032 ScopeInfo BasicNode::lastScopeInfo;
00033 primitive_desc* InterruptCheckNode::_intrCheck;
00034 
00035 int NodeFactory::cumulCost;
00036 
00037 
00038 // Implementation of NodeFactory
00039 
00040 PrologueNode* NodeFactory::new_PrologueNode(LookupKey* key, int nofArgs, int nofTemps) {
00041   PrologueNode* res = new PrologueNode(key, nofArgs, nofTemps);
00042   registerNode(res);
00043   return res;
00044 }
00045 
00046 LoadOffsetNode* NodeFactory::new_LoadOffsetNode(PReg* dst, PReg* base, int offs, bool isArray) {
00047   LoadOffsetNode* res = new LoadOffsetNode(dst, base, offs, isArray);
00048   registerNode(res);
00049   return res;
00050 }
00051 
00052 LoadUplevelNode* NodeFactory::new_LoadUplevelNode(PReg* dst, PReg* context0, int nofLevels, int offset, symbolOop name) {
00053   LoadUplevelNode* res = new LoadUplevelNode(dst, context0, nofLevels, offset, name);
00054   registerNode(res);
00055   return res;
00056 }
00057 
00058 LoadIntNode* NodeFactory::new_LoadIntNode(PReg* dst, int value) {
00059   LoadIntNode* res = new LoadIntNode(dst, value);
00060   registerNode(res);
00061   return res;
00062 }
00063   
00064 StoreOffsetNode* NodeFactory::new_StoreOffsetNode(PReg* src, PReg* base, int offs, bool needStoreCheck) {
00065   StoreOffsetNode* res = new StoreOffsetNode(src, base, offs, needStoreCheck);
00066   registerNode(res);
00067   return res;
00068 }
00069 
00070 StoreUplevelNode* NodeFactory::new_StoreUplevelNode(PReg* src, PReg* context0, int nofLevels, int offset, symbolOop name, bool needStoreCheck) {
00071   StoreUplevelNode* res = new StoreUplevelNode(src, context0, nofLevels, offset, name, needStoreCheck);
00072   registerNode(res);
00073   return res;
00074 }
00075 
00076 AssignNode* NodeFactory::new_AssignNode(PReg* src, PReg* dst) {
00077   AssignNode* res = new AssignNode(src, dst);
00078   registerNode(res);
00079   return res;
00080 }
00081 
00082 ReturnNode* NodeFactory::new_ReturnNode(PReg* result, int bci) {
00083   ReturnNode* res = new ReturnNode(result, bci);
00084   registerNode(res);
00085   return res;
00086 }
00087 
00088 InlinedReturnNode* NodeFactory::new_InlinedReturnNode(int bci, PReg* src, PReg* dst) {
00089   InlinedReturnNode* res = new InlinedReturnNode(bci, src, dst);
00090   registerNode(res);
00091   return res;
00092 }
00093 
00094 NLRSetupNode* NodeFactory::new_NLRSetupNode(PReg* result, int bci) {
00095   NLRSetupNode* res = new NLRSetupNode(result, bci);
00096   registerNode(res);
00097   return res;
00098 }
00099 
00100 NLRContinuationNode* NodeFactory::new_NLRContinuationNode(int bci) {
00101   InlinedScope* scope = theCompiler->currentScope();
00102   PReg* reg = new PReg(scope, NLRResultLoc, false, false);
00103   NLRContinuationNode* res = new NLRContinuationNode(bci, reg, reg);
00104   registerNode(res);
00105   return res;
00106 }
00107 
00108 NLRTestNode* NodeFactory::new_NLRTestNode(int bci) {
00109   NLRTestNode* res = new NLRTestNode(bci);
00110   registerNode(res);
00111   theCompiler->nlrTestPoints->append(res);
00112   return res;
00113 }
00114 
00115 ArithRRNode* NodeFactory::new_ArithRRNode(PReg* dst, PReg* src, ArithOpCode op, PReg* o2) {
00116   ArithRRNode* res = new ArithRRNode(op, src, o2, dst);
00117   registerNode(res);
00118   return res;
00119 }
00120 
00121 ArithRCNode* NodeFactory::new_ArithRCNode(PReg* dst, PReg* src, ArithOpCode op, int   o2) {
00122   ArithRCNode* res = new ArithRCNode(op, src, o2, dst);
00123   registerNode(res);
00124   return res;
00125 }
00126 
00127 TArithRRNode* NodeFactory::new_TArithRRNode(PReg* dst, PReg* src, ArithOpCode op, PReg* o2, bool a1, bool a2) {
00128   TArithRRNode* res = new TArithRRNode(op, src, o2, dst, a1, a2);
00129   registerNode(res);
00130   return res;
00131 }
00132 
00133 FloatArithRRNode* NodeFactory::new_FloatArithRRNode(PReg* dst, PReg* src, ArithOpCode op, PReg* o2) {
00134   FloatArithRRNode* res = new FloatArithRRNode(op, src, o2, dst);
00135   registerNode(res);
00136   return res;
00137 }
00138 
00139 FloatUnaryArithNode* NodeFactory::new_FloatUnaryArithNode(PReg* dst, PReg* src, ArithOpCode op) {
00140   FloatUnaryArithNode* res = new FloatUnaryArithNode(op, src, dst);
00141   registerNode(res);
00142   return res;
00143 }
00144 
00145 MergeNode* NodeFactory::new_MergeNode(Node* prev1, Node* prev2) {
00146   MergeNode* res = new MergeNode(prev1, prev2);
00147   registerNode(res);
00148   return res;
00149 }
00150 
00151 MergeNode* NodeFactory::new_MergeNode(int bci) {
00152   MergeNode* res = new MergeNode(bci);
00153   registerNode(res);
00154   return res;
00155 }
00156 
00157 SendNode* NodeFactory::new_SendNode(LookupKey* key, MergeNode* nlrTestPoint, GrowableArray<PReg*>* args,
00158                                     GrowableArray<PReg*>* expr_stack, bool superSend, SendInfo* info) {
00159   SendNode* res = new SendNode(key, nlrTestPoint, args, expr_stack, superSend, info);
00160   assert(expr_stack, "must have expression stack");
00161   res->scope()->addSend(expr_stack, true);  // arguments to call are debug-visible
00162   registerNode(res);
00163   return res;
00164 }
00165 
00166 PrimNode* NodeFactory::new_PrimNode(primitive_desc* pdesc, MergeNode* nlrTestPoint, GrowableArray<PReg*>* args,
00167                                     GrowableArray<PReg*>* expr_stack) {
00168   PrimNode* res = new PrimNode(pdesc, nlrTestPoint, args, expr_stack);
00169   if (pdesc->can_walk_stack()) {
00170     assert(expr_stack, "must have expression stack");
00171     if (expr_stack) res->scope()->addSend(expr_stack, true);  // arguments to some prim calls are debug-visible
00172   } else {
00173     assert(expr_stack == NULL, "should not have expression stack");
00174   }
00175   registerNode(res);
00176   return res;
00177 }
00178 
00179 DLLNode* NodeFactory::new_DLLNode(symbolOop dll_name, symbolOop function_name, dll_func function, bool async,
00180                                   MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack) {
00181   DLLNode* res = new DLLNode(dll_name, function_name, function, async, nlrTestPoint, args, expr_stack);
00182   res->scope()->addSend(expr_stack, true);  // arguments to DLL call are debug-visible
00183   registerNode(res);
00184   return res;
00185 }
00186 
00187 InterruptCheckNode* NodeFactory::new_InterruptCheckNode(GrowableArray<PReg*>* exprStack) {
00188   InterruptCheckNode* res = new InterruptCheckNode(exprStack);
00189   registerNode(res);
00190   return res;
00191 }
00192 
00193 LoopHeaderNode* NodeFactory::new_LoopHeaderNode() {
00194   LoopHeaderNode* res = new LoopHeaderNode();
00195   registerNode(res);
00196   return res;
00197 }
00198   
00199 BlockCreateNode* NodeFactory::new_BlockCreateNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack) {
00200   BlockCreateNode* res = new BlockCreateNode(b, expr_stack);
00201   registerNode(res);
00202   return res;
00203 }
00204 
00205 BlockMaterializeNode* NodeFactory::new_BlockMaterializeNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack) {
00206   BlockMaterializeNode* res = new BlockMaterializeNode(b, expr_stack);
00207   registerNode(res);
00208   return res;
00209 }
00210 
00211 ContextCreateNode* NodeFactory::new_ContextCreateNode(PReg* parent, PReg* context, int nofTemps, GrowableArray<PReg*>* expr_stack) {
00212   ContextCreateNode* res = new ContextCreateNode(parent, context, nofTemps, expr_stack);
00213   registerNode(res);
00214   return res;
00215 }
00216 
00217 ContextCreateNode* NodeFactory::new_ContextCreateNode(PReg* b, const ContextCreateNode* n, GrowableArray<PReg*>* expr_stack) {
00218   ContextCreateNode* res = new ContextCreateNode(b, n, expr_stack);
00219   registerNode(res);
00220   return res;
00221 }
00222 
00223 ContextInitNode* NodeFactory::new_ContextInitNode(ContextCreateNode* creator) {
00224   ContextInitNode* res = new ContextInitNode(creator);
00225   registerNode(res);
00226   return res;
00227 }
00228 
00229 ContextInitNode* NodeFactory::new_ContextInitNode(PReg* b, const ContextInitNode* n) {
00230   ContextInitNode* res = new ContextInitNode(b, n);
00231   registerNode(res);
00232   return res;
00233 }
00234 
00235 ContextZapNode* NodeFactory::new_ContextZapNode(PReg* context) {
00236   ContextZapNode* res = new ContextZapNode(context);
00237   registerNode(res);
00238   return res;
00239 }
00240 
00241 BranchNode* NodeFactory::new_BranchNode(BranchOpCode op, bool taken_is_uncommon) {
00242   BranchNode* res = new BranchNode(op, taken_is_uncommon);
00243   registerNode(res);
00244   return res;
00245 }
00246 
00247 TypeTestNode* NodeFactory::new_TypeTestNode(PReg* recv, GrowableArray<klassOop>* classes, bool hasUnknown) {
00248   TypeTestNode* res = new TypeTestNode(recv, classes, hasUnknown);
00249   registerNode(res);
00250   res->scope()->addTypeTest(res);
00251   return res;
00252 }
00253 
00254 ArrayAtNode* NodeFactory::new_ArrayAtNode(ArrayAtNode::AccessType access_type, PReg* array, PReg* index, bool smiIndex,
00255                                           PReg* result, PReg* error, int data_offset, int length_offset) {
00256   ArrayAtNode* res = new ArrayAtNode(access_type, array, index, smiIndex, result, error, data_offset, length_offset);
00257   registerNode(res);
00258   return res;
00259 }
00260   
00261 ArrayAtPutNode* NodeFactory::new_ArrayAtPutNode(ArrayAtPutNode::AccessType access_type, PReg* array, PReg* index, bool smi_index,
00262                                                 PReg* element, bool smi_element, PReg* result, PReg* error, int data_offset, int length_offset,
00263                                                 bool needs_store_check) {
00264   ArrayAtPutNode* res = new ArrayAtPutNode(access_type, array, index, smi_index, element, smi_element, result, error, data_offset, length_offset, needs_store_check);
00265   registerNode(res);
00266   return res;
00267 }
00268 
00269 InlinedPrimitiveNode* NodeFactory::new_InlinedPrimitiveNode(InlinedPrimitiveNode::Operation op, PReg* result, PReg* error,
00270                                                             PReg* recv, PReg* arg1, bool arg1_is_smi, PReg* arg2, bool arg2_is_smi) {
00271   InlinedPrimitiveNode* res = new InlinedPrimitiveNode(op, result, error, recv, arg1, arg1_is_smi, arg2, arg2_is_smi);
00272   registerNode(res);
00273   return res;
00274 }
00275   
00276 UncommonNode* NodeFactory::new_UncommonNode(GrowableArray<PReg*>* exprStack, int bci) {
00277   UncommonNode* res = new UncommonNode(exprStack, bci);
00278   registerNode(res);
00279   assert(exprStack, "must have expr. stack");
00280   res->scope()->addSend(exprStack, false);  // current expr stack is debug-visible
00281   return res;
00282 }
00283 
00284 FixedCodeNode* NodeFactory::new_FixedCodeNode(FixedCodeNode::FixedCodeKind k) {
00285   FixedCodeNode* res = new FixedCodeNode(k);
00286   registerNode(res);
00287   return res;
00288 }
00289 
00290 NopNode* NodeFactory::new_NopNode() {
00291   NopNode* res = new NopNode();
00292   registerNode(res);
00293   return res;
00294 }
00295 
00296 CommentNode* NodeFactory::new_CommentNode(char* comment) {
00297   CommentNode* res = new CommentNode(comment);
00298   registerNode(res);
00299   return res;
00300 }
00301 
00302 
00303 
00304 void initNodes() {
00305   Node::currentID = Node::currentCommentID = 0;
00306   Node::lastScopeInfo = (ScopeInfo)-1;
00307   Node::lastBCI = IllegalBCI;
00308   NodeFactory::cumulCost = 0;
00309 }
00310 
00311 
00312 void BasicNode::setScope(InlinedScope* s) {
00313   _scope = s;
00314   _bci = s ? s->bci() : IllegalBCI;
00315   assert(!s || !s->isInlinedScope() || s->bci() <= ((InlinedScope*)s)->nofBytes(), "illegal bci");
00316 }
00317 
00318 
00319 BasicNode::BasicNode() {
00320   _id = currentID++; _bb = NULL;
00321   setScope(theCompiler->currentScope());
00322   _num = -1; 
00323   dontEliminate = deleted = false;
00324   _mapping = NULL;
00325 }
00326 
00327 
00328 PRegMapping* BasicNode::mapping() const {
00329   return new PRegMapping(_mapping);
00330 }
00331 
00332 
00333 void BasicNode::setMapping(PRegMapping* mapping) {
00334   assert(!hasMapping(), "cannot be assigned twice");
00335   _mapping = new PRegMapping(mapping);
00336 }
00337 
00338 
00339 NonTrivialNode::NonTrivialNode() {
00340   _src = _dest = NULL;
00341   srcUse = NULL; destDef = NULL;
00342 }
00343 
00344 
00345 LoadUplevelNode::LoadUplevelNode(PReg* dst, PReg* context0, int nofLevels, int offset, symbolOop name) : LoadNode(dst) {
00346   assert(context0 != NULL, "context0 is NULL");
00347   assert(nofLevels >= 0  , "nofLevels must be >= 0");
00348   assert(offset >= 0     , "offset must be >= 0");
00349   _context0    = context0;  _context0Use = NULL;
00350   _nofLevels   = nofLevels;
00351   _offset      = offset;
00352   _name        = name;
00353 }
00354 
00355 
00356 StoreUplevelNode::StoreUplevelNode(PReg* src, PReg* context0, int nofLevels, int offset, symbolOop name, bool needsStoreCheck)
00357   : StoreNode(src) {
00358   assert(context0 != NULL, "context0 is NULL");
00359   assert(nofLevels >= 0  , "nofLevels must be >= 0");
00360   assert(offset >= 0     , "offset must be >= 0");
00361   _context0             = context0;
00362   _nofLevels            = nofLevels;
00363   _offset               = offset;
00364   _needsStoreCheck      = needsStoreCheck;
00365   _name                 = name;
00366 }
00367 
00368 
00369 AssignNode::AssignNode(PReg* s, PReg* d) : StoreNode(s) {
00370   _dest = d; assert(d, "dest is NULL");
00371   // Fix this Lars assert(!s->isNoPReg(), "source must be a real PReg");
00372   assert(s != d, "creating dummy assignment"); 
00373 }
00374 
00375 
00376 CommentNode::CommentNode(char* s) {
00377   comment = s;
00378   // give all comments negative ids (don't disturb node numbers by turning
00379   // CompilerDebug off and on)
00380   _id = --currentCommentID; currentID--;
00381 }
00382 
00383 
00384 ArrayAtNode::ArrayAtNode(AccessType access_type, PReg* array, PReg* index, bool smiIndex,
00385                          PReg* result, PReg* error, int data_offset, int length_offset)
00386   : AbstractArrayAtNode(array, index, smiIndex, result, error, data_offset, length_offset) {
00387   _access_type = access_type;
00388 }
00389 
00390 
00391 ArrayAtPutNode::ArrayAtPutNode(AccessType access_type, PReg* array, PReg* index, bool smi_index,
00392                                PReg* element, bool smi_element, PReg* result, PReg* error, int data_offset, int length_offset,
00393                                bool needs_store_check)
00394   : AbstractArrayAtPutNode(array, index, smi_index, element, result, error, data_offset, length_offset) {
00395   _access_type                  = access_type;
00396   _needs_store_check            = needs_store_check;
00397   _smi_element                  = smi_element;
00398   _needs_element_range_check    = (access_type == byte_at_put || access_type == double_byte_at_put);
00399 }
00400 
00401 
00402 TypeTestNode::TypeTestNode(PReg* rr, GrowableArray<klassOop>* classes, bool hasUnknown) {
00403   _src = rr;
00404   _classes = classes;
00405   _hasUnknown = hasUnknown;
00406   int len = classes->length();
00407   assert(len > 0, "should have at least one class to test");
00408   // The assertion below has been replaced by a warning since
00409   // sometimes Inliner::inlineMerge(...) creates such a TypeTestNode.
00410   // FIX THIS
00411   // assert((len > 1) || hasUnknown, "TypeTestNode is not necessary");
00412   if ((len == 1) && !hasUnknown) {
00413     warning("TypeTestNode with only one klass & no uncommon case => performance bug");
00414   }
00415 # ifdef ASSERT
00416     for (int i = 0; i < len; i++) {
00417       for (int j = i + 1; j < len; j++) {
00418         assert(classes->at(i) != classes->at(j), "duplicate class");
00419       }
00420     }
00421 # endif
00422 }
00423 
00424 
00425 ArithRRNode::ArithRRNode(ArithOpCode op, PReg* arg1, PReg* arg2, PReg* dst) : ArithNode(op, arg1, dst) {
00426   _oper = arg2;
00427   if (_src->isConstPReg() && ArithOpIsCommutative[_op]) {
00428     // make sure that if there's a constant argument, it's the 2nd one
00429     PReg* t1 = _src; _src = _oper; _oper = t1;
00430   }
00431 }
00432 
00433 
00434 TArithRRNode::TArithRRNode(ArithOpCode op, PReg* arg1, PReg* arg2, PReg* dst, bool arg1IsInt, bool arg2IsInt) {
00435   if (arg1->isConstPReg() && ArithOpIsCommutative[op]) {
00436     // make sure that if there's a constant argument, it's the 2nd one
00437     PReg* t1 = arg1;      arg1      = arg2;      arg2      = t1;
00438     bool  t2 = arg1IsInt; arg1IsInt = arg2IsInt; arg2IsInt = t2;
00439   }
00440   _op = op;
00441   _src = arg1;
00442   _oper = arg2;
00443   _dest = dst;
00444   _arg1IsInt = arg1IsInt;
00445   _arg2IsInt = arg2IsInt;
00446   _constResult = NULL;
00447   dontEliminate = true; // don't eliminate even if result unused because primitive might fail
00448 }
00449   
00450 
00451 PReg* NonTrivialNode::dest() const {
00452   if (!hasDest()) fatal("has no dest");
00453   return _dest;
00454 }
00455 
00456 
00457 void NonTrivialNode::setDest(BB* bb, PReg* d) {
00458   // bb == NULL means don't update defs
00459   if (!hasDest()) fatal("has no dest");
00460   assert(bb || !destDef, "shouldn't have a def");
00461   if (destDef) _dest->removeDef(bb, destDef);
00462   _dest = d;
00463   if (bb) destDef = _dest->addDef(bb, (NonTrivialNode*)this);
00464 }
00465 
00466 
00467 PReg* NonTrivialNode::src() const {
00468   if (!hasSrc()) fatal("has no src");
00469   return _src;
00470 }
00471 
00472 
00473 bool AssignNode::isAccessingFloats() const {
00474   // After building the node data structure, float pregs have a float location but
00475   // later during compilation, this location is transformed into a stack location,
00476   // therefore the two tests. This should change at some point; it would be cleaner
00477   // to have a special FloatPRegs (or a flag in the PReg, respectively).
00478   return
00479     _src ->loc.isFloatLocation() || _src ->loc == topOfFloatStack || Mapping::isFloatTemporary(_src ->loc) ||
00480     _dest->loc.isFloatLocation() || _dest->loc == topOfFloatStack || Mapping::isFloatTemporary(_dest->loc) ;
00481 }
00482 
00483 
00484 oop AssignNode::constantSrc() const {
00485   assert(hasConstantSrc(), "no constant src");
00486   return ((ConstPReg*)_src)->constant;
00487 }
00488 
00489 
00490 bool AssignNode::canBeEliminated() const {
00491   return !(_src->loc.isTopOfStack() || _dest->loc.isTopOfStack());
00492 }
00493 
00494 
00495 bool Node::endsBB() const { 
00496   return next() == NULL || next()->startsBB(); 
00497 }
00498 
00499 void Node::removeMe() {
00500   assert(hasSingleSuccessor() && hasSinglePredecessor(), "subclass");
00501   if (_prev) _prev->moveNext(this, _next);
00502   if (_next) _next->movePrev(this, _prev);
00503   _prev = _next = NULL;
00504 }
00505 
00506 void Node::removePrev(Node* n) {
00507   /* cut the _prev link between this and n      */
00508   assert(hasSinglePredecessor(), "subclass");
00509   assert(_prev == n, "should be same");
00510   _prev = NULL;
00511 }
00512 
00513 void Node::removeNext(Node* n) {
00514   /* cut the next link between this and n */
00515   assert(hasSingleSuccessor(), "subclass");
00516   assert(_next == n, "should be same");
00517   n->removePrev(this);
00518   _next = NULL;
00519 }
00520 
00521 Node* Node::endOfList() const {
00522   if (_next == NULL) return (Node*)this;
00523   for (Node* n = _next; n->_next; n = n->_next) {
00524       assert(n->hasSingleSuccessor(), ">1 successors");
00525   }
00526   return n;
00527 }
00528 
00529 void AbstractMergeNode::removeMe() {
00530   if (hasSinglePredecessor()) {
00531     _prev = firstPrev();
00532     TrivialNode::removeMe();
00533   } else {
00534     fatal("not implemented yet");
00535   }
00536 }
00537 
00538 void AbstractMergeNode::movePrev(Node* from, Node* to) {
00539   for (int i = _prevs->length() - 1; i >= 0; i--) {
00540     if (_prevs->at(i) == from) { _prevs->at_put(i, to); return; }
00541   }
00542   fatal("from not found");
00543 }
00544 
00545 bool AbstractMergeNode::isPredecessor(const Node* n) const {
00546   for (int i = _prevs->length() - 1; i >= 0; i--) {
00547     if (_prevs->at(i) == n) return true;
00548   }
00549   return false;
00550 }
00551 
00552 void AbstractBranchNode::removeMe() {
00553   if (hasSingleSuccessor()) {
00554     if (!_next && _nxt->nonEmpty()) { _next = next1(); _nxt->pop(); }
00555       NonTrivialNode::removeMe();
00556   } else {
00557       fatal("not implemented yet");
00558   }
00559 }
00560 
00561 void AbstractBranchNode::removeNext(Node* n) {
00562   /* cut the next link between this and n */
00563   if (n == _next) {
00564     n->removePrev(this);
00565     _next = NULL;
00566   } else {
00567     for (int i = 0; i < _nxt->length() && _nxt->at(i) != n; i++) ;
00568     assert(i < _nxt->length(), "not found");
00569     n->removePrev(this);
00570     for ( ; i < _nxt->length() - 1; i++) _nxt->at_put(i, _nxt->at(i+1));
00571     _nxt->pop();
00572   }
00573 }
00574 
00575 void AbstractBranchNode::setNext(int i, Node* n) {
00576   if (i == 0) {
00577     setNext(n);
00578   } else {
00579     assert(_nxt->length() == i - 1, "wrong index");
00580     _nxt->append(n);
00581   }
00582 }
00583 
00584 void AbstractBranchNode::moveNext(Node* from, Node* to) {
00585   if (_next == from) {
00586     _next = to;
00587   } else {
00588     for (int i = 0; i < _nxt->length() && _nxt->at(i) != from; i++) ;
00589     assert(i < _nxt->length(), "not found");
00590     _nxt->at_put(i, to);
00591   }
00592 }
00593 
00594 bool AbstractBranchNode::isSuccessor(const Node* n) const {
00595   if (_next == n) {
00596     return true;
00597   } else {
00598     for (int i = 0; i < _nxt->length() && _nxt->at(i) != n; i++) ;
00599     return i < _nxt->length();
00600   }
00601 }
00602 
00603 BB* BasicNode::newBB() {
00604   if (_bb == NULL) {
00605     int len = 0;
00606     _bb = new BB((Node*)this, (Node*)this, 1);     
00607     for (Node* n = (Node*)this; !n->endsBB() && n->next() != NULL; n = n->next()) {
00608       n->_num = len++; n->_bb = _bb;
00609     }
00610     n->_num = len++; n->_bb = _bb;
00611     _bb->last = n;
00612     _bb->nnodes = len;
00613   }
00614   return _bb;
00615 }
00616 
00617 
00618 MergeNode::MergeNode(Node* prev1, Node* prev2) : AbstractMergeNode(prev1, prev2) {
00619   _bci = max(prev1->bci(), prev2->bci());
00620   isLoopStart = isLoopEnd = didStartBB = false;
00621 }
00622 
00623 
00624 MergeNode::MergeNode(int bci) {
00625   _bci = bci;
00626   isLoopStart = isLoopEnd = didStartBB = false;
00627 }
00628 
00629 
00630 BB* MergeNode::newBB() {
00631   if (_bb == NULL) {
00632     // receiver starts a new BB
00633     didStartBB = true;
00634     _bb = Node::newBB();
00635   }
00636   return _bb;
00637 }
00638 
00639 
00640 ReturnNode::ReturnNode(PReg* res, int bci)
00641   : AbstractReturnNode(
00642       bci,
00643       res,
00644       new TempPReg(theCompiler->currentScope(), resultLoc, true, true)
00645     ) {
00646   assert(res->loc == resultLoc, "must be in special location");
00647 }
00648 
00649 
00650 NLRSetupNode::NLRSetupNode(PReg* result, int bci)
00651   : AbstractReturnNode(
00652       bci,
00653       result,
00654       new TempPReg(theCompiler->currentScope(), resultLoc, true, true)
00655     ) {
00656   contextUse = resultUse = NULL;
00657   assert(result->loc == NLRResultLoc, "must be in special location");
00658 }
00659 
00660 
00661 MergeNode* CallNode::nlrTestPoint() const {
00662   if (nSuccessors() > 1) {
00663     assert(next1()->isMergeNode(), "should be a merge");
00664     return (MergeNode*)next1();
00665   } else {
00666     return NULL;
00667   }
00668 }
00669 
00670 
00671 CallNode::CallNode(MergeNode* n, GrowableArray<PReg*>* a, GrowableArray<PReg*>* e) {
00672   if (n != NULL) append1(n);
00673   exprStack = e;
00674   args = a;
00675   _dest = new SAPReg(scope(), resultLoc, false, false, _bci, _bci);
00676   argUses = uplevelUses = NULL;
00677   uplevelDefs = NULL;
00678   uplevelUsed = uplevelDefd = NULL;
00679   nblocks = theCompiler->blockClosures->length();
00680 }
00681 
00682 
00683 SendNode::SendNode(
00684   LookupKey* key,
00685   MergeNode* nlrTestPoint,
00686   GrowableArray<PReg*>* args,
00687   GrowableArray<PReg*>* expr_stack,
00688   bool superSend,
00689   SendInfo* info
00690   )
00691   : CallNode(nlrTestPoint, args, expr_stack) {
00692   _key = key;
00693   _superSend = superSend; _info = info;
00694   assert(exprStack, "should have expr stack");
00695   // Fix this when compiler is more flexible
00696   // not a fatal because it could happen for super sends that fail (no super method found)
00697   if (_superSend && !UseNewBackend) warning("We cannot yet have super sends in nmethods");
00698 }
00699 
00700 
00701 ContextCreateNode::ContextCreateNode(PReg* parent, PReg* context, int nofTemps, GrowableArray<PReg*>* expr_stack)
00702 : PrimNode(primitives::context_allocate(), NULL, NULL, expr_stack) {
00703   _src          = parent;
00704   _dest         = context;
00705   _nofTemps     = nofTemps;
00706   _contextSize  = 0;
00707   _parentContexts = NULL;
00708   _parentContextUses = NULL;
00709   Scope* p = _scope->parent();
00710   PReg* prevContext = parent;
00711   // collect all parent contexts
00712   while (p && p->isInlinedScope() && ((InlinedScope*)p)->context()) {
00713     PReg* c = ((InlinedScope*)p)->context();
00714     if (c != prevContext) {
00715       if (!_parentContexts) _parentContexts = new GrowableArray<PReg*>(5);
00716       _parentContexts->append(c);
00717       prevContext = c;
00718     }
00719     p = p->parent();
00720   }
00721 }
00722 
00723 
00724 ContextCreateNode::ContextCreateNode(PReg* b, const ContextCreateNode* n, GrowableArray<PReg*>* expr_stack)
00725 : PrimNode(primitives::context_allocate(), NULL, NULL, expr_stack) {
00726   warning("check this implementation");
00727   Unimplemented();
00728   // Urs, don't we need a source here?
00729   // I've added hasSrc() (= true) to ContextCreateNode) - should double check this
00730   // What is this constructor good for? Cloning only? src should be taken care of as well, I guess.
00731   // This constructor would be called only for splitting (when copying the node) -- won't happen for now.
00732   _dest         = b;
00733   _nofTemps     = n->_nofTemps;
00734   _parentContextUses  = NULL;
00735 }
00736 
00737 
00738 ContextInitNode::ContextInitNode(ContextCreateNode* creator) {
00739   int nofTemps  = creator->nofTemps();
00740   _src          = creator->context();
00741   assert(_src, "must have context");
00742   _initializers = new GrowableArray<Expr*>(nofTemps, nofTemps, NULL);   // holds initializer for each element (or NULL)
00743   _contentDefs  = NULL;
00744   _initializerUses = NULL;
00745   _materializedBlocks = NULL;
00746 }
00747 
00748 
00749 ContextInitNode::ContextInitNode(PReg* b, const ContextInitNode* node) {
00750   _src          = b;
00751   assert(_src, "must have context");
00752   _initializers = node->_initializers;
00753   assert((node->_contentDefs == NULL) && (node->_initializerUses == NULL), "shouldn't copy after uses have been built");
00754   _contentDefs  = NULL;
00755   _initializerUses = NULL;
00756   _materializedBlocks = NULL;
00757 }
00758 
00759 
00760 BlockCreateNode::BlockCreateNode(BlockPReg* b, GrowableArray<PReg*>* expr_stack) : 
00761 PrimNode(primitives::block_allocate(), NULL, NULL, expr_stack) {
00762   _src = NULL;
00763   _dest = b;
00764   _contextUse = NULL;
00765   switch (b->method()->block_info()) {
00766    case methodOopDesc::expects_nil:             // no context needed
00767         _context = NULL; break;
00768    case methodOopDesc::expects_self:
00769         _context = b->scope()->self()->preg(); break;
00770    case methodOopDesc::expects_parameter:       // fix this -- should find which
00771         _context = NULL;
00772         break;
00773    case methodOopDesc::expects_context:
00774         _context = b->scope()->context(); break;
00775    default:
00776         fatal("unexpected incoming info");
00777   };
00778 }
00779 
00780 
00781 int ContextInitNode::positionOfContextTemp(int n) const {
00782   // return position of ith context temp in compiled (physical) context
00783   int pos = 0;
00784   for (int i = 0; i < n; i++) {
00785     PReg* p = contents()->at(i)->preg();
00786     if (p->loc.isContextLocation()) pos++;
00787   }
00788   return pos;
00789 }
00790 
00791 void ContextInitNode::initialize(int no, Expr* expr) {
00792   assert((_initializers->at(no) == NULL) || (_initializers->at(no)->constant() == nilObj),
00793          "already initialized this context element");
00794   _initializers->at_put(no, expr);
00795 }
00796 
00797 
00798 ContextCreateNode* ContextInitNode::creator() const {
00799   // returns the corresponding context creation node
00800   Node* n = _prev;
00801   assert(n->isContextCreateNode(), "must be creator node");
00802   return (ContextCreateNode*)n;
00803 }
00804 
00805 
00806 void ContextInitNode::addBlockMaterializer(BlockMaterializeNode* n) {
00807   if (!_materializedBlocks) _materializedBlocks = new GrowableArray<BlockMaterializeNode*>(5);
00808   _materializedBlocks->append(n);
00809 }
00810 
00811 void ContextInitNode::notifyNoContext() {
00812   // our context has been optimized away, i.e., all context contents
00813   // will be stack-allocated like normal PRegs
00814   // remove the context use (otherwise the contextPR has 1 use and no defs)
00815   _src->removeUse(bb(), srcUse);
00816   _src = NULL;
00817   if (_materializedBlocks) {
00818     for (int i = _materializedBlocks->length() - 1; i >= 0; i--) {
00819       // remove the block materialization node
00820       BlockMaterializeNode* n = _materializedBlocks->at(i);
00821       n->eliminate(n->bb(), NULL, true, false); 
00822       PReg* blk = n->src();
00823       assert(blk->isBlockPReg(), "must be a block");
00824 
00825       // remove use of block
00826       for (int j = _initializers->length() - 1; j >= 0; j--) {
00827         if (_initializers->at(j)->preg() == blk) {
00828           blk->removeUse(_bb, _initializerUses->at(j));
00829           break;
00830         }
00831       }
00832 
00833       // try to eliminate the block, too 
00834       if (blk->hasNoUses()) {
00835         // eliminate the block
00836         blk->eliminate(false);
00837       }
00838     }
00839   }
00840 }
00841 
00842 
00843 PrimNode::PrimNode(primitive_desc* pdesc, MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack)
00844   : CallNode(nlrTestPoint, args, expr_stack) {
00845   _pdesc = pdesc;
00846   assert(_pdesc->can_perform_NLR() || (nlrTestPoint == NULL), "no NLR target needed"); 
00847   if (pdesc->can_invoke_delta()) {
00848     assert(expr_stack != NULL, "should have expr stack");
00849   } else {
00850     // the expression stack is only needed if the primitive can walk the
00851     // stack (then the elements will be debug-visible) or if the primitive
00852     // can scavenge (then the elems must be allocated to GCable regs)
00853     exprStack = NULL;        
00854   }
00855 }
00856 
00857 
00858 InlinedPrimitiveNode::InlinedPrimitiveNode(Operation op, PReg* result, PReg* error,
00859                                            PReg* recv, PReg* arg1, bool arg1_is_smi, PReg* arg2, bool arg2_is_smi) {
00860   _op           = op;
00861   _dest         = result;
00862   _error        = error;
00863   _src          = recv;
00864   _arg1         = arg1;
00865   _arg2         = arg2;
00866   _arg1_is_smi  = arg1_is_smi;
00867   _arg2_is_smi  = arg2_is_smi;
00868 }
00869 
00870 
00871 bool InlinedPrimitiveNode::canFail() const {
00872   switch (op()) {
00873     case obj_klass        : return false;
00874     case obj_hash         : return false;
00875     case proxy_byte_at    : return !arg1_is_smi();
00876     case proxy_byte_at_put: return !arg1_is_smi() || !arg2_is_smi();
00877   };
00878   ShouldNotReachHere();
00879   return false;
00880 }
00881 
00882 
00883 bool InlinedPrimitiveNode::canBeEliminated() const {
00884   switch (op()) {
00885     case obj_klass        : return true;
00886     case obj_hash         : return true;
00887     case proxy_byte_at    : return !canFail();
00888     case proxy_byte_at_put: return false;
00889   };
00890   ShouldNotReachHere();
00891   return false;
00892 }
00893 
00894 
00895 UncommonNode::UncommonNode(GrowableArray<PReg*>* e, int bci) { exprStack = e; _bci = bci;}
00896 
00897 
00898 bool PrimNode::canBeEliminated() const {
00899   if (!Node::canBeEliminated()) return false;
00900   if (_pdesc->can_be_constant_folded() && !canFail()) return true;
00901   // temporary hack -- fix this
00902   // should test arg types to make sure prim won't fail
00903   // for now, treat cloning etc. special
00904   if (_pdesc->can_be_constant_folded()) return true;    // not safe!
00905   if (_pdesc->fn() == fntype(&behaviorPrimitives::allocate) ||
00906       _pdesc->fn() == fntype(&primitiveNew0) ||
00907       _pdesc->fn() == fntype(&primitiveNew1) ||
00908       _pdesc->fn() == fntype(&primitiveNew2) ||
00909       _pdesc->fn() == fntype(&primitiveNew3) ||
00910       _pdesc->fn() == fntype(&primitiveNew4) ||
00911       _pdesc->fn() == fntype(&primitiveNew5) ||
00912       _pdesc->fn() == fntype(&primitiveNew6) ||
00913       _pdesc->fn() == fntype(&primitiveNew7) ||
00914       _pdesc->fn() == fntype(&primitiveNew8) ||
00915       _pdesc->fn() == fntype(&primitiveNew9)
00916      ) {
00917     return true;
00918   }
00919   return false;
00920 }
00921 
00922 bool PrimNode::canInvokeDelta() const {
00923   return _pdesc->can_invoke_delta();
00924 }
00925 
00926 bool PrimNode::canFail() const {
00927   return _pdesc->can_fail();
00928 }
00929 
00930 
00931 DLLNode::DLLNode(symbolOop dll_name, symbolOop function_name, dll_func function, bool async,
00932                  MergeNode* nlrTestPoint, GrowableArray<PReg*>* args, GrowableArray<PReg*>* expr_stack)
00933   : CallNode(nlrTestPoint, args, expr_stack) {
00934   _dll_name      = dll_name;
00935   _function_name = function_name;
00936   _function      = function;
00937   _async         = async;
00938 }
00939 
00940 
00941 bool DLLNode::canInvokeDelta() const {
00942   return true;          // user-defined DLL code can do anything
00943 }
00944 
00945 
00946 NLRTestNode::NLRTestNode(int bci) {}
00947 
00948 
00949 void NLRTestNode::fixup() {
00950   // connect next() and next1()
00951   if (scope()->isTop()) {
00952     theCompiler->enterScope(scope()); // so that nodes get right scope
00953     // Non-inlined scope: continuation just continues NLR
00954     append(0, NodeFactory::new_NLRContinuationNode(bci()));
00955     // return point returns the NLR result
00956     PReg* nlr_result = new TempPReg(scope(), resultOfNLR, true, true);
00957     Node* n = NodeFactory::new_AssignNode(nlr_result, scope()->resultPR);
00958     append(1, n);
00959     n->append(scope()->returnPoint());
00960     theCompiler->exitScope(scope());
00961   } else {
00962     // Inlined scope: for continuation, follow caller chain until a nlrTestPoint is found
00963     // (the top scope is guaranteed to have a nlrTestPoint, so loop below will terminate correctly)
00964     // introduce an extra assignment to satisfy new backend, will be optimized away
00965     InlinedScope* s = scope()->sender();
00966     while (!s->has_nlrTestPoint()) s = s->sender();
00967     append(0, s->nlrTestPoint());
00968     // now connect to return point and return the NLR value
00969     // s may not have a return point, so search for one
00970     s = scope();
00971     while (s->returnPoint() == NULL) s = s->sender();
00972     theCompiler->enterScope(s); // so that node gets right scope
00973     PReg* nlr_result = new TempPReg(scope(), resultOfNLR, true, true);
00974     Node* n = NodeFactory::new_AssignNode(nlr_result, s->resultPR);
00975     theCompiler->exitScope(s);
00976     append(1, n);
00977     n->append(s->returnPoint());
00978   }
00979 }
00980 
00981 
00982 bool SendNode::isCounting() const       { return _info->counting;       }
00983 bool SendNode::isUninlinable() const    { return _info->uninlinable;    }
00984 bool SendNode::staticReceiver() const   { return _info->receiverStatic; }
00985 
00986 PReg* SendNode::recv() const {
00987   int i = args->length() - 1;
00988   while (i >= 0 && args->at(i)->loc != receiverLoc) i--;
00989   assert(i >= 0, "must have a receiver");
00990   return args->at(i);
00991 }
00992 
00993 
00994 // ==================================================================================
00995 // cloning: copy the node during splitting; returning NULL means node is a de facto
00996 // no-op only need to copy the basic state; defs, uses etc haven't yet been computed
00997 // ==================================================================================
00998 
00999 // general splitting hasn't been implemented yet; only nodes that shouldCopyWhenSplitting()
01000 // are currently copied  -Urs 5/96
01001 
01002 Node* BasicNode::copy(PReg* from, PReg* to) const {
01003   Node* c = clone(from, to);
01004   if (c) { c->_scope = _scope; c->_bci = _bci; }
01005   return c;
01006 }
01007 
01008 # define SHOULD_NOT_CLONE       { Unused(from); Unused(to); ShouldNotCallThis(); return NULL; }
01009 # define TRANSLATE(s)           ((s == from) ? to : s)
01010 
01011 Node* PrologueNode::clone       (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01012 Node* NLRSetupNode::clone       (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01013 Node* NLRContinuationNode::clone(PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01014 Node* ReturnNode::clone         (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01015 Node* BranchNode::clone         (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01016 Node* TypeTestNode::clone       (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01017 Node* FixedCodeNode::clone      (PReg* from, PReg* to) const { SHOULD_NOT_CLONE }
01018 
01019 Node* LoadOffsetNode::clone(PReg* from, PReg* to) const {
01020   return NodeFactory::new_LoadOffsetNode(TRANSLATE(_dest), _src, offset, isArraySize);
01021 }
01022 Node* LoadIntNode::clone(PReg* from, PReg* to) const {
01023   return NodeFactory::new_LoadIntNode(TRANSLATE(_dest), _value);
01024 }
01025 Node* LoadUplevelNode::clone(PReg* from, PReg* to) const {
01026   return NodeFactory::new_LoadUplevelNode(TRANSLATE(_dest), TRANSLATE(_context0), _nofLevels, _offset, _name);
01027 }
01028 Node* StoreOffsetNode::clone(PReg* from, PReg* to) const {
01029   return NodeFactory::new_StoreOffsetNode(TRANSLATE(_src), _base, _offset, _needsStoreCheck);
01030 }
01031 Node* StoreUplevelNode::clone(PReg* from, PReg* to) const {
01032   return NodeFactory::new_StoreUplevelNode(TRANSLATE(_src), TRANSLATE(_context0), _nofLevels, _offset, _name, _needsStoreCheck);
01033 }
01034 Node* AssignNode::clone(PReg* from, PReg* to) const {
01035   return NodeFactory::new_AssignNode(TRANSLATE(_src), TRANSLATE(_dest));
01036 }
01037 Node* ArithRRNode::clone(PReg* from, PReg* to) const {
01038   return NodeFactory::new_ArithRRNode(TRANSLATE(_dest), TRANSLATE(_src), _op, _oper);
01039 }
01040 Node* TArithRRNode::clone(PReg* from, PReg* to) const {
01041   return NodeFactory::new_TArithRRNode(TRANSLATE(_dest), TRANSLATE(_src), _op, _oper, _arg1IsInt, _arg2IsInt);
01042 }
01043 Node* ArithRCNode::clone(PReg* from, PReg* to) const {
01044   return NodeFactory::new_ArithRCNode(TRANSLATE(_dest), TRANSLATE(_src), _op, _oper);
01045 }
01046 
01047 Node* SendNode::clone(PReg* from, PReg* to) const {
01048   Unused(from); Unused(to);
01049   // NB: use current split signature, not the receiver's sig!
01050   SendNode* n = NodeFactory::new_SendNode(_key, nlrTestPoint(), args, exprStack, _superSend, _info);
01051   n->_dest = _dest;         // don't give it a new dest!
01052   return n;
01053 }
01054 
01055 Node* PrimNode::clone(PReg* from, PReg* to) const {
01056   // NB: use scope's current sig, not the receiver's sig!
01057   PrimNode* n = NodeFactory::new_PrimNode(_pdesc, nlrTestPoint(), args, exprStack);
01058   assert(_dest != from, "shouldn't change dest");
01059   n->_dest = _dest;         // don't give it a new dest!
01060   return n;
01061 }
01062 
01063 Node* DLLNode::clone(PReg* from, PReg* to) const {
01064   // NB: use scope's current sig, not the receiver's sig!
01065   DLLNode* n = NodeFactory::new_DLLNode(_dll_name, _function_name, _function, _async, nlrTestPoint(), args, exprStack);
01066   assert(_dest != from, "shouldn't change dest");
01067   n->_dest = _dest;         // don't give it a new dest!
01068   return n;
01069 }
01070 
01071 
01072 Node* InterruptCheckNode::clone(PReg* from, PReg* to) const {
01073   Unused(from); Unused(to);
01074   // NB: use scope's current sig, not the receiver's sig!
01075   InterruptCheckNode* n = NodeFactory::new_InterruptCheckNode(exprStack);
01076   assert(_dest != from, "shouldn't change dest");
01077   n->_dest = _dest;         // don't give it a new dest!
01078   return n;
01079 }
01080 
01081 
01082 Node* BlockCreateNode::clone(PReg* from, PReg* to) const  {
01083   // NB: use scope's current sig, not the receiver's sig!
01084   BlockCreateNode* n = NodeFactory::new_BlockCreateNode((BlockPReg*)TRANSLATE(block()), exprStack);    
01085   assert(_dest != from, "shouldn't change dest");
01086   n->_dest = _dest;         // don't give it a new dest!
01087   return n;
01088 }
01089 
01090 
01091 Node* BlockMaterializeNode::clone(PReg* from, PReg* to) const {
01092   // NB: use scope's current sig, not the receiver's sig!
01093   BlockMaterializeNode* n = NodeFactory::new_BlockMaterializeNode((BlockPReg*)TRANSLATE(block()), exprStack);
01094   assert(_dest != from, "shouldn't change dest");
01095   n->_dest = _dest;         // don't give it a new dest!
01096   return n;
01097 }
01098 
01099 
01100 Node* ContextCreateNode::clone(PReg* from, PReg* to) const {
01101   return NodeFactory::new_ContextCreateNode(TRANSLATE(_dest), this, exprStack);
01102 }
01103 
01104 
01105 Node* ContextInitNode::clone(PReg* from, PReg* to) const {
01106   return NodeFactory::new_ContextInitNode(TRANSLATE(_src), this);
01107 }
01108 
01109 
01110 Node* ContextZapNode::clone(PReg* from, PReg* to) const {
01111   return NodeFactory::new_ContextZapNode(TRANSLATE(_src));
01112 }
01113 
01114 
01115 Node* NLRTestNode::clone(PReg* from, PReg* to) const {
01116   Unimplemented();
01117   return NULL;
01118 }
01119 
01120 
01121 Node* ArrayAtNode::clone(PReg* from, PReg* to) const {
01122   return NodeFactory::new_ArrayAtNode(_access_type,
01123                                       TRANSLATE(_src), TRANSLATE(_arg), _intArg,
01124                                       TRANSLATE(_dest), TRANSLATE(_error),
01125                                       _dataOffset, _sizeOffset);
01126 }
01127 
01128 
01129 Node* ArrayAtPutNode::clone(PReg* from, PReg* to) const {
01130   return NodeFactory::new_ArrayAtPutNode(_access_type,
01131                                          TRANSLATE(_src), TRANSLATE(_arg), _intArg,
01132                                          TRANSLATE(elem), _smi_element, TRANSLATE(_dest),
01133                                          TRANSLATE(_error), _dataOffset, _sizeOffset, _needs_store_check);
01134 }
01135 
01136 
01137 Node* UncommonNode::clone(PReg* from, PReg* to) const {
01138   Unused(from); Unused(to);
01139   return NodeFactory::new_UncommonNode(exprStack, _bci);
01140 }
01141 
01142 
01143 Node* InlinedReturnNode::clone  (PReg* from, PReg* to) const { 
01144   return NodeFactory::new_InlinedReturnNode(bci(), TRANSLATE(src()), TRANSLATE(dest())); 
01145 }
01146 
01147 
01148 # define NO_NEED_TO_COPY        { Unused(from); Unused(to); return NULL; }
01149 
01150 Node* MergeNode::clone          (PReg* from, PReg* to) const { NO_NEED_TO_COPY }
01151 Node* NopNode::clone            (PReg* from, PReg* to) const { NO_NEED_TO_COPY }
01152 Node* CommentNode::clone        (PReg* from, PReg* to) const { NO_NEED_TO_COPY }
01153 
01154 
01155 // ==================================================================================
01156 // makeUses: construct all uses and defs
01157 // ==================================================================================
01158 
01159 void PrologueNode::makeUses(BB* bb) {
01160   InlinedScope* s = scope();
01161   // build initial def for self and context (for blocks only)
01162   bb->addDef(this, s->self()->preg());
01163   if (s->isBlockScope()) {
01164     bb->addDef(this, s->context());
01165   }
01166   // build initial defs for incoming args
01167   for (int i = 0; i < _nofArgs; i++) {
01168     Expr* a = s->argument(i);
01169     if (a) bb->addDef(this, a->preg());
01170   }
01171   // build initial defs for locals (initalization to nil)
01172   for (i = 0; i < _nofTemps; i++) {
01173     Expr* t = s->temporary(i);
01174     if (t) bb->addDef(this, t->preg());
01175   }
01176 }
01177 
01178 void NonTrivialNode::makeUses(BB* bb) {
01179   _bb = bb;
01180   assert(!hasSrc()  || srcUse,  "should have srcUse");
01181   assert(!hasDest() || destDef || _dest->isNoPReg(), "should have destDef");
01182 }
01183 
01184 void LoadNode::makeUses(BB* bb) {
01185   destDef = bb->addDef(this, _dest); NonTrivialNode::makeUses(bb); }
01186 void LoadOffsetNode::makeUses(BB* bb) {
01187   srcUse = bb->addUse(this, _src); LoadNode::makeUses(bb); }
01188 void LoadUplevelNode::makeUses(BB* bb) {
01189   _context0Use = bb->addUse(this, _context0); LoadNode::makeUses(bb);
01190 }
01191 
01192 void StoreNode::makeUses(BB* bb) {
01193   srcUse = bb->addUse(this, _src); NonTrivialNode::makeUses(bb); }
01194 void StoreOffsetNode::makeUses(BB* bb) {
01195   _baseUse = bb->addUse(this, _base); StoreNode::makeUses(bb); }
01196 void StoreUplevelNode::makeUses(BB* bb) {
01197   _context0Use = bb->addUse(this, _context0); StoreNode::makeUses(bb);
01198 }
01199 
01200 void AssignNode::makeUses(BB* bb) {
01201   destDef = bb->addDef(this, _dest); StoreNode::makeUses(bb); }
01202 
01203 void AbstractReturnNode::makeUses(BB* bb) {
01204   srcUse = bb->addUse(this, _src);
01205   destDef = bb->addDef(this, _dest);
01206   NonTrivialNode::makeUses(bb);
01207 }
01208 
01209 void ReturnNode::makeUses(BB* bb) {
01210   // resultUse models the value's use in the caller
01211   resultUse = bb->addUse(this, _dest);
01212   AbstractReturnNode::makeUses(bb);
01213 }
01214 
01215 void NLRSetupNode::makeUses(BB* bb) {
01216   // has no src or dest -- uses hardwired NLR register
01217   // but track them anyway for consistency
01218   // resultUse models the value's use in the caller
01219   resultUse  = bb->addUse(this, _dest);
01220   contextUse = bb->addUse(this, _scope->context());
01221   AbstractReturnNode::makeUses(bb);
01222 }
01223 
01224 void NLRTestNode::makeUses(BB* bb) {
01225   AbstractBranchNode::makeUses(bb);
01226 }
01227 
01228 void NLRContinuationNode::makeUses(BB* bb) {
01229   // has no src or dest -- uses hardwired NLR register
01230   // but track them anyway for consistency
01231   AbstractReturnNode::makeUses(bb);
01232 }
01233 
01234 void ArithNode::makeUses(BB* bb) {
01235   srcUse = bb->addUse(this, _src);  destDef = bb->addDef(this, _dest);
01236   NonTrivialNode::makeUses(bb); 
01237 }
01238 void ArithRRNode::makeUses(BB* bb) { 
01239   _operUse = bb->addUse(this, _oper); ArithNode::makeUses(bb); }
01240 
01241 void TArithRRNode::makeUses(BB* bb) { 
01242   _operUse = bb->addUse(this, _oper);
01243   srcUse = bb->addUse(this, _src);
01244   destDef = bb->addDef(this, _dest);
01245   NonTrivialNode::makeUses(bb);
01246 }
01247 
01248 void CallNode::makeUses(BB* bb) {
01249   destDef = bb->addDef(this, _dest); 
01250   if (args) {
01251     int len = args->length();
01252     argUses = new GrowableArray<Use*>(len);
01253     for (int i = 0; i < len; i++) {
01254       argUses->append(bb->addUse(this, args->at(i)));
01255     }
01256   }
01257   NonTrivialNode::makeUses(bb); 
01258   if (canInvokeDelta()) {
01259     // add defs/uses for all PRegs uplevel-accessed by live blocks
01260     const int InitialSize = 5;
01261     uplevelUses = new GrowableArray<Use*> (InitialSize);
01262     uplevelDefs = new GrowableArray<Def*> (InitialSize);
01263     uplevelUsed = new GrowableArray<PReg*>(InitialSize);
01264     uplevelDefd = new GrowableArray<PReg*>(InitialSize);
01265     GrowableArray<BlockPReg*>* blks = theCompiler->blockClosures;
01266     for (int i = 0; i < nblocks; i++) {
01267       BlockPReg* blk = blks->at(i);
01268       if (blk->escapes()) {
01269         // check if block's home is on current call stack; if not, we don't care about
01270         // the block's uplevel accesses since the block is non-LIFO and we won't access its
01271         // context anyway
01272         Scope* home = blk->scope()->home();
01273         if (home->isSenderOrSame(scope())) {
01274           // ok, this block is live
01275           GrowableArray<PReg*>* uplevelRead = blk->uplevelRead();
01276           for (int j = uplevelRead->length() - 1; j >= 0; j--) {
01277             PReg* r = uplevelRead->at(j);
01278             uplevelUses->append(bb->addUse(this, r));
01279             uplevelUsed->append(r);
01280           }
01281           GrowableArray<PReg*>* uplevelWritten = blk->uplevelWritten();
01282           for (j = uplevelWritten->length() - 1; j >= 0; j--) {
01283             PReg* r = uplevelWritten->at(j);
01284             uplevelDefs->append(bb->addDef(this, r));
01285             uplevelDefd->append(r);
01286           }
01287         }
01288       }
01289     }
01290   }
01291 }
01292 
01293 void BlockCreateNode::makeUses(BB* bb) {
01294   if (_context && !isMemoized()) {
01295     _contextUse = bb->addUse(this, _context);
01296   }
01297   destDef = bb->addDef(this, _dest); 
01298   NonTrivialNode::makeUses(bb);
01299 }
01300 
01301 void BlockMaterializeNode::makeUses(BB* bb) {
01302   // without memoization, BlockMaterializeNode is a no-op
01303   if (isMemoized()) {
01304     srcUse = bb->addUse(this, _src);
01305     if (_context) _contextUse = bb->addUse(this, _context);
01306     BlockCreateNode::makeUses(bb);
01307   }
01308 }
01309 
01310 void ContextCreateNode::makeUses(BB* bb) {
01311   if (_src) srcUse = bb->addUse(this, _src); // no src if there's no incoming context
01312   destDef = bb->addDef(this, _dest); 
01313   if (_parentContexts) {
01314     int len = _parentContexts->length();
01315     _parentContextUses = new GrowableArray<Use*>(len, len, NULL);
01316     for (int i = _parentContexts->length() - 1; i>= 0; i--) {
01317       Use* u = bb->addUse(this, _parentContexts->at(i));
01318       _parentContextUses->at_put(i, u);
01319     }
01320   }
01321   NonTrivialNode::makeUses(bb);
01322 }
01323 
01324 void ContextInitNode::makeUses(BB* bb) {
01325   srcUse = bb->addUse(this, _src);
01326   int i = nofTemps();
01327   _contentDefs = new GrowableArray<Def*>(i, i, NULL);
01328   _initializerUses = new GrowableArray<Use*>(i, i, NULL);
01329   while (i-- > 0) {
01330     PReg* r = contents()->at(i)->preg();
01331     if (r->isBlockPReg()) {
01332       _contentDefs->at_put(i, NULL);      // there is no assignment to the block
01333     } else {
01334       _contentDefs->at_put(i, bb->addDef(this, r));
01335     }
01336     _initializerUses->at_put(i, bb->addUse(this, _initializers->at(i)->preg()));
01337   } 
01338   NonTrivialNode::makeUses(bb);
01339 }
01340 
01341 void ContextZapNode::makeUses(BB* bb) {
01342   srcUse = bb->addUse(this, _src);
01343 }
01344 
01345 void TypeTestNode::makeUses(BB* bb) {
01346   srcUse = bb->addUse(this, _src); AbstractBranchNode::makeUses(bb);
01347 }
01348 
01349 void AbstractArrayAtNode::makeUses(BB* bb) {
01350   srcUse = bb->addUse(this, _src);
01351   destDef = _dest ? bb->addDef(this, _dest) : NULL;
01352   _argUse = bb->addUse(this, _arg);
01353   _errorDef = (_error && canFail()) ? bb->addDef(this, _error) : NULL;
01354   AbstractBranchNode::makeUses(bb);
01355 }
01356 
01357 void AbstractArrayAtPutNode::makeUses(BB* bb) {
01358   elemUse = bb->addUse(this, elem); 
01359   AbstractArrayAtNode::makeUses(bb);
01360 }
01361 
01362 void InlinedPrimitiveNode::makeUses(BB* bb) {
01363   srcUse     = _src   ? bb->addUse(this, _src  ) : NULL;
01364   _arg1_use  = _arg1  ? bb->addUse(this, _arg1 ) : NULL;
01365   _arg2_use  = _arg2  ? bb->addUse(this, _arg2 ) : NULL;
01366   destDef    = _dest  ? bb->addDef(this, _dest ) : NULL; 
01367   _error_def = (_error && canFail()) ? bb->addDef(this, _error) : NULL;
01368   AbstractBranchNode::makeUses(bb);
01369 }
01370 
01371 // ==================================================================================
01372 // removeUses: remove all uses and defs (receiver node has been eliminated)
01373 // ==================================================================================
01374 
01375 // removeUses: remove all uses and defs
01376 void NonTrivialNode::removeUses(BB* bb) { assert(_bb == bb, "wrong BB"); }
01377 
01378 void LoadNode::removeUses(BB* bb) {
01379   _dest->removeDef(bb, destDef); NonTrivialNode::removeUses(bb);
01380 }
01381 
01382 void LoadOffsetNode::removeUses(BB* bb) {
01383   _src->removeUse(bb, srcUse); LoadNode::removeUses(bb);
01384 }
01385 
01386 void LoadUplevelNode::removeUses(BB* bb) {
01387   _context0->removeUse(bb, _context0Use); LoadNode::removeUses(bb);
01388 }
01389 
01390 void StoreNode::removeUses(BB* bb) {
01391   _src->removeUse(bb, srcUse); NonTrivialNode::removeUses(bb);
01392 }
01393 
01394 void StoreOffsetNode::removeUses(BB* bb) {
01395   _base->removeUse(bb, _baseUse); StoreNode::removeUses(bb);
01396 }
01397 
01398 void StoreUplevelNode::removeUses(BB* bb) {
01399   _context0->removeUse(bb, _context0Use); StoreNode::removeUses(bb);
01400 }
01401 
01402 void AssignNode::removeUses(BB* bb) {
01403   _dest->removeDef(bb, destDef); StoreNode::removeUses(bb);
01404 }
01405 
01406 void AbstractReturnNode::removeUses(BB* bb) {
01407   _src->removeUse(bb, srcUse); _dest->removeDef(bb, destDef);
01408   NonTrivialNode::removeUses(bb);
01409 }
01410 
01411 void ReturnNode::removeUses(BB* bb) {
01412   _dest->removeUse(bb, resultUse);
01413   AbstractReturnNode::removeUses(bb); 
01414 }
01415 
01416 void NLRSetupNode::removeUses(BB* bb) {
01417   _dest->removeUse(bb, resultUse);
01418   _scope->context()->removeUse(bb, contextUse);
01419   AbstractReturnNode::removeUses(bb); 
01420 }
01421 
01422 void NLRTestNode::removeUses(BB* bb) {
01423   AbstractBranchNode::removeUses(bb); 
01424 }
01425 
01426 void NLRContinuationNode::removeUses(BB* bb) {
01427   AbstractReturnNode::removeUses(bb); 
01428 }
01429 
01430 void ArithNode::removeUses(BB* bb) {
01431   _src->removeUse(bb, srcUse); _dest->removeDef(bb, destDef);
01432   NonTrivialNode::removeUses(bb);
01433 }
01434 
01435 void ArithRRNode::removeUses(BB* bb) { 
01436   _oper->removeUse(bb, _operUse); ArithNode::removeUses(bb);
01437 }
01438 
01439 void TArithRRNode::removeUses(BB* bb) { 
01440   _oper->removeUse(bb, _operUse);
01441   _src->removeUse(bb, srcUse);
01442   _dest->removeDef(bb, destDef);
01443   NonTrivialNode::removeUses(bb);
01444 }
01445 
01446 void CallNode::removeUses(BB* bb) {
01447   _dest->removeDef(bb, destDef);
01448   if (argUses) {
01449     int len = args->length();
01450     for (int i = 0; i < len; i++) {
01451       args->at(i)->removeUse(bb, argUses->at(i));
01452     }
01453   }
01454   if (uplevelUses) {
01455     for (int i = uplevelUses->length() - 1; i >= 0; i--) uplevelUsed->at(i)->removeUse(bb, uplevelUses->at(i));
01456     for (i = uplevelDefs->length() - 1; i >= 0; i--) uplevelDefd->at(i)->removeDef(bb, uplevelDefs->at(i));
01457   }
01458   NonTrivialNode::removeUses(bb);
01459 }
01460 
01461 void BlockCreateNode::removeUses(BB* bb) {
01462   if (_contextUse) _context->removeUse(bb, _contextUse);
01463   if (_src) _src->removeUse(bb, srcUse);
01464   _dest->removeDef(bb, destDef);
01465   NonTrivialNode::removeUses(bb);
01466 }
01467 
01468 void BlockMaterializeNode::removeUses(BB* bb) {
01469   // without memoization, BlockMaterializeNode is a no-op
01470   if (isMemoized()) BlockCreateNode::removeUses(bb);
01471 }
01472 
01473 void ContextCreateNode::removeUses(BB* bb) {
01474   if (_src) _src->removeUse(bb, srcUse); // no src if there's no incoming context
01475   _dest->removeDef(bb, destDef); 
01476   NonTrivialNode::removeUses(bb);
01477 }
01478 
01479 void ContextInitNode::removeUses(BB* bb) {
01480   int i = nofTemps();
01481   while (i-- > 0) {
01482     contents()->at(i)->preg()->removeDef(bb, _contentDefs->at(i));
01483     _initializers->at(i)->preg()->removeUse(bb, _initializerUses->at(i));
01484   } 
01485   _src->removeUse(bb, srcUse);
01486   NonTrivialNode::removeUses(bb);
01487 }
01488 
01489 void ContextZapNode::removeUses(BB* bb) {
01490   _src->removeUse(bb, srcUse);
01491   NonTrivialNode::removeUses(bb);
01492 }
01493 
01494 void TypeTestNode::removeUses(BB* bb) {
01495   _src->removeUse(bb, srcUse); 
01496   AbstractBranchNode::removeUses(bb); 
01497 }
01498 
01499 void AbstractArrayAtNode::removeUses(BB* bb) {
01500   _src->removeUse(bb, srcUse);
01501   if (_dest) _dest->removeDef(bb, destDef);
01502   _arg->removeUse(bb, _argUse); 
01503   if (_errorDef) _error->removeDef(bb, _errorDef);
01504   AbstractBranchNode::removeUses(bb);
01505 }
01506 
01507 void AbstractArrayAtPutNode::removeUses(BB* bb) {
01508   elem->removeUse(bb, elemUse);
01509   AbstractArrayAtNode::removeUses(bb);
01510 }
01511 
01512 void InlinedPrimitiveNode::removeUses(BB* bb) {
01513   if (srcUse  )   _src ->removeUse (bb, srcUse    );
01514   if (_arg1_use ) _arg1->removeUse (bb, _arg1_use );
01515   if (_arg2_use ) _arg2->removeUse (bb, _arg2_use );
01516   if (destDef )   _dest ->removeDef(bb, destDef   );
01517   if (_error_def) _error->removeDef(bb, _error_def);
01518   AbstractBranchNode::removeUses(bb);
01519 }
01520 
01521 // ==================================================================================
01522 // eliminate: the receiver has just been removed because its
01523 // result was not used.  Propagate this to all nodes whose use count
01524 // has now become zero, too.  The register passed in is the one
01525 // causing the elimination (passed in to catch recursive elimination
01526 // of the same register).
01527 // It is an error to call eliminate() if canBeEliminated() is false.
01528 // If cp is true, the node is eliminated because of copy propagation.
01529 // If removing is true, we're removing dead code (e.g. a branch of a type
01530 // case that will never be executed)
01531 // ==================================================================================
01532 
01533 inline void Node::eliminate(BB* bb, PReg* r, bool removing, bool cp) {
01534   assert(!deleted, "already deleted this node");
01535   if (CompilerDebug) {
01536     char buf[1024];
01537     cout(PrintEliminateUnnededNodes)->print("*%s node N%ld: %s\n", removing ? "removing" : "eliminating",
01538                                             id(), print_string(buf, PrintHexAddresses));
01539   }
01540   assert(!dontEliminate || removing, "shouldn't eliminate this node");
01541   bb->remove(this);
01542 }
01543 
01544 # define CHECK(preg, r)                                               \
01545 if (preg != r && preg->isOnlySoftUsed()) preg->eliminate(false);
01546 
01547 inline void LoadNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01548   if (deleted) return;
01549   assert(canBeEliminated() || rem, "cannot be eliminated");
01550   NonTrivialNode::eliminate(bb, r, rem, cp); CHECK(_dest, r); }
01551 
01552 inline void LoadOffsetNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01553   if (deleted) return;
01554   LoadNode::eliminate(bb, r, rem, cp); CHECK(_src, r); }
01555 
01556 inline void LoadUplevelNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01557   if (deleted) return;
01558   LoadNode::eliminate(bb, r, rem, cp); CHECK(_context0, r);
01559 }
01560 
01561 inline void StoreNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01562   if (deleted) return;
01563   NonTrivialNode::eliminate(bb, r, rem, cp); CHECK(_src, r); }
01564 inline void StoreOffsetNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01565   if (deleted) return;
01566   StoreNode::eliminate(bb, r, rem, cp); CHECK(_base, r); }
01567 inline void StoreUplevelNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01568   if (deleted) return;
01569   StoreNode::eliminate(bb, r, rem, cp); CHECK(_context0, r);
01570 }
01571 
01572 inline void AssignNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01573   if (deleted) return;
01574   StoreNode::eliminate(bb, r, rem, cp); CHECK(_dest, r); }
01575 
01576 inline void ReturnNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01577   if (deleted) return;
01578   assert(rem, "should not delete except during dead-code elimination");
01579   AbstractReturnNode::eliminate(bb, r, rem, cp); CHECK(_src, r); CHECK(_dest, r);
01580   // don't need to check resultPR
01581 }
01582 
01583 inline void ArithNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01584   if (deleted) return;
01585   NonTrivialNode::eliminate(bb, r, rem, cp); CHECK(_src, r); CHECK(_dest, r); }
01586 inline void ArithRRNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) { 
01587   if (deleted) return;
01588   ArithNode::eliminate(bb, r, rem, cp); CHECK(_oper, r); }
01589 
01590 inline void BranchNode::eliminate(BB* bb, PReg* r, bool removing, bool cp) {
01591   if (deleted) return;
01592   if (removing && nSuccessors() <= 1) {
01593     NonTrivialNode::eliminate(bb, r, removing, cp);
01594   } else {
01595     // caller has to handle this
01596     fatal("removing branch node with > 1 successor");
01597   }
01598 }
01599 
01600 inline void BlockMaterializeNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01601   if (deleted) return;
01602   BlockCreateNode::eliminate(bb, r, rem, cp);
01603 }
01604 
01605 void BasicNode::removeUpToMerge() {
01606   BB* thisBB = _bb;
01607   for (Node* n = (Node*)this; n && n->hasSinglePredecessor(); ) {
01608     while (n->nSuccessors() > 1) {
01609       int i = n->nSuccessors() - 1;
01610       Node* succ = n->next(i);
01611       n->removeNext(succ);
01612       succ->removeUpToMerge();
01613     }
01614     Node* nextn = n->next();
01615     if (!n->deleted) n->eliminate(thisBB, NULL, true, false);
01616     if (nextn) {
01617       BB* nextBB = nextn->bb();
01618       if (nextBB != thisBB) {
01619         if (nextn->nPredecessors() >= 2) {
01620           // also remove n's successor so that we can delete past merges
01621           // if all incoming branches of the merges are deleted
01622           n->removeNext(nextn);
01623           // nextn had at least 2 predecessors, so must stop deleting here
01624           // NB: must break here -- if was 2 successors, will now be one
01625           // and loop would continue (was a bug)  -Urs 8/94
01626           break;
01627         }
01628         thisBB = nextBB;
01629       }
01630     }
01631     n = nextn;
01632   }
01633   BB* nextBB = n ? n->bb() : NULL;
01634 }
01635 
01636 void PrimNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01637   if (deleted) return;
01638   assert(rem || canBeEliminated(), "shouldn't call");
01639   if (nlrTestPoint()) {
01640     // remove all unused nodes along NLR branch
01641     // should be exactly 2 nodes (see IRGenerator::makeNLRPoint())
01642     MergeNode* n1 = nlrTestPoint();
01643     Node* n2 = n1->next();
01644     assert(n2->isNLRTestNode(), "unexpected node sequence");
01645     _nxt->pop();                // remove nlrTestPoint
01646     assert(nlrTestPoint() == NULL, "should be NULL now");
01647     n1->eliminate(n1->bb(), NULL, true, false);
01648     n2->eliminate(n2->bb(), NULL, true, false);
01649   }
01650   NonTrivialNode::eliminate(bb, r, rem, cp); 
01651   CHECK(_dest, r);
01652   if (args) {
01653     // check if any arg became unused
01654     int len = args->length();
01655     for (int i = 0; i < len; i++) {
01656       PReg* arg = args->at(i);
01657       if (arg->loc.isTopOfStack()) {
01658         // must delete this push, but node won't be eliminated with topOfStack because of side effect
01659         // so reset location first
01660         arg->loc = unAllocated;
01661       } else {
01662         fatal("internal compiler error");
01663         //fatal("Urs thinks all args should be topOfStack");
01664       }
01665       CHECK(arg, r);
01666     }
01667   }
01668 }
01669 
01670 void TypeTestNode::eliminate(BB* bb, PReg* rr, bool rem, bool cp) {
01671   // completely eliminate receiver and all successors
01672   Unused(rem); Unused(cp);
01673   if (deleted) return;
01674 
01675   eliminate(bb, rr, (ConstPReg*)NULL, (klassOop)badOop);
01676 }
01677 
01678 void TypeTestNode::eliminate(BB* bb, PReg* r, ConstPReg* c, klassOop theKlass) {
01679   // remove node and all successor branches (except for one if rcvr is known)
01680   if (deleted) return;
01681   GrowableArray<Node*>* successors = _nxt;
01682   _nxt = new GrowableArray<Node*>(1);
01683   oop constant = c ? c->constant : 0;
01684   Node* keep = NULL;
01685   if (CompilerDebug) {
01686     cout(PrintEliminateUnnededNodes)->print("*eliminating tt node %#lx const %#lx klass %#lx\n",
01687             PrintHexAddresses ? this : 0, constant, theKlass);
01688   }
01689   Node* un = _next;             // save unknown branch
01690   // remove all successor nodes
01691   for (int i = 0; i < successors->length(); i++) {
01692     Node* succ = successors->at(i);
01693     succ->removePrev(this);
01694     klassOop m = _classes->at(i);
01695     if (constant == m || theKlass == m) {
01696       assert(keep == NULL, "shouldn't have more than one match");
01697       keep = succ;
01698     } else {
01699       _next = succ;
01700       _next->removeUpToMerge();
01701     }
01702   }
01703   
01704   if (keep || theKlass == klassOop(badOop)) {
01705     // found correct prediction, so can delete unknown branch, or
01706     // delete everything (theKlass == badOop)
01707     _next = un;
01708     un->removeUpToMerge();      // delete unknown branch
01709     _next = NULL;
01710   } else {
01711     // the type tests didn't predict for theKlass
01712     // (performance bug: should inline correct case since it's known now;
01713     // also, unknown branch may be uncommon)
01714     if (WizardMode) {
01715         warning("Compiler: typetest didn't predict klass %#lx", theKlass);
01716         lprintf("predicted klasses: ");
01717         _classes->print();
01718       }
01719     _next = un;         // keep unknown branch
01720   }
01721   assert(this == bb->last, "should end my BB");
01722     
01723   if (keep) {
01724     // append remaining case as fall-through
01725     append(keep);
01726   }
01727   NonTrivialNode::eliminate(bb, r, true, false);
01728   CHECK(_dest, r);
01729 }
01730 
01731 void TypeTestNode::eliminateUnnecessary(klassOop m) {
01732   // eliminate unnecessary type test: receiver is known to have map m
01733   eliminate(bb(), NULL, NULL, m);
01734 }
01735 
01736 void AbstractArrayAtNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01737   Unused(cp); Unused(rem);
01738   assert(rem, "shouldn't eliminate because of side effects (errors)");
01739   if (deleted) return;
01740   // remove fail branch nodes first
01741   Node* fail = next1();
01742   if (fail) {
01743     fail->removePrev(this);
01744     fail->removeUpToMerge();
01745   }
01746   AbstractBranchNode::eliminate(bb, r, rem, cp);
01747 }
01748 
01749 void InlinedPrimitiveNode::eliminate(BB* bb, PReg* r, bool rem, bool cp) {
01750   if (deleted) return;
01751   AbstractBranchNode::eliminate(bb, r, rem, cp);
01752   if (_arg1)  CHECK(_arg1, r);
01753   if (_arg2)  CHECK(_arg2, r);
01754   if (_dest)  CHECK(_dest, r);
01755   if (_error) CHECK(_error, r);
01756 }
01757 
01758 void ContextCreateNode::eliminate(BB* bb, PReg* r, bool removing, bool cp) {
01759   if (deleted) return;
01760   PrimNode::eliminate(bb, r, removing, cp);
01761 }
01762 
01763 void ContextInitNode::eliminate(BB* bb, PReg* r, bool removing, bool cp) {
01764   assert(removing, "should only remove when removing unreachable code");
01765   if (deleted) return;
01766   NonTrivialNode::eliminate(bb, r, removing, cp);
01767 }
01768 
01769 void BranchNode::eliminateBranch(int op1, int op2, int res) {
01770   // the receiver can be eliminated because the result it is testing
01771   // is a constant (res)
01772   bool ok;
01773   switch (_op) {
01774     case EQBranchOp:    ok = op1 == op2;        break;
01775     case NEBranchOp:    ok = op1 != op2;        break;
01776     case LTBranchOp:    ok = op1 <  op2;        break;
01777     case LEBranchOp:    ok = op1 <= op2;        break;
01778     case GTBranchOp:    ok = op1 >  op2;        break;
01779     case GEBranchOp:    ok = op1 >= op2;        break;
01780     case LTUBranchOp:   ok = (unsigned)op1 <  (unsigned)op2;    break;
01781     case LEUBranchOp:   ok = (unsigned)op1 <= (unsigned)op2;    break;
01782     case GTUBranchOp:   ok = (unsigned)op1 >  (unsigned)op2;    break;
01783     case GEUBranchOp:   ok = (unsigned)op1 >= (unsigned)op2;    break;
01784     case VSBranchOp:    return;         // can't handle yet
01785     case VCBranchOp:    return;         // can't handle yet
01786     default:            fatal("unexpected branch type");
01787   }
01788   int nodeToRemove;
01789   if (ok) {
01790     nodeToRemove = 0; // branch is taken
01791   } else {
01792     nodeToRemove = 1;
01793   }
01794   
01795   // discard one successor and make the remaining one the fall-thru case
01796   Node* discard = next(nodeToRemove);
01797   removeNext(discard);
01798   discard->removeUpToMerge();
01799   Node* succ = next(1 - nodeToRemove);
01800   removeNext(succ);
01801   append(succ);
01802   bb()->remove(this);   // delete the branch
01803 }
01804 
01805 // ==================================================================================
01806 // likelySuccessor: answers the most likely successor node (or NULL). Used for better
01807 // code positioning (determines traversal order for BBs).
01808 // ==================================================================================
01809 
01810 Node* Node::likelySuccessor() const { 
01811   assert(hasSingleSuccessor(), "should override likelySuccessor()");
01812   return next(); 
01813 }
01814 
01815 Node* TArithRRNode::likelySuccessor() const {
01816   return next();                                // predict success 
01817 }
01818 
01819 Node* CallNode::likelySuccessor() const {
01820   return next();                                // predict normal return, not NLR
01821 }
01822 
01823 Node* NLRTestNode::likelySuccessor() const {
01824   return next();                                // predict home not found
01825 }
01826 
01827 Node* BranchNode::likelySuccessor() const {
01828   return next();                                // predict untaken
01829 }
01830 
01831 Node* TypeTestNode::likelySuccessor() const {
01832   if (deleted) return next();
01833   assert(classes()->length() > 0, "no TypeTestNode needed");
01834   return next(hasUnknown() ? classes()->length() : classes()->length() - 1);
01835 }
01836 
01837 Node* AbstractArrayAtNode::likelySuccessor() const {
01838   return next();                                // predict success 
01839 }
01840 
01841 Node* InlinedPrimitiveNode::likelySuccessor() const {
01842   return next();                                // predict success 
01843 }
01844 
01845 
01846 // ==================================================================================
01847 // uncommonSuccessor: answers the most uncommon successor node (or NULL). Used for
01848 // better code positioning (determines traversal order for BBs).
01849 // ==================================================================================
01850 
01851 Node* Node::uncommonSuccessor() const { 
01852   assert(hasSingleSuccessor(), "should override uncommonSuccessor()");
01853   return NULL;                                  // no uncommon case
01854 }
01855 
01856 Node* TArithRRNode::uncommonSuccessor() const {
01857   return (deleted || !canFail()) ? NULL : next(1);              // failure case is uncommon
01858 }
01859 
01860 Node* CallNode::uncommonSuccessor() const {
01861   return NULL;                                  // no uncommon case (NLR is not uncommon)
01862 }
01863 
01864 Node* NLRTestNode::uncommonSuccessor() const {
01865   return NULL;                                  // no uncommon case (both exits are common)
01866 }
01867 
01868 Node* BranchNode::uncommonSuccessor() const {
01869   return (!deleted && _taken_is_uncommon) ? next(1) : NULL;
01870 }
01871 
01872 Node* TypeTestNode::uncommonSuccessor() const {
01873   if (!deleted && hasUnknown()) {
01874     // fall through case treated as uncommon case
01875     assert(next() != NULL, "just checking");
01876     return next();
01877   } else {
01878     // no unknown case, all cases are common
01879     return NULL;
01880   }
01881 }
01882 
01883 Node* AbstractArrayAtNode::uncommonSuccessor() const {
01884   return (deleted || !canFail()) ? NULL : next(1);      // failure case is uncommon
01885 }
01886 
01887 Node* InlinedPrimitiveNode::uncommonSuccessor() const {
01888   return nSuccessors() == 2 ? next(1) : NULL;   // failure case is uncommon if there
01889 }
01890 
01891 
01892 // ==================================================================================
01893 // copy propagation: replace a use by another use; return false if unsuccessful
01894 // ==================================================================================
01895 
01896 # define CP_HELPER(_src, srcUse, return)                                      \
01897     /* live range must be correct - otherwise reg. allocation breaks   */     \
01898     /* (even if doing just local CP - could fix this by checking for   */     \
01899     /* local conflicts when allocating PRegs, i.e. keep BB alloc info) */     \
01900     if (replace || (!d->loc.isTopOfStack() && d->extendLiveRange(this))) {    \
01901       _src->removeUse(bb, srcUse);                                            \
01902       _src = d;                                                               \
01903       srcUse = _src->addUse(bb, this);                                        \
01904       return true;                                                            \
01905     } else {                                                                  \
01906       return false;                                                           \
01907     }
01908 
01909 // if node can't fail anymore, remove failure branch (if not already removed)
01910 void AbstractBranchNode::removeFailureIfPossible() {
01911   Node* taken = next1();
01912   if (!canFail() && taken != NULL && taken->bb()->isPredecessor(bb())) {
01913     taken->removeUpToMerge();
01914     removeNext(taken);
01915   }
01916 }
01917 
01918 bool BasicNode::canCopyPropagate(Node* fromNode) const {
01919   // current restriction: cannot copy-propagate into a loop
01920   // reason: copy-propagated PReg needs its live range extended to cover the entire loop, 
01921   // not just the stretch between fromNode and this node
01922   return canCopyPropagate() && fromNode->bb()->loopDepth() == _bb->loopDepth();
01923 }
01924   
01925 bool NonTrivialNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01926   assert(canCopyPropagate(), "can't copy-propagate");
01927   assert(hasSrc(), "has no src");
01928   if (srcUse == u) {
01929     CP_HELPER(_src, srcUse, return);
01930   } else {
01931     fatal("copyPropagate: not the source use");
01932   }
01933   return false;
01934 }
01935 
01936 bool LoadOffsetNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01937   if (u == srcUse) {
01938     // minor performance bug: prev. node should probably be deleted
01939     // (loads base reg) - eliminateUnneeded doesn't catch it - fix this
01940     // (happens esp. if d is a constant)
01941     CP_HELPER(_src, srcUse, return);
01942   } else {
01943     return LoadNode::copyPropagate(bb, u, d, replace);
01944   }
01945   return false;
01946   }
01947 
01948 bool LoadUplevelNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01949   if (u == _context0Use) {
01950     CP_HELPER(_context0, _context0Use, return);
01951   } else {
01952     return LoadNode::copyPropagate(bb, u, d, replace);
01953   }
01954   return false;
01955 }
01956 
01957 bool StoreOffsetNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01958   if (u == _baseUse) {
01959     CP_HELPER(_base, _baseUse, return);
01960   } else {
01961     return StoreNode::copyPropagate(bb, u, d, replace);
01962   }
01963   return false;
01964 }
01965 
01966 bool StoreUplevelNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01967   if (u == _context0Use) {
01968     CP_HELPER(_context0, _context0Use, return);
01969   } else {
01970     return StoreNode::copyPropagate(bb, u, d, replace);
01971   }
01972   return false;
01973 }
01974 
01975 bool CallNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01976   //warning("fix this -- propagate args somewhere");
01977   return false;
01978 }
01979 
01980 bool  ArithRRNode::operIsConst() const { return _oper->isConstPReg(); }
01981 int ArithRRNode::operConst() const   {
01982   assert(operIsConst(), "not a constant");
01983   return _oper->isConstPReg(); 
01984 }
01985   
01986 bool ArithNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
01987   bool success = doCopyPropagate(bb, u, d, replace);
01988   if (_src->isConstPReg() && operIsConst()) {
01989     assert(success, "CP must have worked");
01990     // can constant-fold this operation
01991     int c1 = (int)((ConstPReg*)_src)->constant;
01992     int c2 = (int)operConst();
01993     int res;
01994     switch (_op) {
01995     case AddArithOp:
01996       res = c1 + c2; break;
01997 
01998     case SubArithOp:
01999       res = c1 - c2; break;
02000       
02001     case AndArithOp:            
02002       res = c1 & c2; break;
02003       
02004     case OrArithOp:             
02005       res = c1 | c2; break;
02006       
02007     case XOrArithOp:
02008       res = c1 ^ c2; break;
02009       
02010     default:    return success;         // can't constant-fold
02011     }
02012     
02013     _constResult = new_ConstPReg(scope(), (oop)res);
02014     // enable further constant propagation of the result
02015     dontEliminate = false;
02016     _src->removeUse(bb, srcUse);
02017     _src = _constResult;
02018     srcUse = bb->addUse(this, _src);
02019     
02020     // condition codes set -- see if there's a branch we can eliminate
02021     Node* branch = next();
02022     if (branch->isBranchNode()) {
02023       ((BranchNode*)branch)->eliminateBranch(c1, c2, res);
02024     }
02025   }
02026   return success;
02027 }
02028 
02029 bool ArithNode::doCopyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02030   return NonTrivialNode::copyPropagate(bb, u, d, replace);
02031 }
02032 
02033 bool ArithRRNode::doCopyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02034   if (u == _operUse) {
02035     CP_HELPER(_oper, _operUse, return);
02036   } else {
02037     return ArithNode::doCopyPropagate(bb, u, d, replace);
02038   }
02039   return false;
02040 }
02041 
02042 bool TArithRRNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02043   bool res = doCopyPropagate(bb, u, d, replace);
02044   if (_src->isConstPReg() && _oper->isConstPReg()) {
02045     assert(res, "CP must have worked");
02046     // can constant-fold this operation
02047     oop c1 = ((ConstPReg*)_src)->constant;
02048     oop c2 = ((ConstPReg*)_oper)->constant;
02049     oop result;
02050     switch (_op) {
02051       case tAddArithOp  : result = smiOopPrimitives_add(c1, c2);        break;
02052       case tSubArithOp  : result = smiOopPrimitives_subtract(c1, c2);   break;
02053       case tMulArithOp  : result = smiOopPrimitives_multiply(c1, c2);   break;
02054       case tDivArithOp  : result = smiOopPrimitives_div(c1, c2);        break;
02055       case tModArithOp  : result = smiOopPrimitives_mod(c1, c2);        break;
02056       case tAndArithOp  : result = smiOopPrimitives::bitAnd(c1, c2);    break;
02057       case tOrArithOp   : result = smiOopPrimitives::bitOr(c1, c2);     break;
02058       case tXOrArithOp  : result = smiOopPrimitives::bitXor(c1, c2);    break;
02059       case tShiftArithOp: warning("possible performance bug: constant folding of tShiftArithOp not implemented"); return false;
02060       case tCmpArithOp  : warning("possible performance bug: constant folding of tCmpArithOp not implemented"); return false;
02061       default           : fatal1("unknown tagged opcode %ld", _op);
02062     }
02063     bool ok = !result->is_mark();
02064     if (ok) {
02065       // constant-fold this operation
02066       if (CompilerDebug) cout(PrintCopyPropagation)->print("*constant-folding N%d --> %#x\n", _id, result);
02067       _constResult = new_ConstPReg(scope(), result);
02068       // first, discard the error branch (if there)
02069       Node* discard = next1();
02070       if (discard != NULL) {
02071         discard->bb()->remove(discard);
02072         discard->removeUpToMerge();
02073 #     ifdef ASSERT
02074         bb->verify();
02075         ((BB*)bb->next())->verify();
02076 #     endif
02077       }
02078       // now, discard the overflow check
02079       discard = next();
02080       assert(discard->isBranchNode(), "must be a cond. branch");
02081       assert(((BranchNode*)discard)->op() == VSBranchOp, "expected an overflow check");
02082       discard->bb()->remove(discard);
02083       // and the "overflow taken" code
02084       discard = discard->next1();
02085       discard->bb()->remove(discard);
02086       discard->removeUpToMerge();
02087 #     ifdef ASSERT
02088       bb->verify();
02089       ((BB*)bb->next())->verify();
02090 #     endif
02091       // enable further constant propagation of the result
02092       dontEliminate = false;
02093       _src->removeUse(bb, srcUse);
02094       _src = _constResult;
02095       srcUse = bb->addUse(this, _src);
02096     } else {
02097       // for now, can't constant-fold failure - can't use marks in ConstPReg
02098       // (and GC can't handle markOops embedded in compiled code)
02099     }
02100   }
02101   removeFailureIfPossible();
02102   return res;
02103 }
02104 
02105 bool TArithRRNode::doCopyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02106   bool res;
02107   if (u == srcUse) {
02108     if (d->isConstPReg() && ((ConstPReg*)d)->constant->is_smi())
02109       _arg1IsInt = true;
02110     CP_HELPER(_src, srcUse, res = );
02111   } else if (u == _operUse) {
02112     if (d->isConstPReg() && ((ConstPReg*)d)->constant->is_smi())
02113       _arg2IsInt = true;
02114     CP_HELPER(_oper, _operUse, res =);
02115   } else {
02116     fatal("copyPropagate: not the source use");
02117   }
02118   removeFailureIfPossible();
02119   return res;
02120 }
02121 
02122 bool FloatArithRRNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02123   if (d->isConstPReg() && !((ConstPReg*)d)->constant->is_double()) {
02124     // can't handle non-float arguments (don't optimize guaranteed failure)
02125     return false;
02126   }
02127   bool res = ArithRRNode::copyPropagate(bb, u, d, replace);
02128   // should check for constant folding opportunity here -- fix this
02129   return res;
02130 }
02131 
02132 bool FloatUnaryArithNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02133   if (d->isConstPReg() && !((ConstPReg*)d)->constant->is_double()) {
02134     // can't handle non-float arguments (don't optimize guaranteed failure)
02135     return false;
02136   }
02137   bool res = ArithNode::copyPropagate(bb, u, d, replace);
02138   // should check for constant folding opportunity here -- fix this
02139   return res;
02140 }
02141 
02142 bool TypeTestNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02143   if (u == srcUse) {
02144     if (d->isConstPReg()) {
02145       // we know the receiver - the type test is unnecessary!
02146       ConstPReg* c = (ConstPReg*)d;
02147       // The code below has been disabled by Lars Bak 4-19-96 per request by Urs
02148       // Cause:
02149       //   Something may go wrong when deleting the non-integer branch messing up
02150       //   the node graph.
02151       if (false) {
02152         eliminate(bb, NULL, c, c->constant->klass());
02153         return true;
02154       }
02155       return false;
02156     } else {
02157       CP_HELPER(_src, srcUse, return);
02158     }
02159   } else {
02160     fatal("don't have this use");
02161   }
02162   return false;
02163 }
02164 
02165 bool AbstractArrayAtNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02166   if (u == _argUse) {
02167     bool res;
02168     CP_HELPER(_arg, _argUse, res =);
02169     removeFailureIfPossible();
02170     return res;
02171   } else {
02172     return AbstractBranchNode::copyPropagate(bb, u, d, replace);
02173   }
02174   return false;
02175 }
02176 
02177 bool AbstractArrayAtPutNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02178   bool res;
02179   if (u == _argUse) {
02180     CP_HELPER(_arg, _argUse, res = );
02181   } else if (u == elemUse) {
02182     CP_HELPER(elem, elemUse, res =);
02183   } else {
02184     return AbstractBranchNode::copyPropagate(bb, u, d, replace);
02185   } 
02186   removeFailureIfPossible();
02187   return res;
02188 }
02189 
02190 bool InlinedPrimitiveNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02191   // copyPropagate should be fairly easy to put in, right now it is doing nothing.
02192   return false;
02193 }
02194 
02195 bool ContextInitNode::copyPropagate(BB* bb, Use* u, PReg* d, bool replace) {
02196   for (int i = nofTemps() - 1; i >= 0; i--) {
02197     if (_initializerUses->at(i) == u) {
02198       Expr* initExpr = _initializers->at(i);
02199       PReg* initPR = initExpr->preg();
02200       Use* newUse = u;
02201       bool ok;
02202       CP_HELPER(initPR, newUse, ok = );
02203       if (ok) {
02204         assert(newUse != u, "must have new use");
02205         _initializers->at_put(i, initExpr->shallowCopy(d, initExpr->node()));
02206         _initializerUses->at_put(i, newUse);
02207       }
02208       return ok;
02209     }
02210   }
02211   return NonTrivialNode::copyPropagate(bb, u, d, replace);
02212 }
02213 
02214 // ==================================================================================
02215 // markAllocated: for all PRegs used/defined by the node, increment the
02216 // corresponding counters if the PReg is already allocated
02217 // ==================================================================================
02218 
02219 # define U_CHECK(r) if (r->loc.isRegisterLocation()) use_count[r->loc.number()]++
02220 # define D_CHECK(r) if (r->loc.isRegisterLocation()) def_count[r->loc.number()]++
02221 
02222 void LoadNode::markAllocated(int* use_count, int* def_count) {
02223   Unused(use_count);
02224   D_CHECK(_dest);
02225 }
02226 void LoadOffsetNode::markAllocated(int* use_count, int* def_count) {
02227   U_CHECK(_src); LoadNode::markAllocated(use_count, def_count);
02228 }
02229 void LoadUplevelNode::markAllocated(int* use_count, int* def_count) {
02230   U_CHECK(_context0); LoadNode::markAllocated(use_count, def_count);
02231 }
02232 
02233 void StoreNode::markAllocated(int* use_count, int* def_count) {
02234   Unused(def_count);
02235   U_CHECK(_src);
02236 }
02237 void StoreOffsetNode::markAllocated(int* use_count, int* def_count) {
02238   U_CHECK(_base); StoreNode::markAllocated(use_count, def_count);
02239 }
02240 void StoreUplevelNode::markAllocated(int* use_count, int* def_count) {
02241   U_CHECK(_context0); StoreNode::markAllocated(use_count, def_count);
02242 }
02243 void AssignNode::markAllocated(int* use_count, int* def_count) {
02244   U_CHECK(_src); D_CHECK(_dest);
02245 }
02246 
02247 void ReturnNode::markAllocated(int* use_count, int* def_count) {
02248   U_CHECK(_src); D_CHECK(_dest);
02249   AbstractReturnNode::markAllocated(use_count, def_count);
02250 }
02251 
02252 void ArithNode::markAllocated(int* use_count, int* def_count) {
02253   U_CHECK(_src); D_CHECK(_dest); 
02254 }
02255 
02256 void ArithRRNode::markAllocated(int* use_count, int* def_count) {
02257   U_CHECK(_oper); ArithNode::markAllocated(use_count, def_count);
02258 }
02259 
02260 void TArithRRNode::markAllocated(int* use_count, int* def_count) {
02261   U_CHECK(_src); D_CHECK(_dest); 
02262   U_CHECK(_oper); 
02263 }
02264 
02265 void CallNode::markAllocated(int* use_count, int* def_count) {
02266   D_CHECK(_dest);
02267   // CallNode trashes all regs
02268   for (int i = 0; i < nofRegisters; i++) { use_count[i]++; def_count[i]++; }
02269 }
02270 
02271 void BlockCreateNode::markAllocated(int* use_count, int* def_count) {
02272   if (_src) U_CHECK(_src);
02273   if (_context) U_CHECK(_context);
02274   PrimNode::markAllocated(use_count, def_count);
02275 }
02276 
02277 void BlockMaterializeNode::markAllocated(int* use_count, int* def_count) {
02278   if (isMemoized()) BlockCreateNode::markAllocated(use_count, def_count);
02279 }
02280 
02281 void ContextCreateNode::markAllocated(int* use_count, int* def_count) {
02282   if (_src) U_CHECK(_src); // no src if there's no incoming context
02283   if (_parentContexts) {
02284     for (int i = _parentContexts->length() - 1; i>= 0; i--) {
02285       U_CHECK(_parentContexts->at(i));
02286     }
02287   }
02288   PrimNode::markAllocated(use_count, def_count);
02289 };
02290 
02291 void ContextInitNode::markAllocated(int* use_count, int* def_count) {
02292   if (_src) U_CHECK(_src);
02293   int i = nofTemps();
02294   while (i-- > 0) {
02295     D_CHECK(contents()->at(i)->preg());
02296   }
02297 }
02298 
02299 void ContextZapNode::markAllocated(int* use_count, int* def_count) {
02300   U_CHECK(_src);
02301 }
02302 
02303 void TypeTestNode::markAllocated(int* use_count, int* def_count) {
02304   Unused(def_count);
02305   U_CHECK(_src);
02306 }
02307 
02308 void AbstractArrayAtNode::markAllocated(int* use_count, int* def_count) {
02309   U_CHECK(_src);
02310   if (_dest) D_CHECK(_dest);
02311   U_CHECK(_arg);
02312   if (_error) D_CHECK(_error);
02313 }
02314 
02315 void AbstractArrayAtPutNode::markAllocated(int* use_count, int* def_count) {
02316   if (elem) U_CHECK(elem);
02317   AbstractArrayAtNode::markAllocated(use_count, def_count);
02318 }
02319 
02320 void InlinedPrimitiveNode::markAllocated(int* use_count, int* def_count) {
02321   if (_src  ) U_CHECK(_src  );
02322   if (_arg1 ) U_CHECK(_arg1 );
02323   if (_arg2 ) U_CHECK(_arg2 );
02324   if (_dest ) D_CHECK(_dest );
02325   if (_error) D_CHECK(_error);
02326 }
02327 
02328 // trashedMask: return bit mask of trashed registers
02329 SimpleBitVector BasicNode::trashedMask()        { return SimpleBitVector(0); }
02330 SimpleBitVector CallNode::trashedMask()         { return SimpleBitVector(-1); }
02331 
02332 // ==================================================================================
02333 // computeEscapingBlocks: find escaping blocks
02334 // ==================================================================================
02335 
02336 inline void computeEscapingBlocks(Node* n, PReg* src, GrowableArray<BlockPReg*>* l, char* msg) {
02337   // helper function for computing exposed blocks
02338   if (src->isBlockPReg()) {
02339     BlockPReg* r = (BlockPReg*)src;
02340     r->markEscaped(n);
02341     if (!l->contains(r)) l->append(r);
02342     if (msg) theCompiler->reporter->report_block(n, r, msg);
02343   }
02344 }
02345 
02346 void StoreNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02347   // Any store is considered to expose a block -- even if it's a store into a local.
02348   // That's pessimistic, but simple.  
02349   ::computeEscapingBlocks(this, _src, ll, action());
02350 }
02351 
02352 void AbstractReturnNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02353   // a block returned by a nmethod escapes
02354   if (_src) ::computeEscapingBlocks(this, _src, ll, "returned");
02355 }
02356 
02357 void CallNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02358   SubclassResponsibility();
02359 }
02360 
02361 void SendNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02362   // all arguments to a non-inlined call escape
02363   if (exprStack && (args != NULL)) {
02364     // if the receiver is not pushed on the exprStack (self/super sends),
02365     // the exprStack is by 1 shorter than the args array
02366     // (exprStack may be longer than that, so just look at top elems)
02367     int len = exprStack->length();
02368     int i = min(args->length(), len);
02369     while (i-- > 0) {
02370       ::computeEscapingBlocks(this, exprStack->at(--len), ll, "exposed by a send");
02371     }
02372   }
02373 }
02374 
02375 void PrimNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02376   // assume that all block arguments to a primitive call escape
02377   if (exprStack) {
02378     int len = exprStack->length();
02379     int i = min(len, _pdesc->number_of_parameters());
02380     while (i-- > 0) {
02381       ::computeEscapingBlocks(this, exprStack->at(--len), ll, "exposed by a primitive call");
02382     }
02383   }
02384 }
02385 
02386 void DLLNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02387   // assume that all block arguments to a DLL call escape
02388   if (exprStack) {
02389     int len = exprStack->length();
02390     int i = min(len, nofArguments());
02391     while (i-- > 0) {
02392       ::computeEscapingBlocks(this, exprStack->at(--len), ll, "exposed by a DLL call");
02393     }
02394   }
02395 }
02396 
02397 void ContextInitNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02398   // all blocks stored into a context escape
02399   // (later phase will recognize if context isn't created --> block doesn't really escape)
02400   int i = nofTemps();
02401   while (i-- > 0) {
02402     Expr* e = _initializers->at(i);
02403     if (e) ::computeEscapingBlocks(this, e->preg(), ll, NULL);
02404   }
02405 }
02406 
02407 void ArrayAtPutNode::computeEscapingBlocks(GrowableArray<BlockPReg*>* ll) {
02408   // all blocks stored into an array escape
02409   ::computeEscapingBlocks(this, elem, ll, "stored into an array");
02410 }
02411 
02412 
02413 // ==================================================================================
02414 // machine-independent routines for code generation
02415 // ==================================================================================
02416 
02417 bool TypeTestNode::needsKlassLoad() const {
02418   // a test needs a klass load if it tests for any non-smi/bool/nil klass
02419   const int len = _hasUnknown ? _classes->length() : _classes->length() - 1;
02420   for (int i = 0; i < len; i++) {
02421     klassOop klass = _classes->at(i);
02422     if (klass != trueObj->klass() &&
02423         klass != falseObj->klass() &&
02424         klass != nilObj->klass() &&
02425         klass != smiKlassObj) {
02426       return true;
02427     }
02428   }
02429   return false;
02430 }
02431 
02432 static bool hasUnknownCode(Node* n) {
02433   while (n->isTrivial()) n = n->next();
02434   return !n->isUncommonNode();
02435 }
02436 
02437 
02438 bool TypeTestNode::hasUnknownCode() const {
02439   if (!_hasUnknown) return false;     // no unknown type
02440   return ::hasUnknownCode(next());
02441 }
02442 
02443 bool TArithRRNode::hasUnknownCode() const {
02444   return ::hasUnknownCode(next1());
02445 }
02446 
02447 bool AbstractArrayAtNode::hasUnknownCode() const {
02448   return ::hasUnknownCode(next1());
02449 }
02450 
02451 Node* TypeTestNode::smiCase() const {
02452   int i = _classes->length();
02453   while (i-- > 0) {
02454     if (_classes->at(i) == smiKlassObj) return next(i+1);
02455   }
02456   return NULL;
02457 }
02458 
02459 // ==================================================================================
02460 // integer loop optimization
02461 // ==================================================================================
02462 
02463 LoopHeaderNode::LoopHeaderNode() { 
02464   _activated = false; _integerLoop = false; _tests = NULL; 
02465   _enclosingLoop = NULL; _nestedLoops = NULL; 
02466   _nofCalls = 0; _registerCandidates = NULL;
02467 }
02468 
02469 
02470 void LoopHeaderNode::activate(PReg* loopVar, PReg* lowerBound, PReg* upperBound, LoadOffsetNode* loopSizeLoad) {
02471   _activated     = true;
02472   _integerLoop   = true;
02473   _loopVar       = loopVar; 
02474   _lowerBound    = lowerBound; 
02475   _upperBound    = upperBound; 
02476   _upperLoad     = loopSizeLoad;
02477   _arrayAccesses = new GrowableArray<AbstractArrayAtNode*>(10);
02478 }
02479 
02480 void LoopHeaderNode::activate() {
02481   _activated = true;
02482   assert(_tests, "should have type tests");
02483   _loopVar = _lowerBound = _upperBound = NULL; 
02484   _upperLoad = NULL;
02485   _arrayAccesses = NULL;
02486 }
02487 
02488 void LoopHeaderNode::addArray(AbstractArrayAtNode* n) {
02489   assert(_activated, "shouldn't call");
02490   _arrayAccesses->append(n);
02491 }
02492 
02493 void LoopHeaderNode::set_enclosingLoop(LoopHeaderNode* l) {
02494   assert(_enclosingLoop == NULL, "already set");
02495   _enclosingLoop = l;
02496 }
02497 
02498 void LoopHeaderNode::addNestedLoop(LoopHeaderNode* l) {
02499   if (_nestedLoops == NULL) _nestedLoops = new GrowableArray<LoopHeaderNode*>(5);
02500   _nestedLoops->append(l);
02501 }
02502 
02503 void LoopHeaderNode::addRegisterCandidate(LoopRegCandidate* c) {
02504   if (_registerCandidates == NULL) _registerCandidates = new GrowableArray<LoopRegCandidate*>(2);
02505   _registerCandidates->append(c);
02506 }
02507 
02508 
02509 
02510 inline bool is_smi_type(GrowableArray<klassOop>* klasses) {
02511   return klasses->length() == 1 && klasses->at(0) == smiKlassObj;
02512 }
02513 
02514 inline GrowableArray<klassOop>* make_smi_type() {
02515   GrowableArray<klassOop>* t = new GrowableArray<klassOop>(1);
02516   t->append(smiKlassObj);
02517   return t;
02518 }
02519 
02520 void StoreNode::assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n) {
02521   if (is_smi_type(klasses) && r == src()) {
02522     if (CompilerDebug) cout(PrintLoopOpts)->print("*removing store check from N%d\n", id());
02523     setStoreCheck(false);
02524   } 
02525 }
02526 
02527 void AbstractArrayAtNode::assert_in_bounds(PReg* r, LoopHeaderNode* n) {
02528   if (r == _arg) {
02529     if (CompilerDebug && _needBoundsCheck) cout(PrintLoopOpts)->print("*removing bounds check from N%d\n", id());
02530     _needBoundsCheck = false;
02531     removeFailureIfPossible();
02532   }
02533 }
02534 
02535 void AbstractArrayAtNode::collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const {
02536   // ArrayAt node tests index for smi-ness
02537   regs.append(_arg);
02538   klasses.append(make_smi_type());
02539 }
02540 
02541 void AbstractArrayAtNode::assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n) {
02542   if (is_smi_type(klasses) && r == _arg) {
02543     if (CompilerDebug && !_intArg) cout(PrintLoopOpts)->print("*removing index tag check from N%d\n", id());
02544     _intArg = true;
02545     n->addArray(this);
02546     removeFailureIfPossible();
02547   } else if (r != _arg) {
02548     fatal("array can't be an integer");
02549   }
02550 }
02551 
02552 void ArrayAtPutNode::collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const {
02553   // atPut node tests element for smi-ness if character array
02554   AbstractArrayAtNode::collectTypeTests(regs, klasses);
02555   if (stores_smi_elements(_access_type)) {
02556     regs.append(elem);
02557     assert(klasses.first()->first() == smiKlassObj, "must be smi type for index");
02558     klasses.append(klasses.first());    // reuse smi type descriptor
02559   }
02560 }
02561 
02562 void ArrayAtPutNode::assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n) {
02563   if (is_smi_type(klasses) && r == elem) {
02564     if (CompilerDebug && _needs_store_check) 
02565       cout(PrintLoopOpts)->print("*removing array store check from N%d\n", id());
02566     _needs_store_check = false;
02567     removeFailureIfPossible();
02568   } else if (r == _arg) {
02569     AbstractArrayAtPutNode::assert_preg_type(r, klasses, n);
02570   }
02571 }
02572 
02573 void TArithRRNode::collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const {
02574   // tests receiver and/or arg for smi-ness
02575   if (canFail()) {
02576     GrowableArray<klassOop>* t = make_smi_type();
02577     if (!_arg1IsInt) {
02578       regs.append(_src);
02579       klasses.append(t);
02580     }
02581     if (!_arg2IsInt) {
02582       regs.append(_oper);
02583       klasses.append(t);
02584     }
02585   }
02586 }
02587 
02588 void TArithRRNode::assert_preg_type(PReg* r, GrowableArray<klassOop>* klasses, LoopHeaderNode* n) {
02589   if (is_smi_type(klasses) && r == _src) {
02590     if (CompilerDebug && !_arg1IsInt) cout(PrintLoopOpts)->print("*removing arith arg1 tag check from N%d\n", id());
02591     _arg1IsInt = true;
02592   } 
02593   if (is_smi_type(klasses) && r == _oper) {
02594     if (CompilerDebug && !_arg2IsInt) cout(PrintLoopOpts)->print("*removing arith arg2 tag check from N%d\n", id());
02595     _arg2IsInt = true;
02596   }
02597   removeFailureIfPossible();
02598 }
02599 
02600 void TypeTestNode::collectTypeTests(GrowableArray<PReg*>& regs, GrowableArray<GrowableArray<klassOop>*>& klasses) const {
02601   regs.append(_src);
02602   klasses.append(_classes);
02603 }
02604 
02605 void TypeTestNode::assert_preg_type(PReg* r, GrowableArray<klassOop>* k, LoopHeaderNode* n) {
02606   assert(r == src(), "must be source");
02607   if (k->length() == 1) {
02608     // common case: tests for one klass --> can be eliminated
02609     eliminateUnnecessary(k->at(0));
02610   } else {
02611     // can at least eliminate uncommon unknown case
02612     assert(k->length() <= _classes->length(), "type cannot widen");
02613     setUnknown(false);
02614   }
02615 }
02616 
02617 // ==================================================================================
02618 // printing code (for debugging)
02619 // ==================================================================================
02620 
02621 #ifdef PRODUCT
02622   #define DISABLED_IN_PRODUCT return buf;
02623 #else
02624   #define DISABLED_IN_PRODUCT
02625 #endif
02626 
02627 
02628 const int PrintStringLen = 40;  // width of output before printing address
02629 
02630 void BasicNode::print_short()   { char buf[1024]; lprintf(print_string(buf, PrintHexAddresses)); }
02631 static int id_of(Node* node)    { return node == NULL ? -1 : node->id(); }
02632 
02633 char* PrologueNode::print_string(char* buf, bool printAddr) const {
02634   DISABLED_IN_PRODUCT
02635   char* b = buf;
02636   my_sprintf_len(buf, PrintStringLen, "Prologue");
02637   if (printAddr) my_sprintf(buf, "((PrologueNode*)%#lx", this);
02638   return b;
02639 }
02640 
02641 char* InterruptCheckNode::print_string(char* buf, bool printAddr) const {
02642   DISABLED_IN_PRODUCT
02643   char* b = buf;
02644   my_sprintf_len(buf, PrintStringLen, "InterruptCheckNode");
02645   if (printAddr) my_sprintf(buf, "((InterruptCheckNode*)%#lx)", this);
02646   return b;
02647 }
02648 
02649 char* LoadOffsetNode::print_string(char* buf, bool printAddr) const {
02650   DISABLED_IN_PRODUCT
02651   char* b = buf;
02652   my_sprintf_len(buf, PrintStringLen, "LoadOffset %s := %s[%#lx]", _dest->safeName(), _src->safeName(), offset);
02653   if (printAddr) my_sprintf(buf, "((LoadOffsetNode*)%#lx)", this);
02654   return b;
02655 }
02656 
02657 char* LoadIntNode::print_string(char* buf, bool printAddr) const {
02658   DISABLED_IN_PRODUCT
02659   char* b = buf;
02660   my_sprintf_len(buf, PrintStringLen, "LoadInt %s := %#lx", _dest->safeName(), _value);
02661   if (printAddr) my_sprintf(buf, "((LoadIntNode*)%#lx)", this);
02662   return b;
02663 }
02664 
02665 char* LoadUplevelNode::print_string(char* buf, bool printAddr) const {
02666   DISABLED_IN_PRODUCT
02667   char* b = buf;
02668   my_sprintf_len(buf, PrintStringLen, "LoadUpLevel %s := %s^%d[%d]", _dest->safeName(), 
02669                  _context0->safeName(), _nofLevels, _offset);
02670   if (printAddr) my_sprintf(buf, "((LoadUplevelNode*)%#lx)", this);
02671   return b;
02672 }
02673 
02674 char* StoreOffsetNode::print_string(char* buf, bool printAddr) const {
02675   DISABLED_IN_PRODUCT
02676   char* b = buf;
02677   my_sprintf_len(buf, PrintStringLen, "StoreOffset %s[%#lx] := %s", _base->safeName(), _offset, _src->safeName());
02678   if (printAddr) my_sprintf(buf, "((StoreOffsetNode*)%#lx)", this);
02679   return b;
02680 }
02681 
02682 char* StoreUplevelNode::print_string(char* buf, bool printAddr) const {
02683   DISABLED_IN_PRODUCT
02684   char* b = buf;
02685   my_sprintf_len(buf, PrintStringLen, "StoreUpLevel %s^%d[%d] := %s", 
02686                  _context0->safeName(), _nofLevels, _offset, _src->safeName());
02687   if (printAddr) my_sprintf(buf, "((StoreUplevelNode*)%#lx)", this);
02688   return b;
02689 }
02690   
02691 char* AssignNode::print_string(char* buf, bool printAddr) const {
02692   DISABLED_IN_PRODUCT
02693   char* b = buf;
02694   my_sprintf_len(buf, PrintStringLen, "%s := %s", _dest->safeName(), _src->safeName());
02695   if (printAddr) my_sprintf(buf, "((AssignNode*)%#lx)", this);
02696   return b;
02697 }
02698 
02699 char* SendNode::print_string(char* buf, bool printAddr) const {
02700   DISABLED_IN_PRODUCT
02701   char* b = buf;
02702   my_sprintf_len(buf,PrintStringLen, "Send %s NLR %ld ", _key->print_string(), id_of(nlrTestPoint()));
02703   if (printAddr) my_sprintf(buf, "((SendNode*)%#lx)", this);
02704   return b;
02705 }
02706 
02707 
02708 char* PrimNode::print_string(char* buf, bool printAddr) const {
02709   DISABLED_IN_PRODUCT
02710   char* b = buf;
02711   my_sprintf_len(buf, PrintStringLen, "PrimCall _%s NLR %ld", _pdesc->name(), id_of(nlrTestPoint()));
02712   if (printAddr) my_sprintf(buf, "((PrimNode*)%#lx)", this);
02713   return b;
02714   }
02715 
02716 
02717 char* DLLNode::print_string(char* buf, bool printAddr) const {
02718   DISABLED_IN_PRODUCT
02719   char* b = buf;
02720   my_sprintf_len(buf, PrintStringLen, "DLLCall <%s, %s> NLR %ld", _dll_name->as_string(), _function_name->as_string(), id_of(nlrTestPoint()));
02721   if (printAddr) my_sprintf(buf, "((DLLNode*)%#lx)", this);
02722   return b;
02723 }
02724 
02725 
02726 char* BlockCreateNode::print_string(char* buf, bool printAddr) const {
02727   DISABLED_IN_PRODUCT
02728   char* b = buf;
02729   my_sprintf_len(buf, PrintStringLen, "BlockCreate %s", _dest->safeName());
02730   if (printAddr) my_sprintf(buf, "((BlockCreateNode*)%#lx)", this);
02731   return b;
02732 }
02733 
02734 char* BlockMaterializeNode::print_string(char* buf, bool printAddr) const {
02735   DISABLED_IN_PRODUCT
02736   char* b = buf;
02737   my_sprintf_len(buf, PrintStringLen, "BlockMaterialize %s", _dest->safeName());
02738     if (printAddr) my_sprintf(buf, "((BlockMaterializeNode*)%#lx)", this);
02739   return b;
02740 }
02741 
02742 char* InlinedReturnNode::print_string(char* buf, bool printAddr) const {
02743   DISABLED_IN_PRODUCT
02744   char* b = buf;
02745   my_sprintf_len(buf, PrintStringLen, "InlinedReturn %s := %s", _dest->safeName(), _src->safeName());
02746   if (printAddr) my_sprintf(buf, "((InlinedReturnNode*)%#lx)", this);
02747   return b;
02748 }
02749 
02750 char* NLRSetupNode::print_string(char* buf, bool printAddr) const {
02751   DISABLED_IN_PRODUCT
02752   char* b = buf;
02753   my_sprintf_len(buf, PrintStringLen, "NLReturn %s := %s", _dest->safeName(), _src->safeName());
02754   if (printAddr) my_sprintf(buf, "((NLRSetupNode*)%#lx)", this);
02755   return b;
02756 }
02757 
02758 char* NLRContinuationNode::print_string(char* buf, bool printAddr) const {
02759   DISABLED_IN_PRODUCT
02760   char* b = buf;
02761   my_sprintf_len(buf, PrintStringLen, "NLR Continuation");
02762   if (printAddr) my_sprintf(buf, "((NLRContinuationNode*)%#lx)", this);
02763   return b;
02764 }
02765 
02766 char* ReturnNode::print_string(char* buf, bool printAddr) const {
02767   DISABLED_IN_PRODUCT
02768   char* b = buf;
02769   my_sprintf_len(buf, PrintStringLen, "MethodReturn  %s", _src->safeName());
02770   if (printAddr) my_sprintf(buf, "((ReturnNode*)%#lx)", this);
02771   return b;
02772 }
02773 
02774 char* NLRTestNode::print_string(char* buf, bool printAddr) const {
02775   DISABLED_IN_PRODUCT
02776   char* b = buf;
02777   my_sprintf_len(buf, PrintStringLen, "NLRTest  N%ld N%ld", id_of(next1()), id_of(next()));
02778   if (printAddr) my_sprintf(buf, "((NLRTestNode*)%#lx)", this);
02779   return b;
02780 }
02781 
02782 char* ArithNode::opName() const { return ArithOpName[_op]; }
02783 
02784 char* ArithRRNode::print_string(char* buf, bool printAddr) const {
02785   DISABLED_IN_PRODUCT
02786   char* b = buf;
02787   my_sprintf_len(buf, PrintStringLen, "%s := %s %s %s", 
02788                  _dest->safeName(), _src->safeName(), opName(), _oper->safeName());
02789   if (printAddr) my_sprintf(buf, "((ArithRRNode*)%#lx)", this);
02790   return b;
02791 }
02792 
02793 char* FloatArithRRNode::print_string(char* buf, bool printAddr) const {
02794   DISABLED_IN_PRODUCT
02795   char* b = buf;
02796   my_sprintf_len(buf, PrintStringLen, "%s := %s %s %s", 
02797                  _dest->safeName(), _src->safeName(), opName(), _oper->safeName());
02798   if (printAddr) my_sprintf(buf, "((FloatArithRRNode*)%#lx)", this);
02799   return b;
02800 }
02801 
02802 char* FloatUnaryArithNode::print_string(char* buf, bool printAddr) const {
02803   DISABLED_IN_PRODUCT
02804   char* b = buf;
02805   my_sprintf_len(buf, PrintStringLen, "%s := %s %s", 
02806                  _dest->safeName(), opName(), _src->safeName());
02807   if (printAddr) my_sprintf(buf, "((FloatUnaryArithNode*)%#lx)", this);
02808   return b;
02809 }
02810 
02811 char* TArithRRNode::print_string(char* buf, bool printAddr) const {
02812   DISABLED_IN_PRODUCT
02813   char* b = buf;
02814   my_sprintf_len(buf, PrintStringLen, "%s := %s %s %s   N%d, N%d",
02815                  _dest->safeName(), _src->safeName(), ArithOpName[_op], _oper->safeName(),
02816                  id_of(next1()), id_of(next()));
02817   if (printAddr) my_sprintf(buf, "((TArithRRNode*)%#lx)", this);
02818   return b;
02819 }
02820 
02821 char* ArithRCNode::print_string(char* buf, bool printAddr) const {
02822   DISABLED_IN_PRODUCT
02823   char* b = buf;
02824   my_sprintf_len(buf, PrintStringLen, "%s := %s %s %#lx",
02825                  _dest->safeName(), _src->safeName(), opName(), _oper);
02826   if (printAddr) my_sprintf(buf, "((ArithRCNode*)%#lx)", this);
02827   return b;
02828 }
02829 
02830 char* BranchNode::print_string(char* buf, bool printAddr) const {
02831   DISABLED_IN_PRODUCT
02832   char* b = buf;
02833   my_sprintf_len(buf, PrintStringLen, "%s  N%ld N%ld", BranchOpName[_op], id_of(next1()), id_of(next()));
02834   if (printAddr) my_sprintf(buf, "((BranchNode*)%#lx)", this);
02835   return b;
02836 }
02837 
02838 char* TypeTestNode::print_string(char* buf, bool printAddr) const {
02839   DISABLED_IN_PRODUCT
02840   char* b = buf;
02841   my_sprintf(buf, "TypeTest %s, ", _src->safeName());
02842   for (int i = 1; i <= _classes->length(); i++) {
02843     klassOop m = _classes->at(i-1);
02844     my_sprintf(buf, m->print_value_string());
02845     my_sprintf(buf, ": N%ld; ", (i < nSuccessors() && next(i) != NULL) ? next(i)->id() : -1);
02846   }
02847   my_sprintf_len(buf, b + PrintStringLen - buf,
02848                  "N%ld%s", id_of(next()),
02849                  _hasUnknown ? "" : "*");
02850   if (printAddr) my_sprintf(buf, "((TypeTestNode*)%#lx)", this);
02851   return b;
02852 }
02853 
02854 char* ArrayAtNode::print_string(char* buf, bool printAddr) const {
02855   DISABLED_IN_PRODUCT
02856   char* b = buf;
02857   my_sprintf_len(buf, PrintStringLen, "ArrayAt %s := %s[%s]",
02858                  _dest->safeName(), _src->safeName(), _arg->safeName());
02859   if (printAddr) my_sprintf(buf, "((ArrayAtNode*)%#lx)", this);
02860   return b;
02861 }
02862 
02863 char* ArrayAtPutNode::print_string(char* buf, bool printAddr) const {
02864   DISABLED_IN_PRODUCT
02865   char* b = buf;
02866   my_sprintf_len(buf, PrintStringLen, "ArrayAtPut %s[%s] := %s",
02867                    _src->safeName(), _arg->safeName(), elem->safeName());
02868   if (printAddr) my_sprintf(buf, "((ArrayAtPutNode*)%#lx)", this);
02869   return b;
02870 }
02871 
02872 char* FixedCodeNode::print_string(char* buf, bool printAddr) const {
02873   DISABLED_IN_PRODUCT
02874   char* b = buf;
02875   my_sprintf_len(buf, PrintStringLen, "DeadEnd");
02876   if (printAddr) my_sprintf(buf, "((FixedCodeNode*)%#lx)", this);
02877   return b;
02878 }
02879 
02880 static int prevsLen;
02881 static char* mergePrintBuf;
02882 static void printPrevNodes(Node* n) {
02883   my_sprintf(mergePrintBuf, "N%ld%s", id_of(n), --prevsLen > 0 ? ", " : "");
02884 }
02885 
02886 char* MergeNode::print_string(char* buf, bool printAddr) const {
02887   DISABLED_IN_PRODUCT
02888   char* b = buf;
02889   my_sprintf(buf, "Merge ");
02890   prevsLen = _prevs->length();
02891   mergePrintBuf = buf;
02892   _prevs->apply(printPrevNodes);
02893   buf = mergePrintBuf;
02894   my_sprintf_len(buf, b + PrintStringLen - buf, " ");
02895   if (printAddr) my_sprintf(buf, "((MergeNode*)%#lx)", this);
02896   return b;
02897 }
02898 
02899 char* LoopHeaderNode::print_string(char* buf, bool printAddr) const {
02900   DISABLED_IN_PRODUCT
02901   char* b = buf;
02902   my_sprintf(buf, "LoopHeader ");
02903   if (_activated) {
02904     if (_integerLoop) {
02905       my_sprintf(buf, "int ");
02906       my_sprintf(buf, "%s=[%s..%s] ", _loopVar->safeName(), _lowerBound->safeName(), 
02907                  _upperBound ? _upperBound->safeName() : _upperLoad->base()->safeName());
02908     }
02909     if (_registerCandidates != NULL) {
02910       my_sprintf(buf, "reg vars = ");
02911       for (int i = 0; i < _tests->length(); i++) my_sprintf(buf, "%s ", _registerCandidates->at(i)->preg()->name());
02912     }
02913     if (_tests != NULL) {
02914       for (int i = 0; i < _tests->length(); i++) {
02915         HoistedTypeTest* t = _tests->at(i);
02916         if (t->testedPR->loc != unAllocated) {
02917           stringStream s(50);
02918           t->print_test_on(&s);
02919           my_sprintf(buf, "%s ", s.as_string());
02920         }
02921       }
02922     }
02923     my_sprintf_len(buf, PrintStringLen - (buf - b), " ");
02924   } else {
02925     my_sprintf_len(buf, PrintStringLen - 11, "(inactive)");
02926   }
02927   if (printAddr) my_sprintf(buf, "((LoopHeaderNode*)%#lx)", this);
02928   return b;
02929 }
02930 
02931 char* ContextCreateNode::print_string(char* buf, bool printAddr) const {
02932   DISABLED_IN_PRODUCT
02933   char* b = buf;
02934   my_sprintf_len(buf, PrintStringLen, "Create Context %s", _dest->safeName());
02935   if (printAddr) my_sprintf(buf, "((ContextCreateNode*)%#lx)", this);
02936   return b;
02937 }
02938 
02939 char* ContextInitNode::print_string(char* buf, bool printAddr) const {
02940   DISABLED_IN_PRODUCT
02941   char* b = buf;
02942   my_sprintf(buf, "Initialize context ");
02943   if (_src == NULL) {
02944     my_sprintf(buf, "(optimized away) ");
02945   } else {
02946     my_sprintf(buf, "%s { ", _src->safeName());
02947     for (int i = 0; i < contents()->length(); i++) {
02948       my_sprintf(buf, " %s := ", contents()->at(i)->preg()->safeName());
02949       Expr* e = _initializers->at(i);
02950       my_sprintf(buf, " %s; ", e->preg()->safeName());
02951     }
02952   }
02953   my_sprintf_len(buf, b + PrintStringLen - buf, "}");
02954   if (printAddr) my_sprintf(buf, "((ContextInitNode*)%#lx)", this);
02955   return b;
02956 }
02957 
02958 char* ContextZapNode::print_string(char* buf, bool printAddr) const {
02959   DISABLED_IN_PRODUCT
02960   char* b = buf;
02961   my_sprintf_len(buf, PrintStringLen, "Zap Context %s", isActive() ? context()->safeName() : "- inactive");
02962   if (printAddr) my_sprintf(buf, "((ContextZapNode*)%#lx)", this);
02963   return b;
02964 }
02965 
02966 char* InlinedPrimitiveNode::print_string(char* buf, bool printAddr) const {
02967   DISABLED_IN_PRODUCT
02968   char* b = buf;
02969   my_sprintf(buf, "%s := ", _dest->safeName());
02970   char* op_name;
02971   switch (_op) {
02972     case obj_klass              : op_name = "obj_klass";                break;
02973     case obj_hash               : op_name = "obj_hash";                 break;
02974     case proxy_byte_at          : op_name = "proxy_byte_at";            break;
02975     case proxy_byte_at_put      : op_name = "proxy_byte_at_put";        break;
02976     default                     : op_name = "*** unknown primitive ***";break;
02977   }
02978   my_sprintf(buf, "%s(", op_name);
02979   my_sprintf(buf, " %s", _src ->safeName());
02980   my_sprintf(buf, " %s", _arg1->safeName());
02981   my_sprintf(buf, " %s", _arg2->safeName());
02982   my_sprintf_len(buf, b + PrintStringLen - buf, ")");
02983   if (printAddr) my_sprintf(buf, "((InlinedPrimitiveNode*)%#lx)", this);
02984   return b;
02985 }
02986 
02987 char* UncommonNode::print_string(char* buf, bool printAddr) const {
02988   DISABLED_IN_PRODUCT
02989   char* b = buf;
02990   my_sprintf_len(buf, PrintStringLen, "UncommonBranch");
02991   if (printAddr) my_sprintf(buf, "((UncommonNode*)%#lx)", this);
02992   return b;
02993 }
02994 
02995 char* NopNode::print_string(char* buf, bool printAddr) const {
02996   DISABLED_IN_PRODUCT
02997   char* b = buf;
02998   my_sprintf_len(buf, PrintStringLen, "Nop");
02999   if (printAddr) my_sprintf(buf, "((NopNode*)%#lx)", this);
03000   return b;
03001 }
03002 
03003 char* CommentNode::print_string(char* buf, bool printAddr) const {
03004   DISABLED_IN_PRODUCT
03005   char* b = buf;
03006   my_sprintf_len(buf, PrintStringLen, "'%s' ", comment);
03007   if (printAddr) my_sprintf(buf, "((CommentNode*)%#lx)", this);
03008   return b;
03009 }
03010 
03011 void BasicNode::printID() const {
03012   lprintf("%4ld:%1s %-4s", id(), deleted ? "D" : " ", " ");
03013     //c hasSplitSig() ? splitSig()->prefix(buf) : " ");
03014 }
03015 
03016 void Node::verify() const {
03017   if (deleted) return;
03018   if (!firstPrev() && !isPrologueNode())
03019     error("Node %#lx: no predecessor", this);
03020   if (firstPrev() && !firstPrev()->isSuccessor(this))
03021     error("prev->next != this for Node %#lx", this);
03022   if (_bb && !_bb->contains(this))
03023     error("BB doesn't contain Node %#lx", this);
03024   if (next() && ! next()->isPredecessor(this))
03025     error("next->prev != this for Node %#lx", this);
03026   if (bbIterator->blocksBuilt && _bb == NULL) error("Node %#lx: doesn't belong to any BB", this);
03027   if (next() == NULL && !isExitNode() &&
03028       !isCommentNode())   // for the "rest of method omitted (dead)" comment
03029     error("Node %#lx has no successor", this);
03030   if (next() != NULL && isExitNode()) {
03031     for (Node* n = next();
03032          n && (n->isCommentNode() || n->isDeadEndNode());
03033          n = n->next()) ;
03034       if (n) error("exit node %#lx has a successor (%#lx)", this, next());
03035   }
03036 }
03037 
03038 void NonTrivialNode::verify() const {
03039   if (deleted) return;
03040   if (hasSrc()) src()->verify();
03041   if (hasDest()) {
03042     dest()->verify();
03043     if (dest()->isConstPReg()) {
03044       error("Node %#lx: dest %#lx is ConstPR", this, dest());
03045     }
03046   }
03047   if (isAssignmentLike() && (!hasSrc() || !hasDest()))
03048     error("Node %#lx: isAssignmentLike() implies hasSrc/Dest", this);
03049   Node::verify();
03050 }
03051 
03052 void LoadOffsetNode::verify() const {
03053   if (deleted) return;
03054   NonTrivialNode::verify();
03055   base()->verify();
03056   if (offset < 0) error("Node %#lx: offset must be >= 0", this);
03057 }
03058   
03059 void LoadUplevelNode::verify() const {
03060   if (deleted) return;
03061   if (_context0 == NULL) error("Node %#lx: context0 is NULL", this);
03062   if (_nofLevels < 0)    error("Node %#lx: nofLevels must be >= 0", this);
03063   if (_offset < 0)       error("Node %#lx: offset must be >= 0", this);
03064   NonTrivialNode::verify();
03065   _context0->verify();
03066 }
03067 
03068 void StoreOffsetNode::verify() const {
03069   if (deleted) return;
03070   NonTrivialNode::verify();
03071   base()->verify();
03072   if (_offset < 0) error("Node %#lx: offset must be >= 0", this);
03073 }
03074 
03075 void StoreUplevelNode::verify() const {
03076   if (deleted) return;
03077   if (_context0 == NULL) error("Node %#lx: context0 is NULL", this);
03078   if (_nofLevels < 0)    error("Node %#lx: nofLevels must be > 0", this);
03079   if (_offset < 0)       error("Node %#lx: offset must be >= 0", this);
03080   NonTrivialNode::verify();
03081   _context0->verify();
03082 }
03083 
03084 void MergeNode::verify() const {
03085   if (deleted) return;
03086   if (isLoopStart && isLoopEnd) error("MergeNode %#x: cannot be both start and end of loop");
03087   TrivialNode::verify();
03088 }
03089 
03090 void BlockCreateNode::verify() const {
03091   if (deleted) return;
03092   PrimNode::verify();
03093 }
03094 
03095 void ReturnNode::verify() const {
03096   if (deleted) return;
03097   AbstractReturnNode::verify();
03098   if (next()) error("ReturnNode %#lx has a successor", this);
03099 }
03100 
03101 void NLRSetupNode::verify() const {
03102   if (deleted) return;
03103   AbstractReturnNode::verify();
03104   if (next()) error("NLRSetupNode %#lx has a successor", this);
03105 }
03106 
03107 void NLRContinuationNode::verify() const {
03108   if (deleted) return;
03109   AbstractReturnNode::verify();
03110   if (next()) error("NLRContinuationNode %#lx has a successor", this);
03111 }
03112 
03113 void NLRTestNode::verify() const {
03114   if (deleted) return;
03115   AbstractBranchNode::verify(false);
03116   if (next() == NULL)  error("NLRTestNode %#lx has no continue-NLR node", this);
03117   if (next1() == NULL) error("NLRTestNode %#lx has no end-of-NLR node", this);
03118 }
03119 
03120 void InlinedReturnNode::verify() const {
03121   if (deleted) return;
03122   AbstractReturnNode::verify();
03123   if (!next()) { 
03124     error("InlinedReturnNode %#lx has no successor", this);
03125   } else {
03126     Node* nextAfterMerge = next()->next();
03127     if (nextAfterMerge->scope() == scope())
03128       error("InlinedReturnNode %#lx: successor is in same scope", this);
03129   }
03130 }
03131 
03132 void ContextCreateNode::verify() const {
03133   PrimNode::verify();
03134 }
03135 
03136 void ContextInitNode::verify() const {
03137   if (deleted) return;
03138   int n = nofTemps();
03139   if ((n != contents()->length()) ||
03140       (n != _initializers->length()) ||
03141       (_contentDefs != NULL) && (n != _contentDefs->length()) ||
03142       (_initializerUses != NULL) && (n != _initializerUses->length())) {
03143     error("ContextInitNode %#lx: bad nofTemps %d", this, n);
03144   }
03145   int i = nofTemps();
03146   while (i-- > 0) {
03147     Expr* e = _initializers->at(i);
03148     if (e != NULL) e->verify();
03149     contents()->at(i)->verify();
03150     PReg* r = contents()->at(i)->preg();
03151     if (_src == NULL && r->loc.isContextLocation()) {
03152       ((ContextInitNode*)this)->print();
03153       scope()->print();
03154       error("ContextInitNode %#lx: context eliminated but temp %d is context location", this, i);
03155     }
03156     // isInContext is accessing _isInContext which is never set (and thus always 0 initially)
03157     // Should check if we're missing something here or if we can remove the code completely.
03158     // - gri 9/10/96
03159     /*
03160     if (r->isSAPReg() && !r->isBlockPReg() && !((SAPReg*)r)->isInContext()) {
03161       // I'm not sure what the isInContext() flag is supposed to do....but the error is triggered
03162       // in the test suite (when running the standard tests).  Could be because of copy propagation.
03163       // If the assertion does make sense, please also put it in ContextInitNode::initialize().
03164       // (But please turn the condition above into a method, don't duplicate it.)
03165       // Urs 9/8/96
03166       // error("ContextInitNode %#lx: temp %d is non-context SAPReg %s", this, i, r->safeName());
03167     }
03168     */
03169   }
03170 }
03171 
03172 void ContextZapNode::verify() const {
03173   if (deleted) return;
03174   if (_src != scope()->context()) {
03175     error("ContextZapNode %#lx: wrong context %#lx", this, _src);
03176   }
03177   NonTrivialNode::verify();
03178 }
03179 
03180 void CallNode::verify() const {
03181   if (deleted) return;
03182   if ((exprStack != NULL) && (args != NULL)) {
03183     if (exprStack->length() + 1 < args->length()) {
03184       error("CallNode %#lx: exprStack is too short", this);
03185     }
03186   }
03187 }
03188 
03189 void ArithRRNode::verify() const {
03190   if (deleted) return;
03191   ArithNode::verify();
03192   _oper->verify();
03193 }
03194 
03195 void TArithRRNode::verify() const {
03196   if (deleted) return;
03197   AbstractBranchNode::verify(true);
03198   if ((_op < tAddArithOp) || (tCmpArithOp < _op)) {
03199     error("TArithRRNode %#lx: wrong opcode %ld", this, _op);
03200   }
03201 }
03202 
03203 void FloatArithRRNode::verify() const {
03204   if (deleted) return;
03205   ArithRRNode::verify();
03206   // fix this -- check opcode
03207 }
03208 
03209 void FloatUnaryArithNode::verify() const {
03210   if (deleted) return;
03211   ArithNode::verify();
03212   // fix this -- check opcode
03213 }
03214 
03215 void AbstractBranchNode::verify(bool verifySuccessors) const {
03216   if (deleted) return;
03217   NonTrivialNode::verify();
03218   if (verifySuccessors && !canFail() && failureBranch() != NULL) {
03219     error("Node %#x: cannot fail, but failure branch is still there", this);
03220   }
03221 }
03222 
03223 void InlinedPrimitiveNode::verify() const {
03224   if (deleted) return;
03225   AbstractBranchNode::verify(true);
03226   // fix this - check node
03227 }
03228 
03229 void UncommonNode::verify() const {
03230   if (deleted) return;
03231   if ((Node*)this != bb()->last)
03232     error("UncommonNode %#lx: not last node in BB", this);
03233   NonTrivialNode::verify();
03234 }
03235 
03236 void TypeTestNode::verify() const {
03237   if (deleted) return;
03238   if ((Node*)this != bb()->last)
03239     error("TypeTestNode %#lx: not last node in BB", this);
03240   NonTrivialNode::verify();
03241 }
03242 
03243 
03244 // for debugging
03245 void printNodes(Node* n) {
03246   for ( ; n; n = n->next()) {
03247     n->printID(); n->print_short(); lprintf("\n");
03248   }
03249 }
03250   
03251 # endif

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