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
00027 #ifdef DELTA_COMPILER
00028
00029 #include "incls/_recompile.cpp.incl"
00030
00031 nmethod* recompilee = NULL;
00032 Recompilation* theRecompilation;
00033
00034 char* Recompilation::methodOop_invocation_counter_overflow(oop rcvr, methodOop method) {
00035
00036
00037
00038
00039
00040
00041
00042
00043 bool ok = false;
00044 if (Universe::is_heap((oop*)method)) {
00045 memOop obj = as_memOop(Universe::object_start((oop*) method));
00046 if (obj->is_method()) {
00047 ok = true;
00048 }
00049 }
00050 if (!ok) {
00051
00052
00053 char* msg = oop(method)->is_smi() ? "(method might be jump table entry)" : "";
00054 LOG_EVENT3("invocation counter overflow with broken methodOop 0x%x (recv = 0x%x) %s", method, rcvr, msg);
00055 fatal("invocation counter overflow with illegal method - internal error");
00056
00057
00058
00059 return NULL;
00060 }
00061
00062 if (UseRecompilation) {
00063 Recompilation recomp(rcvr, method);
00064 VMProcess::execute(&recomp);
00065 if (recomp.recompiledTrigger()) {
00066 return recomp.result();
00067 } else {
00068 return NULL;
00069 }
00070 } else {
00071 method->set_invocation_count(0);
00072 return NULL;
00073 }
00074 }
00075
00076
00077 char* Recompilation::nmethod_invocation_counter_overflow(oop rcvr, char* retpc) {
00078
00079
00080
00081 ResourceMark rm;
00082 nmethod* trigger = findNMethod(retpc);
00083 LOG_EVENT3("nmethod_invocation_counter_overflow: rcvr = %#x, pc = %#x (nmethod %#x)", rcvr, retpc, trigger);
00084 char* continuationAddr = trigger->verifiedEntryPoint();
00085 #ifdef ASSERT
00086 deltaVFrame* vf = DeltaProcess::active()->last_delta_vframe();
00087 assert(vf->is_compiled_frame() && ((compiledVFrame*)vf)->code() == trigger,
00088 "stack isn't set up right");
00089
00090 #endif
00091 if (UseRecompilation) {
00092 Recompilation recomp(rcvr, trigger);
00093 VMProcess::execute(&recomp);
00094 if (recomp.recompiledTrigger()) {
00095 continuationAddr = recomp.result();
00096 }
00097 } else {
00098
00099 trigger->set_invocation_count(1);
00100 }
00101 return continuationAddr;
00102 }
00103
00104
00105 nmethod* compile_method(LookupKey* key, methodOop m) {
00106 if (UseInliningDatabase && !m->is_blockMethod()) {
00107
00108
00109 RScope* rscope = InliningDatabase::lookup_and_remove(key);
00110 if (rscope) {
00111 VM_OptimizeRScope op(rscope);
00112 VMProcess::execute(&op);
00113 if (TraceInliningDatabase) {
00114 std->print_cr("Inlining database compile ");
00115 key->print_on(std);
00116 std->cr();
00117 }
00118 return op.result();
00119 }
00120 }
00121 VM_OptimizeMethod op(key, m);
00122 VMProcess::execute(&op);
00123 return op.result();
00124 }
00125
00126
00127 void Recompilation::init() {
00128 _newNM = NULL;
00129 _triggerVF = NULL;
00130 _recompiledTrigger = false;
00131 assert(!theRecompilation, "already set");
00132 theRecompilation = this;
00133 if (_method->is_blockMethod() && !isCompiled()) {
00134
00135
00136
00137 if (_rcvr->is_context()) {
00138 contextOop ctx = (contextOop)_rcvr;
00139 } else {
00140 assert(_rcvr == nilObj, "expected nil");
00141 }
00142 }
00143 }
00144
00145
00146 void Recompilation::doit() {
00147 ResourceMark rm;
00148 if (PrintRecompilation) {
00149 lprintf("recompilation trigger: %s (%#x)\n",
00150 _method->selector()->as_string(),
00151 isCompiled() ? (char*)_nm : (char*)_method);
00152 }
00153
00154 _triggerVF = calling_process()->last_delta_vframe();
00155
00156
00157 RFrame* first;
00158 if (isCompiled()) {
00159 first = new CompiledRFrame(_triggerVF->fr());
00160 } else {
00161 first = new InterpretedRFrame(_triggerVF->fr(), _method, _rcvr->klass());
00162 }
00163
00164 RecompilationPolicy policy(first);
00165 if (handleStaleInlineCache(first)) {
00166
00167 } else {
00168 Recompilee* r;
00169 if (_isUncommon) {
00170 assert(isCompiled(), "must be compiled");
00171 r = Recompilee::new_Recompilee(first);
00172 } else {
00173 r = policy.findRecompilee();
00174 }
00175 _recompiledTrigger = r != NULL && r->rframe() == first;
00176 if (r) {
00177 recompile(r);
00178 }
00179
00180 if (true || !_recompiledTrigger) {
00181
00182 if (isCompiled() && !_nm->isUncommonRecompiled()) {
00183
00184 _nm->set_invocation_count(1);
00185 } else {
00186 _method->set_invocation_count(1);
00187 }
00188 }
00189 }
00190 policy.cleanupStaleInlineCaches();
00191 recompilee = NULL;
00192 }
00193
00194 bool Recompilation::handleStaleInlineCache(RFrame* first) {
00195
00196 LookupKey* key = first->key();
00197 nmethod* nm;
00198 if (key && (nm = Universe::code->lookup(key)) != NULL) {
00199
00200 IC_Iterator* it = first->caller()->fr().current_ic_iterator();
00201 if (!it) return false;
00202 assert(it->selector() == key->selector(), "selector mismatch");
00203 while (!it->at_end() && it->klass() != key->klass()) it->advance();
00204 if (it->at_end()) {
00205
00206
00207 } else {
00208 nmethod* target = it->compiled_method();
00209 assert(!target || target == nm || target->key.equal(&nm->key), "inconsistent target");
00210 if (!target || target != nm) {
00211
00212
00213
00214 if (PrintRecompilation) {
00215 if (it->is_interpreted_ic()) {
00216 lprintf("replacing nm %#x in InterpretedIC %#x\n", nm, it->interpreted_ic());
00217 } else {
00218 lprintf("replacing nm %#x in CompiledIC %#x\n", nm, it->compiled_ic());
00219 }
00220 }
00221
00222
00223 if (it->is_interpreted_ic()) {
00224 it->interpreted_ic()->replace(nm);
00225 } else {
00226 it->compiled_ic()->replace(nm);
00227 }
00228
00229 _newNM = nm;
00230 return true;
00231 }
00232 }
00233 }
00234 return false;
00235 }
00236
00237
00238 oop Recompilation::receiverOf(deltaVFrame* vf) const {
00239 return _triggerVF->equal(vf) ? _rcvr : vf->receiver();
00240 }
00241
00242
00243 #ifdef HEAVY_CLEANUP
00244 class CleanupInlineCaches: public ObjectClosure {
00245 void do_object(memOop obj) {
00246 if (obj->is_method())
00247 methodOop(obj)->cleanup_inline_caches();
00248 }
00249 };
00250 #endif
00251
00252
00253 void Recompilation::recompile(Recompilee* r) {
00254
00255 recompilee = r->is_compiled() ? r->code() : NULL;
00256 if (r->rframe()->is_blockMethod()) {
00257 recompile_block(r);
00258 } else {
00259 recompile_method(r);
00260 }
00261
00262 if (_newNM == NULL) return;
00263
00264 if (recompilee) {
00265
00266 recompilee->clear_inline_caches();
00267 }
00268
00269
00270 recompilee = NULL;
00271
00272
00273 vframe* vf = r->rframe()->top_vframe();
00274 IC_Iterator* it = vf->fr().sender_ic_iterator();
00275 if (it) {
00276
00277 if (it->is_interpreted_ic()) {
00278 InterpretedIC* ic = it->interpreted_ic();
00279 if (!ic->is_empty()) ic->replace(_newNM);
00280 } else {
00281 CompiledIC* ic = it->compiled_ic();
00282 if (!ic->is_empty()) ic->replace(_newNM);
00283 }
00284 } else if (!_newNM->is_method()) {
00285
00286 } else {
00287
00288 }
00289
00290
00291 lookupCache::flush(&_newNM->key);
00292 DeltaCallCache::clearAll();
00293 }
00294
00295
00296 void Recompilation::recompile_method(Recompilee* r) {
00297
00298 LookupKey* key = r->key();
00299 methodOop m = r->method();
00300 #ifdef ASSERT
00301 LookupResult res = lookupCache::lookup(key);
00302 assert(res.method() == m, "mismatched method");
00303 #endif
00304 _newNM = Universe::code->lookup(key);
00305
00306 if (_newNM == NULL || _newNM == recompilee) {
00307 if (recompilee && !recompilee->isZombie()) recompilee->unlink();
00308 _newNM = compile_method(key, m);
00309 if (recompilee && !recompilee->isZombie()) recompilee->makeZombie(true);
00310 #ifdef HEAVY_CLEANUP
00311 static int count;
00312 if (count++ > 10) {
00313 count = 0;
00314 TraceTime t("*cleaning inline caches...", PrintRecompilation2);
00315 CleanupInlineCaches blk;
00316 Universe::object_iterate(&blk);
00317 Universe::code->cleanup_inline_caches();
00318 }
00319 #endif
00320 } else {
00321 recompilee = NULL;
00322 }
00323 }
00324
00325
00326 void Recompilation::recompile_block(Recompilee* r) {
00327 assert(r->rframe()->is_blockMethod(), "must be block recompilation");
00328 if (recompilee == NULL) {
00329
00330
00331
00332 compiler_warning("recompilee == NULL when recompile_block is called, possibly internal error");
00333
00334 _newNM = NULL;
00335 return;
00336 }
00337 assert(recompilee != NULL, "must have block recompilee");
00338
00339 deltaVFrame* vf = r->rframe()->top_vframe();
00340 oop block;
00341 if (recompilee && recompilee->is_block()) {
00342 deltaVFrame* sender = vf->sender_delta_frame();
00343 if (sender == NULL) return;
00344 GrowableArray<oop>* exprs = sender->expression_stack();
00345
00346 int nargs = recompilee->method()->nofArgs();
00347 block = exprs->at(nargs);
00348 } else {
00349 block = receiverOf(vf);
00350 }
00351 assert(block->is_block(), "must be a block");
00352 _newNM = jumpTable::compile_block(blockClosureOop(block));
00353 if (recompilee != NULL) recompilee->makeZombie(true);
00354 }
00355
00356
00357 Recompilee* Recompilee::new_Recompilee(RFrame* rf) {
00358 if (rf->is_compiled()) {
00359 return new CompiledRecompilee(rf, ((CompiledRFrame*)rf)->nm());
00360 } else {
00361 InterpretedRFrame* irf = (InterpretedRFrame*)rf;
00362
00363 assert(irf->key() != NULL, "must have a key");
00364 return new InterpretedRecompilee(irf, irf->key(), irf->top_method());
00365 }
00366 }
00367
00368 LookupKey* CompiledRecompilee::key() const { return &_nm->key; }
00369 methodOop CompiledRecompilee::method() const { return _nm->method(); }
00370
00371 #else
00372
00373 extern "C" void invocation_counter_overflow(oop receiver, methodOop method) {
00374 fatal("performance bug: shouldn't count invocations");
00375 }
00376
00377 #endif