00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 # include "incls/_precompiled.incl"
00025 
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     
00058     
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   
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     
00083     
00084     int i;
00085     for (i = 0; i < r->exprs->length(); i++) {
00086       Expr* expr = r->exprs->at(i);
00087       if (!expr->hasKlass()) continue;    
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           
00093           
00094           
00095           
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);      
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;       
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     
00138     
00139     
00140     MergeExpr* r = (MergeExpr*)info->rcvr;
00141     assert(r->isSplittable(), "should be splittable");
00142 
00143     
00144     
00145     
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);
00157     GrowableArray<PReg*>* splitRcvrs = new GrowableArray<PReg*>(10);    
00158     GrowableArray<Node*>* splitHeads = new GrowableArray<Node*>(10);    
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         
00170         
00171         
00172         
00173         
00174         
00175         
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;     
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         
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           
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         
00212         theNodeGen->current = copyPath(mapMerge, rmerge, current,
00213                                        NULL, NULL, r, newRcvr);
00214         
00215         
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         
00225         if (!nth->isUnknownUnlikely()) info->needRealSend = true;
00226       }
00227     }
00228 
00229     UnknownExpr* u = r->findUnknown();
00230     if (u && splitRcvrKlasss->length() > 0) {
00231       
00232       
00233       
00234       
00235       
00236       
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         
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         
00260         if (oldNext) {
00261           
00262           
00263           
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       
00284       
00285       theNodeGen->current = current;
00286     } else {
00287       
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     
00299     
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     
00319     
00320     
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