25
25
#include " precompiled.hpp"
26
26
#include " gc/parallel/objectStartArray.inline.hpp"
27
27
#include " gc/shared/cardTableBarrierSet.hpp"
28
- #include " memory/allocation.inline.hpp"
29
28
#include " nmt/memTracker.hpp"
30
29
#include " oops/oop.inline.hpp"
31
30
#include " runtime/java.hpp"
32
31
#include " utilities/align.hpp"
33
32
34
- uint ObjectStartArray::_card_shift = 0 ;
35
- uint ObjectStartArray::_card_size = 0 ;
36
- uint ObjectStartArray::_card_size_in_words = 0 ;
33
+ static size_t num_bytes_required (MemRegion mr) {
34
+ assert ( CardTable::is_card_aligned (mr. start ()), " precondition " ) ;
35
+ assert ( CardTable::is_card_aligned (mr. end ()), " precondition " ) ;
37
36
38
- void ObjectStartArray::initialize_block_size (uint card_shift) {
39
- _card_shift = card_shift;
40
- _card_size = 1 << _card_shift;
41
- _card_size_in_words = _card_size / sizeof (HeapWord);
37
+ return mr.word_size () / BOTConstants::card_size_in_words ();
42
38
}
43
39
44
40
void ObjectStartArray::initialize (MemRegion reserved_region) {
45
- // We're based on the assumption that we use the same
46
- // size blocks as the card table.
47
- assert (_card_size == CardTable::card_size (), " Sanity" );
48
- assert (_card_size <= MaxBlockSize, " block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize);
49
-
50
41
// Calculate how much space must be reserved
51
- _reserved_region = reserved_region;
52
-
53
- size_t bytes_to_reserve = reserved_region.word_size () / _card_size_in_words;
42
+ size_t bytes_to_reserve = num_bytes_required (reserved_region);
54
43
assert (bytes_to_reserve > 0 , " Sanity" );
55
44
56
45
bytes_to_reserve =
@@ -62,91 +51,96 @@ void ObjectStartArray::initialize(MemRegion reserved_region) {
62
51
if (!backing_store.is_reserved ()) {
63
52
vm_exit_during_initialization (" Could not reserve space for ObjectStartArray" );
64
53
}
65
- MemTracker::record_virtual_memory_type ((address) backing_store.base (), mtGC);
54
+ MemTracker::record_virtual_memory_type (backing_store.base (), mtGC);
66
55
67
56
// We do not commit any memory initially
68
57
_virtual_space.initialize (backing_store);
69
58
70
- _raw_base = (jbyte*)_virtual_space.low_boundary ();
71
- assert (_raw_base != nullptr , " set from the backing_store" );
72
-
73
- _offset_base = _raw_base - (size_t (reserved_region.start ()) >> _card_shift);
74
-
75
- _covered_region.set_start (reserved_region.start ());
76
- _covered_region.set_word_size (0 );
59
+ assert (_virtual_space.low_boundary () != nullptr , " set from the backing_store" );
77
60
78
- _blocks_region.set_start ((HeapWord*)_raw_base);
79
- _blocks_region.set_word_size (0 );
61
+ _offset_base = (uint8_t *)(_virtual_space.low_boundary () - (uintptr_t (reserved_region.start ()) >> BOTConstants::log_card_size ()));
80
62
}
81
63
82
64
void ObjectStartArray::set_covered_region (MemRegion mr) {
83
- assert (_reserved_region.contains (mr), " MemRegion outside of reserved space" );
84
- assert (_reserved_region.start () == mr.start (), " Attempt to move covered region" );
85
-
86
- HeapWord* low_bound = mr.start ();
87
- HeapWord* high_bound = mr.end ();
88
- assert ((uintptr_t (low_bound) & (_card_size - 1 )) == 0 , " heap must start at block boundary" );
89
- assert ((uintptr_t (high_bound) & (_card_size - 1 )) == 0 , " heap must end at block boundary" );
90
-
91
- size_t requested_blocks_size_in_bytes = mr.word_size () / _card_size_in_words;
65
+ DEBUG_ONLY (_covered_region = mr;)
92
66
67
+ size_t requested_size = num_bytes_required (mr);
93
68
// Only commit memory in page sized chunks
94
- requested_blocks_size_in_bytes =
95
- align_up (requested_blocks_size_in_bytes, os::vm_page_size ());
69
+ requested_size = align_up (requested_size, os::vm_page_size ());
96
70
97
- _covered_region = mr ;
71
+ size_t current_size = _virtual_space. committed_size () ;
98
72
99
- size_t current_blocks_size_in_bytes = _blocks_region.byte_size ();
73
+ if (requested_size == current_size) {
74
+ return ;
75
+ }
100
76
101
- if (requested_blocks_size_in_bytes > current_blocks_size_in_bytes ) {
77
+ if (requested_size > current_size ) {
102
78
// Expand
103
- size_t expand_by = requested_blocks_size_in_bytes - current_blocks_size_in_bytes ;
79
+ size_t expand_by = requested_size - current_size ;
104
80
if (!_virtual_space.expand_by (expand_by)) {
105
81
vm_exit_out_of_memory (expand_by, OOM_MMAP_ERROR, " object start array expansion" );
106
82
}
107
- // Clear *only* the newly allocated region
108
- memset (_blocks_region.end (), clean_block, expand_by);
109
- }
110
-
111
- if (requested_blocks_size_in_bytes < current_blocks_size_in_bytes) {
83
+ } else {
112
84
// Shrink
113
- size_t shrink_by = current_blocks_size_in_bytes - requested_blocks_size_in_bytes ;
85
+ size_t shrink_by = current_size - requested_size ;
114
86
_virtual_space.shrink_by (shrink_by);
115
87
}
116
-
117
- _blocks_region.set_word_size (requested_blocks_size_in_bytes / sizeof (HeapWord));
118
-
119
- assert (requested_blocks_size_in_bytes % sizeof (HeapWord) == 0 , " Block table not expanded in word sized increment" );
120
- assert (requested_blocks_size_in_bytes == _blocks_region.byte_size (), " Sanity" );
121
- assert (block_for_addr (low_bound) == &_raw_base[0 ], " Checking start of map" );
122
- assert (block_for_addr (high_bound-1 ) <= &_raw_base[_blocks_region.byte_size ()-1 ], " Checking end of map" );
123
88
}
124
89
125
- void ObjectStartArray::reset () {
126
- memset (_blocks_region.start (), clean_block, _blocks_region.byte_size ());
90
+ static void fill_range (uint8_t * start, uint8_t * end, uint8_t v) {
91
+ // + 1 for inclusive
92
+ memset (start, v, pointer_delta (end, start, sizeof (uint8_t )) + 1 );
127
93
}
128
94
129
- bool ObjectStartArray::object_starts_in_range (HeapWord* start_addr,
130
- HeapWord* end_addr) const {
131
- assert (start_addr <= end_addr,
132
- " Range is wrong. start_addr (" PTR_FORMAT " ) is after end_addr (" PTR_FORMAT " )" ,
133
- p2i (start_addr), p2i (end_addr));
134
-
135
- assert (is_aligned (start_addr, _card_size), " precondition" );
136
-
137
- if (start_addr == end_addr) {
138
- // No objects in empty range.
139
- return false ;
95
+ void ObjectStartArray::update_for_block_work (HeapWord* blk_start,
96
+ HeapWord* blk_end) {
97
+ HeapWord* const cur_card_boundary = align_up_by_card_size (blk_start);
98
+ uint8_t * const offset_entry = entry_for_addr (cur_card_boundary);
99
+
100
+ // The first card holds the actual offset.
101
+ *offset_entry = checked_cast<uint8_t >(pointer_delta (cur_card_boundary, blk_start));
102
+
103
+ // Check if this block spans over other cards.
104
+ uint8_t * const end_entry = entry_for_addr (blk_end - 1 );
105
+ assert (offset_entry <= end_entry, " inv" );
106
+
107
+ if (offset_entry != end_entry) {
108
+ // Handling remaining entries.
109
+ uint8_t * start_entry_for_region = offset_entry + 1 ;
110
+ for (uint i = 0 ; i < BOTConstants::N_powers; i++) {
111
+ // -1 so that the reach ends in this region and not at the start
112
+ // of the next.
113
+ uint8_t * reach = offset_entry + BOTConstants::power_to_cards_back (i + 1 ) - 1 ;
114
+ uint8_t value = checked_cast<uint8_t >(BOTConstants::card_size_in_words () + i);
115
+
116
+ fill_range (start_entry_for_region, MIN2 (reach, end_entry), value);
117
+ start_entry_for_region = reach + 1 ;
118
+
119
+ if (reach >= end_entry) {
120
+ break ;
121
+ }
122
+ }
123
+ assert (start_entry_for_region > end_entry, " Sanity check" );
140
124
}
141
125
142
- jbyte* start_block = block_for_addr (start_addr);
143
- jbyte* end_block = block_for_addr (end_addr - 1 );
126
+ debug_only ( verify_for_block (blk_start, blk_end);)
127
+ }
144
128
145
- for (jbyte* block = start_block; block <= end_block; block++) {
146
- if (*block != clean_block) {
147
- return true ;
129
+ void ObjectStartArray::verify_for_block (HeapWord* blk_start, HeapWord* blk_end) const {
130
+ assert (is_crossing_card_boundary (blk_start, blk_end), " precondition" );
131
+
132
+ const uint8_t * const start_entry = entry_for_addr (align_up_by_card_size (blk_start));
133
+ const uint8_t * const end_entry = entry_for_addr (blk_end - 1 );
134
+ // Check entries in [start_entry, end_entry]
135
+ assert (*start_entry < BOTConstants::card_size_in_words (), " offset entry" );
136
+
137
+ for (const uint8_t * i = start_entry + 1 ; i <= end_entry; ++i) {
138
+ const uint8_t prev = *(i-1 );
139
+ const uint8_t value = *i;
140
+ if (prev != value) {
141
+ assert (value >= prev, " monotonic" );
142
+ size_t n_cards_back = BOTConstants::entry_to_cards_back (value);
143
+ assert (start_entry == (i - n_cards_back), " inv" );
148
144
}
149
145
}
150
-
151
- return false ;
152
146
}
0 commit comments