Mercurial > hg > release > icedtea6-1.11
view patches/openjdk/6990754-handle_renames.patch @ 2909:c5297dd496da
Fix patches to work with patch tools that can not handle renames
2013-06-26 Omair Majid <omajid@redhat.com>
* Makefile.am:
(SECURITY_PATCHES): Add patches/openjdk/6990754-handle_renames.patch and
patches/openjdk/6851834-handle_renames.patch
* patches/openjdk/6990754-use_native_memory_for_symboltable.patch: Don't
rename files using extended-diff-style.
* patches/openjdk/6990754-handle_renames.patch: New file. Contains the
rename portion of 6990754 since some patch programs can not handle
renames.
* patches/openjdk/6851834-restructure.patch: Don't rename files using
extended-diff-style.
* patches/openjdk/6851834-handle_renames.patch: New file. Contains rename
porition of 6851834 since some patch programs can not handle renames.
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Wed, 26 Jun 2013 10:47:13 -0400 |
parents | |
children |
line wrap: on
line source
This handles the rename bits of the original 6990754 diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbol.cpp openjdk/hotspot/src/share/vm/oops/symbol.cpp --- openjdk.orig/hotspot/src/share/vm/oops/symbol.cpp 1969-12-31 19:00:00.000000000 -0500 +++ openjdk/hotspot/src/share/vm/oops/symbol.cpp 2013-06-25 14:49:37.268431428 -0400 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 1997, 2009, 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. + * + */ + + +#include "precompiled.hpp" +#include "oops/oop.inline.hpp" +#include "oops/symbol.hpp" +#include "runtime/os.hpp" +#include "memory/allocation.inline.hpp" + +Symbol::Symbol(const u1* name, int length) : _refcount(0), _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"); +} + +// ------------------------------------------------------------------ +// Symbol::equals +// +// Compares the symbol with a string of the given length. +bool Symbol::equals(const char* str, int len) const { + int l = utf8_length(); + if (l != len) return false; + while (l-- > 0) { + if (str[l] != (char) byte_at(l)) + return false; + } + assert(l == -1, "we should be at the beginning"); + return true; +} + + +// ------------------------------------------------------------------ +// Symbol::starts_with +// +// Tests if the symbol starts with the specified prefix of the given +// length. +bool Symbol::starts_with(const char* prefix, int len) const { + if (len > utf8_length()) return false; + while (len-- > 0) { + if (prefix[len] != (char) byte_at(len)) + return false; + } + assert(len == -1, "we should be at the beginning"); + return true; +} + + +// ------------------------------------------------------------------ +// Symbol::index_of +// +// Finds if the given string is a substring of this symbol's utf8 bytes. +// Return -1 on failure. Otherwise return the first index where str occurs. +int Symbol::index_of_at(int i, const char* str, int len) const { + assert(i >= 0 && i <= utf8_length(), "oob"); + if (len <= 0) return 0; + char first_char = str[0]; + address bytes = (address) ((Symbol*)this)->base(); + address limit = bytes + utf8_length() - len; // inclusive limit + address scan = bytes + i; + if (scan > limit) + return -1; + for (;;) { + scan = (address) memchr(scan, first_char, (limit + 1 - scan)); + if (scan == NULL) + return -1; // not found + assert(scan >= bytes+i && scan <= limit, "scan oob"); + if (memcmp(scan, str, len) == 0) + return (int)(scan - bytes); + } +} + + +char* Symbol::as_C_string(char* buf, int size) const { + if (size > 0) { + int len = MIN2(size - 1, utf8_length()); + for (int i = 0; i < len; i++) { + buf[i] = byte_at(i); + } + buf[len] = '\0'; + } + return buf; +} + +char* Symbol::as_C_string() const { + int len = utf8_length(); + char* str = NEW_RESOURCE_ARRAY(char, len + 1); + return as_C_string(str, len + 1); +} + +char* Symbol::as_C_string_flexible_buffer(Thread* t, + char* buf, int size) const { + char* str; + int len = utf8_length(); + int buf_len = len + 1; + if (size < buf_len) { + str = NEW_RESOURCE_ARRAY(char, buf_len); + } else { + str = buf; + } + return as_C_string(str, buf_len); +} + +void Symbol::print_symbol_on(outputStream* st) const { + st = st ? st : tty; + int length = UTF8::unicode_length((const char*)bytes(), utf8_length()); + const char *ptr = (const char *)bytes(); + jchar value; + for (int index = 0; index < length; index++) { + ptr = UTF8::next(ptr, &value); + if (value >= 32 && value < 127 || value == '\'' || value == '\\') { + st->put(value); + } else { + st->print("\\u%04x", value); + } + } +} + +jchar* Symbol::as_unicode(int& length) const { + Symbol* this_ptr = (Symbol*)this; + length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length()); + jchar* result = NEW_RESOURCE_ARRAY(jchar, length); + if (length > 0) { + UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length); + } + return result; +} + +const char* Symbol::as_klass_external_name(char* buf, int size) const { + if (size > 0) { + char* str = as_C_string(buf, size); + int length = (int)strlen(str); + // Turn all '/'s into '.'s (also for array klasses) + for (int index = 0; index < length; index++) { + if (str[index] == '/') { + str[index] = '.'; + } + } + return str; + } else { + return buf; + } +} + +const char* Symbol::as_klass_external_name() const { + char* str = as_C_string(); + int length = (int)strlen(str); + // Turn all '/'s into '.'s (also for array klasses) + for (int index = 0; index < length; index++) { + if (str[index] == '/') { + str[index] = '.'; + } + } + return str; +} + + +void Symbol::print_on(outputStream* st) const { + if (this == NULL) { + st->print_cr("NULL"); + } else { + st->print("Symbol: '"); + print_symbol_on(st); + st->print("'"); + st->print(" count %d", refcount()); + } +} + +// The print_value functions are present in all builds, to support the +// disassembler and error reporting. +void Symbol::print_value_on(outputStream* st) const { + if (this == NULL) { + st->print("NULL"); + } else { + st->print("'"); + for (int i = 0; i < utf8_length(); i++) { + st->print("%c", byte_at(i)); + } + st->print("'"); + } +} + +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 + } +} + +NOT_PRODUCT(int Symbol::_total_count = 0;) diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbol.hpp openjdk/hotspot/src/share/vm/oops/symbol.hpp --- openjdk.orig/hotspot/src/share/vm/oops/symbol.hpp 1969-12-31 19:00:00.000000000 -0500 +++ openjdk/hotspot/src/share/vm/oops/symbol.hpp 2013-06-25 14:49:37.269431439 -0400 @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1997, 2009, 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_OOPS_SYMBOL_HPP +#define SHARE_VM_OOPS_SYMBOL_HPP + +#include "utilities/utf8.hpp" +#include "memory/allocation.hpp" + +// A Symbol is a canonicalized string. +// All Symbols reside in global SymbolTable and are reference counted. + +// Reference counting +// +// All Symbols are allocated and added to the SymbolTable. +// When a class is unloaded, the reference counts of the Symbol pointers in +// the ConstantPool and in instanceKlass (see release_C_heap_structures) are +// decremented. When the reference count for a Symbol goes to 0, the garbage +// collector can free the Symbol and remove it from the SymbolTable. +// +// 0) Symbols need to be reference counted when a pointer to the Symbol is +// saved in persistent storage. This does not include the pointer +// in the SymbolTable bucket (the _literal field in HashtableEntry) +// that points to the Symbol. All other stores of a Symbol* +// to a field of a persistent variable (e.g., the _name filed in +// FieldAccessInfo or _ptr in a CPSlot) is reference counted. +// +// 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for +// "name" and returns a pointer to F or finds a pre-existing Symbol F for +// "name" and returns a pointer to it. In both cases the reference count for F +// is incremented under the assumption that a pointer to F will be created from +// the return value. Thus the increment of the reference count is on the lookup +// and not on the assignment to the new Symbol*. That is +// Symbol* G = lookup() +// ^ increment on lookup() +// and not +// Symbol* G = lookup() +// ^ increment on assignmnet +// The reference count must be decremented manually when the copy of the +// pointer G is destroyed. +// +// 2) For a local Symbol* A that is a copy of an existing Symbol* B, the +// reference counting is elided when the scope of B is greater than the scope +// of A. For example, in the code fragment +// below "klass" is passed as a parameter to the method. Symbol* "kn" +// is a copy of the name in "klass". +// +// Symbol* kn = klass->name(); +// unsigned int d_hash = dictionary()->compute_hash(kn, class_loader); +// +// The scope of "klass" is greater than the scope of "kn" so the reference +// counting for "kn" is elided. +// +// Symbol* copied from ConstantPool entries are good candidates for reference +// counting elision. The ConstantPool entries for a class C exist until C is +// unloaded. If a Symbol* is copied out of the ConstantPool into Symbol* X, +// the Symbol* in the ConstantPool will in general out live X so the reference +// counting on X can be elided. +// +// For cases where the scope of A is not greater than the scope of B, +// the reference counting is explicitly done. See ciSymbol, +// ResolutionErrorEntry and ClassVerifier for examples. +// +// 3) When a Symbol K is created for temporary use, generally for substrings of +// an existing symbol or to create a new symbol, assign it to a +// TempNewSymbol. The SymbolTable methods new_symbol(), lookup() +// and probe() all potentially return a pointer to a new Symbol. +// The allocation (or lookup) of K increments the reference count for K +// and the destructor decrements the reference count. +// +// Another example of TempNewSymbol usage is parsed_name used in +// ClassFileParser::parseClassFile() where parsed_name is used in the cleanup +// after a failed attempt to load a class. Here parsed_name is a +// 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 { + friend class VMStructs; + friend class SymbolTable; + friend class MoveSymbols; + private: + volatile int _refcount; + int _identity_hash; + unsigned short _length; // number of UTF8 characters in the symbol + jbyte _body[1]; + + enum { + // max_symbol_length is constrained by type of _length + max_symbol_length = (1 << 16) -1 + }; + + static int object_size(int length) { + size_t size = heap_word_size(sizeof(Symbol) + length); + return align_object_size(size); + } + + void byte_at_put(int index, int value) { + assert(index >=0 && index < _length, "symbol index overflow"); + _body[index] = value; + } + + Symbol(const u1* name, int length); + void* operator new(size_t size, int len); + + 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()); } + + // Returns the largest size symbol we can safely hold. + static int max_length() { + return max_symbol_length; + } + + 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 byte_at(int index) const { + assert(index >=0 && index < _length, "symbol index overflow"); + return base()[index]; + } + + const jbyte* bytes() const { return base(); } + + int utf8_length() const { return _length; } + + // Compares the symbol with a string. + bool equals(const char* str, int len) const; + bool equals(const char* str) const { return equals(str, (int) strlen(str)); } + + // Tests if the symbol starts with the given prefix. + bool starts_with(const char* prefix, int len) const; + bool starts_with(const char* prefix) const { + return starts_with(prefix, (int) strlen(prefix)); + } + + // Tests if the symbol starts with the given prefix. + int index_of_at(int i, const char* str, int len) const; + int index_of_at(int i, const char* str) const { + return index_of_at(i, str, (int) strlen(str)); + } + + // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg + // note that the ordering is not alfabetical + inline int fast_compare(Symbol* other) const; + + // Returns receiver converted to null-terminated UTF-8 string; string is + // allocated in resource area, or in the char buffer provided by caller. + char* as_C_string() const; + char* as_C_string(char* buf, int size) const; + // Use buf if needed buffer length is <= size. + char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; + + + // Returns a null terminated utf8 string in a resource array + char* as_utf8() const { return as_C_string(); } + char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const { + return as_C_string_flexible_buffer(t, buf, size); + } + + jchar* as_unicode(int& length) const; + + // Treating this symbol as a class name, returns the Java name for the class. + // String is allocated in resource area if buffer is not provided. + // See Klass::external_name() + const char* as_klass_external_name() const; + const char* as_klass_external_name(char* buf, int size) const; + + // Printing + void print_symbol_on(outputStream* st = NULL) const; + void print_on(outputStream* st) const; // First level print + void print_value_on(outputStream* st) const; // Second level print. + + // printing on default output stream + void print() { print_on(tty); } + void print_value() { print_value_on(tty); } + +#ifndef PRODUCT + // Empty constructor to create a dummy symbol object on stack + // only for getting its vtable pointer. + Symbol() { } + + static int _total_count; +#endif +}; + +// Note: this comparison is used for vtable sorting only; it doesn't matter +// what order it defines, as long as it is a total, time-invariant order +// Since Symbol*s are in C_HEAP, their relative order in memory never changes, +// so use address comparison for speed +int Symbol::fast_compare(Symbol* other) const { + return (((uintptr_t)this < (uintptr_t)other) ? -1 + : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); +} +#endif // SHARE_VM_OOPS_SYMBOL_HPP diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbolOop.cpp openjdk/hotspot/src/share/vm/oops/symbolOop.cpp --- openjdk.orig/hotspot/src/share/vm/oops/symbolOop.cpp 2013-06-25 14:49:37.268431428 -0400 +++ openjdk/hotspot/src/share/vm/oops/symbolOop.cpp 1969-12-31 19:00:00.000000000 -0500 @@ -1,231 +0,0 @@ -/* - * Copyright (c) 1997, 2009, 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. - * - */ - - -#include "precompiled.hpp" -#include "oops/oop.inline.hpp" -#include "oops/symbol.hpp" -#include "runtime/os.hpp" -#include "memory/allocation.inline.hpp" - -Symbol::Symbol(const u1* name, int length) : _refcount(0), _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"); -} - -// ------------------------------------------------------------------ -// Symbol::equals -// -// Compares the symbol with a string of the given length. -bool Symbol::equals(const char* str, int len) const { - int l = utf8_length(); - if (l != len) return false; - while (l-- > 0) { - if (str[l] != (char) byte_at(l)) - return false; - } - assert(l == -1, "we should be at the beginning"); - return true; -} - - -// ------------------------------------------------------------------ -// Symbol::starts_with -// -// Tests if the symbol starts with the specified prefix of the given -// length. -bool Symbol::starts_with(const char* prefix, int len) const { - if (len > utf8_length()) return false; - while (len-- > 0) { - if (prefix[len] != (char) byte_at(len)) - return false; - } - assert(len == -1, "we should be at the beginning"); - return true; -} - - -// ------------------------------------------------------------------ -// Symbol::index_of -// -// Finds if the given string is a substring of this symbol's utf8 bytes. -// Return -1 on failure. Otherwise return the first index where str occurs. -int Symbol::index_of_at(int i, const char* str, int len) const { - assert(i >= 0 && i <= utf8_length(), "oob"); - if (len <= 0) return 0; - char first_char = str[0]; - address bytes = (address) ((Symbol*)this)->base(); - address limit = bytes + utf8_length() - len; // inclusive limit - address scan = bytes + i; - if (scan > limit) - return -1; - for (;;) { - scan = (address) memchr(scan, first_char, (limit + 1 - scan)); - if (scan == NULL) - return -1; // not found - assert(scan >= bytes+i && scan <= limit, "scan oob"); - if (memcmp(scan, str, len) == 0) - return (int)(scan - bytes); - } -} - - -char* Symbol::as_C_string(char* buf, int size) const { - if (size > 0) { - int len = MIN2(size - 1, utf8_length()); - for (int i = 0; i < len; i++) { - buf[i] = byte_at(i); - } - buf[len] = '\0'; - } - return buf; -} - -char* Symbol::as_C_string() const { - int len = utf8_length(); - char* str = NEW_RESOURCE_ARRAY(char, len + 1); - return as_C_string(str, len + 1); -} - -char* Symbol::as_C_string_flexible_buffer(Thread* t, - char* buf, int size) const { - char* str; - int len = utf8_length(); - int buf_len = len + 1; - if (size < buf_len) { - str = NEW_RESOURCE_ARRAY(char, buf_len); - } else { - str = buf; - } - return as_C_string(str, buf_len); -} - -void Symbol::print_symbol_on(outputStream* st) const { - st = st ? st : tty; - int length = UTF8::unicode_length((const char*)bytes(), utf8_length()); - const char *ptr = (const char *)bytes(); - jchar value; - for (int index = 0; index < length; index++) { - ptr = UTF8::next(ptr, &value); - if (value >= 32 && value < 127 || value == '\'' || value == '\\') { - st->put(value); - } else { - st->print("\\u%04x", value); - } - } -} - -jchar* Symbol::as_unicode(int& length) const { - Symbol* this_ptr = (Symbol*)this; - length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length()); - jchar* result = NEW_RESOURCE_ARRAY(jchar, length); - if (length > 0) { - UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length); - } - return result; -} - -const char* Symbol::as_klass_external_name(char* buf, int size) const { - if (size > 0) { - char* str = as_C_string(buf, size); - int length = (int)strlen(str); - // Turn all '/'s into '.'s (also for array klasses) - for (int index = 0; index < length; index++) { - if (str[index] == '/') { - str[index] = '.'; - } - } - return str; - } else { - return buf; - } -} - -const char* Symbol::as_klass_external_name() const { - char* str = as_C_string(); - int length = (int)strlen(str); - // Turn all '/'s into '.'s (also for array klasses) - for (int index = 0; index < length; index++) { - if (str[index] == '/') { - str[index] = '.'; - } - } - return str; -} - - -void Symbol::print_on(outputStream* st) const { - if (this == NULL) { - st->print_cr("NULL"); - } else { - st->print("Symbol: '"); - print_symbol_on(st); - st->print("'"); - st->print(" count %d", refcount()); - } -} - -// The print_value functions are present in all builds, to support the -// disassembler and error reporting. -void Symbol::print_value_on(outputStream* st) const { - if (this == NULL) { - st->print("NULL"); - } else { - st->print("'"); - for (int i = 0; i < utf8_length(); i++) { - st->print("%c", byte_at(i)); - } - st->print("'"); - } -} - -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 - } -} - -NOT_PRODUCT(int Symbol::_total_count = 0;) diff -ruN openjdk.orig/hotspot/src/share/vm/oops/symbolOop.hpp openjdk/hotspot/src/share/vm/oops/symbolOop.hpp --- openjdk.orig/hotspot/src/share/vm/oops/symbolOop.hpp 2013-06-25 14:49:37.269431439 -0400 +++ openjdk/hotspot/src/share/vm/oops/symbolOop.hpp 1969-12-31 19:00:00.000000000 -0500 @@ -1,223 +0,0 @@ -/* - * Copyright (c) 1997, 2009, 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_OOPS_SYMBOL_HPP -#define SHARE_VM_OOPS_SYMBOL_HPP - -#include "utilities/utf8.hpp" -#include "memory/allocation.hpp" - -// A Symbol is a canonicalized string. -// All Symbols reside in global SymbolTable and are reference counted. - -// Reference counting -// -// All Symbols are allocated and added to the SymbolTable. -// When a class is unloaded, the reference counts of the Symbol pointers in -// the ConstantPool and in instanceKlass (see release_C_heap_structures) are -// decremented. When the reference count for a Symbol goes to 0, the garbage -// collector can free the Symbol and remove it from the SymbolTable. -// -// 0) Symbols need to be reference counted when a pointer to the Symbol is -// saved in persistent storage. This does not include the pointer -// in the SymbolTable bucket (the _literal field in HashtableEntry) -// that points to the Symbol. All other stores of a Symbol* -// to a field of a persistent variable (e.g., the _name filed in -// FieldAccessInfo or _ptr in a CPSlot) is reference counted. -// -// 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for -// "name" and returns a pointer to F or finds a pre-existing Symbol F for -// "name" and returns a pointer to it. In both cases the reference count for F -// is incremented under the assumption that a pointer to F will be created from -// the return value. Thus the increment of the reference count is on the lookup -// and not on the assignment to the new Symbol*. That is -// Symbol* G = lookup() -// ^ increment on lookup() -// and not -// Symbol* G = lookup() -// ^ increment on assignmnet -// The reference count must be decremented manually when the copy of the -// pointer G is destroyed. -// -// 2) For a local Symbol* A that is a copy of an existing Symbol* B, the -// reference counting is elided when the scope of B is greater than the scope -// of A. For example, in the code fragment -// below "klass" is passed as a parameter to the method. Symbol* "kn" -// is a copy of the name in "klass". -// -// Symbol* kn = klass->name(); -// unsigned int d_hash = dictionary()->compute_hash(kn, class_loader); -// -// The scope of "klass" is greater than the scope of "kn" so the reference -// counting for "kn" is elided. -// -// Symbol* copied from ConstantPool entries are good candidates for reference -// counting elision. The ConstantPool entries for a class C exist until C is -// unloaded. If a Symbol* is copied out of the ConstantPool into Symbol* X, -// the Symbol* in the ConstantPool will in general out live X so the reference -// counting on X can be elided. -// -// For cases where the scope of A is not greater than the scope of B, -// the reference counting is explicitly done. See ciSymbol, -// ResolutionErrorEntry and ClassVerifier for examples. -// -// 3) When a Symbol K is created for temporary use, generally for substrings of -// an existing symbol or to create a new symbol, assign it to a -// TempNewSymbol. The SymbolTable methods new_symbol(), lookup() -// and probe() all potentially return a pointer to a new Symbol. -// The allocation (or lookup) of K increments the reference count for K -// and the destructor decrements the reference count. -// -// Another example of TempNewSymbol usage is parsed_name used in -// ClassFileParser::parseClassFile() where parsed_name is used in the cleanup -// after a failed attempt to load a class. Here parsed_name is a -// 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 { - friend class VMStructs; - friend class SymbolTable; - friend class MoveSymbols; - private: - volatile int _refcount; - int _identity_hash; - unsigned short _length; // number of UTF8 characters in the symbol - jbyte _body[1]; - - enum { - // max_symbol_length is constrained by type of _length - max_symbol_length = (1 << 16) -1 - }; - - static int object_size(int length) { - size_t size = heap_word_size(sizeof(Symbol) + length); - return align_object_size(size); - } - - void byte_at_put(int index, int value) { - assert(index >=0 && index < _length, "symbol index overflow"); - _body[index] = value; - } - - Symbol(const u1* name, int length); - void* operator new(size_t size, int len); - - 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()); } - - // Returns the largest size symbol we can safely hold. - static int max_length() { - return max_symbol_length; - } - - 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 byte_at(int index) const { - assert(index >=0 && index < _length, "symbol index overflow"); - return base()[index]; - } - - const jbyte* bytes() const { return base(); } - - int utf8_length() const { return _length; } - - // Compares the symbol with a string. - bool equals(const char* str, int len) const; - bool equals(const char* str) const { return equals(str, (int) strlen(str)); } - - // Tests if the symbol starts with the given prefix. - bool starts_with(const char* prefix, int len) const; - bool starts_with(const char* prefix) const { - return starts_with(prefix, (int) strlen(prefix)); - } - - // Tests if the symbol starts with the given prefix. - int index_of_at(int i, const char* str, int len) const; - int index_of_at(int i, const char* str) const { - return index_of_at(i, str, (int) strlen(str)); - } - - // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg - // note that the ordering is not alfabetical - inline int fast_compare(Symbol* other) const; - - // Returns receiver converted to null-terminated UTF-8 string; string is - // allocated in resource area, or in the char buffer provided by caller. - char* as_C_string() const; - char* as_C_string(char* buf, int size) const; - // Use buf if needed buffer length is <= size. - char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const; - - - // Returns a null terminated utf8 string in a resource array - char* as_utf8() const { return as_C_string(); } - char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const { - return as_C_string_flexible_buffer(t, buf, size); - } - - jchar* as_unicode(int& length) const; - - // Treating this symbol as a class name, returns the Java name for the class. - // String is allocated in resource area if buffer is not provided. - // See Klass::external_name() - const char* as_klass_external_name() const; - const char* as_klass_external_name(char* buf, int size) const; - - // Printing - void print_symbol_on(outputStream* st = NULL) const; - void print_on(outputStream* st) const; // First level print - void print_value_on(outputStream* st) const; // Second level print. - - // printing on default output stream - void print() { print_on(tty); } - void print_value() { print_value_on(tty); } - -#ifndef PRODUCT - // Empty constructor to create a dummy symbol object on stack - // only for getting its vtable pointer. - Symbol() { } - - static int _total_count; -#endif -}; - -// Note: this comparison is used for vtable sorting only; it doesn't matter -// what order it defines, as long as it is a total, time-invariant order -// Since Symbol*s are in C_HEAP, their relative order in memory never changes, -// so use address comparison for speed -int Symbol::fast_compare(Symbol* other) const { - return (((uintptr_t)this < (uintptr_t)other) ? -1 - : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1); -} -#endif // SHARE_VM_OOPS_SYMBOL_HPP