7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "classfile/compactHashtable.inline.hpp"
28 #include "classfile/javaClasses.hpp"
29 #include "logging/logMessage.hpp"
30 #include "memory/heapShared.inline.hpp"
31 #include "memory/metadataFactory.hpp"
32 #include "memory/metaspaceShared.hpp"
33 #include "oops/compressedOops.inline.hpp"
34 #include "runtime/vmThread.hpp"
35 #include "utilities/numberSeq.hpp"
36 #include <sys/stat.h>
37
38 /////////////////////////////////////////////////////
39 //
40 // The compact hash table writer implementations
41 //
42 CompactHashtableWriter::CompactHashtableWriter(int num_buckets,
43 CompactHashtableStats* stats) {
44 assert(DumpSharedSpaces, "dump-time only");
45 assert(num_buckets > 0, "no buckets");
46 _num_buckets = num_buckets;
47 _num_entries = 0;
153 double avg_cost = 0.0;
154 if (_num_entries > 0) {
155 avg_cost = double(table_bytes)/double(_num_entries);
156 }
157 msg.info("Shared %s table stats -------- base: " PTR_FORMAT,
158 table_name, (intptr_t)base_address);
159 msg.info("Number of entries : %9d", _num_entries);
160 msg.info("Total bytes used : %9d", table_bytes);
161 msg.info("Average bytes per entry : %9.3f", avg_cost);
162 msg.info("Average bucket size : %9.3f", summary.avg());
163 msg.info("Variance of bucket size : %9.3f", summary.variance());
164 msg.info("Std. dev. of bucket size: %9.3f", summary.sd());
165 msg.info("Empty buckets : %9d", _num_empty_buckets);
166 msg.info("Value_Only buckets : %9d", _num_value_only_buckets);
167 msg.info("Other buckets : %9d", _num_other_buckets);
168 }
169 }
170
171 /////////////////////////////////////////////////////////////
172 //
173 // Customization for dumping Symbol and String tables
174
175 void CompactSymbolTableWriter::add(unsigned int hash, Symbol *symbol) {
176 uintx deltax = MetaspaceShared::object_delta(symbol);
177 // When the symbols are stored into the archive, we already check that
178 // they won't be more than MAX_SHARED_DELTA from the base address, or
179 // else the dumping would have been aborted.
180 assert(deltax <= MAX_SHARED_DELTA, "must not be");
181 u4 delta = u4(deltax);
182
183 CompactHashtableWriter::add(hash, delta);
184 }
185
186 void CompactStringTableWriter::add(unsigned int hash, oop string) {
187 CompactHashtableWriter::add(hash, CompressedOops::encode(string));
188 }
189
190 void CompactSymbolTableWriter::dump(CompactHashtable<Symbol*, char> *cht) {
191 CompactHashtableWriter::dump(cht, "symbol");
192 }
193
194 void CompactStringTableWriter::dump(CompactHashtable<oop, char> *cht) {
195 CompactHashtableWriter::dump(cht, "string");
196 }
197
198 /////////////////////////////////////////////////////////////
199 //
200 // The CompactHashtable implementation
201 //
202
203 void SimpleCompactHashtable::serialize(SerializeClosure* soc) {
204 soc->do_ptr((void**)&_base_address);
205 soc->do_u4(&_entry_count);
206 soc->do_u4(&_bucket_count);
207 soc->do_ptr((void**)&_buckets);
208 soc->do_ptr((void**)&_entries);
209 }
210
211 bool SimpleCompactHashtable::exists(u4 value) {
212 assert(!DumpSharedSpaces, "run-time only");
213
214 if (_entry_count == 0) {
215 return false;
216 }
217
218 unsigned int hash = (unsigned int)value;
219 int index = hash % _bucket_count;
220 u4 bucket_info = _buckets[index];
221 u4 bucket_offset = BUCKET_OFFSET(bucket_info);
222 int bucket_type = BUCKET_TYPE(bucket_info);
223 u4* entry = _entries + bucket_offset;
224
225 if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
226 return (entry[0] == value);
227 } else {
228 u4*entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]);
229 while (entry <entry_max) {
230 if (entry[1] == value) {
231 return true;
232 }
233 entry += 2;
234 }
235 return false;
236 }
237 }
238
239 template <class I>
240 inline void SimpleCompactHashtable::iterate(const I& iterator) {
241 for (u4 i = 0; i < _bucket_count; i++) {
242 u4 bucket_info = _buckets[i];
243 u4 bucket_offset = BUCKET_OFFSET(bucket_info);
244 int bucket_type = BUCKET_TYPE(bucket_info);
245 u4* entry = _entries + bucket_offset;
246
247 if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
248 iterator.do_value(_base_address, entry[0]);
249 } else {
250 u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
251 while (entry < entry_max) {
252 iterator.do_value(_base_address, entry[1]);
253 entry += 2;
254 }
255 }
256 }
257 }
258
259 template <class T, class N> void CompactHashtable<T, N>::serialize(SerializeClosure* soc) {
260 SimpleCompactHashtable::serialize(soc);
261 soc->do_u4(&_type);
262 }
263
264 class CompactHashtable_SymbolIterator {
265 SymbolClosure* const _closure;
266 public:
267 CompactHashtable_SymbolIterator(SymbolClosure *cl) : _closure(cl) {}
268 inline void do_value(address base_address, u4 offset) const {
269 Symbol* sym = (Symbol*)((void*)(base_address + offset));
270 _closure->do_symbol(&sym);
271 }
272 };
273
274 template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) {
275 CompactHashtable_SymbolIterator iterator(cl);
276 iterate(iterator);
277 }
278
279 class CompactHashtable_OopIterator {
280 OopClosure* const _closure;
281 public:
282 CompactHashtable_OopIterator(OopClosure *cl) : _closure(cl) {}
283 inline void do_value(address base_address, u4 offset) const {
284 narrowOop v = (narrowOop)offset;
285 oop obj = HeapShared::decode_from_archive(v);
286 _closure->do_oop(&obj);
287 }
288 };
289
290 template <class T, class N> void CompactHashtable<T, N>::oops_do(OopClosure* cl) {
291 assert(_type == _string_table || _bucket_count == 0, "sanity");
292 CompactHashtable_OopIterator iterator(cl);
293 iterate(iterator);
294 }
295
296 // Explicitly instantiate these types
297 template class CompactHashtable<Symbol*, char>;
298 template class CompactHashtable<oop, char>;
299
300 #ifndef O_BINARY // if defined (Win32) use binary files.
301 #define O_BINARY 0 // otherwise do nothing.
302 #endif
303
304 ////////////////////////////////////////////////////////
305 //
306 // HashtableTextDump
307 //
308 HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) {
309 struct stat st;
310 if (os::stat(filename, &st) != 0) {
311 quit("Unable to get hashtable dump file size", filename);
312 }
313 _size = st.st_size;
314 _fd = open(filename, O_RDONLY | O_BINARY, 0);
315 if (_fd < 0) {
316 quit("Unable to open hashtable dump file", filename);
317 }
318 _base = os::map_memory(_fd, filename, 0, NULL, _size, true, false);
|
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "jvm.h"
27 #include "classfile/compactHashtable.hpp"
28 #include "classfile/javaClasses.hpp"
29 #include "logging/logMessage.hpp"
30 #include "memory/heapShared.inline.hpp"
31 #include "memory/metadataFactory.hpp"
32 #include "memory/metaspaceShared.hpp"
33 #include "oops/compressedOops.inline.hpp"
34 #include "runtime/vmThread.hpp"
35 #include "utilities/numberSeq.hpp"
36 #include <sys/stat.h>
37
38 /////////////////////////////////////////////////////
39 //
40 // The compact hash table writer implementations
41 //
42 CompactHashtableWriter::CompactHashtableWriter(int num_buckets,
43 CompactHashtableStats* stats) {
44 assert(DumpSharedSpaces, "dump-time only");
45 assert(num_buckets > 0, "no buckets");
46 _num_buckets = num_buckets;
47 _num_entries = 0;
153 double avg_cost = 0.0;
154 if (_num_entries > 0) {
155 avg_cost = double(table_bytes)/double(_num_entries);
156 }
157 msg.info("Shared %s table stats -------- base: " PTR_FORMAT,
158 table_name, (intptr_t)base_address);
159 msg.info("Number of entries : %9d", _num_entries);
160 msg.info("Total bytes used : %9d", table_bytes);
161 msg.info("Average bytes per entry : %9.3f", avg_cost);
162 msg.info("Average bucket size : %9.3f", summary.avg());
163 msg.info("Variance of bucket size : %9.3f", summary.variance());
164 msg.info("Std. dev. of bucket size: %9.3f", summary.sd());
165 msg.info("Empty buckets : %9d", _num_empty_buckets);
166 msg.info("Value_Only buckets : %9d", _num_value_only_buckets);
167 msg.info("Other buckets : %9d", _num_other_buckets);
168 }
169 }
170
171 /////////////////////////////////////////////////////////////
172 //
173 // The CompactHashtable implementation
174 //
175
176 void SimpleCompactHashtable::serialize(SerializeClosure* soc) {
177 soc->do_ptr((void**)&_base_address);
178 soc->do_u4(&_entry_count);
179 soc->do_u4(&_bucket_count);
180 soc->do_ptr((void**)&_buckets);
181 soc->do_ptr((void**)&_entries);
182 }
183
184 bool SimpleCompactHashtable::exists(u4 value) {
185 assert(!DumpSharedSpaces, "run-time only");
186
187 if (_entry_count == 0) {
188 return false;
189 }
190
191 unsigned int hash = (unsigned int)value;
192 int index = hash % _bucket_count;
193 u4 bucket_info = _buckets[index];
194 u4 bucket_offset = BUCKET_OFFSET(bucket_info);
195 int bucket_type = BUCKET_TYPE(bucket_info);
196 u4* entry = _entries + bucket_offset;
197
198 if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
199 return (entry[0] == value);
200 } else {
201 u4*entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]);
202 while (entry <entry_max) {
203 if (entry[1] == value) {
204 return true;
205 }
206 entry += 2;
207 }
208 return false;
209 }
210 }
211
212 #ifndef O_BINARY // if defined (Win32) use binary files.
213 #define O_BINARY 0 // otherwise do nothing.
214 #endif
215
216 ////////////////////////////////////////////////////////
217 //
218 // HashtableTextDump
219 //
220 HashtableTextDump::HashtableTextDump(const char* filename) : _fd(-1) {
221 struct stat st;
222 if (os::stat(filename, &st) != 0) {
223 quit("Unable to get hashtable dump file size", filename);
224 }
225 _size = st.st_size;
226 _fd = open(filename, O_RDONLY | O_BINARY, 0);
227 if (_fd < 0) {
228 quit("Unable to open hashtable dump file", filename);
229 }
230 _base = os::map_memory(_fd, filename, 0, NULL, _size, true, false);
|