8210875: Refactor CompactHashtable

Reviewed-by: ccheung, jiangli
This commit is contained in:
Ioi Lam 2018-09-18 21:47:14 -07:00
parent a32f8e382d
commit 6c59cb232f
14 changed files with 200 additions and 326 deletions

View File

@ -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
@ -168,33 +169,6 @@ void CompactHashtableWriter::dump(SimpleCompactHashtable *cht, const char* table
}
}
/////////////////////////////////////////////////////////////
//
// 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 @@ void SimpleCompactHashtable::serialize(SerializeClosure* soc) {
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.

View File

@ -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 @@ public:
int bucket_bytes;
};
#if INCLUDE_CDS
/////////////////////////////////////////////////////////////////////////
//
// The compact hash table writer. Used at dump time for writing out
@ -108,9 +116,6 @@ public:
~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 @@ private:
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 @@ public:
/////////////////////////////////////////////////////////////////////////////
//
// 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 @@ public:
_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);
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 symbols
void symbols_do(SymbolClosure *cl);
// 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;
}
}
}
}
};

View File

@ -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

View File

@ -241,7 +241,7 @@ Handle java_lang_String::basic_create(int length, bool is_latin1, TRAPS) {
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 @@ Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS)
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 @@ char* java_lang_String::as_utf8_string(oop java_string, int start, int len, char
}
}
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 @@ void java_lang_StackTraceElement::fill_in(Handle element,
// 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());

View File

@ -114,8 +114,8 @@ class java_lang_String : AllStatic {
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 @@ class java_lang_String : AllStatic {
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

View File

@ -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 @@ class StringTableLookupJchar : StackObj {
*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 @@ oop StringTable::lookup(Symbol* symbol) {
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 @@ class StringTableGet : public StackObj {
}
};
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 @@ oop StringTable::intern(const char* utf8_string, TRAPS) {
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 @@ class StringTableCreateEntry : public StackObj {
}
};
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 @@ int StringtableDCmd::num_arguments() {
// 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 @@ oop StringTable::create_archived_string(oop s, Thread* THREAD) {
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 @@ void StringTable::write_to_archive() {
// 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 @@ void StringTable::serialize(SerializeClosure* soc) {
}
}
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

View File

@ -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 @@ private:
// 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 @@ private:
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 @@ private:
// 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 @@ private:
// 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);

View File

@ -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"
@ -55,9 +56,28 @@
#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 @@ public:
};
};
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 @@ void SymbolTable::dump(outputStream* st, bool verbose) {
}
#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 @@ struct CopyToArchive : StackObj {
// add to the compact table
_writer->add(fixed_hash, sym);
return true;
}
};
@ -631,7 +676,7 @@ void SymbolTable::write_to_archive() {
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::write_to_archive() {
}
void SymbolTable::serialize(SerializeClosure* soc) {
_shared_table.set_type(CompactHashtable<Symbol*, char>::_symbol_table);
_shared_table.serialize(soc);
if (soc->writing()) {

View File

@ -84,7 +84,6 @@ public:
operator Symbol*() { return _temp; }
};
template <class T, class N> class CompactHashtable;
class CompactSymbolTableWriter;
class SerializeClosure;
@ -108,8 +107,6 @@ private:
// 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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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 @@ bool UNICODE::is_latin1(jchar c) {
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 @@ int UNICODE::utf8_size(jbyte c) {
}
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 @@ int UNICODE::utf8_length(T* base, int length) {
}
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 @@ char* UNICODE::as_utf8(T* base, int& length) {
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 @@ char* UNICODE::as_utf8(jchar* base, int length, char* buf, int buflen) {
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 @@ void UNICODE::convert_to_utf8(const jchar* base, int length, char* utf8_buffer)
// 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 @@ void UNICODE::as_quoted_ascii(const T* base, int length, char* buf, int buflen)
}
// 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);

View File

@ -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 @@ class UNICODE : AllStatic {
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 @@ class UNICODE : AllStatic {
// 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);