src/share/vm/memory/referenceProcessor.hpp

changeset 3175
4dfb2df418f2
parent 3117
eca1193ca245
child 3188
d1bdeef3e3e2
     1.1 --- a/src/share/vm/memory/referenceProcessor.hpp	Thu Sep 22 07:18:51 2011 -0400
     1.2 +++ b/src/share/vm/memory/referenceProcessor.hpp	Thu Sep 22 10:57:37 2011 -0700
     1.3 @@ -48,18 +48,175 @@
     1.4  // forward references
     1.5  class ReferencePolicy;
     1.6  class AbstractRefProcTaskExecutor;
     1.7 -class DiscoveredList;
     1.8 +
     1.9 +// List of discovered references.
    1.10 +class DiscoveredList {
    1.11 +public:
    1.12 +  DiscoveredList() : _len(0), _compressed_head(0), _oop_head(NULL) { }
    1.13 +  oop head() const     {
    1.14 +     return UseCompressedOops ?  oopDesc::decode_heap_oop(_compressed_head) :
    1.15 +                                _oop_head;
    1.16 +  }
    1.17 +  HeapWord* adr_head() {
    1.18 +    return UseCompressedOops ? (HeapWord*)&_compressed_head :
    1.19 +                               (HeapWord*)&_oop_head;
    1.20 +  }
    1.21 +  void set_head(oop o) {
    1.22 +    if (UseCompressedOops) {
    1.23 +      // Must compress the head ptr.
    1.24 +      _compressed_head = oopDesc::encode_heap_oop(o);
    1.25 +    } else {
    1.26 +      _oop_head = o;
    1.27 +    }
    1.28 +  }
    1.29 +  bool   is_empty() const       { return head() == NULL; }
    1.30 +  size_t length()               { return _len; }
    1.31 +  void   set_length(size_t len) { _len = len;  }
    1.32 +  void   inc_length(size_t inc) { _len += inc; assert(_len > 0, "Error"); }
    1.33 +  void   dec_length(size_t dec) { _len -= dec; }
    1.34 +private:
    1.35 +  // Set value depending on UseCompressedOops. This could be a template class
    1.36 +  // but then we have to fix all the instantiations and declarations that use this class.
    1.37 +  oop       _oop_head;
    1.38 +  narrowOop _compressed_head;
    1.39 +  size_t _len;
    1.40 +};
    1.41 +
    1.42 +// Iterator for the list of discovered references.
    1.43 +class DiscoveredListIterator {
    1.44 +private:
    1.45 +  DiscoveredList&    _refs_list;
    1.46 +  HeapWord*          _prev_next;
    1.47 +  oop                _prev;
    1.48 +  oop                _ref;
    1.49 +  HeapWord*          _discovered_addr;
    1.50 +  oop                _next;
    1.51 +  HeapWord*          _referent_addr;
    1.52 +  oop                _referent;
    1.53 +  OopClosure*        _keep_alive;
    1.54 +  BoolObjectClosure* _is_alive;
    1.55 +
    1.56 +  DEBUG_ONLY(
    1.57 +  oop                _first_seen; // cyclic linked list check
    1.58 +  )
    1.59 +
    1.60 +  NOT_PRODUCT(
    1.61 +  size_t             _processed;
    1.62 +  size_t             _removed;
    1.63 +  )
    1.64 +
    1.65 +public:
    1.66 +  inline DiscoveredListIterator(DiscoveredList&    refs_list,
    1.67 +                                OopClosure*        keep_alive,
    1.68 +                                BoolObjectClosure* is_alive):
    1.69 +    _refs_list(refs_list),
    1.70 +    _prev_next(refs_list.adr_head()),
    1.71 +    _prev(NULL),
    1.72 +    _ref(refs_list.head()),
    1.73 +#ifdef ASSERT
    1.74 +    _first_seen(refs_list.head()),
    1.75 +#endif
    1.76 +#ifndef PRODUCT
    1.77 +    _processed(0),
    1.78 +    _removed(0),
    1.79 +#endif
    1.80 +    _next(NULL),
    1.81 +    _keep_alive(keep_alive),
    1.82 +    _is_alive(is_alive)
    1.83 +{ }
    1.84 +
    1.85 +  // End Of List.
    1.86 +  inline bool has_next() const { return _ref != NULL; }
    1.87 +
    1.88 +  // Get oop to the Reference object.
    1.89 +  inline oop obj() const { return _ref; }
    1.90 +
    1.91 +  // Get oop to the referent object.
    1.92 +  inline oop referent() const { return _referent; }
    1.93 +
    1.94 +  // Returns true if referent is alive.
    1.95 +  inline bool is_referent_alive() const {
    1.96 +    return _is_alive->do_object_b(_referent);
    1.97 +  }
    1.98 +
    1.99 +  // Loads data for the current reference.
   1.100 +  // The "allow_null_referent" argument tells us to allow for the possibility
   1.101 +  // of a NULL referent in the discovered Reference object. This typically
   1.102 +  // happens in the case of concurrent collectors that may have done the
   1.103 +  // discovery concurrently, or interleaved, with mutator execution.
   1.104 +  void load_ptrs(DEBUG_ONLY(bool allow_null_referent));
   1.105 +
   1.106 +  // Move to the next discovered reference.
   1.107 +  inline void next() {
   1.108 +    _prev_next = _discovered_addr;
   1.109 +    _prev = _ref;
   1.110 +    move_to_next();
   1.111 +  }
   1.112 +
   1.113 +  // Remove the current reference from the list
   1.114 +  void remove();
   1.115 +
   1.116 +  // Make the Reference object active again.
   1.117 +  void make_active();
   1.118 +
   1.119 +  // Make the referent alive.
   1.120 +  inline void make_referent_alive() {
   1.121 +    if (UseCompressedOops) {
   1.122 +      _keep_alive->do_oop((narrowOop*)_referent_addr);
   1.123 +    } else {
   1.124 +      _keep_alive->do_oop((oop*)_referent_addr);
   1.125 +    }
   1.126 +  }
   1.127 +
   1.128 +  // Update the discovered field.
   1.129 +  inline void update_discovered() {
   1.130 +    // First _prev_next ref actually points into DiscoveredList (gross).
   1.131 +    if (UseCompressedOops) {
   1.132 +      if (!oopDesc::is_null(*(narrowOop*)_prev_next)) {
   1.133 +        _keep_alive->do_oop((narrowOop*)_prev_next);
   1.134 +      }
   1.135 +    } else {
   1.136 +      if (!oopDesc::is_null(*(oop*)_prev_next)) {
   1.137 +        _keep_alive->do_oop((oop*)_prev_next);
   1.138 +      }
   1.139 +    }
   1.140 +  }
   1.141 +
   1.142 +  // NULL out referent pointer.
   1.143 +  void clear_referent();
   1.144 +
   1.145 +  // Statistics
   1.146 +  NOT_PRODUCT(
   1.147 +  inline size_t processed() const { return _processed; }
   1.148 +  inline size_t removed() const   { return _removed; }
   1.149 +  )
   1.150 +
   1.151 +  inline void move_to_next() {
   1.152 +    if (_ref == _next) {
   1.153 +      // End of the list.
   1.154 +      _ref = NULL;
   1.155 +    } else {
   1.156 +      _ref = _next;
   1.157 +    }
   1.158 +    assert(_ref != _first_seen, "cyclic ref_list found");
   1.159 +    NOT_PRODUCT(_processed++);
   1.160 +  }
   1.161 +
   1.162 +};
   1.163  
   1.164  class ReferenceProcessor : public CHeapObj {
   1.165   protected:
   1.166    // Compatibility with pre-4965777 JDK's
   1.167    static bool _pending_list_uses_discovered_field;
   1.168 -  MemRegion   _span; // (right-open) interval of heap
   1.169 -                     // subject to wkref discovery
   1.170 -  bool        _discovering_refs;      // true when discovery enabled
   1.171 -  bool        _discovery_is_atomic;   // if discovery is atomic wrt
   1.172 -                                      // other collectors in configuration
   1.173 -  bool        _discovery_is_mt;       // true if reference discovery is MT.
   1.174 +
   1.175 +  MemRegion   _span;                    // (right-open) interval of heap
   1.176 +                                        // subject to wkref discovery
   1.177 +
   1.178 +  bool        _discovering_refs;        // true when discovery enabled
   1.179 +  bool        _discovery_is_atomic;     // if discovery is atomic wrt
   1.180 +                                        // other collectors in configuration
   1.181 +  bool        _discovery_is_mt;         // true if reference discovery is MT.
   1.182 +
   1.183    // If true, setting "next" field of a discovered refs list requires
   1.184    // write barrier(s).  (Must be true if used in a collector in which
   1.185    // elements of a discovered list may be moved during discovery: for
   1.186 @@ -67,18 +224,19 @@
   1.187    // long-term concurrent marking phase that does weak reference
   1.188    // discovery.)
   1.189    bool        _discovered_list_needs_barrier;
   1.190 -  BarrierSet* _bs;                    // Cached copy of BarrierSet.
   1.191 -  bool        _enqueuing_is_done;     // true if all weak references enqueued
   1.192 -  bool        _processing_is_mt;      // true during phases when
   1.193 -                                      // reference processing is MT.
   1.194 -  int         _next_id;               // round-robin mod _num_q counter in
   1.195 -                                      // support of work distribution
   1.196  
   1.197 -  // For collectors that do not keep GC marking information
   1.198 +  BarrierSet* _bs;                      // Cached copy of BarrierSet.
   1.199 +  bool        _enqueuing_is_done;       // true if all weak references enqueued
   1.200 +  bool        _processing_is_mt;        // true during phases when
   1.201 +                                        // reference processing is MT.
   1.202 +  int         _next_id;                 // round-robin mod _num_q counter in
   1.203 +                                        // support of work distribution
   1.204 +
   1.205 +  // For collectors that do not keep GC liveness information
   1.206    // in the object header, this field holds a closure that
   1.207    // helps the reference processor determine the reachability
   1.208 -  // of an oop (the field is currently initialized to NULL for
   1.209 -  // all collectors but the CMS collector).
   1.210 +  // of an oop. It is currently initialized to NULL for all
   1.211 +  // collectors except for CMS and G1.
   1.212    BoolObjectClosure* _is_alive_non_header;
   1.213  
   1.214    // Soft ref clearing policies
   1.215 @@ -102,10 +260,13 @@
   1.216    DiscoveredList* _discoveredPhantomRefs;
   1.217  
   1.218   public:
   1.219 -  int num_q()                            { return _num_q; }
   1.220 -  int max_num_q()                        { return _max_num_q; }
   1.221 -  void set_active_mt_degree(int v)       { _num_q = v; }
   1.222 -  DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; }
   1.223 +  static int number_of_subclasses_of_ref() { return (REF_PHANTOM - REF_OTHER); }
   1.224 +
   1.225 +  int num_q()                              { return _num_q; }
   1.226 +  int max_num_q()                          { return _max_num_q; }
   1.227 +  void set_active_mt_degree(int v)         { _num_q = v; }
   1.228 +  DiscoveredList* discovered_soft_refs()   { return _discoveredSoftRefs; }
   1.229 +
   1.230    ReferencePolicy* setup_policy(bool always_clear) {
   1.231      _current_soft_ref_policy = always_clear ?
   1.232        _always_clear_soft_ref_policy : _default_soft_ref_policy;
   1.233 @@ -205,6 +366,11 @@
   1.234    void enqueue_discovered_reflists(HeapWord* pending_list_addr, AbstractRefProcTaskExecutor* task_executor);
   1.235  
   1.236   protected:
   1.237 +  // Set the 'discovered' field of the given reference to
   1.238 +  // the given value - emitting barriers depending upon
   1.239 +  // the value of _discovered_list_needs_barrier.
   1.240 +  void set_discovered(oop ref, oop value);
   1.241 +
   1.242    // "Preclean" the given discovered reference list
   1.243    // by removing references with strongly reachable referents.
   1.244    // Currently used in support of CMS only.
   1.245 @@ -290,7 +456,19 @@
   1.246    void      set_span(MemRegion span) { _span = span; }
   1.247  
   1.248    // start and stop weak ref discovery
   1.249 -  void enable_discovery()   { _discovering_refs = true;  }
   1.250 +  void enable_discovery(bool verify_disabled, bool check_no_refs) {
   1.251 +#ifdef ASSERT
   1.252 +    // Verify that we're not currently discovering refs
   1.253 +    assert(!verify_disabled || !_discovering_refs, "nested call?");
   1.254 +
   1.255 +    if (check_no_refs) {
   1.256 +      // Verify that the discovered lists are empty
   1.257 +      verify_no_references_recorded();
   1.258 +    }
   1.259 +#endif // ASSERT
   1.260 +    _discovering_refs = true;
   1.261 +  }
   1.262 +
   1.263    void disable_discovery()  { _discovering_refs = false; }
   1.264    bool discovery_enabled()  { return _discovering_refs;  }
   1.265  
   1.266 @@ -365,7 +543,7 @@
   1.267  
   1.268    ~NoRefDiscovery() {
   1.269      if (_was_discovering_refs) {
   1.270 -      _rp->enable_discovery();
   1.271 +      _rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/);
   1.272      }
   1.273    }
   1.274  };

mercurial