split.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, LongView Technologies. $Revision: 1.6 $ */
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 COMPILER
00027 
00028 # include "incls/_split.cpp.incl"
00029 
00030   const uint32 SplitSig::LevelMask = 0xf;
00031 
00032   struct SplitSetting : StackObj {
00033     SplitSig*& sig;
00034     SplitSig* saved;
00035     SplitSetting(SplitSig*& oldsig, SplitSig* newsig) : sig(oldsig) {
00036       saved = oldsig; oldsig = newsig;
00037     }
00038     ~SplitSetting() { sig = saved; }
00039   };
00040 
00041   SplitSig* new_SplitSig(SplitSig* current, int splitID) {
00042     int level = current->level() + 1;
00043     assert(level <= MaxSplitDepth, "max. split level exceeded");
00044     uint32 newID = splitID << ((MaxSplitDepth - level + 1) << 2);
00045     SplitSig* sig =
00046       (SplitSig*)((uint32(current) & ~SplitSig::LevelMask) | newID | level);
00047     assert(current->contains(sig), "should be in same branch");
00048     return sig;
00049   }
00050 
00051   void SplitSig::print() {
00052     char buf[MaxSplitDepth + 1];
00053     lprintf("SplitSig %#lx: %s", this, prefix(buf));
00054   }
00055 
00056   char* SplitSig::prefix(char* buf) {
00057     // fill buf with an ASCII representation of the receiver and return buf
00058     // e.g. a level-2 sig with first branch = 1 and 2nd branch = 3 --> "AB"
00059     int l = level();
00060     buf[l--] = 0;
00061     uint32 sig = uint32(this) >> 4;
00062     while (l >= 0) {
00063       buf[l--] = 'A' + (sig & 0xf);
00064       sig = sig >> 4;
00065     }
00066     return buf;
00067   }
00068 
00069   // compiler code for splitting
00070 
00071   bool CodeScope::shouldSplit(SendInfo* info) {
00072     assert(info->rcvr->isMergeExpr(), "should be merge expr");
00073     MergeExpr* r = (MergeExpr*) info->rcvr;
00074     assert(r->isSplittable(), "should be splittable");
00075     if (!CompilerSplitting) return false;
00076     if (sig->level() == MaxSplitDepth) return false;
00077     Node* current = theNodeGen->current;
00078     if (!current->isSplittable()) return false;
00079 
00080     int cost = theCompiler->inlineLimit[SplitCostLimit];
00081     Node* n = NULL;
00082     // compute the cost of all nodes that would be copied (i.e. all exprs
00083     // with a map type)
00084     int i;
00085     for (i = 0; i < r->exprs->length(); i++) {
00086       Expr* expr = r->exprs->at(i);
00087       if (!expr->hasKlass()) continue;    // won't copy these
00088       InlinedScope* theScope = expr->node()->scope();
00089       int theBCI = expr->node()->bci();
00090       for (Expr* e = expr; e; e = e->next) {
00091         if (e->node()->scope() != theScope || e->node()->bci() != theBCI) {
00092           // make sure all subexpressions have the same scope
00093           // (otherwise can't describe live range of that value when split)
00094           // could fix this with better splitting (introduce temps to
00095           // "synchronize" the value's scopes)
00096           if (PrintInlining) {
00097             lprintf("%*s*not splitting %s: too complicated (scopes)\n",
00098                     depth, "", info->sel->copy_null_terminated());
00099           }
00100           r->setSplittable(false);      // no sense trying again
00101           return false;
00102         }
00103         Node* prev;
00104         for (n = e->node(); cost > 0 && n && n != current; n = n->next()) {
00105           cost -= n->cost();
00106           if (!n->isSplittable()) {
00107             if (PrintInlining) {
00108               lprintf("%*s*not splitting %s: unsplittable node\n",
00109                      depth, "", info->sel->copy_null_terminated());
00110             }
00111             return false;
00112           }
00113 #         ifdef ASSERT
00114             prev = n;       // for easier debugging
00115 #         endif
00116         }
00117         assert(n, "why didn't we find current?");
00118         if (n == NULL || cost < 0) goto done;
00119       }
00120     }
00121     
00122    done:
00123     if (n != current || cost < 0) {
00124       if (PrintInlining) {
00125         lprintf("%*s*not splitting %s: cost too high (>%ld)\n", depth, "",
00126                info->sel->copy_null_terminated(),
00127                theCompiler->inlineLimit[SplitCostLimit] - cost);
00128       }
00129       if (n == current) theCompiler->registerUninlinable(info, SplitCostLimit,cost);
00130       return false;
00131     }
00132     
00133     return true;
00134   }
00135 
00136   Expr* CodeScope::splitMerge(SendInfo* info, MergeNode*& merge) {
00137     // Split this send: copy nodes between sources of r's parts and the current
00138     // node, then inline the send along all paths; merge paths back at merge,
00139     // result in info->resReg.
00140     MergeExpr* r = (MergeExpr*)info->rcvr;
00141     assert(r->isSplittable(), "should be splittable");
00142 
00143     // performance bug - fix this: can't split on MergeExpr more than once
00144     // because after changing the CFG the old expr points to the wrong nodes.
00145     // For now, just prohibit future splitting on this expr.
00146     r->setSplittable(false);
00147     
00148     Expr* res = NULL;
00149     int ncases = r->exprs->length();
00150     memoizeBlocks(info->sel);
00151     if (PrintInlining) {
00152       lprintf("%*s*splitting %s\n", depth, "", selector_string(info->sel));
00153     }
00154     Node* current = theNodeGen->current;
00155     bool first = true;
00156     GrowableArray<oop>*  splitRcvrKlasss = new GrowableArray<oop>(10);// receiver map of each branch
00157     GrowableArray<PReg*>* splitRcvrs = new GrowableArray<PReg*>(10);    // receiver reg of each branch
00158     GrowableArray<Node*>* splitHeads = new GrowableArray<Node*>(10);    // first node of each branch
00159     bool needKlassLoad = false;
00160     
00161     for (int i = 0; i < ncases; i++) {
00162       Expr* nth = r->exprs->at(i);
00163       assert(!nth->isConstantExpr() || nth->next == NULL ||
00164              nth->constant() == nth->next->constant(),
00165              "shouldn't happen: merged consts - convert to map");
00166       InlinedScope* s;
00167       if (nth->hasKlass() &&
00168           (s = tryLookup(info, nth)) != NULL) {
00169         // Create a new PReg&Expr for the receiver so that it has the right
00170         // scope (the nodes will replace the old result reg with the new
00171         // one while they are copied).  
00172         // (Since we're splitting starting at the original producer, the
00173         // original result may be in an arbitrary subscope of the receiver
00174         // or even in a sibling.  For reg. allocation et al., the result
00175         // must have a PReg that's live from the producing point to here.)
00176         SplitSetting setting(theCompiler->splitSig, new_SplitSig(sig, i + 1));
00177         if (s->isCodeScope()) ((CodeScope*)s)->sig = theCompiler->splitSig;
00178         SplitPReg* newPR = coveringRegFor(nth, theCompiler->splitSig);
00179         Expr* newRcvr = nth->shallowCopy(newPR, nth->node());
00180         
00181         Node* mapMerge = new MergeNode;     // where all copied paths merge
00182         splitHeads->append(mapMerge);
00183         splitRcvrs->append(newPR);
00184         if (nth->isConstantExpr()) {
00185           splitRcvrKlasss->append(nth->constant());
00186         } else {
00187           splitRcvrKlasss->append(nth->klass());
00188           Klass* m = nth->klass()->addr();
00189           needKlassLoad |= m != smiKlassObj && m != doubleKlassObj;
00190         }
00191 
00192         // split off paths of all Exprs with this map up to merge point
00193         Node* rmerge = r->node();
00194         assert(rmerge, "should have a node");
00195         for (Expr* expr = nth; expr; expr = expr->next) {
00196           Node* n = expr->node();
00197           PReg* oldPR = expr->preg();
00198           assert(n->isSplittable(), "can't handle branches etc. yet");
00199           Node* frst = n->next();
00200           n->removeNext(frst);
00201           // replace n's destination or insert an assignment
00202           if (n->hasDest() && n->dest() == oldPR) {
00203             n->setDest(NULL, newPR);
00204           } else if (newPR) {
00205             n = n->append(new AssignNode(oldPR, newPR));
00206           }
00207           n = copyPath(n, frst, rmerge, oldPR, newPR, r, newRcvr);
00208           n = n->append(mapMerge);
00209         }
00210 
00211         // copy everything between mapMerge and current
00212         theNodeGen->current = copyPath(mapMerge, rmerge, current,
00213                                        NULL, NULL, r, newRcvr);
00214         
00215         // now inline the send
00216         Expr* e = doInline(s, newRcvr, theNodeGen->current, NULL);
00217         if (!e->isNoResultExpr()) {
00218           theNodeGen->append(new NopNode);
00219           e = e->shallowCopy(info->resReg, theNodeGen->current);
00220           res = res ? res->mergeWith(e, merge) : e;
00221         }
00222         theNodeGen->branch(merge);
00223       } else {
00224         // can't inline - need to append a real send after current
00225         if (!nth->isUnknownUnlikely()) info->needRealSend = true;
00226       }
00227     }
00228 
00229     UnknownExpr* u = r->findUnknown();
00230     if (u && splitRcvrKlasss->length() > 0) {
00231       // insert a type test after oldMerge (all unknown paths should meet
00232       // at that node)
00233       // Performance bug: the known-but-uninlinable sends will also go
00234       // through the type test; they should be redirected until after the
00235       // test.  The problem is that oldMerge may not be the actual merge
00236       // point but slightly later (i.e. a few InlinedReturns later).
00237       int diff;
00238       if (WizardMode && PrintInlining &&
00239           (diff = r->exprs->length() - splitRcvrKlasss->length()) > 1) {
00240         lprintf("*unnecessary %d-way type test for %d cases\n",
00241                splitRcvrKlasss->length(), diff);
00242       }
00243       Node* oldMerge = r->node();
00244       Node* oldNext = oldMerge->next();
00245       if (oldNext) oldMerge->removeNext(oldNext);
00246       PReg* pr = r->preg();
00247       Node* typeCase = new TypeTestNode(pr, splitRcvrKlasss, needKlassLoad, true);
00248       oldMerge->append(typeCase);
00249       if (info->needRealSend || !theCompiler->useUncommonTraps) {
00250         // connect fall-through (unknown) case to old merge point's successor
00251         info->needRealSend = true;
00252         if (oldNext) {
00253           typeCase->append(oldNext);
00254         } else {
00255           assert(current == oldMerge, "oops");
00256           current = typeCase->append(new NopNode);
00257         }
00258       } else {
00259         // make unknown case uncommon
00260         if (oldNext) {
00261           // must copy nodes between old merge point (i.e. end of the send
00262           // generating the receiver value) and current node; this code
00263           // computes the args of the current send
00264           theNodeGen->current = copyPath(typeCase, oldNext, current,
00265                                          NULL, NULL, r, u);
00266         } else {
00267           assert(current == oldMerge, "oops");
00268           theNodeGen->current = typeCase;
00269         }
00270         theNodeGen->uncommonBranch(currentExprStack(0), info->restartPrim);
00271         if (PrintInlining) {
00272           lprintf("%*s*making %s uncommon (3)\n",
00273                  depth, "", selector_string(info->sel));
00274         }
00275       }
00276       for (int j = 0; j < splitRcvrKlasss->length(); j++) {
00277         Node* n = new AssignNode(pr, splitRcvrs->at(j));
00278         typeCase->append(j + 1, n);
00279         n->append(splitHeads->at(j));
00280       }
00281     }
00282     if (info->needRealSend) {
00283       // The non-inlined send will be generated along the original (merged)
00284       // path, which will then branch to "merge".
00285       theNodeGen->current = current;
00286     } else {
00287       // discard the original path - can no longer reach it
00288       theNodeGen->current = merge;
00289     }
00290 
00291     if (res && res->isMergeExpr()) res->setNode(merge, info->resReg);
00292     return res;
00293   }
00294 
00295   Node* CodeScope::copyPath(Node* n, Node* start, Node* end,
00296                              PReg* oldPR, PReg* newPR,
00297                              MergeExpr* rcvr, Expr* newRcvr) {
00298     // copy the path from start to end, replacing occurrences of oldPR
00299     // with newPR; append copies to n, return last node
00300     if (CompilerDebug) {
00301       char* s = NEW_RESOURCE_ARRAY(char, 100);
00302       sprintf(s, "start of copied code: %#lx(N%d) --> %#lx(N%d) @ %#lx(N%d)",
00303               start, start->id(), end, end->id(), n, n->id());
00304       n = n->append(new CommentNode(s));
00305     } 
00306     assert(!oldPR || !oldPR->isBlockPReg(), "cannot handle BlockPRegs");
00307     for (Node* c = start; true; c = c->next()) {
00308       assert(c->isSplittable(), "can't handle branches yet");
00309       Node* copy = c->copy(oldPR, newPR);
00310       if (copy) n = n->append(copy);
00311       if (c == end) break;
00312     }
00313     if (CompilerDebug) n = n->append(new CommentNode("end of copied code"));
00314     return n;
00315   }
00316 
00317   SplitPReg* CodeScope::coveringRegFor(Expr* expr, SplitSig* sg) {
00318     // create a PReg with a live range covering all nodes between the
00319     // producer and the receiver scope/bci
00320     // see also SAPReg::isLiveAt
00321     InlinedScope* s = expr->node()->scope();
00322     int bci = expr->node()->bci();
00323     assert(s->isCodeScope(), "oops");
00324     SplitPReg* r = regCovering(this, _bci, (CodeScope*)s, bci, sg);
00325 #   ifdef ASSERT
00326       for (Expr* e = expr; e; e = e->next) {
00327         InlinedScope* s2 = e->node()->scope();
00328         int bci2 = e->node()->bci();
00329         assert(s2 == s, "oops");
00330         assert(bci2 == bci, "oops");
00331       }
00332 #   endif
00333     return r;
00334   }
00335 
00336 # endif

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