00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 # include "incls/_precompiled.incl"
00026 #ifdef DELTA_COMPILER
00027 
00028 #include "incls/_recompiler.cpp.incl"
00029 
00030 RecompilationPolicy::RecompilationPolicy(RFrame* first) {
00031   stack = new GrowableArray<RFrame*>(50);
00032   stack->push(first);
00033 }
00034 
00035 
00036 Recompilee* RecompilationPolicy::findRecompilee() {
00037   RFrame* rf = stack->at(0);
00038   if (PrintRecompilation2) {
00039     for (int i = 0; i < 10 && rf; i++, rf = senderOf(rf)) ;   
00040     printStack();
00041   }
00042   RFrame* r = findTopInlinableFrame();
00043   if (r) {
00044     if (PrintRecompilation) r->print();
00045     return Recompilee::new_Recompilee(r);
00046   } else {
00047     return NULL;
00048   }
00049 }
00050 
00051 void RecompilationPolicy::cleanupStaleInlineCaches() {
00052   int len = min(20, stack->length());
00053   for (int i = 0; i < len; i++) stack->at(i)->cleanupStaleInlineCaches();
00054 }
00055 
00056 RFrame* RecompilationPolicy::findTopInlinableFrame() {
00057   
00058   RecompilerInliningPolicy p;
00059   RFrame* current = stack->at(0);       
00060   RFrame* prev = NULL;                  
00061   RFrame* prevMethod = NULL;            
00062   msg = NULL; 
00063   
00064   while (1) {
00065     if (current == NULL) {
00066       
00067       current = prev; 
00068       break;
00069     }
00070 
00071     if ((msg = p.shouldInline(current)) != NULL) {
00072       
00073       break;
00074     }
00075 
00076     
00077     RFrame* next = senderOrParentOf(current);
00078 
00079     if (next) {
00080       if (next->num() > MaxRecompilationSearchLength) {
00081         
00082         msg = "(don't go up any further: next > MaxRecompilationSearchLength)";
00083         break;
00084       }
00085       if (next->distance() > MaxInterpretedSearchLength) {
00086         
00087         msg = "(don't go up any further: next > MaxInterpretedSearchLength)";
00088         break;
00089       }
00090       if (current->is_interpreted()) {
00091         
00092         
00093         
00094         
00095         LookupKey* k = next->key();
00096         if (next->is_compiled()) {
00097           msg = "(not going up into optimized code)";
00098           break;
00099         } else if (k != NULL && Universe::code->lookup(k) != NULL) {
00100           msg = "(already compiled this method)";
00101           break;
00102         } 
00103       }
00104       if (next->is_compiled() && (msg = shouldNotRecompileNMethod(next->nm())) != NULL) {
00105         msg = "nmethod should not be recompiled; don't go up";
00106         break;
00107       }
00108       if (next->is_compiled() && next->sends() < MinSendsBeforeRecompile) {
00109         msg = "don't recompile -- hasn't sent MinSendsBeforeRecompile messages yet";
00110         if (PrintRecompilation && msg) current->print();
00111         break;
00112       }
00113     }
00114     prev = current;
00115     
00116     if (!current->is_blockMethod()) prevMethod = current;
00117     current = next;
00118   }
00119 
00120   if (current) checkCurrent(current, prev, prevMethod);
00121 
00122   if (PrintRecompilation && msg) lprintf("%s\n", msg);
00123 
00124   return current;
00125 }
00126 
00127 void RecompilationPolicy::checkCurrent(RFrame*& current, RFrame*& prev, RFrame*& prevMethod) {
00128   
00129   if (current->is_blockMethod() && current->is_interpreted()) {
00130     
00131     
00132     if (PrintRecompilation && msg) lprintf("%s\n", msg);
00133     fixBlockParent(current);
00134     if (prev && !prev->is_blockMethod()) {
00135       current = prev; prev = prevMethod = NULL;
00136       if (current) checkCurrent(current, prev, prevMethod);
00137       msg = "(can't recompile block in isolation)";
00138     } else {
00139       current = NULL;
00140       msg = "(can't recompile block in isolation, and no callee method found)";
00141     }
00142   } else if (current->is_super()) {
00143     current = prev; prev = prevMethod = NULL;
00144     if (current) checkCurrent(current, prev, prevMethod);
00145     msg = "(can't recompile super nmethods yet)";
00146   } else if (current->is_compiled()) {
00147     char* msg2;
00148     if ((msg2 = shouldNotRecompileNMethod(current->nm())) != NULL) {
00149       current = NULL;
00150       msg = msg2;
00151     } else {
00152       
00153       msg = NULL;
00154     }
00155   }
00156   if (current == NULL) return;      
00157 
00158   
00159   
00160   if (current->is_compiled()) {
00161     if (EnableOptimizedCodeRecompilation) {
00162       LookupKey* k          = current->key();
00163       nmethod*   running_nm = current->nm();
00164       nmethod*   newest_nm  = k ? Universe::code->lookup(k) : NULL;
00165       
00166       if (k && running_nm && running_nm->is_method() && running_nm != newest_nm) {
00167         
00168         
00169         
00170         current = prevMethod; prev = prevMethod = NULL;
00171         if (current) checkCurrent(current, prev, prevMethod);
00172       }
00173     } else {
00174       current = NULL;
00175     }
00176   }
00177 }
00178 
00179 char* RecompilationPolicy::shouldNotRecompileNMethod(nmethod* nm) {
00180   
00181   if (nm->isUncommonRecompiled()) {
00182     if (RecompilationPolicy::shouldRecompileUncommonNMethod(nm)) {
00183       nm->makeOld();
00184       return NULL;        
00185     } else {
00186       return "uncommon nmethod too young";
00187     }
00188   } else if (nm->version() >= MaxVersions) {
00189     return "max. version reached";
00190   } else if (nm->level() == MaxRecompilationLevels - 1) {
00191     return "maximally optimized";
00192   } else if (nm->isYoung()) {
00193     return "nmethod too young";
00194   }
00195   return NULL;
00196 }
00197 
00198 RFrame* RecompilationPolicy::senderOf(RFrame* rf) {
00199   RFrame* sender = rf->caller();
00200   if (sender && sender->num() == stack->length()) stack->push(sender);
00201   return sender;
00202 }
00203 
00204 void RecompilationPolicy::fixBlockParent(RFrame* rf) {
00205   
00206   methodOop blk = rf->top_method();
00207   assert(blk->is_blockMethod(), "must be a block");
00208   methodOop home = blk->home();
00209   int count = home->invocation_count();
00210   count += Interpreter::get_invocation_counter_limit();
00211   count = min(count, methodOopDesc::_invocation_count_max - 1);
00212   home->set_invocation_count(count);
00213   assert(home->invocation_count() >= Interpreter::get_invocation_counter_limit(),
00214          "counter increment didn't work");
00215 }
00216 
00217 RFrame* RecompilationPolicy::senderOrParentOf(RFrame* rf) {
00218   
00219   
00220   
00221   if (rf->is_blockMethod()) {
00222     RFrame* parent = parentOf(rf);
00223     if (parent == NULL) {
00224       
00225       fixBlockParent(rf);
00226       return senderOf(rf);      
00227       
00228       
00229       
00230       
00231       
00232     } else {
00233       if (parent->is_compiled() == rf->is_compiled()) {
00234         
00235         if (CountParentLinksAsOne) parent->set_distance(rf->distance() + 1);
00236         return parent;
00237       } else {
00238         return senderOf(rf);    
00239       }
00240     }
00241   } else if (rf->hasBlockArgs()) {
00242     
00243     
00244     GrowableArray<blockClosureOop>* blockArgs = rf->blockArgs();
00245     RFrame* max = NULL;
00246     for (int i = 0; i < blockArgs->length(); i++) {
00247       blockClosureOop blk = blockArgs->at(i);
00248       
00249       RFrame* home = parentOfBlock(blk);
00250       if (home == NULL) continue;
00251       if (max == NULL || home->num() > max->num()) max = home;
00252     }
00253     if (max) return max;
00254   }
00255   
00256   return senderOf(rf);
00257 }
00258 
00259 RFrame* RecompilationPolicy::parentOf(RFrame* rf) {
00260   assert(rf->is_blockMethod(), "shouldn't call");
00261   
00262   
00263   
00264 
00265   
00266   
00267   
00268   
00269   
00270   
00271   
00272 
00273   deltaVFrame* sender = rf->top_vframe()->sender_delta_frame();  
00274   if (sender == NULL) return NULL;
00275 
00276   oop blk = sender->receiver();
00277   guarantee(blk->is_block(), "should be a block");
00278   return parentOfBlock(blockClosureOop(blk));
00279 }
00280 
00281 RFrame* RecompilationPolicy::parentOfBlock(blockClosureOop blk) {
00282   if (blk->is_pure()) return NULL;
00283   
00284   contextOop ctx = blk->lexical_scope();
00285   assert(ctx->is_context(), "make sure we have a context");
00286 
00287   int* fp = ctx->parent_fp();
00288   if (fp == NULL) {
00289     return NULL;        
00290   } 
00291   
00292   RFrame* parent = stack->first();
00293   for (int i = 0; i < MaxRecompilationSearchLength; i++ ) {
00294     parent = senderOf(parent);
00295     if (!parent) break;
00296     frame fr = parent->fr();
00297     if (fr.fp() == fp) return parent;   
00298   }
00299   return NULL;    
00300 }
00301 
00302 
00303 void RecompilationPolicy::printStack() {        
00304   for (int i = 0; i < stack->length(); i++ ) stack->at(i)->print();
00305 }
00306 
00307 bool RecompilationPolicy::needRecompileCounter(Compiler* c) {
00308   if (!UseRecompilation) return false;
00309   if (c->version() == MaxVersions) return false;    
00310   
00311   
00312   
00313   
00314   return c->level() < MaxRecompilationLevels - 1;
00315 }
00316 
00317 bool RecompilationPolicy::shouldRecompileAfterUncommonTrap(nmethod* nm) {
00318   
00319   
00320   return nm->uncommon_trap_counter() >= UncommonRecompileLimit;
00321 }
00322 
00323 bool RecompilationPolicy::shouldRecompileUncommonNMethod(nmethod* nm) {
00324   assert(nm->isUncommonRecompiled(), "expected an uncommon nmethod");
00325   
00326   
00327   
00328   
00329   
00330   
00331   
00332   
00333   
00334   const int v = nm->version();
00335   const int c = nm->invocation_count();
00336   return  c >= uncommonNMethodInvocationLimit(v) ||
00337          (c >= UncommonInvocationLimit && nm->age() > uncommonNMethodAgeLimit(v));
00338 }
00339 
00340 int RecompilationPolicy::uncommonNMethodInvocationLimit(int version) {
00341   int n = UncommonInvocationLimit;
00342   for (int i = 0; i < version; i++) n *= UncommonAgeBackoffFactor;
00343   return n;
00344 }
00345 
00346 int RecompilationPolicy::uncommonNMethodAgeLimit(int version) {
00347   int n = NMethodAgeLimit;
00348   for (int i = 0; i < version; i++) n *= UncommonAgeBackoffFactor;
00349   return n;
00350 }
00351 
00352 #endif