Mon, 12 Aug 2019 18:30:40 +0300
8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens
tschatzl@6937 | 1 | /* |
tschatzl@6937 | 2 | * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. |
tschatzl@6937 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
tschatzl@6937 | 4 | * |
tschatzl@6937 | 5 | * This code is free software; you can redistribute it and/or modify it |
tschatzl@6937 | 6 | * under the terms of the GNU General Public License version 2 only, as |
tschatzl@6937 | 7 | * published by the Free Software Foundation. |
tschatzl@6937 | 8 | * |
tschatzl@6937 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
tschatzl@6937 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
tschatzl@6937 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
tschatzl@6937 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
tschatzl@6937 | 13 | * accompanied this code). |
tschatzl@6937 | 14 | * |
tschatzl@6937 | 15 | * You should have received a copy of the GNU General Public License version |
tschatzl@6937 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
tschatzl@6937 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
tschatzl@6937 | 18 | * |
tschatzl@6937 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
tschatzl@6937 | 20 | * or visit www.oracle.com if you need additional information or have any |
tschatzl@6937 | 21 | * questions. |
tschatzl@6937 | 22 | * |
tschatzl@6937 | 23 | */ |
tschatzl@6937 | 24 | |
tschatzl@6937 | 25 | #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP |
tschatzl@6937 | 26 | #define SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP |
tschatzl@6937 | 27 | |
tschatzl@6937 | 28 | #include "gc_implementation/g1/dirtyCardQueue.hpp" |
tschatzl@6937 | 29 | #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" |
tschatzl@6937 | 30 | #include "gc_implementation/g1/g1CollectedHeap.hpp" |
tschatzl@6937 | 31 | #include "gc_implementation/g1/g1CollectorPolicy.hpp" |
tschatzl@6937 | 32 | #include "gc_implementation/g1/g1OopClosures.hpp" |
tschatzl@6937 | 33 | #include "gc_implementation/g1/g1RemSet.hpp" |
tschatzl@6937 | 34 | #include "gc_implementation/shared/ageTable.hpp" |
tschatzl@6937 | 35 | #include "memory/allocation.hpp" |
tschatzl@6937 | 36 | #include "oops/oop.hpp" |
tschatzl@6937 | 37 | |
tschatzl@6937 | 38 | class HeapRegion; |
tschatzl@6937 | 39 | class outputStream; |
tschatzl@6937 | 40 | |
tschatzl@6937 | 41 | class G1ParScanThreadState : public StackObj { |
tschatzl@6938 | 42 | private: |
tschatzl@6937 | 43 | G1CollectedHeap* _g1h; |
tschatzl@6937 | 44 | RefToScanQueue* _refs; |
tschatzl@6937 | 45 | DirtyCardQueue _dcq; |
tschatzl@6937 | 46 | G1SATBCardTableModRefBS* _ct_bs; |
tschatzl@6937 | 47 | G1RemSet* _g1_rem; |
tschatzl@6937 | 48 | |
tschatzl@7651 | 49 | G1ParGCAllocator* _g1_par_allocator; |
sjohanss@7118 | 50 | |
tschatzl@7651 | 51 | ageTable _age_table; |
tschatzl@7651 | 52 | InCSetState _dest[InCSetState::Num]; |
tschatzl@7651 | 53 | // Local tenuring threshold. |
tschatzl@7651 | 54 | uint _tenuring_threshold; |
tschatzl@7651 | 55 | G1ParScanClosure _scanner; |
tschatzl@6937 | 56 | |
tschatzl@7651 | 57 | size_t _alloc_buffer_waste; |
tschatzl@7651 | 58 | size_t _undo_waste; |
tschatzl@6937 | 59 | |
tschatzl@6937 | 60 | OopsInHeapRegionClosure* _evac_failure_cl; |
tschatzl@6937 | 61 | |
tschatzl@6937 | 62 | int _hash_seed; |
tschatzl@6937 | 63 | uint _queue_num; |
tschatzl@6937 | 64 | |
tschatzl@6937 | 65 | size_t _term_attempts; |
tschatzl@6937 | 66 | |
tschatzl@6937 | 67 | double _start; |
tschatzl@6937 | 68 | double _start_strong_roots; |
tschatzl@6937 | 69 | double _strong_roots_time; |
tschatzl@6937 | 70 | double _start_term; |
tschatzl@6937 | 71 | double _term_time; |
tschatzl@6937 | 72 | |
tschatzl@6937 | 73 | // Map from young-age-index (0 == not young, 1 is youngest) to |
tschatzl@6937 | 74 | // surviving words. base is what we get back from the malloc call |
tschatzl@6937 | 75 | size_t* _surviving_young_words_base; |
tschatzl@6937 | 76 | // this points into the array, as we use the first few entries for padding |
tschatzl@6937 | 77 | size_t* _surviving_young_words; |
tschatzl@6937 | 78 | |
tschatzl@6937 | 79 | #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t)) |
tschatzl@6937 | 80 | |
tschatzl@6937 | 81 | void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } |
tschatzl@6937 | 82 | void add_to_undo_waste(size_t waste) { _undo_waste += waste; } |
tschatzl@6937 | 83 | |
tschatzl@6937 | 84 | DirtyCardQueue& dirty_card_queue() { return _dcq; } |
tschatzl@6937 | 85 | G1SATBCardTableModRefBS* ctbs() { return _ct_bs; } |
tschatzl@6937 | 86 | |
tschatzl@7651 | 87 | InCSetState dest(InCSetState original) const { |
tschatzl@7651 | 88 | assert(original.is_valid(), |
tschatzl@7651 | 89 | err_msg("Original state invalid: " CSETSTATE_FORMAT, original.value())); |
tschatzl@7651 | 90 | assert(_dest[original.value()].is_valid_gen(), |
tschatzl@7651 | 91 | err_msg("Dest state is invalid: " CSETSTATE_FORMAT, _dest[original.value()].value())); |
tschatzl@7651 | 92 | return _dest[original.value()]; |
tschatzl@7651 | 93 | } |
tschatzl@7651 | 94 | |
tschatzl@6938 | 95 | public: |
tschatzl@6937 | 96 | G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); |
tschatzl@6938 | 97 | ~G1ParScanThreadState(); |
tschatzl@6937 | 98 | |
tschatzl@6937 | 99 | ageTable* age_table() { return &_age_table; } |
tschatzl@6937 | 100 | |
tschatzl@6937 | 101 | #ifdef ASSERT |
tschatzl@6938 | 102 | bool queue_is_empty() const { return _refs->is_empty(); } |
tschatzl@6938 | 103 | |
tschatzl@6937 | 104 | bool verify_ref(narrowOop* ref) const; |
tschatzl@6937 | 105 | bool verify_ref(oop* ref) const; |
tschatzl@6937 | 106 | bool verify_task(StarTask ref) const; |
tschatzl@6937 | 107 | #endif // ASSERT |
tschatzl@6937 | 108 | |
tschatzl@6937 | 109 | template <class T> void push_on_queue(T* ref) { |
tschatzl@6937 | 110 | assert(verify_ref(ref), "sanity"); |
tschatzl@6938 | 111 | _refs->push(ref); |
tschatzl@6937 | 112 | } |
tschatzl@6937 | 113 | |
tschatzl@7218 | 114 | template <class T> void update_rs(HeapRegion* from, T* p, int tid) { |
tschatzl@7218 | 115 | // If the new value of the field points to the same region or |
tschatzl@7218 | 116 | // is the to-space, we don't need to include it in the Rset updates. |
tschatzl@7218 | 117 | if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) { |
tschatzl@7218 | 118 | size_t card_index = ctbs()->index_for(p); |
tschatzl@7218 | 119 | // If the card hasn't been added to the buffer, do it. |
tschatzl@7218 | 120 | if (ctbs()->mark_card_deferred(card_index)) { |
tschatzl@7218 | 121 | dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index)); |
tschatzl@7218 | 122 | } |
tschatzl@7218 | 123 | } |
tschatzl@7218 | 124 | } |
tschatzl@6937 | 125 | |
tschatzl@6937 | 126 | void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) { |
tschatzl@6937 | 127 | _evac_failure_cl = evac_failure_cl; |
tschatzl@6937 | 128 | } |
tschatzl@6938 | 129 | |
tschatzl@6938 | 130 | OopsInHeapRegionClosure* evac_failure_closure() { return _evac_failure_cl; } |
tschatzl@6937 | 131 | |
tschatzl@6937 | 132 | int* hash_seed() { return &_hash_seed; } |
tschatzl@6937 | 133 | uint queue_num() { return _queue_num; } |
tschatzl@6937 | 134 | |
tschatzl@6937 | 135 | size_t term_attempts() const { return _term_attempts; } |
tschatzl@6937 | 136 | void note_term_attempt() { _term_attempts++; } |
tschatzl@6937 | 137 | |
tschatzl@6937 | 138 | void start_strong_roots() { |
tschatzl@6937 | 139 | _start_strong_roots = os::elapsedTime(); |
tschatzl@6937 | 140 | } |
tschatzl@6937 | 141 | void end_strong_roots() { |
tschatzl@6937 | 142 | _strong_roots_time += (os::elapsedTime() - _start_strong_roots); |
tschatzl@6937 | 143 | } |
tschatzl@6937 | 144 | double strong_roots_time() const { return _strong_roots_time; } |
tschatzl@6937 | 145 | |
tschatzl@6937 | 146 | void start_term_time() { |
tschatzl@6937 | 147 | note_term_attempt(); |
tschatzl@6937 | 148 | _start_term = os::elapsedTime(); |
tschatzl@6937 | 149 | } |
tschatzl@6937 | 150 | void end_term_time() { |
tschatzl@6937 | 151 | _term_time += (os::elapsedTime() - _start_term); |
tschatzl@6937 | 152 | } |
tschatzl@6937 | 153 | double term_time() const { return _term_time; } |
tschatzl@6937 | 154 | |
tschatzl@6937 | 155 | double elapsed_time() const { |
tschatzl@6937 | 156 | return os::elapsedTime() - _start; |
tschatzl@6937 | 157 | } |
tschatzl@6937 | 158 | |
tschatzl@6938 | 159 | static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty); |
tschatzl@6938 | 160 | void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const; |
tschatzl@6937 | 161 | |
tschatzl@6937 | 162 | size_t* surviving_young_words() { |
tschatzl@6937 | 163 | // We add on to hide entry 0 which accumulates surviving words for |
tschatzl@6937 | 164 | // age -1 regions (i.e. non-young ones) |
tschatzl@6937 | 165 | return _surviving_young_words; |
tschatzl@6937 | 166 | } |
tschatzl@6937 | 167 | |
tschatzl@6937 | 168 | private: |
tschatzl@6937 | 169 | #define G1_PARTIAL_ARRAY_MASK 0x2 |
tschatzl@6937 | 170 | |
tschatzl@6937 | 171 | inline bool has_partial_array_mask(oop* ref) const { |
tschatzl@6937 | 172 | return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK; |
tschatzl@6937 | 173 | } |
tschatzl@6937 | 174 | |
tschatzl@6937 | 175 | // We never encode partial array oops as narrowOop*, so return false immediately. |
tschatzl@6937 | 176 | // This allows the compiler to create optimized code when popping references from |
tschatzl@6937 | 177 | // the work queue. |
tschatzl@6937 | 178 | inline bool has_partial_array_mask(narrowOop* ref) const { |
tschatzl@6937 | 179 | assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*"); |
tschatzl@6937 | 180 | return false; |
tschatzl@6937 | 181 | } |
tschatzl@6937 | 182 | |
tschatzl@6937 | 183 | // Only implement set_partial_array_mask() for regular oops, not for narrowOops. |
tschatzl@6937 | 184 | // We always encode partial arrays as regular oop, to allow the |
tschatzl@6937 | 185 | // specialization for has_partial_array_mask() for narrowOops above. |
tschatzl@6937 | 186 | // This means that unintentional use of this method with narrowOops are caught |
tschatzl@6937 | 187 | // by the compiler. |
tschatzl@6937 | 188 | inline oop* set_partial_array_mask(oop obj) const { |
tschatzl@6937 | 189 | assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!"); |
tschatzl@6937 | 190 | return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK); |
tschatzl@6937 | 191 | } |
tschatzl@6937 | 192 | |
tschatzl@6937 | 193 | inline oop clear_partial_array_mask(oop* ref) const { |
tschatzl@6937 | 194 | return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK); |
tschatzl@6937 | 195 | } |
tschatzl@6937 | 196 | |
tschatzl@6937 | 197 | inline void do_oop_partial_array(oop* p); |
tschatzl@6937 | 198 | |
tschatzl@6937 | 199 | // This method is applied to the fields of the objects that have just been copied. |
tschatzl@6938 | 200 | template <class T> inline void do_oop_evac(T* p, HeapRegion* from); |
tschatzl@6937 | 201 | |
tschatzl@6938 | 202 | template <class T> inline void deal_with_reference(T* ref_to_scan); |
tschatzl@6937 | 203 | |
tschatzl@6938 | 204 | inline void dispatch_reference(StarTask ref); |
tschatzl@7651 | 205 | |
tschatzl@7651 | 206 | // Tries to allocate word_sz in the PLAB of the next "generation" after trying to |
tschatzl@7651 | 207 | // allocate into dest. State is the original (source) cset state for the object |
tschatzl@7651 | 208 | // that is allocated for. |
tschatzl@7651 | 209 | // Returns a non-NULL pointer if successful, and updates dest if required. |
tschatzl@7651 | 210 | HeapWord* allocate_in_next_plab(InCSetState const state, |
tschatzl@7651 | 211 | InCSetState* dest, |
tschatzl@7651 | 212 | size_t word_sz, |
tschatzl@7651 | 213 | AllocationContext_t const context); |
tschatzl@7651 | 214 | |
apetushkov@9858 | 215 | void report_promotion_event(InCSetState const dest_state, |
apetushkov@9858 | 216 | oop const old, size_t word_sz, uint age, |
apetushkov@9858 | 217 | HeapWord * const obj_ptr, AllocationContext_t context) const; |
apetushkov@9858 | 218 | |
tschatzl@7651 | 219 | inline InCSetState next_state(InCSetState const state, markOop const m, uint& age); |
tschatzl@6938 | 220 | public: |
tschatzl@6937 | 221 | |
tschatzl@7651 | 222 | oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark); |
tschatzl@6937 | 223 | |
tschatzl@6938 | 224 | void trim_queue(); |
tschatzl@6937 | 225 | |
tschatzl@6938 | 226 | inline void steal_and_trim_queue(RefToScanQueueSet *task_queues); |
tschatzl@6937 | 227 | }; |
tschatzl@6937 | 228 | |
tschatzl@6937 | 229 | #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP |