--- a/hotspot/src/share/vm/code/nmethod.hpp Mon Jul 07 12:37:11 2014 +0200
+++ b/hotspot/src/share/vm/code/nmethod.hpp Mon Jul 07 10:12:40 2014 +0200
@@ -111,6 +111,11 @@
friend class NMethodSweeper;
friend class CodeCache; // scavengable oops
private:
+
+ // GC support to help figure out if an nmethod has been
+ // cleaned/unloaded by the current GC.
+ static unsigned char _global_unloading_clock;
+
// Shared fields for all nmethod's
Method* _method;
int _entry_bci; // != InvocationEntryBci if this nmethod is an on-stack replacement method
@@ -118,7 +123,13 @@
// To support simple linked-list chaining of nmethods:
nmethod* _osr_link; // from InstanceKlass::osr_nmethods_head
- nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
+
+ union {
+ // Used by G1 to chain nmethods.
+ nmethod* _unloading_next;
+ // Used by non-G1 GCs to chain nmethods.
+ nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
+ };
static nmethod* volatile _oops_do_mark_nmethods;
nmethod* volatile _oops_do_mark_link;
@@ -180,6 +191,8 @@
// Protected by Patching_lock
volatile unsigned char _state; // {alive, not_entrant, zombie, unloaded}
+ volatile unsigned char _unloading_clock; // Incremented after GC unloaded/cleaned the nmethod
+
#ifdef ASSERT
bool _oops_are_stale; // indicates that it's no longer safe to access oops section
#endif
@@ -437,6 +450,15 @@
bool unload_reported() { return _unload_reported; }
void set_unload_reported() { _unload_reported = true; }
+ void set_unloading_next(nmethod* next) { _unloading_next = next; }
+ nmethod* unloading_next() { return _unloading_next; }
+
+ static unsigned char global_unloading_clock() { return _global_unloading_clock; }
+ static void increase_unloading_clock();
+
+ void set_unloading_clock(unsigned char unloading_clock);
+ unsigned char unloading_clock();
+
bool is_marked_for_deoptimization() const { return _marked_for_deoptimization; }
void mark_for_deoptimization() { _marked_for_deoptimization = true; }
@@ -552,6 +574,10 @@
return (addr >= code_begin() && addr < verified_entry_point());
}
+ // Verify calls to dead methods have been cleaned.
+ void verify_clean_inline_caches();
+ // Verify and count cached icholder relocations.
+ int verify_icholder_relocations();
// Check that all metadata is still alive
void verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive);
@@ -577,6 +603,10 @@
// GC support
void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
+ // The parallel versions are used by G1.
+ bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred);
+ void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred);
+ // Unload a nmethod if the *root object is dead.
bool can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_occurred);
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,