--- a/src/hotspot/share/classfile/compactHashtable.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/compactHashtable.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "jvm.h"
-#include "classfile/compactHashtable.inline.hpp"
+#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.hpp"
#include "logging/logMessage.hpp"
#include "memory/heapShared.inline.hpp"
@@ -35,6 +35,7 @@
#include "utilities/numberSeq.hpp"
#include <sys/stat.h>
+#if INCLUDE_CDS
/////////////////////////////////////////////////////
//
// The compact hash table writer implementations
@@ -170,33 +171,6 @@
/////////////////////////////////////////////////////////////
//
-// Customization for dumping Symbol and String tables
-
-void CompactSymbolTableWriter::add(unsigned int hash, Symbol *symbol) {
- uintx deltax = MetaspaceShared::object_delta(symbol);
- // When the symbols are stored into the archive, we already check that
- // they won't be more than MAX_SHARED_DELTA from the base address, or
- // else the dumping would have been aborted.
- assert(deltax <= MAX_SHARED_DELTA, "must not be");
- u4 delta = u4(deltax);
-
- CompactHashtableWriter::add(hash, delta);
-}
-
-void CompactStringTableWriter::add(unsigned int hash, oop string) {
- CompactHashtableWriter::add(hash, CompressedOops::encode(string));
-}
-
-void CompactSymbolTableWriter::dump(CompactHashtable<Symbol*, char> *cht) {
- CompactHashtableWriter::dump(cht, "symbol");
-}
-
-void CompactStringTableWriter::dump(CompactHashtable<oop, char> *cht) {
- CompactHashtableWriter::dump(cht, "string");
-}
-
-/////////////////////////////////////////////////////////////
-//
// The CompactHashtable implementation
//
@@ -207,95 +181,7 @@
soc->do_ptr((void**)&_buckets);
soc->do_ptr((void**)&_entries);
}
-
-bool SimpleCompactHashtable::exists(u4 value) {
- assert(!DumpSharedSpaces, "run-time only");
-
- if (_entry_count == 0) {
- return false;
- }
-
- unsigned int hash = (unsigned int)value;
- int index = hash % _bucket_count;
- u4 bucket_info = _buckets[index];
- u4 bucket_offset = BUCKET_OFFSET(bucket_info);
- int bucket_type = BUCKET_TYPE(bucket_info);
- u4* entry = _entries + bucket_offset;
-
- if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
- return (entry[0] == value);
- } else {
- u4*entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]);
- while (entry <entry_max) {
- if (entry[1] == value) {
- return true;
- }
- entry += 2;
- }
- return false;
- }
-}
-
-template <class I>
-inline void SimpleCompactHashtable::iterate(const I& iterator) {
- for (u4 i = 0; i < _bucket_count; i++) {
- u4 bucket_info = _buckets[i];
- u4 bucket_offset = BUCKET_OFFSET(bucket_info);
- int bucket_type = BUCKET_TYPE(bucket_info);
- u4* entry = _entries + bucket_offset;
-
- if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
- iterator.do_value(_base_address, entry[0]);
- } else {
- u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
- while (entry < entry_max) {
- iterator.do_value(_base_address, entry[1]);
- entry += 2;
- }
- }
- }
-}
-
-template <class T, class N> void CompactHashtable<T, N>::serialize(SerializeClosure* soc) {
- SimpleCompactHashtable::serialize(soc);
- soc->do_u4(&_type);
-}
-
-class CompactHashtable_SymbolIterator {
- SymbolClosure* const _closure;
-public:
- CompactHashtable_SymbolIterator(SymbolClosure *cl) : _closure(cl) {}
- inline void do_value(address base_address, u4 offset) const {
- Symbol* sym = (Symbol*)((void*)(base_address + offset));
- _closure->do_symbol(&sym);
- }
-};
-
-template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) {
- CompactHashtable_SymbolIterator iterator(cl);
- iterate(iterator);
-}
-
-class CompactHashtable_OopIterator {
- OopClosure* const _closure;
-public:
- CompactHashtable_OopIterator(OopClosure *cl) : _closure(cl) {}
- inline void do_value(address base_address, u4 offset) const {
- narrowOop v = (narrowOop)offset;
- oop obj = HeapShared::decode_from_archive(v);
- _closure->do_oop(&obj);
- }
-};
-
-template <class T, class N> void CompactHashtable<T, N>::oops_do(OopClosure* cl) {
- assert(_type == _string_table || _bucket_count == 0, "sanity");
- CompactHashtable_OopIterator iterator(cl);
- iterate(iterator);
-}
-
-// Explicitly instantiate these types
-template class CompactHashtable<Symbol*, char>;
-template class CompactHashtable<oop, char>;
+#endif // INCLUDE_CDS
#ifndef O_BINARY // if defined (Win32) use binary files.
#define O_BINARY 0 // otherwise do nothing.
--- a/src/hotspot/share/classfile/compactHashtable.hpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/compactHashtable.hpp Tue Sep 18 21:47:14 2018 -0700
@@ -29,7 +29,14 @@
#include "oops/symbol.hpp"
#include "utilities/hashtable.hpp"
-template <class T, class N> class CompactHashtable;
+
+template <
+ typename K,
+ typename V,
+ V (*DECODE)(address base_address, u4 offset),
+ bool (*EQUALS)(V value, K key, int len)
+ >
+class CompactHashtable;
class NumberSeq;
class SimpleCompactHashtable;
class SerializeClosure;
@@ -43,6 +50,7 @@
int bucket_bytes;
};
+#if INCLUDE_CDS
/////////////////////////////////////////////////////////////////////////
//
// The compact hash table writer. Used at dump time for writing out
@@ -108,9 +116,6 @@
~CompactHashtableWriter();
void add(unsigned int hash, u4 value);
- void add(u4 value) {
- add((unsigned int)value, value);
- }
private:
void allocate_table();
@@ -118,24 +123,8 @@
public:
void dump(SimpleCompactHashtable *cht, const char* table_name);
- const char* table_name();
};
-
-class CompactSymbolTableWriter: public CompactHashtableWriter {
-public:
- CompactSymbolTableWriter(int num_buckets, CompactHashtableStats* stats) :
- CompactHashtableWriter(num_buckets, stats) {}
- void add(unsigned int hash, Symbol *symbol);
- void dump(CompactHashtable<Symbol*, char> *cht);
-};
-
-class CompactStringTableWriter: public CompactHashtableWriter {
-public:
- CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) :
- CompactHashtableWriter(num_entries, stats) {}
- void add(unsigned int hash, oop string);
- void dump(CompactHashtable<oop, char> *cht);
-};
+#endif // INCLUDE_CDS
#define REGULAR_BUCKET_TYPE 0
#define VALUE_ONLY_BUCKET_TYPE 1
@@ -148,8 +137,7 @@
/////////////////////////////////////////////////////////////////////////////
//
-// CompactHashtable is used to stored the CDS archive's symbol/string table. Used
-// at runtime only to access the compact table from the archive.
+// CompactHashtable is used to store the CDS archive's symbol/string tables.
//
// Because these tables are read-only (no entries can be added/deleted) at run-time
// and tend to have large number of entries, we try to minimize the footprint
@@ -225,56 +213,82 @@
_entries = entries;
}
- template <class I> inline void iterate(const I& iterator);
-
- bool exists(u4 value);
-
// For reading from/writing to the CDS archive
- void serialize(SerializeClosure* soc);
+ void serialize(SerializeClosure* soc) NOT_CDS_RETURN;
inline bool empty() {
return (_entry_count == 0);
}
};
-template <class T, class N> class CompactHashtable : public SimpleCompactHashtable {
+template <
+ typename K,
+ typename V,
+ V (*DECODE)(address base_address, u4 offset),
+ bool (*EQUALS)(V value, K key, int len)
+ >
+class CompactHashtable : public SimpleCompactHashtable {
friend class VMStructs;
-public:
- enum CompactHashtableType {
- _symbol_table = 0,
- _string_table = 1
- };
+ V decode(u4 offset) const {
+ return DECODE(_base_address, offset);
+ }
-private:
- u4 _type;
-
- inline Symbol* decode_entry(CompactHashtable<Symbol*, char>* const t,
- u4 offset, const char* name, int len);
-
- inline oop decode_entry(CompactHashtable<oop, char>* const t,
- u4 offset, const char* name, int len);
public:
CompactHashtable() : SimpleCompactHashtable() {}
- void set_type(CompactHashtableType type) {
- _type = (u4)type;
+ // Lookup a value V from the compact table using key K
+ inline V lookup(K key, unsigned int hash, int len) const {
+ if (_entry_count > 0) {
+ int index = hash % _bucket_count;
+ u4 bucket_info = _buckets[index];
+ u4 bucket_offset = BUCKET_OFFSET(bucket_info);
+ int bucket_type = BUCKET_TYPE(bucket_info);
+ u4* entry = _entries + bucket_offset;
+
+ if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
+ V value = decode(entry[0]);
+ if (EQUALS(value, key, len)) {
+ return value;
+ }
+ } else {
+ // This is a regular bucket, which has more than one
+ // entries. Each entry is a pair of entry (hash, offset).
+ // Seek until the end of the bucket.
+ u4* entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]);
+ while (entry < entry_max) {
+ unsigned int h = (unsigned int)(entry[0]);
+ if (h == hash) {
+ V value = decode(entry[1]);
+ if (EQUALS(value, key, len)) {
+ return value;
+ }
+ }
+ entry += 2;
+ }
+ }
+ }
+ return NULL;
}
- // Lookup an entry from the compact table
- inline T lookup(const N* name, unsigned int hash, int len);
-
- // iterate over symbols
- void symbols_do(SymbolClosure *cl);
+ template <class ITER>
+ inline void iterate(ITER* iter) const {
+ for (u4 i = 0; i < _bucket_count; i++) {
+ u4 bucket_info = _buckets[i];
+ u4 bucket_offset = BUCKET_OFFSET(bucket_info);
+ int bucket_type = BUCKET_TYPE(bucket_info);
+ u4* entry = _entries + bucket_offset;
- // iterate over strings
- void oops_do(OopClosure* f);
-
- // For reading from/writing to the CDS archive
- void serialize(SerializeClosure* soc);
-
- uintx base_address() {
- return (uintx) _base_address;
+ if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
+ iter->do_value(decode(entry[0]));
+ } else {
+ u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
+ while (entry < entry_max) {
+ iter->do_value(decode(entry[1]));
+ entry += 2;
+ }
+ }
+ }
}
};
--- a/src/hotspot/share/classfile/compactHashtable.inline.hpp Thu Sep 20 18:39:53 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_CLASSFILE_COMPACTHASHTABLE_INLINE_HPP
-#define SHARE_VM_CLASSFILE_COMPACTHASHTABLE_INLINE_HPP
-
-#include "classfile/compactHashtable.hpp"
-#include "classfile/javaClasses.hpp"
-#include "memory/allocation.inline.hpp"
-#include "memory/filemap.hpp"
-#include "memory/heapShared.inline.hpp"
-#include "oops/oop.hpp"
-
-template <class T, class N>
-inline Symbol* CompactHashtable<T, N>::decode_entry(CompactHashtable<Symbol*, char>* const t,
- u4 offset, const char* name, int len) {
- Symbol* sym = (Symbol*)(_base_address + offset);
- if (sym->equals(name, len)) {
- assert(sym->refcount() == PERM_REFCOUNT, "must be shared");
- return sym;
- }
-
- return NULL;
-}
-
-template <class T, class N>
-inline oop CompactHashtable<T, N>::decode_entry(CompactHashtable<oop, char>* const t,
- u4 offset, const char* name, int len) {
- narrowOop v = (narrowOop)offset;
- oop string = HeapShared::decode_from_archive(v);
- if (java_lang_String::equals(string, (jchar*)name, len)) {
- return string;
- }
-
- return NULL;
-}
-
-template <class T, class N>
-inline T CompactHashtable<T,N>::lookup(const N* name, unsigned int hash, int len) {
- if (_entry_count > 0) {
- int index = hash % _bucket_count;
- u4 bucket_info = _buckets[index];
- u4 bucket_offset = BUCKET_OFFSET(bucket_info);
- int bucket_type = BUCKET_TYPE(bucket_info);
- u4* entry = _entries + bucket_offset;
-
- if (bucket_type == VALUE_ONLY_BUCKET_TYPE) {
- T res = decode_entry(this, entry[0], name, len);
- if (res != NULL) {
- return res;
- }
- } else {
- // This is a regular bucket, which has more than one
- // entries. Each entry is a pair of entry (hash, offset).
- // Seek until the end of the bucket.
- u4* entry_max = _entries + BUCKET_OFFSET(_buckets[index + 1]);
- while (entry < entry_max) {
- unsigned int h = (unsigned int)(entry[0]);
- if (h == hash) {
- T res = decode_entry(this, entry[1], name, len);
- if (res != NULL) {
- return res;
- }
- }
- entry += 2;
- }
- }
- }
- return NULL;
-}
-
-#endif // SHARE_VM_CLASSFILE_COMPACTHASHTABLE_INLINE_HPP
--- a/src/hotspot/share/classfile/javaClasses.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/javaClasses.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -241,7 +241,7 @@
return h_obj;
}
-Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS) {
+Handle java_lang_String::create_from_unicode(const jchar* unicode, int length, TRAPS) {
bool is_latin1 = CompactStrings && UNICODE::is_latin1(unicode, length);
Handle h_obj = basic_create(length, is_latin1, CHECK_NH);
typeArrayOop buffer = value(h_obj());
@@ -271,7 +271,7 @@
return h_obj;
}
-oop java_lang_String::create_oop_from_unicode(jchar* unicode, int length, TRAPS) {
+oop java_lang_String::create_oop_from_unicode(const jchar* unicode, int length, TRAPS) {
Handle h_obj = create_from_unicode(unicode, length, CHECK_0);
return h_obj();
}
@@ -643,7 +643,7 @@
}
}
-bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
+bool java_lang_String::equals(oop java_string, const jchar* chars, int len) {
assert(java_string->klass() == SystemDictionary::String_klass(),
"must be java_string");
typeArrayOop value = java_lang_String::value_no_keepalive(java_string);
@@ -2569,7 +2569,7 @@
// Fill in class name
ResourceMark rm(THREAD);
const char* str = holder->external_name();
- oop classname = StringTable::intern((char*) str, CHECK);
+ oop classname = StringTable::intern(str, CHECK);
java_lang_StackTraceElement::set_declaringClass(element(), classname);
java_lang_StackTraceElement::set_declaringClassObject(element(), holder->java_mirror());
--- a/src/hotspot/share/classfile/javaClasses.hpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/javaClasses.hpp Tue Sep 18 21:47:14 2018 -0700
@@ -114,8 +114,8 @@
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
// Instance creation
- static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
- static oop create_oop_from_unicode(jchar* unicode, int len, TRAPS);
+ static Handle create_from_unicode(const jchar* unicode, int len, TRAPS);
+ static oop create_oop_from_unicode(const jchar* unicode, int len, TRAPS);
static Handle create_from_str(const char* utf8_str, TRAPS);
static oop create_oop_from_str(const char* utf8_str, TRAPS);
static Handle create_from_symbol(Symbol* symbol, TRAPS);
@@ -189,7 +189,7 @@
static unsigned int hash_code(oop java_string);
- static bool equals(oop java_string, jchar* chars, int len);
+ static bool equals(oop java_string, const jchar* chars, int len);
static bool equals(oop str1, oop str2);
// Conversion between '.' and '/' formats
--- a/src/hotspot/share/classfile/stringTable.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/stringTable.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -24,7 +24,7 @@
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
-#include "classfile/compactHashtable.inline.hpp"
+#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -35,6 +35,7 @@
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
+#include "memory/heapShared.inline.hpp"
#include "memory/metaspaceShared.inline.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
@@ -62,9 +63,22 @@
// If we have as many dead items as 50% of the number of bucket
#define CLEAN_DEAD_HIGH_WATER_MARK 0.5
+#if INCLUDE_CDS_JAVA_HEAP
+inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
+ assert(sizeof(narrowOop) == sizeof(offset), "must be");
+ narrowOop v = (narrowOop)offset;
+ return HeapShared::decode_from_archive(v);
+}
+
+static CompactHashtable<
+ const jchar*, oop,
+ read_string_from_compact_hashtable,
+ java_lang_String::equals
+> _shared_table;
+#endif
+
// --------------------------------------------------------------------------
StringTable* StringTable::_the_table = NULL;
-CompactHashtable<oop, char> StringTable::_shared_table;
volatile bool StringTable::_shared_string_mapped = false;
volatile bool StringTable::_alt_hash = false;
@@ -134,7 +148,7 @@
*is_dead = true;
return false;
}
- bool equals = java_lang_String::equals(val_oop, (jchar*)_str, _len);
+ bool equals = java_lang_String::equals(val_oop, _str, _len);
if (!equals) {
return false;
}
@@ -236,7 +250,7 @@
return lookup(chars, length);
}
-oop StringTable::lookup(jchar* name, int len) {
+oop StringTable::lookup(const jchar* name, int len) {
unsigned int hash = java_lang_String::hash_code(name, len);
oop string = StringTable::the_table()->lookup_shared(name, len, hash);
if (string != NULL) {
@@ -263,7 +277,7 @@
}
};
-oop StringTable::do_lookup(jchar* name, int len, uintx hash) {
+oop StringTable::do_lookup(const jchar* name, int len, uintx hash) {
Thread* thread = Thread::current();
StringTableLookupJchar lookup(thread, hash, name, len);
StringTableGet stg(thread);
@@ -308,7 +322,7 @@
return result;
}
-oop StringTable::intern(Handle string_or_null_h, jchar* name, int len, TRAPS) {
+oop StringTable::intern(Handle string_or_null_h, const jchar* name, int len, TRAPS) {
// shared table always uses java_lang_String::hash_code
unsigned int hash = java_lang_String::hash_code(name, len);
oop found_string = StringTable::the_table()->lookup_shared(name, len, hash);
@@ -346,7 +360,7 @@
}
};
-oop StringTable::do_intern(Handle string_or_null_h, jchar* name,
+oop StringTable::do_intern(Handle string_or_null_h, const jchar* name,
int len, uintx hash, TRAPS) {
HandleMark hm(THREAD); // cleanup strings created
Handle string_h;
@@ -775,10 +789,10 @@
// Sharing
#if INCLUDE_CDS_JAVA_HEAP
-oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
+oop StringTable::lookup_shared(const jchar* name, int len, unsigned int hash) {
assert(hash == java_lang_String::hash_code(name, len),
"hash must be computed using java_lang_String::hash_code");
- return _shared_table.lookup((const char*)name, hash, len);
+ return _shared_table.lookup(name, hash, len);
}
oop StringTable::create_archived_string(oop s, Thread* THREAD) {
@@ -805,6 +819,15 @@
return new_s;
}
+class CompactStringTableWriter: public CompactHashtableWriter {
+public:
+ CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) :
+ CompactHashtableWriter(num_entries, stats) {}
+ void add(unsigned int hash, oop string) {
+ CompactHashtableWriter::add(hash, CompressedOops::encode(string));
+ }
+};
+
struct CopyToArchive : StackObj {
CompactStringTableWriter* _writer;
CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {}
@@ -849,11 +872,10 @@
// Copy the interned strings into the "string space" within the java heap
copy_shared_string_table(&writer);
- writer.dump(&_shared_table);
+ writer.dump(&_shared_table, "string");
}
void StringTable::serialize(SerializeClosure* soc) {
- _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
_shared_table.serialize(soc);
if (soc->writing()) {
@@ -864,7 +886,17 @@
}
}
+class SharedStringIterator {
+ OopClosure* _oop_closure;
+public:
+ SharedStringIterator(OopClosure* f) : _oop_closure(f) {}
+ void do_value(oop string) {
+ _oop_closure->do_oop(&string);
+ }
+};
+
void StringTable::shared_oops_do(OopClosure* f) {
- _shared_table.oops_do(f);
+ SharedStringIterator iter(f);
+ _shared_table.iterate(&iter);
}
#endif //INCLUDE_CDS_JAVA_HEAP
--- a/src/hotspot/share/classfile/stringTable.hpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/stringTable.hpp Tue Sep 18 21:47:14 2018 -0700
@@ -33,7 +33,6 @@
#include "oops/weakHandle.hpp"
#include "utilities/concurrentHashTable.hpp"
-template <class T, class N> class CompactHashtable;
class CompactStringTableWriter;
class SerializeClosure;
@@ -56,8 +55,6 @@
// The string table
static StringTable* _the_table;
- // Shared string table
- static CompactHashtable<oop, char> _shared_table;
static volatile bool _shared_string_mapped;
static volatile bool _alt_hash;
@@ -88,9 +85,9 @@
StringTable();
- static oop intern(Handle string_or_null_h, jchar* name, int len, TRAPS);
- oop do_intern(Handle string_or_null, jchar* name, int len, uintx hash, TRAPS);
- oop do_lookup(jchar* name, int len, uintx hash);
+ static oop intern(Handle string_or_null_h, const jchar* name, int len, TRAPS);
+ oop do_intern(Handle string_or_null, const jchar* name, int len, uintx hash, TRAPS);
+ oop do_lookup(const jchar* name, int len, uintx hash);
void concurrent_work(JavaThread* jt);
void print_table_statistics(outputStream* st, const char* table_name);
@@ -151,7 +148,7 @@
// Probing
static oop lookup(Symbol* symbol);
- static oop lookup(jchar* chars, int length);
+ static oop lookup(const jchar* chars, int length);
// Interning
static oop intern(Symbol* symbol, TRAPS);
@@ -165,7 +162,7 @@
// Sharing
private:
- oop lookup_shared(jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
+ oop lookup_shared(const jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
static void copy_shared_string_table(CompactStringTableWriter* ch_table) NOT_CDS_JAVA_HEAP_RETURN;
public:
static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL);
--- a/src/hotspot/share/classfile/symbolTable.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/symbolTable.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -24,11 +24,12 @@
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
-#include "classfile/compactHashtable.inline.hpp"
+#include "classfile/compactHashtable.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/metaspaceClosure.hpp"
+#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
@@ -56,8 +57,27 @@
#define ON_STACK_BUFFER_LENGTH 128
// --------------------------------------------------------------------------
+inline Symbol* read_symbol_from_compact_hashtable(address base_address, u4 offset) {
+ return (Symbol*)(base_address + offset);
+}
+
+inline bool symbol_equals_compact_hashtable_entry(Symbol* value, const char* key, int len) {
+ if (value->equals(key, len)) {
+ assert(value->refcount() == PERM_REFCOUNT, "must be shared");
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static CompactHashtable<
+ const char*, Symbol*,
+ read_symbol_from_compact_hashtable,
+ symbol_equals_compact_hashtable_entry
+> _shared_table;
+
+// --------------------------------------------------------------------------
SymbolTable* SymbolTable::_the_table = NULL;
-CompactHashtable<Symbol*, char> SymbolTable::_shared_table;
volatile bool SymbolTable::_alt_hash = false;
volatile bool SymbolTable::_lookup_shared_first = false;
// Static arena for symbols that are not deallocated
@@ -224,10 +244,20 @@
};
};
+class SharedSymbolIterator {
+ SymbolClosure* _symbol_closure;
+public:
+ SharedSymbolIterator(SymbolClosure* f) : _symbol_closure(f) {}
+ void do_value(Symbol* symbol) {
+ _symbol_closure->do_symbol(&symbol);
+ }
+};
+
// Call function for all symbols in the symbol table.
void SymbolTable::symbols_do(SymbolClosure *cl) {
// all symbols from shared table
- _shared_table.symbols_do(cl);
+ SharedSymbolIterator iter(cl);
+ _shared_table.iterate(&iter);
// all symbols from the dynamic table
SymbolsDo sd(cl);
@@ -597,6 +627,22 @@
}
#if INCLUDE_CDS
+class CompactSymbolTableWriter: public CompactHashtableWriter {
+public:
+ CompactSymbolTableWriter(int num_buckets, CompactHashtableStats* stats) :
+ CompactHashtableWriter(num_buckets, stats) {}
+ void add(unsigned int hash, Symbol *symbol) {
+ uintx deltax = MetaspaceShared::object_delta(symbol);
+ // When the symbols are stored into the archive, we already check that
+ // they won't be more than MAX_SHARED_DELTA from the base address, or
+ // else the dumping would have been aborted.
+ assert(deltax <= MAX_SHARED_DELTA, "must not be");
+ u4 delta = u4(deltax);
+
+ CompactHashtableWriter::add(hash, delta);
+ }
+};
+
struct CopyToArchive : StackObj {
CompactSymbolTableWriter* _writer;
CopyToArchive(CompactSymbolTableWriter* writer) : _writer(writer) {}
@@ -613,7 +659,6 @@
// add to the compact table
_writer->add(fixed_hash, sym);
-
return true;
}
};
@@ -631,7 +676,7 @@
CompactSymbolTableWriter writer(num_buckets > 1 ? num_buckets : 1,
&MetaspaceShared::stats()->symbol);
copy_shared_symbol_table(&writer);
- writer.dump(&_shared_table);
+ writer.dump(&_shared_table, "symbol");
// Verify table is correct
Symbol* sym = vmSymbols::java_lang_Object();
@@ -642,7 +687,6 @@
}
void SymbolTable::serialize(SerializeClosure* soc) {
- _shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
_shared_table.serialize(soc);
if (soc->writing()) {
--- a/src/hotspot/share/classfile/symbolTable.hpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/symbolTable.hpp Tue Sep 18 21:47:14 2018 -0700
@@ -84,7 +84,6 @@
operator Symbol*() { return _temp; }
};
-template <class T, class N> class CompactHashtable;
class CompactSymbolTableWriter;
class SerializeClosure;
@@ -108,8 +107,6 @@
// The symbol table
static SymbolTable* _the_table;
- // Shared symbol table.
- static CompactHashtable<Symbol*, char> _shared_table;
static volatile bool _lookup_shared_first;
static volatile bool _alt_hash;
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -28,7 +28,6 @@
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/classLoaderExt.hpp"
-#include "classfile/compactHashtable.inline.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
--- a/src/hotspot/share/memory/filemap.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/memory/filemap.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -26,7 +26,6 @@
#include "jvm.h"
#include "classfile/classLoader.inline.hpp"
#include "classfile/classLoaderExt.hpp"
-#include "classfile/compactHashtable.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionaryShared.hpp"
--- a/src/hotspot/share/services/diagnosticCommand.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/services/diagnosticCommand.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -26,7 +26,6 @@
#include "jvm.h"
#include "classfile/classLoaderHierarchyDCmd.hpp"
#include "classfile/classLoaderStats.hpp"
-#include "classfile/compactHashtable.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/directivesParser.hpp"
#include "gc/shared/vmGCOperations.hpp"
--- a/src/hotspot/share/utilities/utf8.cpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/utilities/utf8.cpp Tue Sep 18 21:47:14 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -401,7 +401,7 @@
return (c <= 0x00FF);
}
-bool UNICODE::is_latin1(jchar* base, int length) {
+bool UNICODE::is_latin1(const jchar* base, int length) {
for (int index = 0; index < length; index++) {
if (base[index] > 0x00FF) {
return false;
@@ -434,7 +434,7 @@
}
template<typename T>
-int UNICODE::utf8_length(T* base, int length) {
+int UNICODE::utf8_length(const T* base, int length) {
int result = 0;
for (int index = 0; index < length; index++) {
T c = base[index];
@@ -444,7 +444,7 @@
}
template<typename T>
-char* UNICODE::as_utf8(T* base, int& length) {
+char* UNICODE::as_utf8(const T* base, int& length) {
int utf8_len = utf8_length(base, length);
u_char* buf = NEW_RESOURCE_ARRAY(u_char, utf8_len + 1);
char* result = as_utf8(base, length, (char*) buf, utf8_len + 1);
@@ -454,7 +454,7 @@
return (char*) result;
}
-char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) {
+char* UNICODE::as_utf8(const jchar* base, int length, char* buf, int buflen) {
u_char* p = (u_char*)buf;
for (int index = 0; index < length; index++) {
jchar c = base[index];
@@ -466,7 +466,7 @@
return buf;
}
-char* UNICODE::as_utf8(jbyte* base, int length, char* buf, int buflen) {
+char* UNICODE::as_utf8(const jbyte* base, int length, char* buf, int buflen) {
u_char* p = (u_char*)buf;
u_char* end = (u_char*)buf + buflen;
for (int index = 0; index < length; index++) {
@@ -496,7 +496,7 @@
// returns the quoted ascii length of a unicode string
template<typename T>
-int UNICODE::quoted_ascii_length(T* base, int length) {
+int UNICODE::quoted_ascii_length(const T* base, int length) {
int result = 0;
for (int i = 0; i < length; i++) {
T c = base[i];
@@ -529,11 +529,11 @@
}
// Explicit instantiation for all supported types.
-template int UNICODE::utf8_length(jbyte* base, int length);
-template int UNICODE::utf8_length(jchar* base, int length);
-template char* UNICODE::as_utf8(jbyte* base, int& length);
-template char* UNICODE::as_utf8(jchar* base, int& length);
-template int UNICODE::quoted_ascii_length<jbyte>(jbyte* base, int length);
-template int UNICODE::quoted_ascii_length<jchar>(jchar* base, int length);
+template int UNICODE::utf8_length(const jbyte* base, int length);
+template int UNICODE::utf8_length(const jchar* base, int length);
+template char* UNICODE::as_utf8(const jbyte* base, int& length);
+template char* UNICODE::as_utf8(const jchar* base, int& length);
+template int UNICODE::quoted_ascii_length<jbyte>(const jbyte* base, int length);
+template int UNICODE::quoted_ascii_length<jchar>(const jchar* base, int length);
template void UNICODE::as_quoted_ascii<jbyte>(const jbyte* base, int length, char* buf, int buflen);
template void UNICODE::as_quoted_ascii<jchar>(const jchar* base, int length, char* buf, int buflen);
--- a/src/hotspot/share/utilities/utf8.hpp Thu Sep 20 18:39:53 2018 +0200
+++ b/src/hotspot/share/utilities/utf8.hpp Tue Sep 18 21:47:14 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -90,14 +90,14 @@
static bool is_latin1(jchar c);
// checks if the given string can be encoded as latin1
- static bool is_latin1(jchar* base, int length);
+ static bool is_latin1(const jchar* base, int length);
// returns the utf8 size of a unicode character
static int utf8_size(jchar c);
static int utf8_size(jbyte c);
// returns the utf8 length of a unicode string
- template<typename T> static int utf8_length(T* base, int length);
+ template<typename T> static int utf8_length(const T* base, int length);
// converts a unicode string to utf8 string
static void convert_to_utf8(const jchar* base, int length, char* utf8_buffer);
@@ -105,12 +105,12 @@
// converts a unicode string to a utf8 string; result is allocated
// in resource area unless a buffer is provided. The unicode 'length'
// parameter is set to the length of the result utf8 string.
- template<typename T> static char* as_utf8(T* base, int& length);
- static char* as_utf8(jchar* base, int length, char* buf, int buflen);
- static char* as_utf8(jbyte* base, int length, char* buf, int buflen);
+ template<typename T> static char* as_utf8(const T* base, int& length);
+ static char* as_utf8(const jchar* base, int length, char* buf, int buflen);
+ static char* as_utf8(const jbyte* base, int length, char* buf, int buflen);
// returns the quoted ascii length of a unicode string
- template<typename T> static int quoted_ascii_length(T* base, int length);
+ template<typename T> static int quoted_ascii_length(const T* base, int length);
// converts a unicode string to quoted ascii
template<typename T> static void as_quoted_ascii(const T* base, int length, char* buf, int buflen);