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 DELTA_COMPILER
00027
00028 # include "incls/_inliner.cpp.incl"
00029
00030
00031
00032 #ifdef later
00033 static const int DefaultCompilerMaxSplitCost = 50;
00034 static const int DefaultCompilerMaxBlockInstrSize = 400;
00035 static const int DefaultCompilerMaxFnInstrSize = 250;
00036 static const int DefaultCompilerMaxBlockFnInstrSize = 600;
00037 static const int DefaultCompilerMaxNmethodInstrSize = 5000;
00038 #endif
00039
00040 static CompilerInliningPolicy inliningPolicy;
00041
00042 bool InliningPolicy::shouldNotInline() const {
00043 if (method->method_inlining_info() == methodOopDesc::never_inline) return true;
00044 const symbolOop sel = method->selector();
00045 return (sel == vmSymbols::error() ||
00046 sel == vmSymbols::error_() ||
00047 sel == vmSymbols::subclassResponsibility());
00048 }
00049
00050 bool InliningPolicy::isCriticalSmiSelector(const symbolOop sel) {
00051
00052
00053 return sel == vmSymbols::plus() ||
00054 sel == vmSymbols::minus() ||
00055 sel == vmSymbols::multiply() ||
00056 sel == vmSymbols::divide() ||
00057 sel == vmSymbols::mod() ||
00058 sel == vmSymbols::equal() ||
00059 sel == vmSymbols::not_equal() ||
00060 sel == vmSymbols::less_than() ||
00061 sel == vmSymbols::less_than() ||
00062 sel == vmSymbols::less_than_or_equal() ||
00063 sel == vmSymbols::greater_than() ||
00064 sel == vmSymbols::greater_than_or_equal() ||
00065 sel == vmSymbols::double_equal() ||
00066 sel == vmSymbols::bitAnd_() ||
00067 sel == vmSymbols::bitOr_() ||
00068 sel == vmSymbols::bitXor_() ||
00069 sel == vmSymbols::bitShift_() ||
00070 sel == vmSymbols::bitInvert();
00071 }
00072
00073 bool InliningPolicy::isCriticalArraySelector(const symbolOop sel) {
00074 return sel == vmSymbols::at() ||
00075 sel == vmSymbols::at_put() ||
00076 sel == vmSymbols::size();
00077 }
00078
00079 bool InliningPolicy::isCriticalBoolSelector(const symbolOop sel) {
00080 return sel == vmSymbols::and_() ||
00081 sel == vmSymbols::or_() ||
00082 sel == vmSymbols::and() ||
00083 sel == vmSymbols::or() ||
00084 sel == vmSymbols::and1() ||
00085 sel == vmSymbols::or1() ||
00086 sel == vmSymbols::and() ||
00087 sel == vmSymbols::not() ||
00088 sel == vmSymbols::xor_() ||
00089 sel == vmSymbols::eqv_();
00090 }
00091
00092 bool InliningPolicy::isPredictedSmiSelector(const symbolOop sel) {
00093 return sel != vmSymbols::equal() &&
00094 sel != vmSymbols::not_equal() &&
00095 isCriticalSmiSelector(sel);
00096 }
00097
00098 bool InliningPolicy::isPredictedArraySelector(const symbolOop sel) {
00099 return isCriticalArraySelector(sel);
00100 }
00101 bool InliningPolicy::isPredictedBoolSelector(const symbolOop sel) {
00102 return isCriticalBoolSelector(sel);
00103 }
00104
00105 bool InliningPolicy::isInterpreterPredictedSmiSelector(const symbolOop sel) {
00106
00107
00108 return sel == vmSymbols::plus() ||
00109 sel == vmSymbols::minus() ||
00110 sel == vmSymbols::multiply() ||
00111 sel == vmSymbols::divide() ||
00112 sel == vmSymbols::mod() ||
00113 sel == vmSymbols::equal() ||
00114 sel == vmSymbols::not_equal() ||
00115 sel == vmSymbols::less_than() ||
00116 sel == vmSymbols::less_than() ||
00117 sel == vmSymbols::less_than_or_equal() ||
00118 sel == vmSymbols::greater_than() ||
00119 sel == vmSymbols::greater_than_or_equal();
00120 }
00121
00122 bool InliningPolicy::isInterpreterPredictedArraySelector(const symbolOop sel) {
00123 return false;
00124 }
00125
00126 bool InliningPolicy::isInterpreterPredictedBoolSelector(const symbolOop sel) {
00127 return false;
00128 }
00129
00130
00131
00132 bool InliningPolicy::isBuiltinMethod() const {
00133
00134
00135 if (method->method_inlining_info() == methodOopDesc::always_inline) return true;
00136 const symbolOop sel = method->selector();
00137 const klassOop klass = receiverKlass();
00138 const bool isNum = klass == Universe::smiKlassObj() || klass == Universe::doubleKlassObj();
00139 if (isNum && isCriticalSmiSelector(sel)) return true;
00140
00141 const bool isArr = klass == Universe::objArrayKlassObj() ||
00142 klass == Universe::byteArrayKlassObj() ||
00143 klass == Universe::symbolKlassObj() ||
00144 false;
00145 if (isArr && isCriticalArraySelector(sel)) return true;
00146
00147 const bool isBool = klass == Universe::trueObj()->klass() || klass == Universe::falseObj()->klass();
00148 if (isBool && isCriticalBoolSelector(sel)) return true;
00149 return false;
00150 }
00151
00152 char* CompilerInliningPolicy::shouldInline(InlinedScope* s, InlinedScope* callee) {
00153 if (callee == NULL) {
00154 return "cannot handle super sends";
00155 }
00156
00157 if (callee->rscope->isDatabaseScope()) {
00158
00159
00160 return NULL;
00161 }
00162
00163 if (s->rscope->isDatabaseScope()) {
00164
00165
00166 return "do not inline (Inlining Database)";
00167 }
00168
00169
00170 sender = s;
00171 this->method = callee->method();
00172 this->rcvr = callee->self();
00173 if (NodeFactory::cumulCost > MaxNmInstrSize) {
00174 theCompiler->reporter->report_toobig(callee);
00175 return "method getting too big";
00176 }
00177 if (shouldNotInline()) return "should not inline (special)";
00178
00179
00180
00181 if (sender->isRecursiveCall(method, callee->selfKlass(), MaxRecursionUnroll)) return "recursive";
00182 return basic_shouldInline(method);
00183 }
00184
00185 char* InliningPolicy::basic_shouldInline(methodOop method) {
00186
00187 if (method->method_inlining_info() == methodOopDesc::always_inline) return NULL;
00188 calleeCost = method->estimated_inline_cost(receiverKlass());
00189
00190 if (method->is_blockMethod()) {
00191
00192 int parentCost = method->parent()->estimated_inline_cost(receiverKlass());
00193 assert(parentCost > calleeCost, "must be higher");
00194 if (float(parentCost - calleeCost) / parentCost * 100.0 < MinBlockCostFraction) return NULL;
00195 }
00196
00197
00198 int cost_limit = method->is_blockMethod() ? MaxBlockInlineCost : MaxFnInlineCost;
00199 for (int i = method->number_of_arguments() - 1; i >= 0; i--) {
00200 klassOop k = nthArgKlass(i);
00201 if (k && k->klass_part()->oop_is_block()) cost_limit += BlockArgAdditionalAllowedInlineCost;
00202 }
00203 if (calleeCost < cost_limit) return NULL;
00204 if (isBuiltinMethod()) return NULL;
00205 return "too big";
00206 }
00207
00208 klassOop CompilerInliningPolicy::nthArgKlass(int i) const {
00209 int first = sender->exprStack()->length() - method->number_of_arguments();
00210 Expr* e = sender->exprStack()->at(first + i);
00211 return e->hasKlass() ? e->klass() : NULL;
00212 }
00213
00214 klassOop CompilerInliningPolicy::receiverKlass() const { return rcvr->klass(); }
00215
00216 klassOop RecompilerInliningPolicy::nthArgKlass(int i) const { return _vf ? _vf->argument_at(i)->klass() : NULL; }
00217 klassOop RecompilerInliningPolicy::receiverKlass() const {
00218 return _vf ? theRecompilation->receiverOf(_vf)->klass() : NULL;
00219 }
00220
00221 char* RecompilerInliningPolicy::shouldInline(RFrame* rf) {
00222
00223
00224
00225
00226
00227
00228 extern bool SuperSendsAreAlwaysInlined;
00229 assert(SuperSendsAreAlwaysInlined, "fix this");
00230 if (rf->is_super()) return NULL;
00231
00232 _vf = rf->top_vframe();
00233 this->method = rf->top_method();
00234 nmethod* nm = NULL;
00235 if (rf->is_interpreted()) {
00236
00237 LookupKey* key = rf->key();
00238 if (key) {
00239 nm = Universe::code->lookup(key);
00240 } else {
00241
00242
00243 }
00244 } else {
00245 assert(rf->is_compiled(), "oops");
00246 nm = ((CompiledRFrame*)rf)->nm();
00247 }
00248 if (nm) {
00249 return shouldInline(nm);
00250 } else {
00251 return basic_shouldInline(method);
00252 }
00253 }
00254
00255 char* RecompilerInliningPolicy::shouldInline(nmethod* nm) {
00256 if (!CodeSizeImpactsInlining) return NULL;
00257 if (method->method_inlining_info() == methodOopDesc::always_inline) return NULL;
00258
00259 int cost_limit = method->is_blockMethod() ? MaxBlockInstrSize : MaxFnInstrSize;
00260 int i = method->number_of_arguments();
00261 while (i-- > 0) {
00262 klassOop k = nthArgKlass(i);
00263 if (k && k->klass_part()->oop_is_block()) cost_limit += BlockArgAdditionalInstrSize;
00264 }
00265 if (nm->size() < cost_limit) return NULL;
00266 if (isBuiltinMethod()) return NULL;
00267 return "too big (compiled)";
00268 }
00269
00270
00271
00272 void Inliner::initialize() {
00273 _info = NULL;
00274 res = NULL;
00275 callee = NULL;
00276 gen = NULL;
00277 merge = NULL;
00278 resultPR = NULL;
00279 depth = 0;
00280 _msg = NULL;
00281 lastLookupFailed = false;
00282 }
00283
00284 void Inliner::initialize(SendInfo* info, SendKind kind) {
00285 initialize();
00286 _info = info;
00287 this->kind = kind;
00288 sender = _info->senderScope;
00289 gen = sender->gen();
00290 _info->resReg = resultPR = new SAPReg(sender);
00291 depth = sender->depth;
00292 }
00293
00294 Expr* Inliner::inlineNormalSend(SendInfo* info) {
00295 initialize(info, NormalSend);
00296 return inlineSend();
00297 }
00298
00299 Expr* Inliner::inlineSuperSend(SendInfo* info) {
00300 initialize(info, SuperSend);
00301 return inlineSend();
00302 }
00303
00304 Expr* Inliner::inlineSelfSend(SendInfo* info) {
00305 initialize(info, SelfSend);
00306 return inlineSend();
00307 }
00308
00309 Expr* Inliner::inlineSend() {
00310 if (!Inline) {
00311
00312 _info->needRealSend = true;
00313 } else if (gen->is_in_dead_code()) {
00314
00315 res = new NoResultExpr;
00316 gen->abort();
00317 if (CompilerDebug) cout(PrintInlining)->print("%*s*skipping %s (dead code)\n", depth, "", _info->sel->as_string());
00318 } else {
00319 tryInlineSend();
00320 }
00321
00322
00323 if (_info->needRealSend) {
00324 Expr* r = genRealSend();
00325 res = res ? res->mergeWith(r, merge) : r;
00326 assert(res, "must have result");
00327 }
00328
00329 if (merge && res && !res->isNoResultExpr()) gen->branch(merge);
00330
00331
00332 if (gen != sender->gen()) sender->gen()->setCurrent(gen->current());
00333
00334
00335 if (!res) res = new NoResultExpr;
00336 return res;
00337 }
00338
00339 Expr* Inliner::genRealSend() {
00340 const int nofArgs = _info->sel->number_of_arguments();
00341 bool uninlinable = theCompiler->registerUninlinable(this);
00342 if (CompilerDebug) {
00343 cout(PrintInlining)->print("%*s*sending %s %s%s\n", depth, "", _info->sel->as_string(),
00344 uninlinable ? "(unlinlinable) " : "",
00345 _info->counting ? "(counting) " : "");
00346 }
00347 switch(kind) {
00348 case NormalSend: gen->gen_normal_send(_info, nofArgs, resultPR); break;
00349 case SelfSend: gen->gen_self_send (_info, nofArgs, resultPR); break;
00350 case SuperSend: gen->gen_super_send (_info, nofArgs, resultPR); break;
00351 default: fatal1("illegal SendKind %d", kind);
00352 }
00353 return new UnknownExpr(resultPR, gen->current());
00354 }
00355
00356 void Inliner::tryInlineSend() {
00357 const symbolOop sel = _info->sel;
00358
00359 UnknownExpr* u = _info->rcvr->findUnknown();
00360 bool usingInliningDB = sender->rscope->isDatabaseScope();
00361
00362 if (TypeFeedback && u) {
00363 assert(kind != SuperSend, "shouldn't PIC-predict super sends");
00364
00365
00366 _info->rcvr = picPredict();
00367 }
00368
00369
00370 if (TypePredict && !usingInliningDB && u && !u->isUnlikely() && !_info->uninlinable) {
00371 _info->rcvr = typePredict();
00372 }
00373
00374 if (_info->rcvr->really_hasKlass(sender)) {
00375
00376 callee = tryLookup(_info->rcvr);
00377 if (callee) {
00378 Expr* r = doInline(sender->current());
00379 res = makeResult(r);
00380 } else {
00381
00382 if (lastLookupFailed) {
00383
00384 _info->receiverStatic = true;
00385 }
00386 _info->needRealSend = true;
00387 }
00388 } else if (_info->rcvr->isMergeExpr()) {
00389 res = inlineMerge(_info);
00390 if (res) {
00391
00392 if (!theCompiler->is_uncommon_compile()) {
00393 _info->uninlinable = true;
00394 _info->counting = false;
00395 }
00396 } else {
00397
00398 _info->needRealSend = true;
00399 }
00400 } else {
00401
00402
00403
00404 if (CompilerDebug) cout(PrintInlining)->print("%*s*cannot inline %s (unknown receiver)\n", depth, "", sel->as_string());
00405 if (_info->rcvr->findUnknown()->isUnlikely()) {
00406
00407 gen->append_exit(NodeFactory::new_UncommonNode(sender->gen()->copyCurrentExprStack(), sender->bci()));
00408 _info->needRealSend = false;
00409 if (CompilerDebug) cout(PrintInlining)->print("%*s*making %s uncommon\n", depth, "", sel->as_string());
00410 res = new NoResultExpr();
00411
00412 assert(gen->current() == NULL, "expected no current node");
00413 gen->abort();
00414 } else {
00415 _info->needRealSend = true;
00416 }
00417 }
00418 }
00419
00420
00421 Expr* Inliner::inlineMerge(SendInfo* info) {
00422
00423 merge = NodeFactory::new_MergeNode(sender->bci());
00424 Expr* res = NULL;
00425 assert(info->rcvr->isMergeExpr(), "must be a merge");
00426 MergeExpr* r = (MergeExpr*)info->rcvr;
00427 symbolOop sel = info->sel;
00428
00429 int nexprs = r->exprs->length();
00430 int ncases = nexprs - (r->containsUnknown() ? 1 : 0);
00431 if (ncases > MaxTypeCaseSize) {
00432 info->needRealSend = true;
00433 info->uninlinable = true;
00434 info->counting = false;
00435 if (CompilerDebug) cout(PrintInlining)->print("%*s*not type-casing %s (%ld > MaxTypeCaseSize)\n",
00436 depth, "", sel->as_string(), ncases);
00437 return res;
00438 }
00439
00440
00441
00442 GrowableArray<InlinedScope*>* scopes = new GrowableArray<InlinedScope*>(nexprs);
00443 GrowableArray<InlinedScope*>* scopes2 = new GrowableArray<InlinedScope*>(nexprs);
00444 GrowableArray<Expr*>* exprs = new GrowableArray<Expr*>(nexprs);
00445 GrowableArray<Expr*>* exprs2 = new GrowableArray<Expr*>(nexprs);
00446 GrowableArray<Expr*>* others = new GrowableArray<Expr*>(nexprs);
00447 GrowableArray<klassOop>* klasses = new GrowableArray<klassOop>(nexprs);
00448 GrowableArray<klassOop>* klasses2= new GrowableArray<klassOop>(nexprs);
00449 const bool containsUnknown = r->containsUnknown();
00450
00451 for (int i = 0; i < nexprs; i++) {
00452 Expr* nth = r->exprs->at(i)->shallowCopy(r->preg(), NULL);
00453 assert(!nth->isConstantExpr() || nth->next == NULL ||
00454 nth->constant() == nth->next->constant(),
00455 "shouldn't happen: merged consts - convert to klass");
00456
00457
00458
00459 if (containsUnknown && nth->isConstantExpr()) {
00460 nth = nth->convertToKlass(nth->preg(), nth->node());
00461 }
00462
00463 InlinedScope* s;
00464 if (nth->hasKlass() &&
00465 (s = tryLookup(nth)) != NULL) {
00466
00467 klassOop klass = nth->klass();
00468 if (klass == smiKlassObj) {
00469 scopes ->append(s);
00470 exprs ->append(nth);
00471 klasses ->append(klass);
00472 } else {
00473 scopes2 ->append(s);
00474 exprs2 ->append(nth);
00475 klasses2->append(klass);
00476 }
00477 } else {
00478 if (lastLookupFailed) {
00479
00480
00481
00482 if (others->isEmpty()) {
00483 others->append(new UnknownExpr(nth->preg(), NULL, theCompiler->useUncommonTraps));
00484 }
00485 } else {
00486 others->append(nth);
00487 }
00488 info->needRealSend = true;
00489 }
00490 }
00491
00492
00493 klasses->appendAll(klasses2);
00494 exprs ->appendAll(exprs2);
00495 scopes ->appendAll(scopes2);
00496
00497
00498
00499
00500 bool useUncommonBranchForUnknown = false;
00501 if (others->length() == 1 && others->first()->isUnknownExpr() &&
00502 ((UnknownExpr*)others->first())->isUnlikely()) {
00503
00504 useUncommonBranchForUnknown = true;
00505 if (CompilerDebug) cout(PrintInlining)->print("%*s*making %s uncommon (2)\n", depth,"",sel->as_string());
00506 }
00507
00508
00509 Node* typeCase = NULL;
00510 Node* fallThrough = NULL;
00511 if (scopes->length() > 0) {
00512
00513
00514 if (CompilerDebug) {
00515 char* s = NEW_RESOURCE_ARRAY(char, 200);
00516 sprintf(s, "begin type-case of %s (ends at node N%ld)",
00517 sel->copy_null_terminated(), merge->id());
00518 gen->comment(s);
00519 }
00520 if (CompilerDebug) cout(PrintInlining)->print("%*s*type-casing %s (%d cases)\n", depth, "", sel->as_string(), scopes->length());
00521
00522 typeCase = NodeFactory::new_TypeTestNode(r->preg(), klasses, info->needRealSend || containsUnknown);
00523 gen->append(typeCase);
00524 fallThrough = typeCase->append(NodeFactory::new_NopNode());
00525 for (i = 0; i < scopes->length(); i++) {
00526
00527 Inliner* inliner = new Inliner(sender);
00528 inliner->initialize(new SendInfo(*info), kind);
00529 inliner->callee = scopes->at(i);
00530 inliner->gen = callee->gen();
00531 inliner->gen->setCurrent(typeCase->append(i + 1, NodeFactory::new_NopNode()));
00532 Expr* rcvr = exprs->at(i);
00533 inliner->info()->rcvr = rcvr;
00534 assert(r->scope()->isSenderOf(inliner->callee), "r must be from caller scope");
00535 Expr* e = inliner->doInline(inliner->gen->current());
00536 if (e->isNoResultExpr()) {
00537 if (!res) res = e;
00538 } else {
00539 assert(e->preg()->scope()->isSenderOf(inliner->callee),
00540 "result register must be from caller scope");
00541 gen->append(NodeFactory::new_NopNode());
00542 e = e->shallowCopy(info->resReg, gen->current());
00543 res = res ? res->mergeWith(e, merge) : e;
00544 }
00545 gen->branch(merge);
00546 }
00547 assert(gen == sender->gen(), "oops");
00548 gen->setCurrent(fallThrough);
00549 } else {
00550
00551 if (!info->counting && !theCompiler->is_uncommon_compile()) info->uninlinable = true;
00552 useUncommonBranchForUnknown = false;
00553 }
00554
00555 if (res && res->isMergeExpr()) res->setNode(merge, info->resReg);
00556
00557 assert( info->needRealSend && others->length() ||
00558 !info->needRealSend && !others->length(), "inconsistent");
00559
00560 if (useUncommonBranchForUnknown) {
00561
00562 gen->append_exit(NodeFactory::new_UncommonNode(gen->copyCurrentExprStack(), sender->bci()));
00563 info->needRealSend = false;
00564 } else if (others->isEmpty()) {
00565
00566 gen->append_exit(NodeFactory::new_FixedCodeNode(FixedCodeNode::dead_end));
00567 }
00568
00569 return res;
00570 }
00571
00572
00573 Expr* Inliner::makeResult(Expr* r) {
00574 Expr* res;
00575
00576 if (r->isNoResultExpr()) {
00577 res = r;
00578 } else {
00579
00580 if (r->scope() == sender) {
00581 res = r;
00582 } else {
00583 assert(r->scope() == callee, "what scope?");
00584
00585 ShouldNotReachHere();
00586
00587 Node* n = NodeFactory::new_NopNode();
00588 assert(n->scope() == sender, "wrong scope");
00589 gen->append(n);
00590 res = r->shallowCopy(r->preg(), n);
00591 }
00592 }
00593 return res;
00594 }
00595
00596 Expr* Inliner::doInline(Node* start) {
00597
00598
00599 #define calleeSize(n) 0
00600
00601 if (CompilerDebug) {
00602 cout(PrintInlining)->print("%*s*inlining %s, cost %ld/size %ld (%#lx)%s\n", depth, "",
00603 callee->selector()->as_string(), inliningPolicy.calleeCost, calleeSize(callee->rscope),
00604 PrintHexAddresses ? callee : 0, callee->rscope->isNullScope() ? "" : "*");
00605 if (PrintInlining) callee->method()->pretty_print();
00606 }
00607
00608
00609 theCompiler->rec->add_dependant(callee->key());
00610
00611 Node* next = start->next();
00612 assert(!next, "can't insert code (?)");
00613
00614
00615 gen = callee->gen();
00616 gen->setCurrent(start);
00617 callee->genCode();
00618
00619
00620 gen = sender->gen();
00621 gen->setCurrent(callee->returnPoint());
00622 assert(gen->current()->next() == NULL, "shouldn't have successor");
00623 return callee->result;
00624 }
00625
00626 Expr* Inliner::picPredict() {
00627
00628 const int bci = sender->bci();
00629 RScope* rscope = sender->rscope;
00630
00631 if (!rscope->hasSubScopes(bci)) {
00632
00633
00634
00635 return _info->rcvr;
00636 }
00637
00638
00639 GrowableArray<RScope*>* l = sender->rscope->subScopes(sender->bci());
00640
00641
00642 if (l->length() == 1) {
00643 if (l->first()->isUntakenScope()) {
00644
00645 return picPredictUnlikely(_info, (RUntakenScope*)l->first());
00646 } else if (l->first()->isUninlinableScope()) {
00647 if (CompilerDebug)
00648 cout(PrintInlining)->print("%*s*PIC-predicting %s as uninlinable/megamorphic\n", depth, "", _info->sel->as_string());
00649 _info->uninlinable = true;
00650 return _info->rcvr;
00651 }
00652 }
00653
00654
00655 if (!_info->rcvr->containsUnknown()) {
00656 return _info->rcvr;
00657 }
00658
00659
00660 GrowableArray<Expr*> klasses(5);
00661 MergeExpr* allKlasses = new MergeExpr(_info->rcvr->preg(), NULL);
00662 for (int i = 0; i < l->length(); i++) {
00663 RScope* r = l->at(i);
00664 Expr* expr = r->receiverExpr(_info->rcvr->preg());
00665 if (expr->isUnknownExpr()) {
00666
00667
00668 assert(((UnknownExpr*)expr)->isUnlikely(), "performance bug: should make unknown unlikely");
00669 continue;
00670 }
00671 klasses.append(expr);
00672 allKlasses = (MergeExpr*)allKlasses->mergeWith(expr, NULL);
00673 }
00674
00675
00676
00677 int npic = klasses.length();
00678 int nstatic = _info->rcvr->nklasses();
00679 if (npic != 0 && _info->rcvr->isMergeExpr()) {
00680 Expr* newRcvr = _info->rcvr;
00681 for (int i = ((MergeExpr*)_info->rcvr)->exprs->length() - 1; i >= 0; i--) {
00682 Expr* e = ((MergeExpr*)_info->rcvr)->exprs->at(i);
00683 if (e->isUnknownExpr()) continue;
00684 if (!allKlasses->findKlass(e->klass())) {
00685 if (PrintInlining) {
00686 std->print("%*s*discarding static type info for send %s (not found in PIC): ",
00687 depth, "", _info->sel->as_string());
00688 e->print();
00689 }
00690 newRcvr = newRcvr->copyWithout(e);
00691 }
00692 }
00693 _info->rcvr = newRcvr;
00694 }
00695
00696 if (CompilerDebug)
00697 cout(PrintInlining)->print("%*s*PIC-type-predicting %s (%ld klasses): ", depth, "",
00698 _info->sel->as_string(), npic);
00699
00700
00701 for (i = 0; i < klasses.length(); i++) {
00702 Expr* expr = klasses.at(i);
00703
00704 if (CompilerDebug) {
00705 #ifndef PRODUCT // otherwise we get a syntax error (C++ compiler bug?) - gri 11/28/01
00706 expr->klass()->klass_part()->print_name_on(cout(PrintInlining));
00707 cout(PrintInlining)->print(" ");
00708 #endif
00709 }
00710 Expr* alreadyThere = _info->rcvr->findKlass(expr->klass());
00711
00712
00713 if (alreadyThere) {
00714
00715 if (alreadyThere->isConstantExpr()) {
00716 _info->rcvr = _info->rcvr->mergeWith(expr, NULL);
00717 }
00718 } else {
00719 _info->predicted = true;
00720 _info->rcvr = _info->rcvr->mergeWith(expr, NULL);
00721 if (expr->hasConstant() && klasses.length() == 1) {
00722
00723
00724
00725
00726 oop c = expr->constant();
00727 PReg* p = _info->rcvr->preg();
00728 if (c == trueObj && !_info->rcvr->findKlass(falseObj->klass())) {
00729 Expr* f = new ConstantExpr(falseObj, p, NULL);
00730 _info->rcvr = _info->rcvr->mergeWith(f, NULL);
00731 } else if (c == falseObj && !_info->rcvr->findKlass(trueObj->klass())) {
00732 Expr* t = new ConstantExpr(trueObj, p, NULL);
00733 _info->rcvr = _info->rcvr->mergeWith(t, NULL);
00734 }
00735 }
00736 }
00737 }
00738 if (CompilerDebug) cout(PrintInlining)->print("\n");
00739
00740
00741 UnknownExpr* u = _info->rcvr->findUnknown();
00742 const bool canBeUnlikely = theCompiler->useUncommonTraps;
00743 if (u && canBeUnlikely && !rscope->isNotUncommonAt(bci)) {
00744 _info->rcvr = _info->rcvr->makeUnknownUnlikely(sender);
00745 }
00746
00747 assert(_info->rcvr->preg(), "should have a preg");
00748 return _info->rcvr;
00749 }
00750
00751 Expr* Inliner::picPredictUnlikely(SendInfo* info, RUntakenScope* uscope) {
00752 if (!theCompiler->useUncommonTraps) return info->rcvr;
00753
00754 bool makeUncommon = uscope->isUnlikely();
00755 if (!makeUncommon && info->inPrimFailure) {
00756
00757
00758
00759
00760
00761
00762
00763
00764 makeUncommon = false;
00765 }
00766 if (false && CompilerDebug) {
00767 cout(PrintInlining)->print("%*s*%sPIC-type-predicting %s as never executed\n",
00768 depth, "", makeUncommon ? "" : "NOT ",
00769 info->sel->copy_null_terminated());
00770 }
00771 if (makeUncommon) {
00772 return new UnknownExpr(info->rcvr->preg(), NULL, true);
00773 } else {
00774 return info->rcvr;
00775 }
00776 }
00777
00778 Expr* Inliner::typePredict() {
00779
00780 Expr* r = _info->rcvr;
00781 if (!(r->isUnknownExpr() ||
00782 r->isMergeExpr() &&
00783 ((MergeExpr*)r)->exprs->length() == 1 &&
00784 ((MergeExpr*)r)->exprs->at(0)->isUnknownExpr())) {
00785
00786
00787
00788
00789 return _info->rcvr;
00790 }
00791
00792
00793 if (InliningPolicy::isPredictedSmiSelector(_info->sel)) {
00794 r = r->mergeWith(new KlassExpr(smiKlassObj, r->preg(), NULL), NULL);
00795 } else if (InliningPolicy::isPredictedArraySelector(_info->sel)) {
00796
00797 if (TypePredictArrays) {
00798 r = r->mergeWith(new KlassExpr(Universe::objArrayKlassObj(), r->preg(), NULL), NULL);
00799 } else {
00800 return r;
00801 }
00802 } else if (InliningPolicy::isPredictedBoolSelector(_info->sel)) {
00803 r = r->mergeWith(new ConstantExpr(trueObj, r->preg(), NULL), NULL);
00804 r = r->mergeWith(new ConstantExpr(falseObj, r->preg(), NULL), NULL);
00805 } else {
00806 return r;
00807 }
00808
00809
00810 if (theCompiler->useUncommonTraps) {
00811
00812 r = r->makeUnknownUnlikely(sender);
00813 }
00814 return r;
00815 }
00816
00817 extern bool SuperSendsAreAlwaysInlined = true;
00818
00819 InlinedScope* Inliner::tryLookup(Expr* rcvr) {
00820
00821
00822
00823
00824 assert(rcvr->hasKlass(), "should know klass");
00825
00826 const klassOop klass = (kind == SuperSend) ? sender->methodHolder() : rcvr->klass();
00827 if (klass == NULL) {
00828 _info->uninlinable = true;
00829 assert(kind == SuperSend, "shouldn't happen for normal sends");
00830 return notify("super send in Object");
00831 }
00832
00833 const symbolOop selector = _info->sel;
00834 const methodOop method = (kind == SuperSend) ?
00835 lookupCache::compile_time_super_lookup (klass, selector) :
00836 lookupCache::compile_time_normal_lookup(klass, selector);
00837 lastLookupFailed = method == NULL;
00838
00839 if (lastLookupFailed) {
00840
00841 _info->uninlinable = true;
00842 return notify("lookup failed");
00843 }
00844
00845
00846 LookupKey* key = kind == SuperSend
00847 ? LookupKey::allocate(rcvr->klass(), method)
00848 : LookupKey::allocate(rcvr->klass(), selector);
00849
00850 if (CompilerDebug) cout(PrintInlining)->print("%*s found %s --> %#x\n", sender->depth, "", key->print_string(), PrintHexAddresses ? method : 0);
00851
00852
00853
00854 InlinedScope* callee = makeScope(rcvr, rcvr->klass(), key, method);
00855 assert(kind != SuperSend || callee != NULL, "Super send must be inlined");
00856
00857 _msg = inliningPolicy.shouldInline(sender, callee);
00858 if (kind == SuperSend) {
00859
00860
00861 SuperSendsAreAlwaysInlined = true;
00862 assert(!_info->predicted, "shouldn't PIC-predict super sends");
00863 _msg = NULL;
00864 } else {
00865 if (_msg == NULL && sender->gen()->in_prim_failure_block()) {
00866 _msg = checkSendInPrimFailure();
00867 }
00868 }
00869 if (_msg) return notify(_msg);
00870
00871 return callee;
00872 }
00873
00874 char* Inliner::checkSendInPrimFailure() {
00875
00876
00877 RScope* rs = sender->rscope;
00878 if (rs->isNullScope() || rs->isInterpretedScope()) {
00879
00880
00881 if (UseRecompilation) _info->counting = true;
00882 return "send in primitive failure (null/interpreted sender)";
00883 }
00884 RScope* callee = rs->subScope(sender->bci(), _info->key);
00885 if (callee->isUntakenScope()) {
00886
00887
00888
00889 if (WizardMode) warning("probably should have made primitive failure uncommon");
00890 return "untaken send in primitive failure";
00891 }
00892 if (callee->isInlinedScope()) {
00893
00894 return NULL;
00895 }
00896 if (callee->isNullScope()) {
00897
00898 return "untaken send in primitive failure (NullScope)";
00899 }
00900
00901 return NULL;
00902 }
00903
00904 RScope* Inliner::makeBlockRScope(const Expr* rcvr, LookupKey* key, const methodOop method) {
00905
00906 if (!TypeFeedback) return new RNullScope;
00907 if (!rcvr->preg()->isBlockPReg()) {
00908 return new RNullScope;
00909 }
00910
00911
00912 const int senderBCI = sender->bci();
00913 GrowableArray<RScope*>* subScopes = sender->rscope->subScopes(senderBCI);
00914 if (subScopes->length() == 1 && subScopes->first()->method() == method) {
00915 RScope* rs = subScopes->first();
00916 assert(rs->method() == method, "mismatched block methods");
00917 return rs;
00918 }
00919
00920
00921
00922 InlinedScope* parent = rcvr->preg()->scope();
00923 RScope* rparent = parent->rscope;
00924 const int level = rparent->isNullScope() ? 1 : ((RNonDummyScope*)rparent)->level();
00925 if (rparent->isCompiled()) {
00926
00927 nmethod* parentNM = rparent->get_nmethod();
00928
00929 int blockIndex = 0;
00930 for (blockIndex = parentNM->number_of_noninlined_blocks(); blockIndex >= 1; blockIndex--) {
00931 if (parentNM->noninlined_block_method_at(blockIndex) == method &&
00932 checkSenderPath(parent, parentNM->noninlined_block_scope_at(blockIndex)->parent())) {
00933 break;
00934 }
00935 }
00936 if (blockIndex >= 1) {
00937
00938 jumpTableEntry* jte = parentNM->noninlined_block_jumpEntry_at(blockIndex);
00939 if (jte->is_nmethod_stub()) {
00940
00941 nmethod* blockNM = jte->method();
00942 assert(blockNM->method() == method, "method mismatch");
00943 return new RInlinedScope(NULL, senderBCI, blockNM, blockNM->scopes()->root(), level);
00944 } else {
00945
00946 return new RInterpretedScope(NULL, senderBCI, key, method, level, true);
00947 }
00948 } else {
00949
00950 assert(sender->rscope->isNullScope() || sender->rscope->isLite(), "should have found subscope");
00951 return new RInterpretedScope(NULL, senderBCI, key, method, level, true);
00952 }
00953 } else {
00954
00955 return new RInterpretedScope(NULL, senderBCI, key, method, level, true);
00956 }
00957 }
00958
00959
00960 bool Inliner::checkSenderPath(Scope* here, ScopeDesc* there) const {
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 while (here && !there->isTop()) {
00971 InlinedScope* sen = here->sender();
00972 if (sen == NULL) break;
00973 if (sen->bci() != there->senderBCI()) return false;
00974 here = here->sender();
00975 there = there->sender();
00976 }
00977 return true;
00978 }
00979
00980
00981 InlinedScope* Inliner::makeScope(const Expr* rcvr, const klassOop klass, const LookupKey* key, const methodOop method) {
00982
00983 SendInfo* calleeInfo = new SendInfo(*_info);
00984 calleeInfo->key = (LookupKey*) key;
00985 const klassOop methodHolder = klass->klass_part()->lookup_method_holder_for(method);
00986
00987 if (method->is_blockMethod()) {
00988 RScope* rs = makeBlockRScope(rcvr, calleeInfo->key, method);
00989 # ifdef ASSERT
00990 bool isNullRScope = rs->isNullScope();
00991 # endif
00992 if (rcvr->preg()->isBlockPReg()) {
00993 InlinedScope* parent = rcvr->preg()->scope();
00994 calleeInfo->rcvr = parent->self();
00995 callee = BlockScope::new_BlockScope(method, methodHolder, parent, sender, rs, calleeInfo);
00996 callee->set_self(parent->self());
00997 } else {
00998
00999 return notify("block parent in different nmethod");
01000 }
01001 } else {
01002
01003 RScope* rs = sender->rscope->subScope(sender->bci(), calleeInfo->key);
01004 # ifdef ASSERT
01005 bool isNullRScope = rs->isNullScope();
01006 # endif
01007 callee = MethodScope::new_MethodScope(method, methodHolder, sender, rs, calleeInfo);
01008 callee->set_self(rcvr->asReceiver());
01009 }
01010
01011 return callee;
01012 }
01013
01014 InlinedScope* Inliner::notify(const char* msg) {
01015 if (CompilerDebug) {
01016 cout(PrintInlining)->print("%*s*cannot inline %s, cost = %ld (%s)\n", depth, "", _info->sel->as_string(),
01017 inliningPolicy.calleeCost, msg);
01018 }
01019 _msg = (char*)msg;
01020 return NULL;
01021 }
01022
01023 void Inliner::print() {
01024 std->print("((Inliner*)%#x)\n", PrintHexAddresses ? this : 0);
01025 }
01026
01027 Expr* Inliner::inlineBlockInvocation(SendInfo* info) {
01028 initialize(info, NormalSend);
01029 Expr* blockExpr = info->rcvr;
01030 assert(blockExpr->preg()->isBlockPReg(), "must be a BlockPR");
01031 const BlockPReg* block = (BlockPReg*)blockExpr->preg();
01032 const methodOop method = block->closure()->method();
01033 const InlinedScope* parent = block->closure()->parent_scope();
01034
01035 if (CompilerDebug) cout(PrintInlining)->print("%*s*inlining block invocation\n", sender->depth, "");
01036
01037
01038 LookupKey* key = LookupKey::allocate(parent->selfKlass(), method);
01039
01040 makeScope(blockExpr, parent->selfKlass(), key, method);
01041 if (callee) {
01042 Expr* r = doInline(sender->current());
01043 return makeResult(r);
01044 } else {
01045 return NULL;
01046 }
01047 }
01048
01049 # endif