// Write the compact table's entries juint* CompactHashtableWriter::dump_buckets(juint* compact_table, juint* p, NumberSeq* summary) { uintx base_address = 0; uintx max_delta = 0; int num_compact_buckets = 0; if (_type == CompactHashtable<Symbol*, char>::_symbol_table) { base_address = uintx(MetaspaceShared::shared_rs()->base()); max_delta = uintx(MetaspaceShared::shared_rs()->size()); assert(max_delta <= 0x7fffffff, "range check"); } else { assert((_type == CompactHashtable<oop, char>::_string_table), "unknown table"); assert(UseCompressedOops, "UseCompressedOops is required"); } assert(p != NULL, "sanity"); for (int index = 0; index < _num_buckets; index++) { juint count = 0; int bucket_size = _bucket_sizes[index]; int bucket_type = BUCKET_TYPE(compact_table[index]); if (bucket_size == 1) { assert(bucket_type == COMPACT_BUCKET_TYPE, "Bad bucket type"); num_compact_buckets ++; } for (Entry* tent = _buckets[index]; tent; tent = tent->next()) { if (bucket_type == REGULAR_BUCKET_TYPE) { *p++ = juint(tent->hash()); // write entry hash } if (_type == CompactHashtable<Symbol*, char>::_symbol_table) { uintx deltax = uintx(tent->value()) - base_address; assert(deltax < max_delta, "range check"); juint delta = juint(deltax); *p++ = delta; // write entry offset } else { *p++ = oopDesc::encode_heap_oop(tent->string()); } count ++; } assert(count == _bucket_sizes[index], "sanity"); } // Adjust the hashentry_bytes in CompactHashtableStats. Each compact // bucket saves 4-byte. _stats->hashentry_bytes -= num_compact_buckets * 4; return p; }
// Write the compact table void CompactHashtableWriter::dump(char** top, char* end) { NumberSeq summary; char* old_top = *top; juint* p = (juint*)(*top); uintx base_address = uintx(MetaspaceShared::shared_rs()->base()); *p++ = high(base_address); *p++ = low (base_address); // base address *p++ = _num_entries; // number of entries in the table *p++ = _num_buckets; // number of buckets in the table juint* first_bucket = NULL; juint* compact_table = dump_table(p, &first_bucket, &summary); juint* bucket_end = dump_buckets(compact_table, first_bucket, &summary); assert(bucket_end <= (juint*)end, "cannot write past end"); *top = (char*)bucket_end; if (PrintSharedSpaces) { double avg_cost = 0.0; if (_num_entries > 0) { avg_cost = double(_required_bytes)/double(_num_entries); } tty->print_cr("Shared %s table stats -------- base: " PTR_FORMAT, _table_name, (intptr_t)base_address); tty->print_cr("Number of entries : %9d", _num_entries); tty->print_cr("Total bytes used : %9d", (int)((*top) - old_top)); tty->print_cr("Average bytes per entry : %9.3f", avg_cost); tty->print_cr("Average bucket size : %9.3f", summary.avg()); tty->print_cr("Variance of bucket size : %9.3f", summary.variance()); tty->print_cr("Std. dev. of bucket size: %9.3f", summary.sd()); tty->print_cr("Maximum bucket size : %9d", (int)summary.maximum()); } }
///////////////////////////////////////////////////////////// // // The CompactHashtable implementation // template <class T, class N> const char* CompactHashtable<T, N>::init(const char* buffer) { assert(!DumpSharedSpaces, "run-time only"); juint*p = (juint*)buffer; juint upper = *p++; juint lower = *p++; _base_address = uintx(jlong_from(upper, lower)); _entry_count = *p++; _bucket_count = *p++; _buckets = p; _table_end_offset = BUCKET_OFFSET(p[_bucket_count]); // located at the end of the bucket_info table juint *end = _buckets + _table_end_offset; return (const char*)end; }
// Write the compact table's entries juint* CompactHashtableWriter::dump_buckets(juint* compact_table, juint* p, NumberSeq* summary) { uintx base_address = uintx(MetaspaceShared::shared_rs()->base()); uintx max_delta = uintx(MetaspaceShared::shared_rs()->size()); assert(max_delta <= 0x7fffffff, "range check"); int num_compact_buckets = 0; assert(p != NULL, "sanity"); for (int index = 0; index < _num_buckets; index++) { juint count = 0; int bucket_size = _bucket_sizes[index]; int bucket_type = BUCKET_TYPE(compact_table[index]); if (bucket_size == 1) { assert(bucket_type == COMPACT_BUCKET_TYPE, "Bad bucket type"); num_compact_buckets ++; } for (Entry* tent = _buckets[index]; tent; tent = tent->next()) { if (bucket_type == REGULAR_BUCKET_TYPE) { *p++ = juint(tent->hash()); // write symbol hash } uintx deltax = uintx(tent->value()) - base_address; assert(deltax < max_delta, "range check"); juint delta = juint(deltax); *p++ = delta; // write symbol offset count ++; } assert(count == _bucket_sizes[index], "sanity"); } // Adjust the hashentry_bytes in CompactHashtableStats. Each compact // bucket saves 4-byte. _stats->hashentry_bytes -= num_compact_buckets * 4; return p; }