< prev index next >

src/hotspot/share/prims/resolvedMethodTable.cpp

Print this page




   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "gc/shared/oopStorage.inline.hpp"
  28 #include "logging/log.hpp"
  29 #include "memory/allocation.hpp"
  30 #include "memory/resourceArea.hpp"
  31 #include "oops/access.inline.hpp"
  32 #include "oops/oop.inline.hpp"
  33 #include "oops/method.hpp"

  34 #include "oops/weakHandle.inline.hpp"
  35 #include "prims/resolvedMethodTable.hpp"
  36 #include "runtime/handles.inline.hpp"
  37 #include "runtime/interfaceSupport.inline.hpp"
  38 #include "runtime/mutexLocker.hpp"
  39 #include "runtime/safepointVerifiers.hpp"
  40 #include "runtime/timerTrace.hpp"
  41 #include "utilities/concurrentHashTable.inline.hpp"
  42 #include "utilities/concurrentHashTableTasks.inline.hpp"
  43 #include "utilities/macros.hpp"
  44 
  45 // 2^24 is max size
  46 static const size_t END_SIZE = 24;
  47 // If a chain gets to 32 something might be wrong
  48 static const size_t GROW_HINT = 32;
  49 
  50 static const size_t ResolvedMethodTableSizeLog = 10;
  51 
  52 unsigned int method_hash(const Method* method) {
  53   unsigned int name_hash = method->name()->identity_hash();
  54   unsigned int signature_hash = method->signature()->identity_hash();
  55   return name_hash ^ signature_hash;
  56 }
  57 
  58 class ResolvedMethodTableConfig : public ResolvedMethodTableHash::BaseConfig {
  59  private:
  60  public:
  61   static uintx get_hash(WeakHandle<vm_resolved_method_table_data> const& value,
  62                         bool* is_dead) {
  63     EXCEPTION_MARK;
  64     oop val_oop = value.peek();
  65     if (val_oop == NULL) {
  66       *is_dead = true;
  67       return 0;
  68     }
  69     *is_dead = false;
  70     Method* method = java_lang_invoke_ResolvedMethodName::vmtarget(val_oop);
  71     return method_hash(method);
  72   }
  73 
  74   // We use default allocation/deallocation but counted
  75   static void* allocate_node(size_t size, WeakHandle<vm_resolved_method_table_data> const& value) {
  76     ResolvedMethodTable::item_added();
  77     return ResolvedMethodTableHash::BaseConfig::allocate_node(size, value);
  78   }
  79   static void free_node(void* memory, WeakHandle<vm_resolved_method_table_data> const& value) {
  80     value.release();
  81     ResolvedMethodTableHash::BaseConfig::free_node(memory, value);
  82     ResolvedMethodTable::item_removed();
  83   }
  84 };
  85 
  86 ResolvedMethodTableHash* ResolvedMethodTable::_local_table           = NULL;
  87 size_t                   ResolvedMethodTable::_current_size          = (size_t)1 << ResolvedMethodTableSizeLog;
  88 
  89 OopStorage*              ResolvedMethodTable::_weak_handles          = NULL;
  90 
  91 volatile bool            ResolvedMethodTable::_has_work              = false;
  92 volatile size_t          ResolvedMethodTable::_items_count           = 0;
  93 volatile size_t          ResolvedMethodTable::_uncleaned_items_count = 0;
  94 
  95 void ResolvedMethodTable::create_table() {
  96   _local_table  = new ResolvedMethodTableHash(ResolvedMethodTableSizeLog, END_SIZE, GROW_HINT);
  97   _weak_handles = new OopStorage("ResolvedMethodTable weak",
  98                                  ResolvedMethodTableWeakAlloc_lock,
  99                                  ResolvedMethodTableWeakActive_lock);
 100   log_trace(membername, table)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
 101                                _current_size, ResolvedMethodTableSizeLog);
 102 }
 103 
 104 size_t ResolvedMethodTable::table_size() {
 105   return (size_t)1 << _local_table->get_size_log2(Thread::current());
 106 }
 107 
 108 class ResolvedMethodTableLookup : StackObj {
 109  private:
 110   Thread*       _thread;
 111   uintx         _hash;
 112   const Method* _method;
 113   Handle        _found;
 114 
 115  public:
 116   ResolvedMethodTableLookup(Thread* thread, uintx hash, const Method* key)
 117     : _thread(thread), _hash(hash), _method(key) {
 118   }
 119   uintx get_hash() const {
 120     return _hash;
 121   }
 122   bool equals(WeakHandle<vm_resolved_method_table_data>* value, bool* is_dead) {
 123     oop val_oop = value->peek();
 124     if (val_oop == NULL) {
 125       // dead oop, mark this hash dead for cleaning
 126       *is_dead = true;
 127       return false;
 128     }
 129     bool equals = _method == java_lang_invoke_ResolvedMethodName::vmtarget(val_oop);
 130     if (!equals) {
 131       return false;
 132     }
 133     // Need to resolve weak handle and Handleize through possible safepoint.
 134     _found = Handle(_thread, value->resolve());
 135     return true;
 136   }
 137 };
 138 
 139 
 140 class ResolvedMethodGet : public StackObj {
 141   Thread*       _thread;
 142   const Method* _method;
 143   Handle        _return;
 144 public:
 145   ResolvedMethodGet(Thread* thread, const Method* method) : _thread(thread), _method(method) {}
 146   void operator()(WeakHandle<vm_resolved_method_table_data>* val) {
 147     oop result = val->resolve();
 148     assert(result != NULL, "Result should be reachable");
 149     _return = Handle(_thread, result);
 150     log_get();
 151   }
 152   oop get_res_oop() {
 153     return _return();
 154   }
 155   void log_get() {
 156     LogTarget(Trace, membername, table) log;
 157     if (log.is_enabled()) {
 158       ResourceMark rm;
 159       log.print("ResolvedMethod entry found for %s",
 160                 _method->name_and_sig_as_C_string());
 161     }
 162   }
 163 };
 164 
 165 oop ResolvedMethodTable::find_method(const Method* method) {
 166   Thread* thread = Thread::current();
 167 
 168   ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
 169   ResolvedMethodGet rmg(thread, method);
 170   _local_table->get(thread, lookup, rmg);
 171 
 172   return rmg.get_res_oop();
 173 }
 174 
 175 static void log_insert(const Method* method) {
 176   LogTarget(Debug, membername, table) log;
 177   if (log.is_enabled()) {
 178     ResourceMark rm;
 179     log_debug(membername, table) ("ResolvedMethod entry added for %s",
 180                                   method->name_and_sig_as_C_string());
 181   }
 182 }
 183 
 184 oop ResolvedMethodTable::add_method(const Method* method, Handle rmethod_name) {
 185   Thread* thread = Thread::current();
 186 
 187   ResolvedMethodTableLookup lookup(thread, method_hash(method), method);
 188   ResolvedMethodGet rmg(thread, method);
 189 
 190   while (true) {
 191     if (_local_table->get(thread, lookup, rmg)) {
 192       return rmg.get_res_oop();
 193     }
 194     WeakHandle<vm_resolved_method_table_data> wh = WeakHandle<vm_resolved_method_table_data>::create(rmethod_name);
 195     // The hash table takes ownership of the WeakHandle, even if it's not inserted.
 196     if (_local_table->insert(thread, lookup, wh)) {
 197       log_insert(method);
 198       return wh.resolve();
 199     }
 200   }
 201 
























 202   return rmethod_name();
 203 }
 204 
 205 void ResolvedMethodTable::item_added() {
 206   Atomic::inc(&_items_count);
 207 }
 208 
 209 void ResolvedMethodTable::item_removed() {
 210   Atomic::dec(&_items_count);
 211   log_trace(membername, table) ("ResolvedMethod entry removed");

 212 }
 213 
 214 bool ResolvedMethodTable::has_work() {
 215   return _has_work;
 216 }
 217 
 218 OopStorage* ResolvedMethodTable::weak_storage() {
 219   return _weak_handles;
 220 }
 221 
 222 double ResolvedMethodTable::get_load_factor() {
 223   return (double)_items_count/_current_size;
 224 }










 225 
 226 double ResolvedMethodTable::get_dead_factor() {
 227   return (double)_uncleaned_items_count/_current_size;
 228 }
 229 
 230 static const double PREF_AVG_LIST_LEN = 2.0;
 231 // If we have as many dead items as 50% of the number of bucket
 232 static const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5;
 233 
 234 void ResolvedMethodTable::check_concurrent_work() {
 235   if (_has_work) {
 236     return;
 237   }
 238 
 239   double load_factor = get_load_factor();
 240   double dead_factor = get_dead_factor();
 241   // We should clean/resize if we have more dead than alive,
 242   // more items than preferred load factor or
 243   // more dead items than water mark.
 244   if ((dead_factor > load_factor) ||
 245       (load_factor > PREF_AVG_LIST_LEN) ||
 246       (dead_factor > CLEAN_DEAD_HIGH_WATER_MARK)) {
 247     log_debug(membername, table)("Concurrent work triggered, live factor: %g dead factor: %g",
 248                                  load_factor, dead_factor);
 249     trigger_concurrent_work();
 250   }
 251 }
 252 
 253 void ResolvedMethodTable::trigger_concurrent_work() {
 254   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
 255   _has_work = true;
 256   Service_lock->notify_all();
 257 }
 258 
 259 void ResolvedMethodTable::do_concurrent_work(JavaThread* jt) {
 260   _has_work = false;
 261   double load_factor = get_load_factor();
 262   log_debug(membername, table)("Concurrent work, live factor: %g", load_factor);
 263   // We prefer growing, since that also removes dead items
 264   if (load_factor > PREF_AVG_LIST_LEN && !_local_table->is_max_size_reached()) {
 265     grow(jt);
 266   } else {
 267     clean_dead_entries(jt);
 268   }
 269 }
 270 
 271 void ResolvedMethodTable::grow(JavaThread* jt) {
 272   ResolvedMethodTableHash::GrowTask gt(_local_table);
 273   if (!gt.prepare(jt)) {
 274     return;
 275   }
 276   log_trace(membername, table)("Started to grow");
 277   {
 278     TraceTime timer("Grow", TRACETIME_LOG(Debug, membername, table, perf));
 279     while (gt.do_task(jt)) {
 280       gt.pause(jt);
 281       {
 282         ThreadBlockInVM tbivm(jt);
 283       }
 284       gt.cont(jt);
 285     }
 286   }
 287   gt.done(jt);
 288   _current_size = table_size();
 289   log_info(membername, table)("Grown to size:" SIZE_FORMAT, _current_size);
 290 }
 291 
 292 struct ResolvedMethodTableDoDelete : StackObj {
 293   void operator()(WeakHandle<vm_resolved_method_table_data>* val) {
 294     /* do nothing */
 295   }
 296 };
 297 
 298 struct ResolvedMethodTableDeleteCheck : StackObj {
 299   long _count;
 300   long _item;
 301   ResolvedMethodTableDeleteCheck() : _count(0), _item(0) {}
 302   bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
 303     ++_item;
 304     oop tmp = val->peek();
 305     if (tmp == NULL) {
 306       ++_count;
 307       return true;
 308     } else {
 309       return false;
 310     }
 311   }
 312 };
 313 
 314 void ResolvedMethodTable::clean_dead_entries(JavaThread* jt) {
 315   ResolvedMethodTableHash::BulkDeleteTask bdt(_local_table);
 316   if (!bdt.prepare(jt)) {
 317     return;
 318   }
 319   ResolvedMethodTableDeleteCheck stdc;
 320   ResolvedMethodTableDoDelete stdd;
 321   {
 322     TraceTime timer("Clean", TRACETIME_LOG(Debug, membername, table, perf));
 323     while(bdt.do_task(jt, stdc, stdd)) {
 324       bdt.pause(jt);
 325       {
 326         ThreadBlockInVM tbivm(jt);



 327       }
 328       bdt.cont(jt);
 329     }
 330     bdt.done(jt);
 331   }
 332   log_info(membername, table)("Cleaned %ld of %ld", stdc._count, stdc._item);
 333 }
 334 void ResolvedMethodTable::reset_dead_counter() {
 335   _uncleaned_items_count = 0;
 336 }
 337 
 338 void ResolvedMethodTable::inc_dead_counter(size_t ndead) {
 339   size_t total = Atomic::add(ndead, &_uncleaned_items_count);
 340   log_trace(membername, table)(
 341      "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
 342      _uncleaned_items_count, ndead, total);
 343 }
 344 
 345 // After the parallel walk this method must be called to trigger
 346 // cleaning. Note it might trigger a resize instead.
 347 void ResolvedMethodTable::finish_dead_counter() {
 348   check_concurrent_work();
 349 
 350 #ifdef ASSERT
 351   if (SafepointSynchronize::is_at_safepoint()) {
 352     size_t fail_cnt = verify_and_compare_entries();
 353     if (fail_cnt != 0) {
 354       tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt);
 355       guarantee(fail_cnt == 0, "unexpected ResolvedMethodTable verification failures");
 356     }
 357   }
 358 #endif // ASSERT
 359 }

 360 
 361 #if INCLUDE_JVMTI
 362 class AdjustMethodEntries : public StackObj {
 363   bool* _trace_name_printed;
 364 public:
 365   AdjustMethodEntries(bool* trace_name_printed) : _trace_name_printed(trace_name_printed) {};
 366   bool operator()(WeakHandle<vm_resolved_method_table_data>* entry) {
 367     oop mem_name = entry->peek();
 368     if (mem_name == NULL) {
 369       // Removed
 370       return true;
 371     }
 372 
 373     Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
 374 
 375     if (old_method->is_old()) {
 376 
 377       Method* new_method = (old_method->is_deleted()) ?
 378                             Universe::throw_no_such_method_error() :
 379                             old_method->get_new_method();
 380       java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
 381 
 382       ResourceMark rm;
 383       if (!(*_trace_name_printed)) {
 384         log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
 385          *_trace_name_printed = true;
 386       }
 387       log_debug(redefine, class, update, constantpool)
 388         ("ResolvedMethod method update: %s(%s)",
 389          new_method->name()->as_C_string(), new_method->signature()->as_C_string());
 390     }
 391 
 392     return true;
 393   }
 394 };
 395 
 396 // It is called at safepoint only for RedefineClasses
 397 void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
 398   assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
 399   // For each entry in RMT, change to new method
 400   AdjustMethodEntries adjust(trace_name_printed);
 401   _local_table->do_safepoint_scan(adjust);
 402 }
 403 #endif // INCLUDE_JVMTI







 404 
 405 // Verification and comp
 406 class VerifyCompResolvedMethod : StackObj {
 407   GrowableArray<oop>* _oops;
 408  public:
 409   size_t _errors;
 410   VerifyCompResolvedMethod(GrowableArray<oop>* oops) : _oops(oops), _errors(0) {}
 411   bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
 412     oop s = val->peek();
 413     if (s == NULL) {
 414       return true;
 415     }
 416     int len = _oops->length();
 417     for (int i = 0; i < len; i++) {
 418       bool eq = s == _oops->at(i);
 419       assert(!eq, "Duplicate entries");
 420       if (eq) {
 421         _errors++;
 422       }
 423     }
 424     _oops->push(s);
 425     return true;
 426   };
 427 };
 428 
 429 size_t ResolvedMethodTable::items_count() {
 430   return _items_count;
 431 }
 432 
 433 size_t ResolvedMethodTable::verify_and_compare_entries() {
 434   Thread* thr = Thread::current();
 435   GrowableArray<oop>* oops =
 436     new (ResourceObj::C_HEAP, mtInternal)
 437       GrowableArray<oop>((int)_current_size, true);
 438 
 439   VerifyCompResolvedMethod vcs(oops);
 440   if (!_local_table->try_scan(thr, vcs)) {
 441     log_info(membername, table)("verify unavailable at this moment");
 442   }
 443   delete oops;
 444   return vcs._errors;
 445 }



   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"

  27 #include "logging/log.hpp"
  28 #include "memory/allocation.hpp"
  29 #include "memory/resourceArea.hpp"
  30 #include "oops/access.inline.hpp"
  31 #include "oops/oop.inline.hpp"
  32 #include "oops/method.hpp"
  33 #include "oops/symbol.hpp"
  34 #include "oops/weakHandle.inline.hpp"
  35 #include "prims/resolvedMethodTable.hpp"
  36 #include "runtime/handles.inline.hpp"

  37 #include "runtime/mutexLocker.hpp"
  38 #include "runtime/safepointVerifiers.hpp"
  39 #include "utilities/hashtable.inline.hpp"


  40 #include "utilities/macros.hpp"
  41 




  42 
  43 oop ResolvedMethodEntry::object() {
  44   return literal().resolve();




  45 }
  46 
  47 oop ResolvedMethodEntry::object_no_keepalive() {
  48   // The AS_NO_KEEPALIVE peeks at the oop without keeping it alive.
  49   // This is dangerous in general but is okay if the loaded oop does
  50   // not leak out past a thread transition where a safepoint can happen.
  51   // A subsequent oop_load without AS_NO_KEEPALIVE (the object() accessor)
  52   // keeps the oop alive before doing so.
  53   return literal().peek();
  54 }
  55 
  56 ResolvedMethodTable::ResolvedMethodTable()
  57   : Hashtable<ClassLoaderWeakHandle, mtClass>(_table_size, sizeof(ResolvedMethodEntry)) { }
  58 
  59 oop ResolvedMethodTable::lookup(int index, unsigned int hash, Method* method) {
  60   assert_locked_or_safepoint(ResolvedMethodTable_lock);
  61   for (ResolvedMethodEntry* p = bucket(index); p != NULL; p = p->next()) {
  62     if (p->hash() == hash) {
  63 
  64       // Peek the object to check if it is the right target.
  65       oop target = p->object_no_keepalive();
  66 
  67       // The method is in the table as a target already
  68       if (target != NULL && java_lang_invoke_ResolvedMethodName::vmtarget(target) == method) {
  69         ResourceMark rm;
  70         log_debug(membername, table) ("ResolvedMethod entry found for %s index %d",
  71                                        method->name_and_sig_as_C_string(), index);
  72         // The object() accessor makes sure the target object is kept alive before
  73         // leaking out.
  74         return p->object();
  75       }










































































  76     }
  77   }
  78   return NULL;









  79 }
  80 
  81 unsigned int ResolvedMethodTable::compute_hash(Method* method) {
  82   unsigned int name_hash = method->name()->identity_hash();
  83   unsigned int signature_hash = method->signature()->identity_hash();
  84   return name_hash ^ signature_hash;



  85 }
  86 

















  87 
  88 oop ResolvedMethodTable::lookup(Method* method) {
  89   unsigned int hash = compute_hash(method);
  90   int index = hash_to_index(hash);
  91   return lookup(index, hash, method);
  92 }
  93 
  94 oop ResolvedMethodTable::basic_add(Method* method, Handle rmethod_name) {
  95   assert_locked_or_safepoint(ResolvedMethodTable_lock);
  96 
  97   unsigned int hash = compute_hash(method);
  98   int index = hash_to_index(hash);
  99 
 100   // One was added while aquiring the lock
 101   oop entry = lookup(index, hash, method);
 102   if (entry != NULL) {
 103     return entry;
 104   }
 105 
 106   ClassLoaderWeakHandle w = ClassLoaderWeakHandle::create(rmethod_name);
 107   ResolvedMethodEntry* p = (ResolvedMethodEntry*) Hashtable<ClassLoaderWeakHandle, mtClass>::new_entry(hash, w);
 108   Hashtable<ClassLoaderWeakHandle, mtClass>::add_entry(index, p);
 109   ResourceMark rm;
 110   log_debug(membername, table) ("ResolvedMethod entry added for %s index %d",
 111                                  method->name_and_sig_as_C_string(), index);
 112   return rmethod_name();
 113 }
 114 
 115 ResolvedMethodTable* ResolvedMethodTable::_the_table = NULL;


 116 
 117 oop ResolvedMethodTable::find_method(Method* method) {
 118   MutexLocker ml(ResolvedMethodTable_lock);
 119   oop entry = _the_table->lookup(method);
 120   return entry;
 121 }
 122 
 123 oop ResolvedMethodTable::add_method(const methodHandle& m, Handle resolved_method_name) {
 124   MutexLocker ml(ResolvedMethodTable_lock);
 125   DEBUG_ONLY(NoSafepointVerifier nsv);
 126 
 127   Method* method = m();
 128   // Check if method has been redefined while taking out ResolvedMethodTable_lock, if so
 129   // use new method.  The old method won't be deallocated because it's passed in as a Handle.
 130   if (method->is_old()) {
 131     // Replace method with redefined version
 132     InstanceKlass* holder = method->method_holder();
 133     method = holder->method_with_idnum(method->method_idnum());
 134     if (method == NULL) {
 135       // Replace deleted method with NSME.
 136       method = Universe::throw_no_such_method_error();
 137     }
 138     java_lang_invoke_ResolvedMethodName::set_vmtarget(resolved_method_name(), method);
 139   }
 140   // Set flag in class to indicate this InstanceKlass has entries in the table
 141   // to avoid walking table during redefinition if none of the redefined classes
 142   // have any membernames in the table.
 143   method->method_holder()->set_has_resolved_methods();
 144 
 145   return _the_table->basic_add(method, resolved_method_name);

 146 }
 147 
 148 // Removing entries
 149 int ResolvedMethodTable::_total_oops_removed = 0;

 150 
 151 // There are no dead entries at start
 152 bool ResolvedMethodTable::_dead_entries = false;


 153 
 154 void ResolvedMethodTable::trigger_cleanup() {














 155   MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
 156   _dead_entries = true;
 157   Service_lock->notify_all();
 158 }
 159 
 160 // Serially invoke removed unused oops from the table.
 161 // This is done by the ServiceThread after being notified on class unloading
 162 void ResolvedMethodTable::unlink() {
 163   MutexLocker ml(ResolvedMethodTable_lock);
 164   int _oops_removed = 0;
 165   int _oops_counted = 0;
 166   for (int i = 0; i < _the_table->table_size(); ++i) {
 167     ResolvedMethodEntry** p = _the_table->bucket_addr(i);
 168     ResolvedMethodEntry* entry = _the_table->bucket(i);
 169     while (entry != NULL) {
 170       _oops_counted++;
 171       oop l = entry->object_no_keepalive();
 172       if (l != NULL) {
 173         p = entry->next_addr();
 174       } else {
 175         // Entry has been removed.
 176         _oops_removed++;
 177         if (log_is_enabled(Debug, membername, table)) {
 178           log_debug(membername, table) ("ResolvedMethod entry removed for index %d", i);
 179         }
 180         entry->literal().release();
 181         *p = entry->next();
 182         _the_table->free_entry(entry);

 183       }
 184       // get next entry
 185       entry = (ResolvedMethodEntry*)HashtableEntry<ClassLoaderWeakHandle, mtClass>::make_ptr(*p);
























 186     }
 187   }
 188   log_debug(membername, table) ("ResolvedMethod entries counted %d removed %d",
 189                                 _oops_counted, _oops_removed);
 190   _total_oops_removed += _oops_removed;
 191   _dead_entries = false;
 192 }
 193 
 194 #ifndef PRODUCT
 195 void ResolvedMethodTable::print() {
 196   MutexLocker ml(ResolvedMethodTable_lock);
 197   for (int i = 0; i < table_size(); ++i) {
 198     ResolvedMethodEntry* entry = bucket(i);
 199     while (entry != NULL) {
 200       tty->print("%d : ", i);
 201       oop rmethod_name = entry->object_no_keepalive();
 202       if (rmethod_name != NULL) {
 203         rmethod_name->print();
 204         Method* m = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(rmethod_name);
 205         m->print();
 206       }
 207       entry = entry->next();
 208     }

 209   }



























 210 }
 211 #endif // PRODUCT
 212 
 213 #if INCLUDE_JVMTI


































 214 // It is called at safepoint only for RedefineClasses
 215 void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) {
 216   assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
 217   // For each entry in RMT, change to new method
 218   for (int i = 0; i < _the_table->table_size(); ++i) {
 219     for (ResolvedMethodEntry* entry = _the_table->bucket(i);
 220          entry != NULL;
 221          entry = entry->next()) {
 222 
 223       oop mem_name = entry->object_no_keepalive();
 224       // except ones removed
 225       if (mem_name == NULL) {
 226         continue;
 227       }
 228       Method* old_method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(mem_name);
 229 
 230       if (old_method->is_old()) {
 231 
 232         Method* new_method = (old_method->is_deleted()) ?
 233                               Universe::throw_no_such_method_error() :
 234                               old_method->get_new_method();
 235         java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method);
 236 
 237         ResourceMark rm;
 238         if (!(*trace_name_printed)) {
 239           log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name());
 240            *trace_name_printed = true;
 241         }
 242         log_debug(redefine, class, update, constantpool)
 243           ("ResolvedMethod method update: %s(%s)",
 244            new_method->name()->as_C_string(), new_method->signature()->as_C_string());


 245       }
 246     }


















 247   }


 248 }
 249 #endif // INCLUDE_JVMTI
< prev index next >