inliningdb.cpp

Go to the documentation of this file.
00001 /* Copyright 1996, LongView Technologies L.L.C. $Revision: 1.18 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 
00026 # include "incls/_inliningdb.cpp.incl"
00027 
00028 char* InliningDatabase::_directory = NULL;
00029 
00030 char* InliningDatabase::default_directory() {
00031   return ".\\Inlining";
00032 }
00033 
00034 void InliningDatabase::set_directory(char* dir) {
00035   _directory = dir;
00036 }
00037 
00038 char* InliningDatabase::directory() {
00039   return _directory == NULL 
00040        ? default_directory() 
00041        : _directory;
00042 }
00043 
00044 # include <ctype.h>
00045 
00046 const char  quote = '_';
00047 const char* quote_string = "_\\/:; *?~|><,+=@%&!-";
00048 
00049 char* InliningDatabase::mangle_name(char *str) {
00050   char* result = NEW_RESOURCE_ARRAY(char, 100);
00051   int i = 0;
00052   int j = 0;
00053   while (str[i] != '\0') {
00054     int c = str[i];
00055     if (strchr(quote_string,c)) {
00056       result[j++] = quote;
00057       result[j++] = get_unsigned_bitfield(c, 6, 3) + '0';
00058       result[j++] = get_unsigned_bitfield(c, 3, 3) + '0';
00059       result[j++] = get_unsigned_bitfield(c, 0, 3) + '0';
00060     } else if (isupper(c)) {
00061       result[j++] = quote;
00062       result[j++] = c + ('a' - 'A');
00063     } else {
00064       result[j++] = c;
00065     } 
00066     i++;
00067   }
00068   result[j++] = '\0';
00069   return result;
00070 }
00071 
00072 char* InliningDatabase::unmangle_name(char* str) {
00073   char* result = NEW_RESOURCE_ARRAY(char, 100);
00074   int i = 0;
00075   int j = 0;
00076   while (str[i] != '\0') {
00077     int c = str[i];
00078     if (c == quote) {
00079       i++;
00080       assert(str[i] != '\0', "we cannot end with a quote");
00081       c = str[i];
00082       if (isdigit(c)) {
00083         int value = (c - '0') << 6;
00084         i++;
00085         assert(str[i] != '\0', "we cannot end with a quote");
00086         c = str[i];
00087         value += (c - '0') << 3;
00088         i++;
00089         assert(str[i] != '\0', "we cannot end with a quote");
00090         c = str[i];
00091         value += (c - '0');
00092         result[j++] = value;
00093       } else {
00094         result[j++] = c - ('a' - 'A');
00095       }
00096     } else {
00097       result[j++] = c;
00098     }
00099     i++;
00100   }
00101   result[j++] = '\0';
00102   return result;
00103 }
00104 
00105 char* InliningDatabase::selector_string(symbolOop selector) {
00106   stringStream st(100);
00107   selector->print_symbol_on(&st);
00108   return st.as_string();
00109 }
00110 
00111 char* InliningDatabase::method_string(methodOop method) {
00112   stringStream st(100);
00113   method->print_inlining_database_on(&st);
00114   return st.as_string();
00115 }
00116 
00117 char* InliningDatabase::klass_string(klassOop klass) {
00118   stringStream st(100);
00119   klass->klass_part()->print_name_on(&st);
00120   return st.as_string();
00121 }
00122 
00123 bool check_directory(char* dir_name) {
00124   return os::check_directory(dir_name);
00125 }
00126 
00127 char* InliningDatabase::compute_file_name(LookupKey* outer, LookupKey* inner, bool create_directories) {
00128   char* name = NEW_RESOURCE_ARRAY(char, 1024);
00129 
00130   // Outer key
00131   char* outer_klass_name    = mangle_name(klass_string(outer->klass()));
00132   char* outer_selector_name = mangle_name(selector_string(outer->selector()));
00133 
00134   if (create_directories) {
00135     if (!check_directory(directory())) return NULL;
00136   }
00137 
00138   strcpy(name, directory());
00139   strcat(name, "\\");
00140   strcat(name, outer_klass_name);
00141 
00142   if (create_directories) {
00143     if (!check_directory(name)) return NULL;
00144   }
00145 
00146   strcat(name, "\\");
00147   strcat(name, outer_selector_name);
00148 
00149   if (inner) {
00150     // Inner key
00151     char* inner_klass_name  = mangle_name(klass_string(inner->klass()));
00152     char* inner_method_name = mangle_name(method_string(inner->method()));
00153 
00154     if (create_directories) {
00155       if (!check_directory(name)) return NULL;
00156     }
00157     strcat(name, "\\");
00158     strcat(name, inner_klass_name);
00159 
00160     if (create_directories) {
00161       if (!check_directory(name)) return NULL;
00162     }
00163     strcat(name, "\\");
00164     strcat(name, inner_method_name);
00165   }
00166   strcat(name, ".txt");
00167   return name;
00168 }
00169 
00170 bool InliningDatabase::file_out(nmethod* nm, outputStream* index_st) {
00171   ResourceMark rm;
00172 
00173   LookupKey* outer_key = NULL;
00174   LookupKey* inner_key = NULL;
00175 
00176   if (nm->is_block()) {
00177     nmethod* outer = nm->outermost();
00178     if (outer->isZombie()) return false;
00179     outer_key = &outer->key;
00180     inner_key = &nm->key;
00181   } else {
00182     outer_key = &nm->key;
00183     inner_key = NULL;
00184   }
00185 
00186 
00187   // construct nmethod's RScope tree; we only want the inlined scopes, so use trusted = false
00188   RScope* rs = RNonDummyScope::constructRScopes(nm, false);
00189   // Ignore nmethods with small inlining trees
00190   if (rs->inlining_database_size() < InliningDatabasePruningLimit) return false;
00191   
00192 
00193   add_lookup_entry(outer_key, inner_key);
00194 
00195   if (index_st) {
00196     if (inner_key) {
00197       inner_key->print_inlining_database_on(index_st);
00198       index_st->cr();
00199     }
00200     outer_key->print_inlining_database_on(index_st);
00201     index_st->cr();
00202   }
00203 
00204   char* file_name = compute_file_name(outer_key, inner_key, true);
00205   if (file_name == NULL) return false;
00206 
00207   if (TraceInliningDatabase) {
00208     std->print_cr("Dumping %s", file_name);
00209   }
00210   fileStream out(file_name);
00211   if (out.is_open()) {
00212     GrowableArray<PcDesc*>* uncommon = nm->uncommonBranchList();
00213     // if (TraceInliningDatabase) rs->printTree(0,0);
00214     rs->print_inlining_database_on(&out, uncommon);
00215     return true;
00216   }
00217   return false;
00218 }
00219 
00220 char* find_type(char* line, bool* is_super, bool* is_block) {
00221   // Find "::", "^^" or "->"
00222   char* sub = strstr(line+1, "::");
00223   if (sub) {
00224     *is_super = false;
00225     *is_block = false;
00226     return sub;
00227   }
00228 
00229   sub = strstr(line+1, "^^");
00230   if (sub) {
00231     *is_super = true;
00232     *is_block = false;
00233     return sub;
00234   }
00235 
00236   sub = strstr(line+1, "->");
00237   if (sub) {
00238     *is_super = false;
00239     *is_block = true;
00240     return sub;
00241   }
00242 
00243   return NULL;
00244 }
00245 
00246 // Returns whether the key was succesfully scanned
00247 bool scan_key(RScope* sender, char* line, klassOop* receiver_klass, methodOop* method) {
00248   bool is_super;
00249   bool is_block;
00250 
00251   char* sub = find_type(line, &is_super, &is_block);
00252   if (sub == NULL)
00253     return false;
00254 
00255   *sub = '\0';
00256 
00257   char* class_name = line;
00258   char* method_id  = sub + 2;
00259   
00260   bool class_side = false;
00261   char* class_start = strstr(class_name, " class");
00262   if (class_start != NULL) {
00263     *class_start = '\0';
00264     class_side = true;
00265   }
00266 
00267   klassOop rec = klassOop(Universe::find_global(class_name, true));
00268   if (rec == NULL || !rec->is_klass()) return false;
00269   if (class_side) rec = rec->klass();
00270   *receiver_klass = rec;
00271  
00272   GrowableArray<int>* bcis = new GrowableArray<int>(10);
00273 
00274   char* bcis_string = strstr(method_id, " ");
00275 
00276   if (bcis_string) {
00277     *bcis_string++ = '\0';
00278     while (*bcis_string != '\0') {
00279       int index;
00280       int bci;
00281       if (sscanf(bcis_string, "%d%n", &bci, &index) != 1) return 0;
00282       bcis->push(bci);
00283       bcis_string += index;
00284       if (*bcis_string == ' ') 
00285         bcis_string++;
00286     }
00287   }
00288   symbolOop selector = oopFactory::new_symbol(method_id);
00289 
00290 
00291   if (is_super) {
00292     assert(sender, "sender must be present");
00293     klassOop method_holder = sender->receiverKlass()->klass_part()->lookup_method_holder_for(sender->method());
00294     
00295     if (method_holder) {
00296       methodOop met = method_holder->klass_part()->superKlass()->klass_part()->lookup(selector);
00297       if (met) {
00298         *method = met;
00299         return true;
00300       }
00301     }
00302     return false;
00303   }
00304 
00305   methodOop met = rec->klass_part()->lookup(selector);
00306   if (met == NULL) return false;
00307 
00308   for (int index = 0; index < bcis->length(); index++) {
00309     int bci = bcis->at(index);
00310     met = met->block_method_at(bci);
00311     if (met == NULL) return false;
00312   }
00313 
00314   *method = met;
00315   return true;
00316 }
00317 
00318 // Returns the index where the scan terminated.
00319 // index is 0 is the scan failed
00320 int scan_prefix(char* line, int* bci, int* level) {
00321   int index;
00322 
00323   int l = 0;
00324   while (*line == ' ') {
00325     line++;
00326     l++;
00327   }
00328   if (sscanf(line, "%d %n", bci, &index) != 1) return 0;
00329   *level = l / 2;
00330   return l + index;
00331 }
00332 
00333 // Returns whether the uncommon word was succesfully scanned
00334 bool scan_uncommon(char* line) {
00335   return strcmp(line, "uncommon") == 0;
00336 }
00337 
00338 static bool create_rscope(char* line, GrowableArray<RDatabaseScope*>* stack) {
00339   // remove the cr
00340   int len = strlen(line);
00341   if (len > 1 && line[len-1] == '\n') 
00342     line[len-1] = '\0';
00343 
00344   int       bci            = 0;
00345   int       level          = 0;
00346   methodOop method         = NULL;
00347   klassOop  receiver_klass = NULL;
00348 
00349   RScope* result = NULL;
00350 
00351   if (stack->isEmpty()) {
00352     // the root scope
00353     if (!scan_key(NULL, line, &receiver_klass, &method)) return false;
00354     stack->push(new RDatabaseScope(NULL, -1, receiver_klass, method, 0));
00355   } else {
00356     // sub scope
00357     int index = scan_prefix(line, &bci, &level);
00358     if (index <= 0) return false;
00359 
00360     while (stack->length() > level) 
00361       stack->pop();
00362     RDatabaseScope* sender = stack->top();
00363     if (scan_uncommon(&line[index])) {
00364       sender->mark_as_uncommon(bci);
00365     } else if (scan_key(sender, &line[index], &receiver_klass, &method)) {
00366       stack->push(new RDatabaseScope(sender, bci, receiver_klass, method, level));
00367     } else {
00368       return false;
00369     }
00370   }
00371   return true;
00372 }
00373 
00374 outputStream* InliningDatabase::index_st = NULL;
00375 
00376 int      InliningDatabase::local_number_of_nmethods_written = 0;
00377 klassOop InliningDatabase::local_klass                      = NULL;
00378 
00379 void InliningDatabase::local_file_out_all(nmethod* nm) {
00380   if (nm->isZombie()) return;
00381   if (file_out(nm)) {
00382     local_number_of_nmethods_written++;
00383   }
00384 }
00385 
00386 char* InliningDatabase::index_file_name() {
00387   char* name = NEW_RESOURCE_ARRAY(char, 1024);
00388   if (!check_directory(directory())) return NULL;
00389   strcpy(name, directory());
00390   strcat(name, "\\index.txt");
00391   return name;
00392 }
00393 
00394 bool scan_key(char* line, LookupKey* key) {
00395   int len = strlen(line);
00396   if (len > 1 && line[len-1] == '\n') 
00397     line[len-1] = '\0';
00398 
00399   bool is_super;
00400   bool is_block;
00401 
00402   char* sub = find_type(line, &is_super, &is_block);
00403   if (sub == NULL)
00404     return false;
00405 
00406   *sub = '\0';
00407 
00408   char* class_name = line;
00409   char* method_id  = sub + 2;
00410   
00411   bool class_side = false;
00412   char* class_start = strstr(class_name, " class");
00413   if (class_start != NULL) {
00414     *class_start = '\0';
00415     class_side = true;
00416   }
00417 
00418   klassOop rec = klassOop(Universe::find_global(class_name, true));
00419   if (rec == NULL || !rec->is_klass()) return false;
00420   if (class_side) rec = rec->klass();
00421 
00422 
00423   GrowableArray<int>* bcis = new GrowableArray<int>(10);
00424 
00425   char* bcis_string = strstr(method_id, " ");
00426 
00427   if (bcis_string) {
00428     *bcis_string++ = '\0';
00429     while (*bcis_string != '\0') {
00430       int index;
00431       int bci;
00432       if (sscanf(bcis_string, "%d%n", &bci, &index) != 1) return 0;
00433       bcis->push(bci);
00434       bcis_string += index;
00435       if (*bcis_string == ' ') 
00436         bcis_string++;
00437     }
00438   }
00439   symbolOop selector = oopFactory::new_symbol(method_id);
00440  
00441   if (is_block) {
00442     methodOop met = rec->klass_part()->lookup(selector);
00443     if (met == NULL) return false;
00444     for (int index = 0; index < bcis->length(); index++) {
00445       int bci = bcis->at(index);
00446       met = met->block_method_at(bci);
00447       if (met == NULL) return false;
00448     }
00449     key->initialize(rec, met);
00450   } else {
00451     key->initialize(rec, selector);
00452   }
00453   return true;
00454 }
00455 
00456 
00457 void InliningDatabase::load_index_file() {
00458   ResourceMark rm;
00459   TraceTime t("Loading index for inlining database");
00460 
00461   // Open the file
00462   FILE* stream = fopen(index_file_name(), "rt");
00463   if (!stream) return;
00464 
00465   char line[1000];
00466 
00467   LookupKey first;
00468   LookupKey second;
00469 
00470   while (fgets( line, 1000, stream)) {
00471     if (scan_key(line, &first)) {
00472       if (first.is_block_type()) {
00473         if (fgets( line, 1000, stream)) {
00474           if (scan_key(line, &second)) {
00475             // std->print("Block ");
00476             // first.print_on(std);
00477             // std->print(" outer ");
00478             // second.print_on(std);
00479             // std->cr();
00480             add_lookup_entry(&second, &first);
00481           } else {
00482             std->print_cr("Index file parsing block failed for %s", line);
00483           }
00484         }
00485       } else {
00486         // std->print("Method ");
00487         // first.print_on(std);
00488         // std->cr();
00489         add_lookup_entry(&first);
00490       }
00491     } else {
00492       std->print_cr("Index file parsing failed for %s", line);
00493     }
00494   }
00495   fclose(stream);
00496 }
00497 
00498 void InliningDatabase::local_file_out_klass(nmethod* nm) {
00499   if (nm->isZombie()) return;
00500   if (nm->receiver_klass() == local_klass) {
00501     if (file_out(nm)) {
00502       local_number_of_nmethods_written++;
00503     }
00504   }
00505 }
00506 
00507 int InliningDatabase::file_out(klassOop klass) {
00508   local_number_of_nmethods_written = 0;
00509   local_klass                      = klass;
00510   Universe::code->nmethods_do(local_file_out_klass);
00511   return local_number_of_nmethods_written;
00512 }
00513 
00514 RScope* InliningDatabase::file_in_from(FILE* stream) {
00515   GrowableArray<RDatabaseScope*>* stack = new GrowableArray<RDatabaseScope*>(10);
00516 
00517   char line[1000];
00518 
00519   // Read the first top scope
00520   if (!fgets( line, 1000, stream)) return NULL;
00521   if (!create_rscope(line, stack)) return NULL;
00522 
00523   // Read the sub scopes
00524   while (fgets( line, 1000, stream)) {
00525     if (!create_rscope(line, stack)) return NULL;
00526   }
00527 
00528   // Return the top scope
00529   return stack->at(0);
00530 }
00531 
00532 RScope* InliningDatabase::file_in(char* file_path) {
00533   // Open the file
00534   FILE* stream = fopen(file_path, "rt");
00535 
00536   if (!stream) {
00537     return NULL;
00538   }
00539   RScope* result = file_in_from(stream);
00540   fclose(stream);
00541   return result;
00542 }
00543 
00544 RScope* InliningDatabase::file_in(LookupKey* outer, LookupKey* inner) {
00545   char* file_name = compute_file_name(outer, inner, false);
00546   if (file_name == NULL) {
00547     if (TraceInliningDatabase) {
00548       std->print("Failed opening file for ");
00549       if (inner) {
00550         inner->print();
00551         std->print(" ");
00552       }
00553       outer->print();
00554       std->cr();
00555     }
00556     return NULL;
00557   }
00558   RScope* result = file_in(file_name);
00559   
00560   if (TraceInliningDatabase && result == NULL) {
00561     std->print("Failed parsing file for ");
00562     if (inner) {
00563       inner->print();
00564       std->print(" ");
00565     }
00566     outer->print();
00567     std->cr();
00568   }
00569  
00570   return result;
00571 }
00572 
00573 class InliningDatabaseKey {
00574  public:
00575   LookupKey outer;
00576   LookupKey inner;
00577 
00578   bool is_empty()   const { return outer.selector_or_method() == smiOop_zero; }
00579   bool is_filled()  const { return smiOop(outer.klass())      != smiOop_zero; }
00580   bool is_deleted() const { return outer.selector_or_method() == smiOop_one;  }
00581 
00582   bool is_inner()   const { return inner.selector_or_method() != smiOop_zero; }
00583   bool is_outer()   const { return !is_inner(); }
00584 
00585   void clear() {
00586     outer.initialize(NULL, smiOop_zero);
00587     inner.initialize(NULL, smiOop_zero);
00588   }
00589 
00590   void set_deleted() {
00591     outer.initialize(NULL, smiOop_one);
00592   }
00593 
00594   bool equal(LookupKey* o, LookupKey* i) {
00595     return outer.equal(o) && (is_outer() || inner.equal(i));
00596   }
00597 
00598   void oops_do(void f(oop*)) {
00599     if (is_filled()) {
00600      outer.oops_do(f);
00601      if(is_inner()) 
00602        inner.oops_do(f);
00603     }
00604   }
00605 };
00606 
00607 InliningDatabaseKey*   InliningDatabase::table = NULL;
00608 unsigned int InliningDatabase::table_size      = 0;
00609 unsigned int InliningDatabase::table_size_mask = 0;
00610 unsigned int InliningDatabase::table_no        = 0;
00611 
00612 inline unsigned int InliningDatabase::index_for(LookupKey* outer, LookupKey* inner) {
00613   unsigned int hash = (unsigned int) outer->klass()->identity_hash() ^ (unsigned int) outer->selector()->identity_hash();
00614   if (inner) {
00615     hash ^= (unsigned int) inner->klass()->identity_hash() ^ (unsigned int) inner->selector()->identity_hash();
00616   }
00617   return hash & table_size_mask;
00618 }
00619 
00620 inline unsigned int InliningDatabase::next_index(unsigned int index) {
00621   return (index + 1) & table_size_mask;
00622 }
00623 
00624 void InliningDatabase::reset_lookup_table() {
00625   if (table) {
00626     FreeHeap(table);
00627     table           = NULL;
00628     table_size      = 0;
00629     table_size_mask = 0;
00630     table_no        = 0;
00631   }
00632 }
00633 
00634 RScope* InliningDatabase::select_and_remove(bool* end_of_table) {
00635   if (table_no == 0) return NULL;  // Skim the cream
00636 
00637   for (unsigned int index = 0 ; index < table_size; index++) {
00638     if (table[index].is_filled() && table[index].is_outer()) {
00639       RScope* result = file_in(&table[index].outer);
00640       table[index].set_deleted();
00641       table_no--;
00642       *end_of_table = false;
00643       return result;
00644     }
00645   }
00646   *end_of_table = true;
00647   return NULL;
00648 }
00649 
00650 void InliningDatabase::allocate_table(unsigned int size) {
00651   if (TraceInliningDatabase) {
00652     std->print_cr("InliningDatabase::allocate_table(%d)", size);
00653   }
00654   table_size      = size;
00655   table_size_mask = size - 1;
00656   table_no        = 0;
00657   table           = NEW_C_HEAP_ARRAY(InliningDatabaseKey, table_size);
00658   // clear the table
00659   for (unsigned int index = 0 ; index < table_size; index++) {
00660     table[index].clear();
00661   }
00662 }
00663 
00664 void InliningDatabase::add_lookup_entry(LookupKey* outer, LookupKey* inner) {
00665   if (table_no * 2 >= table_size) {
00666     if (table == NULL) {
00667       allocate_table(4 * K);
00668     } else {
00669       // Expand table
00670       InliningDatabaseKey* old_table      = table;
00671       unsigned int         old_table_size = table_size;
00672       allocate_table(table_size * 2);
00673       for (unsigned int index = 0 ; index < old_table_size; index++) {
00674         if (old_table[index].is_filled())
00675           add_lookup_entry(&old_table[index].outer, &old_table[index].inner);
00676       }
00677       FreeHeap(old_table);
00678     }
00679   }
00680   assert(table_no * 2 < table_size, "just checking density");
00681   
00682   unsigned int index = index_for(outer, inner);
00683 
00684   while (table[index].is_filled()) {
00685     if (table[index].equal(outer, inner)) return;
00686     index = next_index(index);
00687   }
00688 
00689   table[index].outer = *outer;
00690   if (inner) {
00691     table[index].inner = *inner;
00692   }
00693   table_no++;
00694 
00695   if (TraceInliningDatabase) {
00696     std->print_cr("InliningDatabase::add_lookup_entry @ %d", index);
00697     if (inner) {
00698       inner->print();
00699       std->print(" ");
00700     }
00701     outer->print();
00702     std->cr();
00703   }
00704 }
00705 
00706 bool InliningDatabase::lookup(LookupKey* outer, LookupKey* inner) {
00707   if (table_no == 0) return NULL;  // Skim the cream
00708 
00709   unsigned int index = index_for(outer, inner);
00710   if (!table[index].is_filled()) return false; 
00711   while (!table[index].equal(outer, inner)) {
00712     index = next_index(index);
00713     if (table[index].is_empty()) return false;
00714   }
00715   return true;
00716 }
00717 
00718 
00719 RScope* InliningDatabase::lookup_and_remove(LookupKey* outer, LookupKey* inner) {
00720   if (table_no == 0) return NULL;  // Skim the cream
00721 
00722   unsigned int index = index_for(outer, inner);
00723   if (!table[index].is_filled()) return NULL; 
00724   while (!table[index].equal(outer, inner)) {
00725     index = next_index(index);
00726     if (table[index].is_empty()) return NULL;
00727   }
00728   table[index].set_deleted();
00729   table_no--;
00730   return file_in(outer, inner);
00731 }
00732 
00733 void InliningDatabase::oops_do(void f(oop*)) {
00734   for (unsigned int index = 0; index < table_size; index++) {
00735     table[index].oops_do(f);
00736   }
00737 }
00738 
00739 int InliningDatabase::file_out_all() {
00740   ResourceMark rm;
00741 
00742   // The lookup table is used to create the index file.
00743 
00744   // Flush the lookup table
00745   reset_lookup_table();
00746 
00747   // File in the current index file.
00748   load_index_file();
00749 
00750   local_number_of_nmethods_written = 0;
00751   Universe::code->nmethods_do(local_file_out_all);
00752 
00753   fileStream index(index_file_name());
00754 
00755   // File out the index file.
00756   for (unsigned int i = 0 ; i < table_size; i++) {
00757     if (table[i].is_filled()) {
00758       if (table[i].is_inner()) {
00759         table[i].inner.print_inlining_database_on(&index);
00760         index.cr();
00761       }
00762       table[i].outer.print_inlining_database_on(&index);
00763       index.cr();
00764     }
00765   }
00766 
00767   // Flush the lookup table
00768   reset_lookup_table();
00769 
00770   return local_number_of_nmethods_written;
00771 }

Generated on Mon Oct 9 13:37:11 2006 for Strongtalk VM by  doxygen 1.4.7