8210875: Refactor CompactHashtable
Reviewed-by: ccheung, jiangli
This commit is contained in:
parent
a32f8e382d
commit
6c59cb232f
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
@ -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());
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user