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