42 void set_card_table(G1CardTable* card_table) { _card_table = card_table; } |
42 void set_card_table(G1CardTable* card_table) { _card_table = card_table; } |
43 |
43 |
44 virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); |
44 virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); |
45 }; |
45 }; |
46 |
46 |
47 class G1CardTable: public CardTable { |
47 class G1CardTable : public CardTable { |
48 friend class VMStructs; |
48 friend class VMStructs; |
49 friend class G1CardTableChangedListener; |
49 friend class G1CardTableChangedListener; |
50 |
50 |
51 G1CardTableChangedListener _listener; |
51 G1CardTableChangedListener _listener; |
52 |
52 |
|
53 public: |
53 enum G1CardValues { |
54 enum G1CardValues { |
54 g1_young_gen = CT_MR_BS_last_reserved << 1 |
55 g1_young_gen = CT_MR_BS_last_reserved << 1, |
|
56 |
|
57 // During evacuation we use the card table to consolidate the cards we need to |
|
58 // scan for roots onto the card table from the various sources. Further it is |
|
59 // used to record already completely scanned cards to avoid re-scanning them |
|
60 // when incrementally evacuating the old gen regions of a collection set. |
|
61 // This means that already scanned cards should be preserved. |
|
62 // |
|
63 // The merge at the start of each evacuation round simply sets cards to dirty |
|
64 // that are clean; scanned cards are set to 0x1. |
|
65 // |
|
66 // This means that the LSB determines what to do with the card during evacuation |
|
67 // given the following possible values: |
|
68 // |
|
69 // 11111111 - clean, do not scan |
|
70 // 00000001 - already scanned, do not scan |
|
71 // 00000000 - dirty, needs to be scanned. |
|
72 // |
|
73 g1_card_already_scanned = 0x1 |
55 }; |
74 }; |
56 |
75 |
57 public: |
76 static const size_t WordAllClean = SIZE_MAX; |
|
77 static const size_t WordAllDirty = 0; |
|
78 |
|
79 STATIC_ASSERT(BitsPerByte == 8); |
|
80 static const size_t WordAlreadyScanned = (SIZE_MAX / 255) * g1_card_already_scanned; |
|
81 |
58 G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() { |
82 G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() { |
59 _listener.set_card_table(this); |
83 _listener.set_card_table(this); |
60 } |
|
61 bool is_card_dirty(size_t card_index) { |
|
62 return _byte_map[card_index] == dirty_card_val(); |
|
63 } |
84 } |
64 |
85 |
65 static CardValue g1_young_card_val() { return g1_young_gen; } |
86 static CardValue g1_young_card_val() { return g1_young_gen; } |
66 |
87 |
67 /* |
|
68 Claimed and deferred bits are used together in G1 during the evacuation |
|
69 pause. These bits can have the following state transitions: |
|
70 1. The claimed bit can be put over any other card state. Except that |
|
71 the "dirty -> dirty and claimed" transition is checked for in |
|
72 G1 code and is not used. |
|
73 2. Deferred bit can be set only if the previous state of the card |
|
74 was either clean or claimed. mark_card_deferred() is wait-free. |
|
75 We do not care if the operation is be successful because if |
|
76 it does not it will only result in duplicate entry in the update |
|
77 buffer because of the "cache-miss". So it's not worth spinning. |
|
78 */ |
|
79 |
|
80 bool is_card_claimed(size_t card_index) { |
|
81 CardValue val = _byte_map[card_index]; |
|
82 return (val & (clean_card_mask_val() | claimed_card_val())) == claimed_card_val(); |
|
83 } |
|
84 |
|
85 inline void set_card_claimed(size_t card_index); |
|
86 |
|
87 void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN; |
88 void verify_g1_young_region(MemRegion mr) PRODUCT_RETURN; |
88 void g1_mark_as_young(const MemRegion& mr); |
89 void g1_mark_as_young(const MemRegion& mr); |
89 |
90 |
90 bool mark_card_deferred(size_t card_index); |
91 size_t index_for_cardvalue(CardValue const* p) const { |
|
92 return pointer_delta(p, _byte_map, sizeof(CardValue)); |
|
93 } |
91 |
94 |
92 bool is_card_deferred(size_t card_index) { |
95 // Mark the given card as Dirty if it is Clean. |
93 CardValue val = _byte_map[card_index]; |
96 inline void mark_clean_as_dirty(size_t card_index); |
94 return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val(); |
97 |
95 } |
98 // Change Clean cards in a (large) area on the card table as Dirty, preserving |
|
99 // already scanned cards. Assumes that most cards in that area are Clean. |
|
100 inline void mark_region_dirty(size_t start_card_index, size_t num_cards); |
|
101 |
|
102 // Mark the given range of cards as Scanned. All of these cards must be Dirty. |
|
103 inline void mark_as_scanned(size_t start_card_index, size_t num_cards); |
|
104 |
|
105 inline uint region_idx_for(CardValue* p); |
96 |
106 |
97 static size_t compute_size(size_t mem_region_size_in_words) { |
107 static size_t compute_size(size_t mem_region_size_in_words) { |
98 size_t number_of_slots = (mem_region_size_in_words / card_size_in_words); |
108 size_t number_of_slots = (mem_region_size_in_words / card_size_in_words); |
99 return ReservedSpace::allocation_align_size_up(number_of_slots); |
109 return ReservedSpace::allocation_align_size_up(number_of_slots); |
100 } |
110 } |