# HG changeset patch # User coleenp # Date 1332515765 14400 # Node ID fc9d8850ab8bf827255fcf5445cd5ed7887c1905 # Parent 51612f0c0a79d90f5ac442d0e55da8e7d36022c5 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 diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ #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 // this function (_current can be allocated in a register, with scalar // replacement of aggregates). The _current pointer is copied back to @@ -272,7 +272,7 @@ indices[names_count] = index; hashValues[names_count++] = hash; 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; } } else { @@ -289,7 +289,7 @@ // Allocate the remaining symbols 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(). @@ -318,7 +318,7 @@ 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(); constantPoolHandle nullHandle; @@ -337,7 +337,7 @@ ConstantPoolCleaner cp_in_error(cp); // set constant pool to be cleaned up. // 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 @@ -2758,7 +2758,7 @@ _relax_verify = Verifier::relax_verify_for(class_loader()); // 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. int cp_size = cp->length(); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/classfile/classFileParser.hpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -68,9 +68,10 @@ void set_stream(ClassFileStream* st) { _stream = st; } // 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 objArrayHandle parse_interfaces(constantPoolHandle cp, diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/classfile/symbolTable.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #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" @@ -37,34 +38,35 @@ // -------------------------------------------------------------------------- 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*. if (len > Symbol::max_length()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "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"); return sym; } -bool SymbolTable::allocate_symbols(int names_count, const u1** names, - int* lengths, Symbol** syms, TRAPS) { - for (int i = 0; i< names_count; i++) { - if (lengths[i] > Symbol::max_length()) { - THROW_MSG_0(vmSymbols::java_lang_InternalError(), - "name is too long to represent"); - } +void SymbolTable::initialize_symbols(int arena_alloc_size) { + // Initialize the arena for global symbols, size passed in depends on CDS. + if (arena_alloc_size == 0) { + _arena = new Arena(); + } else { + _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. @@ -83,8 +85,7 @@ int SymbolTable::symbols_counted = 0; // Remove unreferenced symbols from the symbol table -// This is done late during GC. This doesn't use the hash table unlink because -// it assumes that the literals are oops. +// This is done late during GC. void SymbolTable::unlink() { int removed = 0; int total = 0; @@ -156,7 +157,7 @@ if (s != NULL) return s; // 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) { @@ -192,7 +193,7 @@ // We can't include the code in No_Safepoint_Verifier because of the // 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, @@ -256,71 +257,81 @@ } } -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, unsigned int* hashValues, TRAPS) { 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); if (!added) { // do it the hard way for (int i=0; ihash_to_index(hashValues[i]); - Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], - hashValues[i], CHECK); + bool c_heap = class_loader() != NULL; + Symbol* sym = table->basic_add(index, (u1*)names[i], lengths[i], hashValues[i], c_heap, CHECK); 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, - unsigned int hashValue, TRAPS) { + unsigned int hashValue, bool c_heap, TRAPS) { assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), "proposed name of symbol must be stable"); - // We assume that lookup() has been called already, that it failed, - // 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 + // Grab SymbolTable_lock first. 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 // thread beat us in the race to insert the symbol. - Symbol* test = lookup(index, (char*)name, len, hashValue); if (test != NULL) { - // A race occurred and another thread introduced the symbol, this one - // will be dropped and collected. - delete sym; + // A race occurred and another thread introduced the symbol. assert(test->refcount() != 0, "lookup should have incremented the count"); 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* entry = new_entry(hashValue, sym); - sym->increment_refcount(); add_entry(index, entry); 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, int* cp_indices, unsigned int* hashValues, TRAPS) { - Symbol* syms[symbol_alloc_batch_size]; - bool allocated = allocate_symbols(names_count, (const u1**)names, lengths, - syms, CHECK_false); - if (!allocated) { - return false; + + // Check symbol names are not too long. If any are too long, don't add any. + for (int i = 0; i< names_count; i++) { + if (lengths[i] > Symbol::max_length()) { + 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); for (int i=0; iequals(names[i], lengths[i]), "symbol must be properly initialized"); // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. int index = hash_to_index(hashValues[i]); @@ -330,16 +341,17 @@ // will be dropped and collected. Use test instead. cp->symbol_at_put(cp_indices[i], test); assert(test->refcount() != 0, "lookup should have incremented the count"); - delete syms[i]; } 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* entry = new_entry(hashValues[i], sym); - sym->increment_refcount(); // increment refcount in external hashtable add_entry(index, entry); cp->symbol_at_put(cp_indices[i], sym); } } - return true; } @@ -406,6 +418,8 @@ ((float)symbols_removed/(float)symbols_counted)* 100); } 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("%8s %5d", "Total ", total); tty->print_cr("%8s %5d", "Maximum", max_symbols); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/classfile/symbolTable.hpp --- a/src/share/vm/classfile/symbolTable.hpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/classfile/symbolTable.hpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -82,24 +82,24 @@ static int symbols_removed; static int symbols_counted; - Symbol* allocate_symbol(const u1* name, int len, TRAPS); // Assumes no characters larger than 0x7F - bool allocate_symbols(int names_count, const u1** names, int* lengths, Symbol** syms, TRAPS); + Symbol* allocate_symbol(const u1* name, int len, bool c_heap, TRAPS); // Assumes no characters larger than 0x7F // Adding elements - Symbol* basic_add(int index, u1* name, int len, - unsigned int hashValue, TRAPS); - bool basic_add(constantPoolHandle cp, int names_count, + Symbol* basic_add(int index, u1* name, int len, unsigned int hashValue, + bool c_heap, TRAPS); + + bool basic_add(Handle class_loader, constantPoolHandle cp, int names_count, const char** names, int* lengths, int* cp_indices, 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, int* cp_indices, unsigned int* hashValues, 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 enum { symbol_table_size = 20011 @@ -114,10 +114,16 @@ : Hashtable(symbol_table_size, sizeof (HashtableEntry), t, 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: 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 @@ -126,6 +132,7 @@ static void create_table() { assert(_the_table == NULL, "One symbol table allowed."); _the_table = new SymbolTable(); + initialize_symbols(symbol_alloc_arena_size); } static void create_table(HashtableBucket* t, int length, @@ -134,6 +141,9 @@ assert(length == symbol_table_size * sizeof(HashtableBucket), "bad shared symbol size."); _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); @@ -151,7 +161,7 @@ static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); 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, unsigned int* hashValues, TRAPS); @@ -174,6 +184,9 @@ 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 static Symbol* lookup(int index, const char* name, int len, TRAPS); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/classfile/vmSymbols.cpp --- a/src/share/vm/classfile/vmSymbols.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/classfile/vmSymbols.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ if (!UseSharedSpaces) { const char* string = &vm_symbol_bodies[0]; 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; string += strlen(string); // skip string body string += 1; // skip trailing null @@ -128,7 +128,7 @@ // Spot-check correspondence between strings, symbols, and enums: assert(_symbols[NO_SID] == NULL, "must be"); 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(jlo == java_lang_Object(), ""); SID sid = VM_SYMBOL_ENUM_NAME(java_lang_Object); @@ -147,7 +147,7 @@ // The string "format" happens (at the moment) not to be a vmSymbol, // though it is a method name in java.lang.String. str = "format"; - TempNewSymbol fmt = SymbolTable::new_symbol(str, CHECK); + TempNewSymbol fmt = SymbolTable::new_permanent_symbol(str, CHECK); sid = find_sid(fmt); assert(sid == NO_SID, "symbol index works (negative test)"); } diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/memory/dump.cpp --- a/src/share/vm/memory/dump.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/memory/dump.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -1490,12 +1490,11 @@ // sun.io.Converters 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 static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; - SymbolTable::lookup(map_entry_array_sig, (int)strlen(map_entry_array_sig), - THREAD); + (void)SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); tty->print("Loading classes to share ... "); while ((fgets(class_name, sizeof class_name, file)) != NULL) { @@ -1514,7 +1513,7 @@ computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1); // 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."); klassOop klass = SystemDictionary::resolve_or_null(class_name_symbol, THREAD); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/oops/objArrayKlassKlass.cpp --- a/src/share/vm/oops/objArrayKlassKlass.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/oops/objArrayKlassKlass.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -137,7 +137,7 @@ new_str[idx++] = ';'; } 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()) { instanceKlass* ik = instanceKlass::cast(element_klass()); ik->set_array_name(name); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/oops/symbol.cpp --- a/src/share/vm/oops/symbol.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/oops/symbol.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,25 @@ #include "runtime/os.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(); for (int i = 0; i < _length; i++) { byte_at_put(i, name[i]); } } -void* Symbol::operator new(size_t size, int len) { - return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol"); +void* Symbol::operator new(size_t sz, int len, TRAPS) { + 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::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);) - } -} - -void Symbol::decrement_refcount() { - if (_refcount >= 0) { - Atomic::dec(&_refcount); -#ifdef ASSERT - if (_refcount < 0) { - print(); - assert(false, "reference count underflow for symbol"); - } -#endif - } -} - +// SymbolTable prints this in its statistics NOT_PRODUCT(int Symbol::_total_count = 0;) diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/oops/symbol.hpp --- a/src/share/vm/oops/symbol.hpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/oops/symbol.hpp Fri Mar 23 11:16:05 2012 -0400 @@ -1,5 +1,5 @@ /* - * 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. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "utilities/utf8.hpp" #include "memory/allocation.hpp" +#include "runtime/atomic.hpp" // A Symbol is a canonicalized string. // All Symbols reside in global SymbolTable and are reference counted. @@ -95,7 +96,7 @@ // TempNewSymbol (passed in as a parameter) so the reference count on its symbol // will be decremented when it goes out of scope. -class Symbol : public CHeapObj { +class Symbol : public ResourceObj { friend class VMStructs; friend class SymbolTable; friend class MoveSymbols; @@ -111,7 +112,7 @@ }; 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); } @@ -120,28 +121,25 @@ _body[index] = value; } - Symbol(const u1* name, int length); - void* operator new(size_t size, int len); + Symbol(const u1* name, int length, int refcount); + void* operator new(size_t size, int len, TRAPS); + void* operator new(size_t size, int len, Arena* arena, TRAPS); public: // Low-level access (used with care, since not GC-safe) 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. - static int max_length() { - return max_symbol_length; - } + static int max_length() { return max_symbol_length; } - int identity_hash() { - return _identity_hash; - } + int identity_hash() { return _identity_hash; } // Reference counting. See comments above this class for when to use. - int refcount() const { return _refcount; } - void increment_refcount(); - void decrement_refcount(); + int refcount() const { return _refcount; } + inline void increment_refcount(); + inline void decrement_refcount(); int byte_at(int index) const { assert(index >=0 && index < _length, "symbol index overflow"); @@ -220,4 +218,26 @@ return (((uintptr_t)this < (uintptr_t)other) ? -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 diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/oops/typeArrayKlass.cpp --- a/src/share/vm/oops/typeArrayKlass.cpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/oops/typeArrayKlass.cpp Fri Mar 23 11:16:05 2012 -0400 @@ -55,7 +55,7 @@ Symbol* sym = 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()); diff -r 51612f0c0a79 -r fc9d8850ab8b src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Mar 15 13:37:13 2012 +0100 +++ b/src/share/vm/runtime/globals.hpp Fri Mar 23 11:16:05 2012 -0400 @@ -3807,7 +3807,7 @@ product(uintx, SharedReadOnlySize, 10*M, \ "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)") \ \ product(uintx, SharedMiscCodeSize, 4*M, \