提交 8613a1c5 编写于 作者: C coleenp

7150058: Allocate symbols from null boot loader to an arena for NMT

Summary: Move symbol allocation to an arena so NMT doesn't have to track them at startup.
Reviewed-by: never, kamg, zgu
上级 72e1760d
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
#define JAVA_7_VERSION 51 #define JAVA_7_VERSION 51
void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) { void ClassFileParser::parse_constant_pool_entries(Handle class_loader, constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize // Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
// this function (_current can be allocated in a register, with scalar // this function (_current can be allocated in a register, with scalar
// replacement of aggregates). The _current pointer is copied back to // replacement of aggregates). The _current pointer is copied back to
...@@ -272,7 +272,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len ...@@ -272,7 +272,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
indices[names_count] = index; indices[names_count] = index;
hashValues[names_count++] = hash; hashValues[names_count++] = hash;
if (names_count == SymbolTable::symbol_alloc_batch_size) { if (names_count == SymbolTable::symbol_alloc_batch_size) {
SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
names_count = 0; names_count = 0;
} }
} else { } else {
...@@ -289,7 +289,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len ...@@ -289,7 +289,7 @@ void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int len
// Allocate the remaining symbols // Allocate the remaining symbols
if (names_count > 0) { if (names_count > 0) {
SymbolTable::new_symbols(cp, names_count, names, lengths, indices, hashValues, CHECK); SymbolTable::new_symbols(class_loader, cp, names_count, names, lengths, indices, hashValues, CHECK);
} }
// Copy _current pointer of local copy back to stream(). // Copy _current pointer of local copy back to stream().
...@@ -318,7 +318,7 @@ class ConstantPoolCleaner : public StackObj { ...@@ -318,7 +318,7 @@ class ConstantPoolCleaner : public StackObj {
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); } bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
ClassFileStream* cfs = stream(); ClassFileStream* cfs = stream();
constantPoolHandle nullHandle; constantPoolHandle nullHandle;
...@@ -337,7 +337,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) { ...@@ -337,7 +337,7 @@ constantPoolHandle ClassFileParser::parse_constant_pool(TRAPS) {
ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up. ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up.
// parsing constant pool entries // parsing constant pool entries
parse_constant_pool_entries(cp, length, CHECK_(nullHandle)); parse_constant_pool_entries(class_loader, cp, length, CHECK_(nullHandle));
int index = 1; // declared outside of loops for portability int index = 1; // declared outside of loops for portability
...@@ -2758,7 +2758,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -2758,7 +2758,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
_relax_verify = Verifier::relax_verify_for(class_loader()); _relax_verify = Verifier::relax_verify_for(class_loader());
// Constant pool // Constant pool
constantPoolHandle cp = parse_constant_pool(CHECK_(nullHandle)); constantPoolHandle cp = parse_constant_pool(class_loader, CHECK_(nullHandle));
ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up. ConstantPoolCleaner error_handler(cp); // set constant pool to be cleaned up.
int cp_size = cp->length(); int cp_size = cp->length();
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -68,9 +68,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { ...@@ -68,9 +68,10 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
void set_stream(ClassFileStream* st) { _stream = st; } void set_stream(ClassFileStream* st) { _stream = st; }
// Constant pool parsing // Constant pool parsing
void parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS); void parse_constant_pool_entries(Handle class_loader,
constantPoolHandle cp, int length, TRAPS);
constantPoolHandle parse_constant_pool(TRAPS); constantPoolHandle parse_constant_pool(Handle class_loader, TRAPS);
// Interface parsing // Interface parsing
objArrayHandle parse_interfaces(constantPoolHandle cp, objArrayHandle parse_interfaces(constantPoolHandle cp,
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "classfile/symbolTable.hpp" #include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp" #include "memory/filemap.hpp"
#include "memory/gcLocker.inline.hpp" #include "memory/gcLocker.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
...@@ -37,34 +38,35 @@ ...@@ -37,34 +38,35 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
SymbolTable* SymbolTable::_the_table = NULL; SymbolTable* SymbolTable::_the_table = NULL;
// Static arena for symbols that are not deallocated
Arena* SymbolTable::_arena = NULL;
Symbol* SymbolTable::allocate_symbol(const u1* name, int len, TRAPS) { Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
// Don't allow symbols to be created which cannot fit in a Symbol*. // Don't allow symbols to be created which cannot fit in a Symbol*.
if (len > Symbol::max_length()) { if (len > Symbol::max_length()) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), THROW_MSG_0(vmSymbols::java_lang_InternalError(),
"name is too long to represent"); "name is too long to represent");
} }
Symbol* sym = new (len) Symbol(name, len); Symbol* sym;
// 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
sym = new (len, THREAD) Symbol(name, len, 1);
} else {
sym = new (len, arena(), THREAD) Symbol(name, len, -1);
}
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted"); assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
return sym; return sym;
} }
bool SymbolTable::allocate_symbols(int names_count, const u1** names, void SymbolTable::initialize_symbols(int arena_alloc_size) {
int* lengths, Symbol** syms, TRAPS) { // Initialize the arena for global symbols, size passed in depends on CDS.
for (int i = 0; i< names_count; i++) { if (arena_alloc_size == 0) {
if (lengths[i] > Symbol::max_length()) { _arena = new Arena();
THROW_MSG_0(vmSymbols::java_lang_InternalError(), } else {
"name is too long to represent"); _arena = new Arena(arena_alloc_size);
}
}
for (int i = 0; i< names_count; i++) {
int len = lengths[i];
syms[i] = new (len) Symbol(names[i], len);
assert(syms[i] != NULL, "new should call vm_exit_out_of_memory if "
"C_HEAP is exhausted");
} }
return true;
} }
// Call function for all symbols in the symbol table. // Call function for all symbols in the symbol table.
...@@ -83,8 +85,7 @@ int SymbolTable::symbols_removed = 0; ...@@ -83,8 +85,7 @@ int SymbolTable::symbols_removed = 0;
int SymbolTable::symbols_counted = 0; int SymbolTable::symbols_counted = 0;
// Remove unreferenced symbols from the symbol table // Remove unreferenced symbols from the symbol table
// This is done late during GC. This doesn't use the hash table unlink because // This is done late during GC.
// it assumes that the literals are oops.
void SymbolTable::unlink() { void SymbolTable::unlink() {
int removed = 0; int removed = 0;
int total = 0; int total = 0;
...@@ -156,7 +157,7 @@ Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) { ...@@ -156,7 +157,7 @@ Symbol* SymbolTable::lookup(const char* name, int len, TRAPS) {
if (s != NULL) return s; if (s != NULL) return s;
// Otherwise, add to symbol to table // Otherwise, add to symbol to table
return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL); return the_table()->basic_add(index, (u1*)name, len, hashValue, true, CHECK_NULL);
} }
Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
...@@ -192,7 +193,7 @@ Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) { ...@@ -192,7 +193,7 @@ Symbol* SymbolTable::lookup(const Symbol* sym, int begin, int end, TRAPS) {
// We can't include the code in No_Safepoint_Verifier because of the // We can't include the code in No_Safepoint_Verifier because of the
// ResourceMark. // ResourceMark.
return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL); return the_table()->basic_add(index, (u1*)buffer, len, hashValue, true, CHECK_NULL);
} }
Symbol* SymbolTable::lookup_only(const char* name, int len, Symbol* SymbolTable::lookup_only(const char* name, int len,
...@@ -256,71 +257,81 @@ Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length, ...@@ -256,71 +257,81 @@ Symbol* SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
} }
} }
void SymbolTable::add(constantPoolHandle cp, int names_count, void SymbolTable::add(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS) { unsigned int* hashValues, TRAPS) {
SymbolTable* table = the_table(); SymbolTable* table = the_table();
bool added = table->basic_add(cp, names_count, names, lengths, bool added = table->basic_add(class_loader, cp, names_count, names, lengths,
cp_indices, hashValues, CHECK); cp_indices, hashValues, CHECK);
if (!added) { if (!added) {
// do it the hard way // do it the hard way
for (int i=0; i<names_count; i++) { for (int i=0; i<names_count; i++) {
int index = table->hash_to_index(hashValues[i]); int index = table->hash_to_index(hashValues[i]);
Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], bool c_heap = class_loader() != NULL;
hashValues[i], CHECK); Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK);
cp->symbol_at_put(cp_indices[i], sym); cp->symbol_at_put(cp_indices[i], sym);
} }
} }
} }
Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) {
unsigned int hash;
Symbol* result = SymbolTable::lookup_only((char*)name, (int)strlen(name), hash);
if (result != NULL) {
return result;
}
SymbolTable* table = the_table();
int index = table->hash_to_index(hash);
return table->basic_add(index, (u1*)name, (int)strlen(name), hash, false, THREAD);
}
Symbol* SymbolTable::basic_add(int index, u1 *name, int len, Symbol* SymbolTable::basic_add(int index, u1 *name, int len,
unsigned int hashValue, TRAPS) { unsigned int hashValue, bool c_heap, TRAPS) {
assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
"proposed name of symbol must be stable"); "proposed name of symbol must be stable");
// We assume that lookup() has been called already, that it failed, // Grab SymbolTable_lock first.
// and symbol was not found. We create the symbol here.
Symbol* sym = allocate_symbol(name, len, CHECK_NULL);
// Allocation must be done before grabbing the SymbolTable_lock lock
MutexLocker ml(SymbolTable_lock, THREAD); MutexLocker ml(SymbolTable_lock, THREAD);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
// Since look-up was done lock-free, we need to check if another // Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol. // thread beat us in the race to insert the symbol.
Symbol* test = lookup(index, (char*)name, len, hashValue); Symbol* test = lookup(index, (char*)name, len, hashValue);
if (test != NULL) { if (test != NULL) {
// A race occurred and another thread introduced the symbol, this one // A race occurred and another thread introduced the symbol.
// will be dropped and collected.
delete sym;
assert(test->refcount() != 0, "lookup should have incremented the count"); assert(test->refcount() != 0, "lookup should have incremented the count");
return test; return test;
} }
// Create a new symbol.
Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
sym->increment_refcount();
add_entry(index, entry); add_entry(index, entry);
return sym; return sym;
} }
bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, // This version of basic_add adds symbols in batch from the constant pool
// parsing.
bool SymbolTable::basic_add(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** names, int* lengths, const char** names, int* lengths,
int* cp_indices, unsigned int* hashValues, int* cp_indices, unsigned int* hashValues,
TRAPS) { TRAPS) {
Symbol* syms[symbol_alloc_batch_size];
bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, // Check symbol names are not too long. If any are too long, don't add any.
syms, CHECK_false); for (int i = 0; i< names_count; i++) {
if (!allocated) { if (lengths[i] > Symbol::max_length()) {
return false; THROW_MSG_0(vmSymbols::java_lang_InternalError(),
"name is too long to represent");
}
} }
// Allocation must be done before grabbing the SymbolTable_lock lock // Hold SymbolTable_lock through the symbol creation
MutexLocker ml(SymbolTable_lock, THREAD); MutexLocker ml(SymbolTable_lock, THREAD);
for (int i=0; i<names_count; i++) { for (int i=0; i<names_count; i++) {
assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
// Since look-up was done lock-free, we need to check if another // Since look-up was done lock-free, we need to check if another
// thread beat us in the race to insert the symbol. // thread beat us in the race to insert the symbol.
int index = hash_to_index(hashValues[i]); int index = hash_to_index(hashValues[i]);
...@@ -330,16 +341,17 @@ bool SymbolTable::basic_add(constantPoolHandle cp, int names_count, ...@@ -330,16 +341,17 @@ bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
// will be dropped and collected. Use test instead. // will be dropped and collected. Use test instead.
cp->symbol_at_put(cp_indices[i], test); cp->symbol_at_put(cp_indices[i], test);
assert(test->refcount() != 0, "lookup should have incremented the count"); assert(test->refcount() != 0, "lookup should have incremented the count");
delete syms[i];
} else { } else {
Symbol* sym = syms[i]; // Create a new symbol. The null class loader is never unloaded so these
// are allocated specially in a permanent arena.
bool c_heap = class_loader() != NULL;
Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be???
HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym); HashtableEntry<Symbol*>* entry = new_entry(hashValues[i], sym);
sym->increment_refcount(); // increment refcount in external hashtable
add_entry(index, entry); add_entry(index, entry);
cp->symbol_at_put(cp_indices[i], sym); cp->symbol_at_put(cp_indices[i], sym);
} }
} }
return true; return true;
} }
...@@ -406,6 +418,8 @@ void SymbolTable::print_histogram() { ...@@ -406,6 +418,8 @@ void SymbolTable::print_histogram() {
((float)symbols_removed/(float)symbols_counted)* 100); ((float)symbols_removed/(float)symbols_counted)* 100);
} }
tty->print_cr("Reference counts %5d", Symbol::_total_count); tty->print_cr("Reference counts %5d", Symbol::_total_count);
tty->print_cr("Symbol arena size %5d used %5d",
arena()->size_in_bytes(), arena()->used());
tty->print_cr("Histogram of symbol length:"); tty->print_cr("Histogram of symbol length:");
tty->print_cr("%8s %5d", "Total ", total); tty->print_cr("%8s %5d", "Total ", total);
tty->print_cr("%8s %5d", "Maximum", max_symbols); tty->print_cr("%8s %5d", "Maximum", max_symbols);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -82,24 +82,24 @@ private: ...@@ -82,24 +82,24 @@ private:
static int symbols_removed; static int symbols_removed;
static int symbols_counted; static int symbols_counted;
Symbol* allocate_symbol(const u1* name, int len, TRAPS); // Assumes no characters larger than 0x7F Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F
bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS);
// Adding elements // Adding elements
Symbol* basic_add(int index, u1* name, int len, Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue,
unsigned int hashValue, TRAPS); bool c_heap, TRAPS);
bool basic_add(constantPoolHandle cp, int names_count,
bool basic_add(Handle class_loader, constantPoolHandle cp, int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS); unsigned int* hashValues, TRAPS);
static void new_symbols(constantPoolHandle cp, int names_count, static void new_symbols(Handle class_loader, constantPoolHandle cp,
int names_count,
const char** name, int* lengths, const char** name, int* lengths,
int* cp_indices, unsigned int* hashValues, int* cp_indices, unsigned int* hashValues,
TRAPS) { TRAPS) {
add(cp, names_count, name, lengths, cp_indices, hashValues, THREAD); add(class_loader, cp, names_count, name, lengths, cp_indices, hashValues, THREAD);
} }
// Table size // Table size
enum { enum {
symbol_table_size = 20011 symbol_table_size = 20011
...@@ -114,10 +114,16 @@ private: ...@@ -114,10 +114,16 @@ private:
: Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t, : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t,
number_of_entries) {} number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
static Arena* _arena;
static Arena* arena() { return _arena; } // called for statistics
static void initialize_symbols(int arena_alloc_size = 0);
public: public:
enum { enum {
symbol_alloc_batch_size = 8 symbol_alloc_batch_size = 8,
// Pick initial size based on java -version size measurements
symbol_alloc_arena_size = 360*K
}; };
// The symbol table // The symbol table
...@@ -126,6 +132,7 @@ public: ...@@ -126,6 +132,7 @@ public:
static void create_table() { static void create_table() {
assert(_the_table == NULL, "One symbol table allowed."); assert(_the_table == NULL, "One symbol table allowed.");
_the_table = new SymbolTable(); _the_table = new SymbolTable();
initialize_symbols(symbol_alloc_arena_size);
} }
static void create_table(HashtableBucket* t, int length, static void create_table(HashtableBucket* t, int length,
...@@ -134,6 +141,9 @@ public: ...@@ -134,6 +141,9 @@ public:
assert(length == symbol_table_size * sizeof(HashtableBucket), assert(length == symbol_table_size * sizeof(HashtableBucket),
"bad shared symbol size."); "bad shared symbol size.");
_the_table = new SymbolTable(t, number_of_entries); _the_table = new SymbolTable(t, number_of_entries);
// if CDS give symbol table a default arena size since most symbols
// are already allocated in the shared misc section.
initialize_symbols();
} }
static Symbol* lookup(const char* name, int len, TRAPS); static Symbol* lookup(const char* name, int len, TRAPS);
...@@ -151,7 +161,7 @@ public: ...@@ -151,7 +161,7 @@ public:
static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); static Symbol* lookup_unicode(const jchar* name, int len, TRAPS);
static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
static void add(constantPoolHandle cp, int names_count, static void add(Handle class_loader, constantPoolHandle cp, int names_count,
const char** names, int* lengths, int* cp_indices, const char** names, int* lengths, int* cp_indices,
unsigned int* hashValues, TRAPS); unsigned int* hashValues, TRAPS);
...@@ -174,6 +184,9 @@ public: ...@@ -174,6 +184,9 @@ public:
return lookup(sym, begin, end, THREAD); return lookup(sym, begin, end, THREAD);
} }
// Create a symbol in the arena for symbols that are not deleted
static Symbol* new_permanent_symbol(const char* name, TRAPS);
// Symbol lookup // Symbol lookup
static Symbol* lookup(int index, const char* name, int len, TRAPS); static Symbol* lookup(int index, const char* name, int len, TRAPS);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -79,7 +79,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -79,7 +79,7 @@ void vmSymbols::initialize(TRAPS) {
if (!UseSharedSpaces) { if (!UseSharedSpaces) {
const char* string = &vm_symbol_bodies[0]; const char* string = &vm_symbol_bodies[0];
for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) { for (int index = (int)FIRST_SID; index < (int)SID_LIMIT; index++) {
Symbol* sym = SymbolTable::new_symbol(string, CHECK); Symbol* sym = SymbolTable::new_permanent_symbol(string, CHECK);
_symbols[index] = sym; _symbols[index] = sym;
string += strlen(string); // skip string body string += strlen(string); // skip string body
string += 1; // skip trailing null string += 1; // skip trailing null
...@@ -128,7 +128,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -128,7 +128,7 @@ void vmSymbols::initialize(TRAPS) {
// Spot-check correspondence between strings, symbols, and enums: // Spot-check correspondence between strings, symbols, and enums:
assert(_symbols[NO_SID] == NULL, "must be"); assert(_symbols[NO_SID] == NULL, "must be");
const char* str = "java/lang/Object"; const char* str = "java/lang/Object";
TempNewSymbol jlo = SymbolTable::new_symbol(str, CHECK); TempNewSymbol jlo = SymbolTable::new_permanent_symbol(str, CHECK);
assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, ""); assert(strncmp(str, (char*)jlo->base(), jlo->utf8_length()) == 0, "");
assert(jlo == java_lang_Object(), ""); assert(jlo == java_lang_Object(), "");
SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object);
...@@ -147,7 +147,7 @@ void vmSymbols::initialize(TRAPS) { ...@@ -147,7 +147,7 @@ void vmSymbols::initialize(TRAPS) {
// The string "format" happens (at the moment) not to be a vmSymbol, // The string "format" happens (at the moment) not to be a vmSymbol,
// though it is a method name in java.lang.String. // though it is a method name in java.lang.String.
str = "format"; str = "format";
TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK); TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str, CHECK);
sid = find_sid(fmt); sid = find_sid(fmt);
assert(sid == NO_SID, "symbol index works (negative test)"); assert(sid == NO_SID, "symbol index works (negative test)");
} }
......
/* /*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1490,12 +1490,11 @@ void GenCollectedHeap::preload_and_dump(TRAPS) { ...@@ -1490,12 +1490,11 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
// sun.io.Converters // sun.io.Converters
static const char obj_array_sig[] = "[[Ljava/lang/Object;"; static const char obj_array_sig[] = "[[Ljava/lang/Object;";
SymbolTable::lookup(obj_array_sig, (int)strlen(obj_array_sig), THREAD); (void)SymbolTable::new_permanent_symbol(obj_array_sig, THREAD);
// java.util.HashMap // java.util.HashMap
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
SymbolTable::lookup(map_entry_array_sig, (int)strlen(map_entry_array_sig), (void)SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
THREAD);
tty->print("Loading classes to share ... "); tty->print("Loading classes to share ... ");
while ((fgets(class_name, sizeof class_name, file)) != NULL) { while ((fgets(class_name, sizeof class_name, file)) != NULL) {
...@@ -1514,7 +1513,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) { ...@@ -1514,7 +1513,7 @@ void GenCollectedHeap::preload_and_dump(TRAPS) {
computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1); computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1);
// Got a class name - load it. // Got a class name - load it.
TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name, THREAD); Symbol* class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol."); guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol, klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol,
THREAD); THREAD);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -137,7 +137,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand ...@@ -137,7 +137,7 @@ klassOop objArrayKlassKlass::allocate_objArray_klass_impl(objArrayKlassKlassHand
new_str[idx++] = ';'; new_str[idx++] = ';';
} }
new_str[idx++] = '\0'; new_str[idx++] = '\0';
name = SymbolTable::new_symbol(new_str, CHECK_0); name = SymbolTable::new_permanent_symbol(new_str, CHECK_0);
if (element_klass->oop_is_instance()) { if (element_klass->oop_is_instance()) {
instanceKlass* ik = instanceKlass::cast(element_klass()); instanceKlass* ik = instanceKlass::cast(element_klass());
ik->set_array_name(name); ik->set_array_name(name);
......
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -29,15 +29,25 @@ ...@@ -29,15 +29,25 @@
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) { Symbol::Symbol(const u1* name, int length, int refcount) : _refcount(refcount), _length(length) {
_identity_hash = os::random(); _identity_hash = os::random();
for (int i = 0; i < _length; i++) { for (int i = 0; i < _length; i++) {
byte_at_put(i, name[i]); byte_at_put(i, name[i]);
} }
} }
void* Symbol::operator new(size_t size, int len) { void* Symbol::operator new(size_t sz, int len, TRAPS) {
return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol"); int alloc_size = object_size(len)*HeapWordSize;
address res = (address) AllocateHeap(alloc_size, "symbol");
DEBUG_ONLY(set_allocation_type(res, ResourceObj::C_HEAP);)
return res;
}
void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) {
int alloc_size = object_size(len)*HeapWordSize;
address res = (address)arena->Amalloc(alloc_size);
DEBUG_ONLY(set_allocation_type(res, ResourceObj::ARENA);)
return res;
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
...@@ -206,26 +216,5 @@ void Symbol::print_value_on(outputStream* st) const { ...@@ -206,26 +216,5 @@ void Symbol::print_value_on(outputStream* st) const {
} }
} }
void Symbol::increment_refcount() { // SymbolTable prints this in its statistics
// Only increment the refcount if positive. If negative either
// overflow has occurred or it is a permanent symbol in a read only
// shared archive.
if (_refcount >= 0) {
Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);)
}
}
void Symbol::decrement_refcount() {
if (_refcount >= 0) {
Atomic::dec(&_refcount);
#ifdef ASSERT
if (_refcount < 0) {
print();
assert(false, "reference count underflow for symbol");
}
#endif
}
}
NOT_PRODUCT(int Symbol::_total_count = 0;) NOT_PRODUCT(int Symbol::_total_count = 0;)
/* /*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "utilities/utf8.hpp" #include "utilities/utf8.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "runtime/atomic.hpp"
// A Symbol is a canonicalized string. // A Symbol is a canonicalized string.
// All Symbols reside in global SymbolTable and are reference counted. // All Symbols reside in global SymbolTable and are reference counted.
...@@ -95,7 +96,7 @@ ...@@ -95,7 +96,7 @@
// TempNewSymbol (passed in as a parameter) so the reference count on its symbol // TempNewSymbol (passed in as a parameter) so the reference count on its symbol
// will be decremented when it goes out of scope. // will be decremented when it goes out of scope.
class Symbol : public CHeapObj { class Symbol : public ResourceObj {
friend class VMStructs; friend class VMStructs;
friend class SymbolTable; friend class SymbolTable;
friend class MoveSymbols; friend class MoveSymbols;
...@@ -111,7 +112,7 @@ class Symbol : public CHeapObj { ...@@ -111,7 +112,7 @@ class Symbol : public CHeapObj {
}; };
static int object_size(int length) { static int object_size(int length) {
size_t size = heap_word_size(sizeof(Symbol) + length); size_t size = heap_word_size(sizeof(Symbol) + (length > 0 ? length - 1 : 0));
return align_object_size(size); return align_object_size(size);
} }
...@@ -120,28 +121,25 @@ class Symbol : public CHeapObj { ...@@ -120,28 +121,25 @@ class Symbol : public CHeapObj {
_body[index] = value; _body[index] = value;
} }
Symbol(const u1* name, int length); Symbol(const u1* name, int length, int refcount);
void* operator new(size_t size, int len); void* operator new(size_t size, int len, TRAPS);
void* operator new(size_t size, int len, Arena* arena, TRAPS);
public: public:
// Low-level access (used with care, since not GC-safe) // Low-level access (used with care, since not GC-safe)
const jbyte* base() const { return &_body[0]; } const jbyte* base() const { return &_body[0]; }
int object_size() { return object_size(utf8_length()); } int object_size() { return object_size(utf8_length()); }
// Returns the largest size symbol we can safely hold. // Returns the largest size symbol we can safely hold.
static int max_length() { static int max_length() { return max_symbol_length; }
return max_symbol_length;
}
int identity_hash() { int identity_hash() { return _identity_hash; }
return _identity_hash;
}
// Reference counting. See comments above this class for when to use. // Reference counting. See comments above this class for when to use.
int refcount() const { return _refcount; } int refcount() const { return _refcount; }
void increment_refcount(); inline void increment_refcount();
void decrement_refcount(); inline void decrement_refcount();
int byte_at(int index) const { int byte_at(int index) const {
assert(index >=0 && index < _length, "symbol index overflow"); assert(index >=0 && index < _length, "symbol index overflow");
...@@ -220,4 +218,26 @@ int Symbol::fast_compare(Symbol* other) const { ...@@ -220,4 +218,26 @@ int Symbol::fast_compare(Symbol* other) const {
return (((uintptr_t)this < (uintptr_t)other) ? -1 return (((uintptr_t)this < (uintptr_t)other) ? -1
: ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
} }
inline void Symbol::increment_refcount() {
// Only increment the refcount if positive. If negative either
// overflow has occurred or it is a permanent symbol in a read only
// shared archive.
if (_refcount >= 0) {
Atomic::inc(&_refcount);
NOT_PRODUCT(Atomic::inc(&_total_count);)
}
}
inline void Symbol::decrement_refcount() {
if (_refcount >= 0) {
Atomic::dec(&_refcount);
#ifdef ASSERT
if (_refcount < 0) {
print();
assert(false, "reference count underflow for symbol");
}
#endif
}
}
#endif // SHARE_VM_OOPS_SYMBOL_HPP #endif // SHARE_VM_OOPS_SYMBOL_HPP
...@@ -55,7 +55,7 @@ klassOop typeArrayKlass::create_klass(BasicType type, int scale, ...@@ -55,7 +55,7 @@ klassOop typeArrayKlass::create_klass(BasicType type, int scale,
Symbol* sym = NULL; Symbol* sym = NULL;
if (name_str != NULL) { if (name_str != NULL) {
sym = SymbolTable::new_symbol(name_str, CHECK_NULL); sym = SymbolTable::new_permanent_symbol(name_str, CHECK_NULL);
} }
KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj()); KlassHandle klassklass (THREAD, Universe::typeArrayKlassKlassObj());
......
...@@ -3807,7 +3807,7 @@ class CommandLineFlags { ...@@ -3807,7 +3807,7 @@ class CommandLineFlags {
product(uintx, SharedReadOnlySize, 10*M, \ product(uintx, SharedReadOnlySize, 10*M, \
"Size of read-only space in permanent generation (in bytes)") \ "Size of read-only space in permanent generation (in bytes)") \
\ \
product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M), \ product(uintx, SharedMiscDataSize, NOT_LP64(4*M) LP64_ONLY(5*M) NOT_PRODUCT(+1*M), \
"Size of the shared data area adjacent to the heap (in bytes)") \ "Size of the shared data area adjacent to the heap (in bytes)") \
\ \
product(uintx, SharedMiscCodeSize, 4*M, \ product(uintx, SharedMiscCodeSize, 4*M, \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册