< prev index next > src/hotspot/share/gc/shenandoah/shenandoahNMethod.hpp
Print this page
#include "gc/shenandoah/shenandoahPadding.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "utilities/growableArray.hpp"
// 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
#include "gc/shenandoah/shenandoahPadding.hpp"
#include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
#include "utilities/growableArray.hpp"
+ class BarrierSetNMethod;
+
// Use ShenandoahReentrantLock as ShenandoahNMethodLock
typedef ShenandoahReentrantLock<ShenandoahSimpleLock> ShenandoahNMethodLock;
typedef ShenandoahLocker<ShenandoahNMethodLock> ShenandoahNMethodLocker;
+ struct ShenandoahPatchableJump {
+ int32_t _rel_pc;
+ int32_t _rel_target_pc;
+ char _gc_state;
+ bool _jump_when_state;
+ };
+
// 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;
+ ShenandoahPatchableJump* _patchable_jumps;
+ int _patchable_jumps_count;
bool _has_non_immed_oops;
bool _unregistered;
ShenandoahNMethodLock _lock;
ShenandoahNMethodLock _ic_lock;
public:
! ShenandoahNMethod(nmethod *nm);
~ShenandoahNMethod();
+ static bool decode_reloc_jump_when_state(uint16_t reloc) {
+ return (reloc & (1 << 8)) != 0;
+ }
+
+ static char decode_reloc_gc_state(uint16_t reloc) {
+ return (reloc & 0xFF);
+ }
+
+ static uint16_t encode_to_reloc(char gc_state, bool jump_when_state) {
+ uint16_t res = (gc_state & 0xFF) | (jump_when_state ? (1 << 8) : 0);
+ assert(decode_reloc_jump_when_state(res) == jump_when_state, "Round-trip");
+ assert(decode_reloc_gc_state(res) == gc_state, "Round-trip");
+ return res;
+ }
+
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 bool handle_oops(nmethod* nm);
+ static bool handle_jumps(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;
+ bool has_patchable_jumps() {
+ return _patchable_jumps_count > 0;
+ }
+
private:
! void init_from(nmethod* nm);
+ static void parse(nmethod* nm, GrowableArray<oop*>& oops, bool& _has_non_immed_oops, GrowableArray<ShenandoahPatchableJump>& jumps);
+ static bool patch_jump(address pc, address target_pc, bool should_jump);
};
class ShenandoahNMethodTable;
// ShenandoahNMethodList holds registered nmethod data. The list is reference counted.
enum {
minSize = 1024
};
ShenandoahHeap* const _heap;
+ BarrierSetNMethod* const _bs_nm;
+
ShenandoahNMethodList* _list;
int _index;
ShenandoahLock _lock;
int _itr_cnt;
< prev index next >