< prev index next > src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp
Print this page
// Use ShenandoahReentrantLock as ShenandoahNMethodLock
typedef ShenandoahReentrantLock<ShenandoahSimpleLock> ShenandoahNMethodLock;
typedef ShenandoahLocker<ShenandoahNMethodLock> ShenandoahNMethodLocker;
// ShenandoahNMethod tuple records the internal locations of oop slots within reclocation stream in
// the nmethod. This allows us to quickly scan the oops without doing the nmethod-internal scans,
// that sometimes involves parsing the machine code. Note it does not record the oops themselves,
// because it would then require handling these tuples as the new class of roots.
class ShenandoahNMethod : public CHeapObj<mtGC> {
private:
nmethod* const _nm;
oop** _oops;
int _oops_count;
bool _has_non_immed_oops;
bool _unregistered;
ShenandoahNMethodLock _lock;
ShenandoahNMethodLock _ic_lock;
public:
! ShenandoahNMethod(nmethod *nm, GrowableArray<oop*>& oops, bool has_non_immed_oops);
~ShenandoahNMethod();
inline nmethod* nm() const;
inline ShenandoahNMethodLock* lock();
inline ShenandoahNMethodLock* ic_lock();
inline void oops_do(OopClosure* oops, bool fix_relocations = false);
// Update oops when the nmethod is re-registered
// Use ShenandoahReentrantLock as ShenandoahNMethodLock
typedef ShenandoahReentrantLock<ShenandoahSimpleLock> ShenandoahNMethodLock;
typedef ShenandoahLocker<ShenandoahNMethodLock> ShenandoahNMethodLocker;
+ struct ShenandoahNMethodBarrier {
+ address _pc;
+ address _stub_addr;
+ int _index;
+ };
+
// ShenandoahNMethod tuple records the internal locations of oop slots within reclocation stream in
// the nmethod. This allows us to quickly scan the oops without doing the nmethod-internal scans,
// that sometimes involves parsing the machine code. Note it does not record the oops themselves,
// because it would then require handling these tuples as the new class of roots.
class ShenandoahNMethod : public CHeapObj<mtGC> {
private:
nmethod* const _nm;
oop** _oops;
int _oops_count;
+ ShenandoahNMethodBarrier* _barriers;
+ int _barriers_count;
bool _has_non_immed_oops;
bool _unregistered;
ShenandoahNMethodLock _lock;
ShenandoahNMethodLock _ic_lock;
+ enum ShenandoahNMethodGCState {
+ FORWARDED = ShenandoahHeap::HAS_FORWARDED,
+ MARKING = ShenandoahHeap::MARKING,
+ WEAK = ShenandoahHeap::WEAK_ROOTS,
+ FORWARDED_MARKING = ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING,
+ FORWARDED_WEAK = ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::WEAK_ROOTS,
+ MARKING_WEAK = ShenandoahHeap::MARKING | ShenandoahHeap::WEAK_ROOTS,
+ FORWARDED_MARKING_WEAK = ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING | ShenandoahHeap::WEAK_ROOTS
+ };
+
+ enum ShenandoahNMethodGCStatePos {
+ POS_FORWARDED = 0,
+ POS_MARKING = 1,
+ POS_WEAK = 2,
+ POS_FORWARDED_MARKING = 3,
+ POS_FORWARDED_WEAK = 4,
+ POS_MARKING_WEAK = 5,
+ POS_FORWARDED_MARKING_WEAK = 6,
+ POS_MAX
+ };
+
public:
! ShenandoahNMethod(nmethod *nm);
~ShenandoahNMethod();
+ static int gc_state_to_reloc(char gc_state) {
+ if (gc_state == FORWARDED) return POS_FORWARDED;
+ if (gc_state == MARKING) return POS_MARKING;
+ if (gc_state == WEAK) return POS_WEAK;
+ if (gc_state == FORWARDED_MARKING) return POS_FORWARDED_MARKING;
+ if (gc_state == FORWARDED_WEAK) return POS_FORWARDED_WEAK;
+ if (gc_state == MARKING_WEAK) return POS_MARKING_WEAK;
+ if (gc_state == FORWARDED_MARKING_WEAK) return POS_FORWARDED_MARKING_WEAK;
+ ShouldNotReachHere();
+ return 0;
+ }
+
+ static char reloc_to_gc_state(int index) {
+ if (index == POS_FORWARDED) return FORWARDED;
+ if (index == POS_MARKING) return MARKING;
+ if (index == POS_WEAK) return WEAK;
+ if (index == POS_FORWARDED_MARKING) return FORWARDED_MARKING;
+ if (index == POS_FORWARDED_WEAK) return FORWARDED_WEAK;
+ if (index == POS_MARKING_WEAK) return MARKING_WEAK;
+ if (index == POS_FORWARDED_MARKING_WEAK) return FORWARDED_MARKING_WEAK;
+ ShouldNotReachHere();
+ return 0;
+ }
+
inline nmethod* nm() const;
inline ShenandoahNMethodLock* lock();
inline ShenandoahNMethodLock* ic_lock();
inline void oops_do(OopClosure* oops, bool fix_relocations = false);
// Update oops when the nmethod is re-registered
static ShenandoahNMethod* for_nmethod(nmethod* nm);
static inline ShenandoahNMethodLock* lock_for_nmethod(nmethod* nm);
static inline ShenandoahNMethodLock* ic_lock_for_nmethod(nmethod* nm);
static void heal_nmethod(nmethod* nm);
static inline void heal_nmethod_metadata(ShenandoahNMethod* nmethod_data);
! static inline void disarm_nmethod(nmethod* nm);
static inline ShenandoahNMethod* gc_data(nmethod* nm);
static inline void attach_gc_data(nmethod* nm, ShenandoahNMethod* gc_data);
void assert_correct() NOT_DEBUG_RETURN;
void assert_same_oops() NOT_DEBUG_RETURN;
private:
! static void detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& _has_non_immed_oops);
};
class ShenandoahNMethodTable;
// ShenandoahNMethodList holds registered nmethod data. The list is reference counted.
static ShenandoahNMethod* for_nmethod(nmethod* nm);
static inline ShenandoahNMethodLock* lock_for_nmethod(nmethod* nm);
static inline ShenandoahNMethodLock* ic_lock_for_nmethod(nmethod* nm);
static void heal_nmethod(nmethod* nm);
+ static void update_barriers(nmethod* nm);
static inline void heal_nmethod_metadata(ShenandoahNMethod* nmethod_data);
! static inline void complete_and_disarm_nmethod(nmethod* nm);
+ static inline void complete_and_disarm_nmethod_unlocked(nmethod* nm);
static inline ShenandoahNMethod* gc_data(nmethod* nm);
static inline void attach_gc_data(nmethod* nm, ShenandoahNMethod* gc_data);
+ static void assert_barriers(nmethod* nm, bool armed) NOT_DEBUG_RETURN;
void assert_correct() NOT_DEBUG_RETURN;
void assert_same_oops() NOT_DEBUG_RETURN;
private:
! void init_from(nmethod* nm);
+ static void parse(nmethod* nm, GrowableArray<oop*>& oops, bool& _has_non_immed_oops, GrowableArray<ShenandoahNMethodBarrier>& barriers);
};
class ShenandoahNMethodTable;
// ShenandoahNMethodList holds registered nmethod data. The list is reference counted.
< prev index next >