/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*
*/
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/gcLocker.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/hashtable.inline.hpp"
#include "utilities/numberSeq.hpp"
// --------------------------------------------------------------------------
// Static arena for symbols that are not deallocated
// Allocate symbols in the C heap when dumping shared spaces in case there
// are temporary symbols we can remove.
if (c_heap || DumpSharedSpaces) {
// refcount starts as 1
} else {
}
return sym;
}
// Initialize the arena for global symbols, size passed in depends on CDS.
if (arena_alloc_size == 0) {
} else {
}
}
// Call function for all symbols in the symbol table.
const int n = the_table()->table_size();
for (int i = 0; i < n; i++) {
p != NULL;
p = p->next()) {
}
}
}
// Remove unreferenced symbols from the symbol table
// This is done late during GC.
int removed = 0;
int total = 0;
for (int i = 0; i < the_table()->table_size(); ++i) {
// Shared entries are normally at the end of the bucket and if we run into
// a shared entry, then there is nothing more to remove. However, if we
// have rehashed the table, then the shared entries are no longer at the
// end of the bucket.
break;
}
memory_total += s->object_size();
total++;
// If reference count is zero, remove.
if (s->refcount() == 0) {
delete s;
removed++;
} else {
}
// get next entry
}
}
symbols_counted += total;
// Exclude printing for normal PrintGCDetails because people parse
// this output.
}
}
// Create a new table and using alternate hash code, populate the new table
// with the existing strings. Set flag to use the alternate hash code afterwards.
// This should never happen with -Xshare:dump but it might in testing mode.
if (DumpSharedSpaces) return;
// Create a new symbol table
// Delete the table and buckets (entries are reused in new table).
delete _the_table;
// Don't check if we need rehashing until the table gets unbalanced again.
// Then rehash with a new global seed.
_needs_rehashing = false;
}
// Lookup a symbol in a bucket.
int count = 0;
count++; // count all entries in this bucket, not just ones with same hash
// something is referencing this symbol now.
return sym;
}
}
}
// If the bucket size is too deep check if this hash code is insufficient.
}
return NULL;
}
// Pick hashing algorithm.
return use_alternate_hashcode() ?
}
// We take care not to be blocking while holding the
// SymbolTable_lock. Otherwise, the system might deadlock, since the
// symboltable is used during compilation (VM_thread) The lock free
// synchronization is simplified by the fact that we do not delete
// entries in the symbol table during normal execution (only during
// safepoints).
// Found
if (s != NULL) return s;
// Grab SymbolTable_lock first.
// Otherwise, add to symbol to table
}
char* buffer;
unsigned int hashValue;
char* name;
{
// Found
if (s != NULL) return s;
}
// Otherwise, add to symbol to table. Copy to a C string first.
if (len <= 128) {
} else {
}
for (int i=0; i<len; i++) {
}
// Make sure there is no safepoint in the code above since name can't move.
// We can't include the code in No_Safepoint_Verifier because of the
// ResourceMark.
// Grab SymbolTable_lock first.
}
unsigned int& hash) {
return s;
}
// Look up the address of the literal in the SymbolTable for this Symbol*
// Do not create any new symbols
// Do not increment the reference count to keep this alive
if (sym == literal_sym) {
return e->literal_addr();
}
}
}
return NULL;
}
// Suggestion: Push unicode-based lookup all the way into the hashing
// and probing logic, so there is no need for convert_to_utf8 until
// an actual new Symbol* is created.
if (utf8_length < (int) sizeof(stack_buf)) {
} else {
}
}
unsigned int& hash) {
if (utf8_length < (int) sizeof(stack_buf)) {
} else {
}
}
int names_count,
unsigned int* hashValues, TRAPS) {
// Grab SymbolTable_lock first.
if (!added) {
// do it the hard way
for (int i=0; i<names_count; i++) {
}
}
}
unsigned int hash;
return result;
}
// Grab SymbolTable_lock first.
}
"proposed name of symbol must be stable");
// Don't allow symbols to be created which cannot fit in a Symbol*.
"name is too long to represent");
}
// Cannot hit a safepoint in this function because the "this" pointer can move.
// Check if the symbol table has been rehashed, if so, need to recalculate
// the hash value and index.
unsigned int hashValue;
int index;
if (use_alternate_hashcode()) {
} else {
}
// Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol.
// A race occurred and another thread introduced the symbol.
return test;
}
// Create a new symbol.
return sym;
}
// This version of basic_add adds symbols in batch from the constant pool
// parsing.
int names_count,
int* cp_indices, unsigned int* hashValues,
TRAPS) {
// Check symbol names are not too long. If any are too long, don't add any.
for (int i = 0; i< names_count; i++) {
"name is too long to represent");
}
}
// Cannot hit a safepoint in this function because the "this" pointer can move.
for (int i=0; i<names_count; i++) {
// Check if the symbol table has been rehashed, if so, need to recalculate
// the hash value.
unsigned int hashValue;
if (use_alternate_hashcode()) {
} else {
hashValue = hashValues[i];
}
// Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol.
// A race occurred and another thread introduced the symbol, this one
// will be dropped and collected. Use test instead.
} else {
// Create a new symbol. The null class loader is never unloaded so these
// are allocated specially in a permanent arena.
assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be???
}
}
return true;
}
for (int i = 0; i < the_table()->table_size(); ++i) {
"wrong index in symbol table");
}
}
}
for (int i = 0; i < the_table()->table_size(); ++i) {
int count = 0;
count++;
}
}
}
//---------------------------------------------------------------------------
// Non-product code
#ifndef PRODUCT
int i,j;
// initialize results to zero
for (j = 0; j < results_length; j++) {
results[j] = 0;
}
int total = 0;
int max_symbols = 0;
int out_of_range = 0;
int memory_total = 0;
int count = 0;
for (i = 0; i < the_table()->table_size(); i++) {
count++;
if (counter < results_length) {
} else {
out_of_range++;
}
}
}
if (symbols_counted > 0) {
}
for (i = 0; i < results_length; i++) {
if (results[i] > 0) {
}
}
if (Verbose) {
for (i = 0; i < results_length; i++) {
if (results[i] > 0) {
for (j = 0; (j < results[i]) && (j < line_length); j++) {
}
if (j == line_length) {
}
}
}
}
}
for (int i = 0; i < the_table()->table_size(); ++i) {
}
}
}
}
#endif // PRODUCT
// --------------------------------------------------------------------------
#ifdef ASSERT
return _size;
} else {
// copy head and tail
}
}
public:
}
bool verify() {
}
};
#endif
// --------------------------------------------------------------------------
// Pick hashing algorithm
}
int count = 0;
count++;
return l->literal();
}
}
}
// If the bucket size is too deep check if this hash code is insufficient.
}
return NULL;
}
"string must be properly initialized");
// Cannot hit a safepoint in this function because the "this" pointer can move.
// Check if the symbol table has been rehashed, if so, need to recalculate
// the hash value and index before second lookup.
unsigned int hashValue;
int index;
if (use_alternate_hashcode()) {
} else {
}
// Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol.
// Entry already added
return test;
}
return string();
}
int length;
}
// Found
"proposed name of symbol must be stable");
// try to reuse the string if possible
} else {
}
// Grab the StringTable_lock before getting the_table() because it could
// change at safepoint.
// Otherwise, add to symbol to table
}
int length;
return result;
}
{
int length;
return result;
}
return result;
}
// Readers of the table are unlocked, so we should only be removing
// entries at a safepoint.
for (int i = 0; i < the_table()->table_size(); ++i) {
// Shared entries are normally at the end of the bucket and if we run into
// a shared entry, then there is nothing more to remove. However, if we
// have rehashed the table, then the shared entries are no longer at the
// end of the bucket.
break;
}
} else {
}
}
}
}
// Did the closure remove the literal from the table?
} else {
}
}
}
}
}
for (;;) {
// Grab next set of buckets to scan
// End of table
break;
}
}
}
for (int i = 0; i < the_table()->table_size(); ++i) {
unsigned int h = java_lang_String::hash_string(s);
"wrong index in string table");
}
}
}
for (int i = 0; i < the_table()->table_size(); ++i) {
int count = 0;
count++;
}
}
}
// Create a new table and using alternate hash code, populate the new table
// with the existing strings. Set flag to use the alternate hash code afterwards.
// This should never happen with -Xshare:dump but it might in testing mode.
if (DumpSharedSpaces) return;
// Rehash the table
// Delete the table and buckets (entries are reused in new table).
delete _the_table;
// Don't check if we need rehashing until the table gets unbalanced again.
// Then rehash with a new global seed.
_needs_rehashing = false;
}