00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 # include "incls/_precompiled.incl"
00024
00025 # ifdef COMPILER
00026
00027 # include "incls/_inline.cpp.incl"
00028
00029 static int msgCost = 0;
00030
00031
00032 void CodeScope::memoizeBlocks(symbolOop sel) {
00033
00034 int top = exprStack->length();
00035 int argc = sel->arg_count();
00036 for (int i = 1; i <= argc; i++) {
00037 PReg* r = exprStack->nth(top - i)->preg();
00038 if (r->isBlockPReg()) ((BlockPReg*)r)->memoize();
00039 }
00040 }
00041
00042 int InlinedScope::calleeSize(RScope* rs) {
00043
00044 if (!rs->isPICScope()) return 0;
00045 RPICScope* ps = (RPICScope*)rs;
00046 nmethod* inlinee = ps->nm;
00047 if (inlinee->compiler() == NIC) {
00048 return 0;
00049 }
00050 int size = inlinee->instsLen() - oopSize * PrologueSize;
00051 if (inlinee->isUncommonRecompiled()) {
00052
00053
00054 size /= 2;
00055 }
00056 return size;
00057 }
00058
00059 bool CodeScope::calleeTooBig(SendInfo* info, RScope* rs,
00060 InlineLimitType limitType) {
00061
00062 int size = calleeSize(rs);
00063
00064 assert(limitType >= NormalFnLimit && limitType <= BlockFnLimit,
00065 "bad limit");
00066 limitType = InlineLimitType(limitType + NormalFnInstrLimit-NormalFnLimit);
00067 int cutoff = theCompiler->inlineLimit[limitType];
00068 int estimated = theCompiler->estimatedSize();
00069 int limit = theCompiler->inlineLimit[NmInstrLimit];
00070
00071 bool bad = size > cutoff &&
00072 !(info->rcvr->hasKlass() &&
00073 isCheapMessage(info->sel, info->rcvr->klass()));
00074 if (bad && estimated + size < limit / 2) {
00075
00076 if (recompilee &&
00077 recompilee->instsLen() - oopSize * PrologueSize < cutoff) {
00078 bad = false;
00079 }
00080 }
00081
00082
00083 bad = bad || estimated + size >= limit;
00084 if (bad &&
00085 estimated + size < 2 * limit &&
00086 (size == 0 || size < cutoff / 8) &&
00087 info->rcvr->hasKlass() &&
00088 isReallyCheapMessage(info->sel, info->rcvr->klass())) {
00089 bad = false;
00090 }
00091 if (bad && PrintInlining) {
00092 lprintf("%*s*not inlining %s: callee too big (%d/%d/%d/%d)\n", depth, "",
00093 selector_string(info->sel), size, cutoff, estimated, limit);
00094 }
00095 if (CompilerDebug && bad && estimated > limit)
00096 warning("Compiler: (while compiling %s/%s) estimated nmethod size > limit (%ld > %ld)",
00097 selector_string(theCompiler->key->L.selector),
00098 selector_string(info->sel), estimated, limit);
00099 return bad;
00100 }
00101
00102 bool CodeScope::calleeIsSmall(SendInfo* info, RScope* rs,
00103 InlineLimitType limitType) {
00104
00105 int size = calleeSize(rs);
00106 if (!size) return false;
00107 assert(limitType >= NormalFnLimit && limitType <= BlockFnLimit,
00108 "bad limit");
00109 limitType = InlineLimitType(limitType + NormalFnInstrLimit-NormalFnLimit);
00110 int cutoff = theCompiler->inlineLimit[limitType];
00111 int estimated = theCompiler->estimatedSize();
00112 int limit = theCompiler->inlineLimit[NmInstrLimit];
00113 bool ok = size <= cutoff && estimated + size < limit;
00114 if (ok && PrintInlining) {
00115 lprintf("%*s*inlining %s anyway: callee is small (%d/%d/%d/%d)\n",
00116 depth, "", selector_string(info->sel),
00117 size, cutoff, estimated, limit);
00118 }
00119 return ok;
00120 }
00121
00122 bool CodeScope::shouldInlineSend(SendInfo* info, RScope* rs, Expr* rcvr,
00123 oop m, InlineLimitType limitType) {
00124 LookupKey* L = info->L;
00125 if (!L->selector->is_string()) return false;
00126
00127 if (isRecursiveCall(m, L->receiverKlass, MaxRecursionUnroll)) {
00128 info->uninlinable = true;
00129 return false;
00130 }
00131
00132 if (limitType == NormalFnLimit) {
00133
00134 int top = exprStack->length();
00135 int argc = symbolOop(L->selector)->arg_count();
00136 for (int i = argc; i > 0; i--) {
00137 if (exprStack->nth(top - i)->preg()->isBlockPReg()) {
00138 limitType = BlockArgFnLimit;
00139 goto done;
00140 }
00141 }
00142
00143 if (lookupReceiverIsDelta(L->lookupType)) {
00144 if (self->preg()->isBlockPReg()) limitType = BlockArgFnLimit;
00145 } else if (exprStack->nth(top - argc - 1)->preg()->isBlockPReg()) {
00146 limitType = BlockArgFnLimit;
00147 }
00148 }
00149
00150 done:
00151 if (calleeTooBig(info, rs, limitType)) {
00152
00153 theCompiler->registerUninlinable(info, limitType, 9999);
00154 return false;
00155 }
00156
00157
00158
00159 if (isCheapMessage(symbolOop(L->selector))) {
00160 msgCost = costP->cheapSendCost;
00161 return true;
00162 }
00163
00164 int cutoff = theCompiler->inlineLimit[limitType];
00165 msgCost = sicCost((methodKlass*)m->klass(), this, costP);
00166 if (info->primFailure &&
00167 info->nsends < MinPrimFailureInvocations) {
00168 if (rs->isPICScope() && ((RPICScope*)rs)->sd->isOptimized()) {
00169
00170 } else if (rs->isInlinedScope()) {
00171
00172 } else {
00173
00174 if (msgCost > MaxTrivialPrimFailureCost) return false;
00175
00176 Klass* map = rcvr->klass()->addr();
00177 if (map->is_block()) {
00178 memOop method = ((blockKlass*)map)->value();
00179 msgCost = sicCost((methodKlass*)method->klass(), this, failCostP);
00180
00181
00182
00183
00184 if (msgCost > MaxTrivialPrimFailureCost) return false;
00185 }
00186 }
00187 }
00188 if (msgCost > cutoff) {
00189 if (calleeIsSmall(info, rs, limitType)) return true;
00190 theCompiler->registerUninlinable(info, limitType, msgCost);
00191 return false;
00192 }
00193 return true;
00194 }
00195
00196 bool CodeScope::shouldInlineBlock(SendInfo* info, RScope* rs,
00197 Expr* rcvr, oop method) {
00198 return shouldInlineSend(info, rs, rcvr, method, BlockFnLimit);
00199 }
00200
00201 bool CodeScope::shouldInlineMethod(SendInfo* info, RScope* rs,
00202 Expr* rcvr, oop meth) {
00203 return shouldInlineSend(info, rs, rcvr, meth, NormalFnLimit);
00204 }
00205
00206 Expr* CodeScope::picPredictUnlikely(SendInfo* info,
00207 RUntakenScope* uscope) {
00208 if (theCompiler->useUncommonTraps &&
00209 info->primFailure && uscope->isUnlikely()) {
00210
00211
00212
00213
00214
00215
00216
00217
00218 info->nsends = 0;
00219 const int MinSends = MinPrimFailureInvocations;
00220 int count = uscope->caller->invocationCount();
00221 if (count <= 0) {
00222
00223 count = MinSends + 1;
00224 }
00225 bool makeUncommon = count >= MinSends && uscope->sd->wasNeverExecuted();
00226 if (PrintInlining) {
00227 lprintf("%*s*%sPIC-type-predicting %s as never executed\n",
00228 depth, "", makeUncommon ? "" : "NOT ",
00229 info->sel->copy_null_terminated());
00230 }
00231 if (makeUncommon) {
00232 return new UnknownExpr(info->rcvr->preg(), NULL, true);
00233 }
00234 }
00235 return info->rcvr;
00236 }
00237
00238 Expr* CodeScope::picPredict(SendInfo* info) {
00239
00240 if (!UsePICRecompilation) return info->rcvr;
00241 bool canBeUnlikely = theCompiler->useUncommonTraps;
00242 if (rscope->hasSubScopes(_bci)) {
00243 RScopeBList* l = rscope->subScopes(_bci);
00244 if (l->first()->isUntakenScope() && l->length() == 1) {
00245 return picPredictUnlikely(info, (RUntakenScope*)l->first());
00246 } else if (info->rcvr->containsUnknown()) {
00247 if (PrintInlining) {
00248 lprintf("%*s*PIC-type-predicting %s (%ld maps)\n", depth, "",
00249 info->sel->copy_null_terminated(), l->length());
00250 }
00251 for (int i = 0; i < l->length(); i++) {
00252 RScope* r = l->nth(i);
00253 Expr* expr = r->receiverExpr();
00254 if (expr->isUnknownExpr()) {
00255
00256 } else if (expr->klass()->addr()->is_block()) {
00257
00258
00259 if (PrintInlining) {
00260 lprintf("%*s*not predicting block map\n", depth, "");
00261 }
00262 canBeUnlikely = false;
00263 } else {
00264 Expr* alreadyThere = info->rcvr->findKlass(expr->klass());
00265 if (alreadyThere) {
00266
00267 if (alreadyThere->isConstantExpr())
00268 info->rcvr = info->rcvr->mergeWith(expr, NULL);
00269 } else {
00270
00271 info->predicted = true;
00272 info->rcvr = info->rcvr->mergeWith(expr, NULL);
00273 if (expr->hasConstant() && l->length() == 1) {
00274
00275
00276
00277
00278 oop c = expr->constant();
00279 if (c == Memory->trueObj &&
00280 !info->rcvr->findKlass(as_klassOop(Memory->falseObj->klass()))) {
00281 Expr* f = new ConstantExpr(Memory->falseObj, NULL, NULL);
00282 info->rcvr = info->rcvr->mergeWith(f, NULL);
00283 } else if (c == Memory->falseObj &&
00284 !info->rcvr->findKlass(as_klassOop(Memory->trueObj->klass()))) {
00285 Expr* t = new ConstantExpr(Memory->trueObj, NULL, NULL);
00286 info->rcvr = info->rcvr->mergeWith(t, NULL);
00287 }
00288 }
00289 }
00290 }
00291 }
00292 } else {
00293
00294 return info->rcvr;
00295 }
00296
00297 UnknownExpr* u = info->rcvr->findUnknown();
00298 if (u && canBeUnlikely && theCompiler->useUncommonTraps &&
00299 rscope->isUncommonAt(_bci, false)) {
00300 info->rcvr = info->rcvr->makeUnknownUnlikely(this);
00301 }
00302 } else if (theCompiler->useUncommonTraps &&
00303 info->primFailure &&
00304 rscope->isUncommonAt(_bci, true)) {
00305
00306
00307
00308 if (PrintInlining) {
00309 lprintf("%*s*PIC-type-predicting %s as never executed (2)\n",
00310 depth, "", info->sel->copy_null_terminated());
00311 }
00312 info->rcvr = new UnknownExpr(info->rcvr->preg(), NULL, true);
00313 }
00314
00315 assert(info->rcvr->preg(), "should have a preg");
00316 return info->rcvr;
00317 }
00318
00319 Expr* CodeScope::typePredict(SendInfo* info) {
00320
00321 PReg* r = info->rcvr->preg();
00322 symbolOop sel = info->sel;
00323 if (sel == VMString[IF_TRUE_] ||
00324 sel == VMString[IF_FALSE_] ||
00325 sel == VMString[IF_TRUE_FALSE_] ||
00326 sel == VMString[IF_FALSE_TRUE_] ||
00327 sel == VMString[OR] || sel == VMString[AND] || sel == VMString[NOT]) {
00328
00329 if (PrintInlining) {
00330 lprintf("%*s*type-predicting %s\n", depth, "",
00331 sel->copy_null_terminated());
00332 }
00333 info->predicted = true;
00334 bool allowUnlikely = theCompiler->useUncommonTraps;
00335 if (CompilerDeferUncommonBranches &&
00336 (sel == VMString[IF_TRUE_] ||
00337 sel == VMString[IF_FALSE_] ||
00338 sel == VMString[IF_TRUE_FALSE_] ||
00339 sel == VMString[IF_FALSE_TRUE_])) {
00340
00341
00342
00343 allowUnlikely = true;
00344 }
00345 if (allowUnlikely) {
00346 if (rscope->isUncommonAt(_bci, false)) {
00347
00348 } else if (rscope->hasSubScopes(_bci)) {
00349
00350
00351 RScopeBList* subs = rscope->subScopes(_bci);
00352 for (int i = subs->length() - 1; i >= 0; i--) {
00353 RScope* s = subs->nth(i);
00354 Expr* rcvr = s->receiverExpr();
00355 if (rcvr->hasKlass()) {
00356 Klass* m = rcvr->klass()->addr();
00357 if (m != Memory->trueObj->klass() &&
00358 m != Memory->falseObj->klass()) {
00359 allowUnlikely = false;
00360 break;
00361 }
00362 }
00363 }
00364 if (WizardMode && !allowUnlikely)
00365 warning("Compiler: non-bool receiver for ifTrue: et al. detected");
00366 }
00367 if (allowUnlikely) {
00368
00369 info->rcvr = info->rcvr->makeUnknownUnlikely(this);
00370 }
00371 }
00372 Expr* rcvr = info->rcvr;
00373 Expr* t = new ConstantExpr(Memory->trueObj , r, NULL);
00374 Expr* f = new ConstantExpr(Memory->falseObj, r, NULL);
00375
00376
00377 if (rcvr->findKlass(as_klassOop(Memory->trueObj->klass())) == NULL)
00378 d135 1
00379 a135 1
00380 if (rcvr->findKlass(as_klassOop(Memory->falseObj->klass())) == NULL)
00381 d141 7
00382 # endif