< prev index next >

src/hotspot/share/classfile/compactHashtable.cpp

Print this page


   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);


< prev index next >