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 # include "incls/_lookupCache.cpp.incl"
00026
00027 int lookupCache::number_of_primary_hits;
00028 int lookupCache::number_of_secondary_hits;
00029 int lookupCache::number_of_misses;
00030
00031 methodOop LookupResult::method() const {
00032 assert(!is_empty(), "connot be empty");
00033 if (is_method())
00034 return methodOop(_result);
00035 return get_nmethod()->method();
00036 }
00037
00038 methodOop LookupResult::method_or_null() const {
00039 if (is_empty()) return NULL;
00040 if (is_method()) return methodOop(_result);
00041 return get_nmethod()->method();
00042 }
00043
00044 jumpTableEntry* LookupResult::entry() const {
00045 assert(!is_empty(), "cannot be empty");
00046 return is_entry() ? (jumpTableEntry*) _result : NULL;
00047 }
00048
00049 nmethod* LookupResult::get_nmethod() const {
00050 jumpTableEntry* e = entry();
00051 return e ? e->method() : NULL;
00052 }
00053
00054 bool LookupResult::matches(methodOop m) const {
00055 if (is_empty()) return false;
00056 return is_method() ? method() == m : false;
00057 }
00058
00059 bool LookupResult::matches(nmethod* nm) const {
00060 if (is_empty()) return false;
00061 return is_entry() ? entry()->method() == nm : false;
00062 }
00063
00064 void LookupResult::print_on(outputStream* st) const {
00065 if (is_empty()) {
00066 st->print("empty");
00067 } else {
00068 method()->print_value_on(st);
00069 st->print(", 0x%lx", value());
00070 }
00071 }
00072
00073 void LookupResult::print_short_on(outputStream* st) const {
00074 if (is_empty()) {
00075 st->print("empty");
00076 } else {
00077 st->print("0x%lx", value());
00078 }
00079 }
00080
00081 class cacheElement : ValueObj {
00082 public:
00083 LookupKey key;
00084 LookupResult result;
00085 int filler;
00086
00087 cacheElement() : key(), result() {}
00088
00089 void verify() {
00090 if (key.klass() || key.selector_or_method()) {
00091 if (result.is_empty()) {
00092 std->print("Verify failed in lookupCache: ");
00093 std->cr();
00094 std->print(" element = (");
00095 key.klass()->print_value_on(std);
00096 std->print("::");
00097 key.selector_or_method()->print_value_on(std);
00098 std->print(")");
00099 std->cr();
00100 std->print(" result = (");
00101 result.print_on(std);
00102 std->print_cr(")");
00103 fatal("lookupCache verify failed");
00104 }
00105 nmethod* nm = Universe::code->lookup(&key);
00106 if (result.is_method() && nm) {
00107 error("key %s has interpreted method in lookupTable but should have nmethod %#x", key.print_string(), nm);
00108 } else if (result.is_entry() && result.get_nmethod() != nm) {
00109 error("key %s: nmethod does not match codeTable nmethod", key.print_string());
00110 }
00111 if (UseInliningDatabaseEagerly && result.is_method() && InliningDatabase::lookup(&key) != NULL) {
00112 error("key %s: interpreted method in lookupTable despite inlining DB entry", key.print_string());
00113 }
00114 }
00115 }
00116
00117
00118 void clear() {
00119 key.initialize(NULL, NULL);
00120 result.clear();
00121 }
00122
00123 void initialize(LookupKey* k, LookupResult r) {
00124 key = *k;
00125 result = r;
00126 }
00127 };
00128
00129 static cacheElement primary[primary_cache_size];
00130 static cacheElement secondary[secondary_cache_size];
00131
00132 int lookupCache::primary_cache_address() { return int(&primary[0]); }
00133 int lookupCache::secondary_cache_address() { return int(&secondary[0]); }
00134
00135 void lookupCache::flush() {
00136 int index;
00137
00138 for (index = 0; index < primary_cache_size; index ++)
00139 primary[index].clear();
00140
00141 for (index = 0; index < secondary_cache_size; index ++)
00142 secondary[index].clear();
00143
00144 number_of_primary_hits = 0;
00145 number_of_secondary_hits = 0;
00146 number_of_misses = 0;
00147 }
00148
00149
00150 void lookupCache::flush(LookupKey* key) {
00151
00152 int primary_index = hash_value(key) % primary_cache_size;
00153 int secondary_index = primary_index % secondary_cache_size;
00154
00155 if (primary[primary_index].key.equal(key)) {
00156
00157
00158 primary[primary_index] = secondary[secondary_index];
00159 secondary[secondary_index].clear();
00160 return;
00161 }
00162
00163 if (secondary[secondary_index].key.equal(key)) {
00164
00165 secondary[secondary_index].clear();
00166 }
00167 }
00168
00169
00170 void lookupCache::verify() {
00171 int index;
00172 for (index = 0; index < primary_cache_size; index ++)
00173 primary[index].verify();
00174 for (index = 0; index < secondary_cache_size; index ++)
00175 secondary[index].verify();
00176 }
00177
00178 inline unsigned int lookupCache::hash_value(LookupKey* key) {
00179 return
00180 ((unsigned int) key->klass() ^ (unsigned int) key->selector_or_method())
00181 / sizeof(cacheElement);
00182 }
00183
00184 inline LookupResult lookupCache::lookup_probe(LookupKey* key) {
00185 assert(key->verify(), "Lookupkey: verify failed");
00186
00187 int primary_index = hash_value(key) % primary_cache_size;
00188
00189 if (primary[primary_index].key.equal(key)) {
00190 return primary[primary_index].result;
00191 }
00192
00193 int secondary_index = primary_index % secondary_cache_size;
00194 if (secondary[secondary_index].key.equal(key)) {
00195 cacheElement tmp;
00196
00197 tmp = primary[primary_index];
00198 primary[primary_index] = secondary[secondary_index];
00199 secondary[secondary_index] = tmp;
00200 return primary[primary_index].result;
00201 }
00202 LookupResult nothing;
00203 return nothing;
00204 }
00205
00206 inline LookupResult lookupCache::lookup(LookupKey* key, bool compile) {
00207
00208
00209
00210
00211
00212
00213
00214 assert(key->verify(), "Lookupkey: verify failed");
00215
00216
00217 int primary_index = hash_value(key) % primary_cache_size;
00218
00219 if (primary[primary_index].key.equal(key)) {
00220 #ifdef DEBUG
00221
00222 number_of_primary_hits++;
00223 #endif
00224 return primary[primary_index].result;
00225 }
00226
00227
00228 int secondary_index = primary_index % secondary_cache_size;
00229 if (secondary[secondary_index].key.equal(key)) {
00230 #ifdef DEBUG
00231 number_of_secondary_hits++;
00232 #endif
00233 cacheElement tmp;
00234
00235 tmp = primary[primary_index];
00236 primary[primary_index] = secondary[secondary_index];
00237 secondary[secondary_index] = tmp;
00238 return primary[primary_index].result;
00239 }
00240
00241
00242 number_of_misses++;
00243 LookupResult result = cache_miss_lookup(key, compile);
00244 if (!result.is_empty()) {
00245 if (UseInliningDatabaseEagerly && result.is_method() && InliningDatabase::lookup(key) != NULL) {
00246
00247
00248 assert(theCompiler, "should only happen during compilation");
00249 } else {
00250 secondary[secondary_index] = primary[primary_index];
00251 primary[primary_index].initialize(key, result);
00252 #ifdef ASSERT
00253 primary[primary_index].verify();
00254 #endif
00255 }
00256 }
00257 return result;
00258 }
00259
00260 LookupResult lookupCache::cache_miss_lookup(LookupKey* key, bool compile) {
00261
00262 if (TraceLookupAtMiss) {
00263 ResourceMark rm;
00264 key->print();
00265 }
00266
00267 if (compile && Sweeper::is_running()) {
00268
00269
00270
00271 compile = false;
00272 }
00273
00274
00275 if (UseInliningDatabase && UseInliningDatabaseEagerly && compile) {
00276 ResourceMark rm;
00277 RScope* rs = InliningDatabase::lookup_and_remove(key);
00278 if (rs) {
00279 if (TraceInliningDatabase) {
00280 std->print("ID compile: ");
00281 key->print();
00282 std->cr();
00283 }
00284
00285
00286 nmethod* old_nm = Universe::code->lookup(rs->key());
00287 VM_OptimizeRScope op(rs);
00288 VMProcess::execute(&op);
00289 if (old_nm) old_nm->makeZombie(true);
00290
00291 if (op.result()) {
00292 LookupResult result(op.result());
00293 return result;
00294 }
00295 }
00296 }
00297
00298
00299 nmethod* nm = Universe::code->lookup(key);
00300 if (nm) {
00301 LookupResult result(nm);
00302 return nm;
00303 }
00304
00305
00306 methodOop method = key->is_normal_type()
00307 ? key->klass()->klass_part()->lookup(key->selector())
00308 : key->method();
00309
00310 if (!method) {
00311 LookupResult result;
00312 return result;
00313 }
00314
00315 if (CompiledCodeOnly && compile) {
00316 nm = compile_method(key, method);
00317 if (nm) {
00318 LookupResult result(nm);
00319 return nm;
00320 }
00321 }
00322
00323 LookupResult result(method);
00324 return method;
00325 }
00326
00327 methodOop lookupCache::compile_time_normal_lookup(klassOop receiver_klass, symbolOop selector) {
00328 LookupKey key(receiver_klass, selector);
00329 LookupResult res = lookup(&key, false);
00330 return res.method_or_null();
00331 }
00332
00333 methodOop lookupCache::compile_time_super_lookup(klassOop receiver_klass, symbolOop selector) {
00334 methodOop method = method_lookup(receiver_klass->klass_part()->superKlass(), selector);
00335 if (method == NULL) return NULL;
00336 LookupKey key(receiver_klass, method);
00337 LookupResult res = lookup(&key, false);
00338 return res.method_or_null();
00339 }
00340
00341 methodOop lookupCache::method_lookup(klassOop receiver_klass, symbolOop selector) {
00342 LookupKey key(receiver_klass, selector);
00343 methodOop method = key.klass()->klass_part()->lookup(key.selector());
00344 return method;
00345 }
00346
00347 nmethod* lookupCache::compile_method(LookupKey *key, methodOop method) {
00348 if (!DeltaProcess::active()->in_vm_operation()) {
00349 VM_OptimizeMethod op(key, method);
00350 VMProcess::execute(&op);
00351 assert(op.result(), "nmethod must be there");
00352 assert(Universe::code->lookup(key), "nmethod must be there");
00353 return op.result();
00354 }
00355 return NULL;
00356 }
00357
00358
00359 inline LookupResult lookupCache::ic_lookup(klassOop receiver_klass, oop selector_or_method) {
00360 LookupKey key(receiver_klass, selector_or_method);
00361 return lookup(&key, true);
00362 }
00363
00364 LookupResult lookupCache::ic_normal_lookup(klassOop receiver_klass, symbolOop selector) {
00365 return lookupCache::ic_lookup(receiver_klass, selector);
00366 }
00367
00368 LookupResult lookupCache::ic_super_lookup(klassOop receiver_klass, klassOop superKlass, symbolOop selector) {
00369 methodOop method = method_lookup(superKlass, selector);
00370 return ic_lookup(receiver_klass, method);
00371 }
00372
00373 LookupResult interpreter_normal_lookup(klassOop receiver_klass, symbolOop selector) {
00374 LookupKey key(receiver_klass, selector);
00375 return lookupCache::lookup(&key, true);
00376 }
00377
00378 LookupResult interpreter_super_lookup(symbolOop selector) {
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 ResourceMark rm;
00392 frame f = DeltaProcess::active()->last_frame();
00393 assert(f.is_interpreted_frame(), "must be interpreter frame");
00394
00395
00396 methodOop sendingMethod = f.method()->home();
00397
00398 klassOop sendingMethodHolder = f.receiver()->blueprint()->lookup_method_holder_for(sendingMethod);
00399
00400
00401 if (sendingMethodHolder == NULL) {
00402 fatal("sending method holder cannot be found; this might be caused by a programming change -- fix this");
00403 }
00404 klassOop superKlass = sendingMethodHolder->klass_part()->superKlass();
00405 methodOop superMethod = lookupCache::method_lookup(superKlass, selector);
00406
00407 LookupResult result(superMethod);
00408 return result;
00409 }
00410
00411 LookupResult lookupCache::lookup(LookupKey* key) {
00412 return ic_lookup(key->klass(), key->selector_or_method());
00413 }
00414
00415 oop lookupCache::normal_lookup(klassOop receiver_klass, symbolOop selector) {
00416 VerifyNoScavenge vna;
00417 LookupKey key(receiver_klass, selector);
00418 LookupResult result = ic_normal_lookup(receiver_klass, selector);
00419 assert(result.value() != NULL, "message not understood not implemented yet for compiled code");
00420 return result.value();
00421 }
00422
00423 static void print_counter(char* title, int counter, int total) {
00424 lprintf("%20s: %3.1f%% (%d)\n",
00425 title,
00426 total == 0 ? 0.0 : 100.0 * (double) counter / (double) total,
00427 counter);
00428 }
00429
00430 void lookupCache::clear_statistics() {
00431 number_of_primary_hits = 0;
00432 number_of_secondary_hits = 0;
00433 number_of_misses = 0;
00434 }
00435
00436 void lookupCache::print_statistics() {
00437 int total = number_of_primary_hits
00438 + number_of_secondary_hits
00439 + number_of_misses;
00440 lprintf("Lookup Cache: size(%d, %d)\n",
00441 primary_cache_size, secondary_cache_size);
00442 print_counter("Primary Hit Ratio", number_of_primary_hits, total);
00443 print_counter("Secondary Hit Ratio", number_of_secondary_hits, total);
00444 print_counter("Miss Ratio", number_of_misses, total);
00445 }