Mercurial > hg > truffle
comparison src/share/vm/utilities/hashtable.hpp @ 6197:d2a62e0f25eb
6995781: Native Memory Tracking (Phase 1)
7151532: DCmd for hotspot native memory tracking
Summary: Implementation of native memory tracking phase 1, which tracks VM native memory usage, and related DCmd
Reviewed-by: acorn, coleenp, fparain
author | zgu |
---|---|
date | Thu, 28 Jun 2012 17:03:16 -0400 |
parents | 246d977b51f2 |
children | ace99a6ffc83 |
comparison
equal
deleted
inserted
replaced
6174:74533f63b116 | 6197:d2a62e0f25eb |
---|---|
38 // %note: | 38 // %note: |
39 // - TableEntrys are allocated in blocks to reduce the space overhead. | 39 // - TableEntrys are allocated in blocks to reduce the space overhead. |
40 | 40 |
41 | 41 |
42 | 42 |
43 class BasicHashtableEntry : public CHeapObj { | 43 template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> { |
44 friend class VMStructs; | 44 friend class VMStructs; |
45 private: | 45 private: |
46 unsigned int _hash; // 32-bit hash for item | 46 unsigned int _hash; // 32-bit hash for item |
47 | 47 |
48 // Link to next element in the linked list for this bucket. EXCEPT | 48 // Link to next element in the linked list for this bucket. EXCEPT |
50 // unlinked from the table. Bit 0 is set during the dumping of the | 50 // unlinked from the table. Bit 0 is set during the dumping of the |
51 // archive. Since shared entries are immutable, _next fields in the | 51 // archive. Since shared entries are immutable, _next fields in the |
52 // shared entries will not change. New entries will always be | 52 // shared entries will not change. New entries will always be |
53 // unshared and since pointers are align, bit 0 will always remain 0 | 53 // unshared and since pointers are align, bit 0 will always remain 0 |
54 // with no extra effort. | 54 // with no extra effort. |
55 BasicHashtableEntry* _next; | 55 BasicHashtableEntry<F>* _next; |
56 | 56 |
57 // Windows IA64 compiler requires subclasses to be able to access these | 57 // Windows IA64 compiler requires subclasses to be able to access these |
58 protected: | 58 protected: |
59 // Entry objects should not be created, they should be taken from the | 59 // Entry objects should not be created, they should be taken from the |
60 // free list with BasicHashtable.new_entry(). | 60 // free list with BasicHashtable.new_entry(). |
67 | 67 |
68 unsigned int hash() const { return _hash; } | 68 unsigned int hash() const { return _hash; } |
69 void set_hash(unsigned int hash) { _hash = hash; } | 69 void set_hash(unsigned int hash) { _hash = hash; } |
70 unsigned int* hash_addr() { return &_hash; } | 70 unsigned int* hash_addr() { return &_hash; } |
71 | 71 |
72 static BasicHashtableEntry* make_ptr(BasicHashtableEntry* p) { | 72 static BasicHashtableEntry<F>* make_ptr(BasicHashtableEntry<F>* p) { |
73 return (BasicHashtableEntry*)((intptr_t)p & -2); | 73 return (BasicHashtableEntry*)((intptr_t)p & -2); |
74 } | 74 } |
75 | 75 |
76 BasicHashtableEntry* next() const { | 76 BasicHashtableEntry<F>* next() const { |
77 return make_ptr(_next); | 77 return make_ptr(_next); |
78 } | 78 } |
79 | 79 |
80 void set_next(BasicHashtableEntry* next) { | 80 void set_next(BasicHashtableEntry<F>* next) { |
81 _next = next; | 81 _next = next; |
82 } | 82 } |
83 | 83 |
84 BasicHashtableEntry** next_addr() { | 84 BasicHashtableEntry<F>** next_addr() { |
85 return &_next; | 85 return &_next; |
86 } | 86 } |
87 | 87 |
88 bool is_shared() const { | 88 bool is_shared() const { |
89 return ((intptr_t)_next & 1) != 0; | 89 return ((intptr_t)_next & 1) != 0; |
90 } | 90 } |
91 | 91 |
92 void set_shared() { | 92 void set_shared() { |
93 _next = (BasicHashtableEntry*)((intptr_t)_next | 1); | 93 _next = (BasicHashtableEntry<F>*)((intptr_t)_next | 1); |
94 } | 94 } |
95 }; | 95 }; |
96 | 96 |
97 | 97 |
98 | 98 |
99 template <class T> class HashtableEntry : public BasicHashtableEntry { | 99 template <class T, MEMFLAGS F> class HashtableEntry : public BasicHashtableEntry<F> { |
100 friend class VMStructs; | 100 friend class VMStructs; |
101 private: | 101 private: |
102 T _literal; // ref to item in table. | 102 T _literal; // ref to item in table. |
103 | 103 |
104 public: | 104 public: |
106 T literal() const { return _literal; } | 106 T literal() const { return _literal; } |
107 T* literal_addr() { return &_literal; } | 107 T* literal_addr() { return &_literal; } |
108 void set_literal(T s) { _literal = s; } | 108 void set_literal(T s) { _literal = s; } |
109 | 109 |
110 HashtableEntry* next() const { | 110 HashtableEntry* next() const { |
111 return (HashtableEntry*)BasicHashtableEntry::next(); | 111 return (HashtableEntry*)BasicHashtableEntry<F>::next(); |
112 } | 112 } |
113 HashtableEntry** next_addr() { | 113 HashtableEntry** next_addr() { |
114 return (HashtableEntry**)BasicHashtableEntry::next_addr(); | 114 return (HashtableEntry**)BasicHashtableEntry<F>::next_addr(); |
115 } | 115 } |
116 }; | 116 }; |
117 | 117 |
118 | 118 |
119 | 119 |
120 class HashtableBucket : public CHeapObj { | 120 template <MEMFLAGS F> class HashtableBucket : public CHeapObj<F> { |
121 friend class VMStructs; | 121 friend class VMStructs; |
122 private: | 122 private: |
123 // Instance variable | 123 // Instance variable |
124 BasicHashtableEntry* _entry; | 124 BasicHashtableEntry<F>* _entry; |
125 | 125 |
126 public: | 126 public: |
127 // Accessing | 127 // Accessing |
128 void clear() { _entry = NULL; } | 128 void clear() { _entry = NULL; } |
129 | 129 |
130 // The following methods use order access methods to avoid race | 130 // The following methods use order access methods to avoid race |
131 // conditions in multiprocessor systems. | 131 // conditions in multiprocessor systems. |
132 BasicHashtableEntry* get_entry() const; | 132 BasicHashtableEntry<F>* get_entry() const; |
133 void set_entry(BasicHashtableEntry* l); | 133 void set_entry(BasicHashtableEntry<F>* l); |
134 | 134 |
135 // The following method is not MT-safe and must be done under lock. | 135 // The following method is not MT-safe and must be done under lock. |
136 BasicHashtableEntry** entry_addr() { return &_entry; } | 136 BasicHashtableEntry<F>** entry_addr() { return &_entry; } |
137 }; | 137 }; |
138 | 138 |
139 | 139 |
140 class BasicHashtable : public CHeapObj { | 140 template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> { |
141 friend class VMStructs; | 141 friend class VMStructs; |
142 | 142 |
143 public: | 143 public: |
144 BasicHashtable(int table_size, int entry_size); | 144 BasicHashtable(int table_size, int entry_size); |
145 BasicHashtable(int table_size, int entry_size, | 145 BasicHashtable(int table_size, int entry_size, |
146 HashtableBucket* buckets, int number_of_entries); | 146 HashtableBucket<F>* buckets, int number_of_entries); |
147 | 147 |
148 // Sharing support. | 148 // Sharing support. |
149 void copy_buckets(char** top, char* end); | 149 void copy_buckets(char** top, char* end); |
150 void copy_table(char** top, char* end); | 150 void copy_table(char** top, char* end); |
151 | 151 |
160 void reverse(); | 160 void reverse(); |
161 | 161 |
162 private: | 162 private: |
163 // Instance variables | 163 // Instance variables |
164 int _table_size; | 164 int _table_size; |
165 HashtableBucket* _buckets; | 165 HashtableBucket<F>* _buckets; |
166 BasicHashtableEntry* _free_list; | 166 BasicHashtableEntry<F>* _free_list; |
167 char* _first_free_entry; | 167 char* _first_free_entry; |
168 char* _end_block; | 168 char* _end_block; |
169 int _entry_size; | 169 int _entry_size; |
170 int _number_of_entries; | 170 int _number_of_entries; |
171 | 171 |
186 | 186 |
187 // Accessor | 187 // Accessor |
188 int entry_size() const { return _entry_size; } | 188 int entry_size() const { return _entry_size; } |
189 | 189 |
190 // The following method is MT-safe and may be used with caution. | 190 // The following method is MT-safe and may be used with caution. |
191 BasicHashtableEntry* bucket(int i); | 191 BasicHashtableEntry<F>* bucket(int i); |
192 | 192 |
193 // The following method is not MT-safe and must be done under lock. | 193 // The following method is not MT-safe and must be done under lock. |
194 BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); } | 194 BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); } |
195 | 195 |
196 // Table entry management | 196 // Table entry management |
197 BasicHashtableEntry* new_entry(unsigned int hashValue); | 197 BasicHashtableEntry<F>* new_entry(unsigned int hashValue); |
198 | 198 |
199 // Check that the table is unbalanced | 199 // Check that the table is unbalanced |
200 bool check_rehash_table(int count); | 200 bool check_rehash_table(int count); |
201 | 201 |
202 // Used when moving the entry to another table | 202 // Used when moving the entry to another table |
203 // Clean up links, but do not add to free_list | 203 // Clean up links, but do not add to free_list |
204 void unlink_entry(BasicHashtableEntry* entry) { | 204 void unlink_entry(BasicHashtableEntry<F>* entry) { |
205 entry->set_next(NULL); | 205 entry->set_next(NULL); |
206 --_number_of_entries; | 206 --_number_of_entries; |
207 } | 207 } |
208 | 208 |
209 // Move over freelist and free block for allocation | 209 // Move over freelist and free block for allocation |
219 // Free the buckets in this hashtable | 219 // Free the buckets in this hashtable |
220 void free_buckets(); | 220 void free_buckets(); |
221 | 221 |
222 public: | 222 public: |
223 int table_size() { return _table_size; } | 223 int table_size() { return _table_size; } |
224 void set_entry(int index, BasicHashtableEntry* entry); | 224 void set_entry(int index, BasicHashtableEntry<F>* entry); |
225 | 225 |
226 void add_entry(int index, BasicHashtableEntry* entry); | 226 void add_entry(int index, BasicHashtableEntry<F>* entry); |
227 | 227 |
228 void free_entry(BasicHashtableEntry* entry); | 228 void free_entry(BasicHashtableEntry<F>* entry); |
229 | 229 |
230 int number_of_entries() { return _number_of_entries; } | 230 int number_of_entries() { return _number_of_entries; } |
231 | 231 |
232 void verify() PRODUCT_RETURN; | 232 void verify() PRODUCT_RETURN; |
233 }; | 233 }; |
234 | 234 |
235 | 235 |
236 template <class T> class Hashtable : public BasicHashtable { | 236 template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> { |
237 friend class VMStructs; | 237 friend class VMStructs; |
238 | 238 |
239 public: | 239 public: |
240 Hashtable(int table_size, int entry_size) | 240 Hashtable(int table_size, int entry_size) |
241 : BasicHashtable(table_size, entry_size) { } | 241 : BasicHashtable<F>(table_size, entry_size) { } |
242 | 242 |
243 Hashtable(int table_size, int entry_size, | 243 Hashtable(int table_size, int entry_size, |
244 HashtableBucket* buckets, int number_of_entries) | 244 HashtableBucket<F>* buckets, int number_of_entries) |
245 : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { } | 245 : BasicHashtable<F>(table_size, entry_size, buckets, number_of_entries) { } |
246 | 246 |
247 // Debugging | 247 // Debugging |
248 void print() PRODUCT_RETURN; | 248 void print() PRODUCT_RETURN; |
249 | 249 |
250 // Reverse the order of elements in each of the buckets. Hashtable | 250 // Reverse the order of elements in each of the buckets. Hashtable |
262 int index_for(Symbol* name) { | 262 int index_for(Symbol* name) { |
263 return hash_to_index(compute_hash(name)); | 263 return hash_to_index(compute_hash(name)); |
264 } | 264 } |
265 | 265 |
266 // Table entry management | 266 // Table entry management |
267 HashtableEntry<T>* new_entry(unsigned int hashValue, T obj); | 267 HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj); |
268 | 268 |
269 // The following method is MT-safe and may be used with caution. | 269 // The following method is MT-safe and may be used with caution. |
270 HashtableEntry<T>* bucket(int i) { | 270 HashtableEntry<T, F>* bucket(int i) { |
271 return (HashtableEntry<T>*)BasicHashtable::bucket(i); | 271 return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i); |
272 } | 272 } |
273 | 273 |
274 // The following method is not MT-safe and must be done under lock. | 274 // The following method is not MT-safe and must be done under lock. |
275 HashtableEntry<T>** bucket_addr(int i) { | 275 HashtableEntry<T, F>** bucket_addr(int i) { |
276 return (HashtableEntry<T>**)BasicHashtable::bucket_addr(i); | 276 return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i); |
277 } | 277 } |
278 | 278 |
279 // Function to move these elements into the new table. | 279 // Function to move these elements into the new table. |
280 void move_to(Hashtable<T>* new_table); | 280 void move_to(Hashtable<T, F>* new_table); |
281 virtual unsigned int new_hash(T) { ShouldNotReachHere(); return 0; } // should be overridden | 281 virtual unsigned int new_hash(T) { ShouldNotReachHere(); return 0; } // should be overridden |
282 }; | 282 }; |
283 | 283 |
284 | 284 |
285 // Verions of hashtable where two handles are used to compute the index. | 285 // Verions of hashtable where two handles are used to compute the index. |
286 | 286 |
287 template <class T> class TwoOopHashtable : public Hashtable<T> { | 287 template <class T, MEMFLAGS F> class TwoOopHashtable : public Hashtable<T, F> { |
288 friend class VMStructs; | 288 friend class VMStructs; |
289 protected: | 289 protected: |
290 TwoOopHashtable(int table_size, int entry_size) | 290 TwoOopHashtable(int table_size, int entry_size) |
291 : Hashtable<T>(table_size, entry_size) {} | 291 : Hashtable<T, F>(table_size, entry_size) {} |
292 | 292 |
293 TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t, | 293 TwoOopHashtable(int table_size, int entry_size, HashtableBucket<F>* t, |
294 int number_of_entries) | 294 int number_of_entries) |
295 : Hashtable<T>(table_size, entry_size, t, number_of_entries) {} | 295 : Hashtable<T, F>(table_size, entry_size, t, number_of_entries) {} |
296 | 296 |
297 public: | 297 public: |
298 unsigned int compute_hash(Symbol* name, Handle loader) { | 298 unsigned int compute_hash(Symbol* name, Handle loader) { |
299 // Be careful with identity_hash(), it can safepoint and if this | 299 // Be careful with identity_hash(), it can safepoint and if this |
300 // were one expression, the compiler could choose to unhandle each | 300 // were one expression, the compiler could choose to unhandle each |