28 #include "gc/g1/g1BlockOffsetTable.hpp" |
28 #include "gc/g1/g1BlockOffsetTable.hpp" |
29 #include "gc/g1/heapRegion.hpp" |
29 #include "gc/g1/heapRegion.hpp" |
30 #include "gc/shared/memset_with_concurrent_readers.hpp" |
30 #include "gc/shared/memset_with_concurrent_readers.hpp" |
31 #include "gc/shared/space.hpp" |
31 #include "gc/shared/space.hpp" |
32 |
32 |
33 inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) { |
33 inline HeapWord* G1BlockOffsetTablePart::block_start(const void* addr) { |
34 if (addr >= _bottom && addr < _end) { |
34 if (addr >= _space->bottom() && addr < _space->end()) { |
35 return block_start_unsafe(addr); |
35 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1); |
|
36 return forward_to_block_containing_addr(q, addr); |
36 } else { |
37 } else { |
37 return NULL; |
38 return NULL; |
38 } |
39 } |
39 } |
40 } |
40 |
41 |
41 inline HeapWord* |
42 inline HeapWord* G1BlockOffsetTablePart::block_start_const(const void* addr) const { |
42 G1BlockOffsetTable::block_start_const(const void* addr) const { |
43 if (addr >= _space->bottom() && addr < _space->end()) { |
43 if (addr >= _bottom && addr < _end) { |
44 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1); |
44 return block_start_unsafe_const(addr); |
45 HeapWord* n = q + block_size(q); |
|
46 return forward_to_block_containing_addr_const(q, n, addr); |
45 } else { |
47 } else { |
46 return NULL; |
48 return NULL; |
47 } |
49 } |
48 } |
50 } |
49 |
51 |
50 u_char G1BlockOffsetSharedArray::offset_array(size_t index) const { |
52 u_char G1BlockOffsetTable::offset_array(size_t index) const { |
51 check_index(index, "index out of range"); |
53 check_index(index, "index out of range"); |
52 return _offset_array[index]; |
54 return _offset_array[index]; |
53 } |
55 } |
54 |
56 |
55 void G1BlockOffsetSharedArray::set_offset_array(size_t index, u_char offset) { |
57 void G1BlockOffsetTable::set_offset_array(size_t index, u_char offset) { |
56 check_index(index, "index out of range"); |
58 check_index(index, "index out of range"); |
57 set_offset_array_raw(index, offset); |
59 set_offset_array_raw(index, offset); |
58 } |
60 } |
59 |
61 |
60 void G1BlockOffsetSharedArray::set_offset_array(size_t index, HeapWord* high, HeapWord* low) { |
62 void G1BlockOffsetTable::set_offset_array(size_t index, HeapWord* high, HeapWord* low) { |
61 check_index(index, "index out of range"); |
63 check_index(index, "index out of range"); |
62 assert(high >= low, "addresses out of order"); |
64 assert(high >= low, "addresses out of order"); |
63 size_t offset = pointer_delta(high, low); |
65 size_t offset = pointer_delta(high, low); |
64 check_offset(offset, "offset too large"); |
66 check_offset(offset, "offset too large"); |
65 set_offset_array(index, (u_char)offset); |
67 set_offset_array(index, (u_char)offset); |
66 } |
68 } |
67 |
69 |
68 void G1BlockOffsetSharedArray::set_offset_array(size_t left, size_t right, u_char offset) { |
70 void G1BlockOffsetTable::set_offset_array(size_t left, size_t right, u_char offset) { |
69 check_index(right, "right index out of range"); |
71 check_index(right, "right index out of range"); |
70 assert(left <= right, "indexes out of order"); |
72 assert(left <= right, "indexes out of order"); |
71 size_t num_cards = right - left + 1; |
73 size_t num_cards = right - left + 1; |
72 memset_with_concurrent_readers(&_offset_array[left], offset, num_cards); |
74 memset_with_concurrent_readers(&_offset_array[left], offset, num_cards); |
73 } |
75 } |
74 |
76 |
75 // Variant of index_for that does not check the index for validity. |
77 // Variant of index_for that does not check the index for validity. |
76 inline size_t G1BlockOffsetSharedArray::index_for_raw(const void* p) const { |
78 inline size_t G1BlockOffsetTable::index_for_raw(const void* p) const { |
77 return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN; |
79 return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN; |
78 } |
80 } |
79 |
81 |
80 inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const { |
82 inline size_t G1BlockOffsetTable::index_for(const void* p) const { |
81 char* pc = (char*)p; |
83 char* pc = (char*)p; |
82 assert(pc >= (char*)_reserved.start() && |
84 assert(pc >= (char*)_reserved.start() && |
83 pc < (char*)_reserved.end(), |
85 pc < (char*)_reserved.end(), |
84 "p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")", |
86 "p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")", |
85 p2i(p), p2i(_reserved.start()), p2i(_reserved.end())); |
87 p2i(p), p2i(_reserved.start()), p2i(_reserved.end())); |
86 size_t result = index_for_raw(p); |
88 size_t result = index_for_raw(p); |
87 check_index(result, "bad index from address"); |
89 check_index(result, "bad index from address"); |
88 return result; |
90 return result; |
89 } |
91 } |
90 |
92 |
91 inline HeapWord* |
93 inline HeapWord* G1BlockOffsetTable::address_for_index(size_t index) const { |
92 G1BlockOffsetSharedArray::address_for_index(size_t index) const { |
|
93 check_index(index, "index out of range"); |
94 check_index(index, "index out of range"); |
94 HeapWord* result = address_for_index_raw(index); |
95 HeapWord* result = address_for_index_raw(index); |
95 assert(result >= _reserved.start() && result < _reserved.end(), |
96 assert(result >= _reserved.start() && result < _reserved.end(), |
96 "bad address from index result " PTR_FORMAT |
97 "bad address from index result " PTR_FORMAT |
97 " _reserved.start() " PTR_FORMAT " _reserved.end() " PTR_FORMAT, |
98 " _reserved.start() " PTR_FORMAT " _reserved.end() " PTR_FORMAT, |
98 p2i(result), p2i(_reserved.start()), p2i(_reserved.end())); |
99 p2i(result), p2i(_reserved.start()), p2i(_reserved.end())); |
99 return result; |
100 return result; |
100 } |
101 } |
101 |
102 |
102 inline size_t |
103 inline size_t G1BlockOffsetTablePart::block_size(const HeapWord* p) const { |
103 G1BlockOffsetArray::block_size(const HeapWord* p) const { |
104 return _space->block_size(p); |
104 return gsp()->block_size(p); |
|
105 } |
105 } |
106 |
106 |
107 inline HeapWord* |
107 inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr, |
108 G1BlockOffsetArray::block_at_or_preceding(const void* addr, |
108 bool has_max_index, |
109 bool has_max_index, |
109 size_t max_index) const { |
110 size_t max_index) const { |
110 assert(_bot->offset_array(0) == 0, "objects can't cross covered areas"); |
111 assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); |
111 size_t index = _bot->index_for(addr); |
112 size_t index = _array->index_for(addr); |
|
113 // We must make sure that the offset table entry we use is valid. If |
112 // We must make sure that the offset table entry we use is valid. If |
114 // "addr" is past the end, start at the last known one and go forward. |
113 // "addr" is past the end, start at the last known one and go forward. |
115 if (has_max_index) { |
114 if (has_max_index) { |
116 index = MIN2(index, max_index); |
115 index = MIN2(index, max_index); |
117 } |
116 } |
118 HeapWord* q = _array->address_for_index(index); |
117 HeapWord* q = _bot->address_for_index(index); |
119 |
118 |
120 uint offset = _array->offset_array(index); // Extend u_char to uint. |
119 uint offset = _bot->offset_array(index); // Extend u_char to uint. |
121 while (offset >= N_words) { |
120 while (offset >= N_words) { |
122 // The excess of the offset from N_words indicates a power of Base |
121 // The excess of the offset from N_words indicates a power of Base |
123 // to go back by. |
122 // to go back by. |
124 size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset); |
123 size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset); |
125 q -= (N_words * n_cards_back); |
124 q -= (N_words * n_cards_back); |
126 index -= n_cards_back; |
125 index -= n_cards_back; |
127 offset = _array->offset_array(index); |
126 offset = _bot->offset_array(index); |
128 } |
127 } |
129 assert(offset < N_words, "offset too large"); |
128 assert(offset < N_words, "offset too large"); |
130 q -= offset; |
129 q -= offset; |
131 return q; |
130 return q; |
132 } |
131 } |
133 |
132 |
134 inline HeapWord* |
133 inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n, |
135 G1BlockOffsetArray:: |
134 const void* addr) const { |
136 forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n, |
135 if (addr >= _space->top()) return _space->top(); |
137 const void* addr) const { |
|
138 if (addr >= gsp()->top()) return gsp()->top(); |
|
139 while (n <= addr) { |
136 while (n <= addr) { |
140 q = n; |
137 q = n; |
141 oop obj = oop(q); |
138 oop obj = oop(q); |
142 if (obj->klass_or_null() == NULL) return q; |
139 if (obj->klass_or_null() == NULL) { |
|
140 return q; |
|
141 } |
143 n += block_size(q); |
142 n += block_size(q); |
144 } |
143 } |
145 assert(q <= n, "wrong order for q and addr"); |
144 assert(q <= n, "wrong order for q and addr"); |
146 assert(addr < n, "wrong order for addr and n"); |
145 assert(addr < n, "wrong order for addr and n"); |
147 return q; |
146 return q; |
148 } |
147 } |
149 |
148 |
150 inline HeapWord* |
149 inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWord* q, |
151 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q, |
150 const void* addr) { |
152 const void* addr) { |
151 if (oop(q)->klass_or_null() == NULL) { |
153 if (oop(q)->klass_or_null() == NULL) return q; |
152 return q; |
|
153 } |
154 HeapWord* n = q + block_size(q); |
154 HeapWord* n = q + block_size(q); |
155 // In the normal case, where the query "addr" is a card boundary, and the |
155 // In the normal case, where the query "addr" is a card boundary, and the |
156 // offset table chunks are the same size as cards, the block starting at |
156 // offset table chunks are the same size as cards, the block starting at |
157 // "q" will contain addr, so the test below will fail, and we'll fall |
157 // "q" will contain addr, so the test below will fail, and we'll fall |
158 // through quickly. |
158 // through quickly. |