src/share/vm/oops/symbol.hpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2497
3582bf76420e
child 2708
1d1603768966
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

duke@435 1 /*
coleenp@2497 2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
coleenp@2497 25 #ifndef SHARE_VM_OOPS_SYMBOL_HPP
coleenp@2497 26 #define SHARE_VM_OOPS_SYMBOL_HPP
stefank@2314 27
stefank@2314 28 #include "utilities/utf8.hpp"
coleenp@2497 29 #include "memory/allocation.hpp"
stefank@2314 30
coleenp@2497 31 // A Symbol is a canonicalized string.
coleenp@2497 32 // All Symbols reside in global SymbolTable and are reference counted.
duke@435 33
coleenp@2497 34 // Reference counting
coleenp@2497 35 //
coleenp@2497 36 // All Symbols are allocated and added to the SymbolTable.
coleenp@2497 37 // When a class is unloaded, the reference counts of the Symbol pointers in
coleenp@2497 38 // the ConstantPool and in instanceKlass (see release_C_heap_structures) are
coleenp@2497 39 // decremented. When the reference count for a Symbol goes to 0, the garbage
coleenp@2497 40 // collector can free the Symbol and remove it from the SymbolTable.
coleenp@2497 41 //
coleenp@2497 42 // 0) Symbols need to be reference counted when a pointer to the Symbol is
coleenp@2497 43 // saved in persistent storage. This does not include the pointer
coleenp@2497 44 // in the SymbolTable bucket (the _literal field in HashtableEntry)
coleenp@2497 45 // that points to the Symbol. All other stores of a Symbol*
coleenp@2497 46 // to a field of a persistent variable (e.g., the _name filed in
coleenp@2497 47 // FieldAccessInfo or _ptr in a CPSlot) is reference counted.
coleenp@2497 48 //
coleenp@2497 49 // 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for
coleenp@2497 50 // "name" and returns a pointer to F or finds a pre-existing Symbol F for
coleenp@2497 51 // "name" and returns a pointer to it. In both cases the reference count for F
coleenp@2497 52 // is incremented under the assumption that a pointer to F will be created from
coleenp@2497 53 // the return value. Thus the increment of the reference count is on the lookup
coleenp@2497 54 // and not on the assignment to the new Symbol*. That is
coleenp@2497 55 // Symbol* G = lookup()
coleenp@2497 56 // ^ increment on lookup()
coleenp@2497 57 // and not
coleenp@2497 58 // Symbol* G = lookup()
coleenp@2497 59 // ^ increment on assignmnet
coleenp@2497 60 // The reference count must be decremented manually when the copy of the
coleenp@2497 61 // pointer G is destroyed.
coleenp@2497 62 //
coleenp@2497 63 // 2) For a local Symbol* A that is a copy of an existing Symbol* B, the
coleenp@2497 64 // reference counting is elided when the scope of B is greater than the scope
coleenp@2497 65 // of A. For example, in the code fragment
coleenp@2497 66 // below "klass" is passed as a parameter to the method. Symbol* "kn"
coleenp@2497 67 // is a copy of the name in "klass".
coleenp@2497 68 //
coleenp@2497 69 // Symbol* kn = klass->name();
coleenp@2497 70 // unsigned int d_hash = dictionary()->compute_hash(kn, class_loader);
coleenp@2497 71 //
coleenp@2497 72 // The scope of "klass" is greater than the scope of "kn" so the reference
coleenp@2497 73 // counting for "kn" is elided.
coleenp@2497 74 //
coleenp@2497 75 // Symbol* copied from ConstantPool entries are good candidates for reference
coleenp@2497 76 // counting elision. The ConstantPool entries for a class C exist until C is
coleenp@2497 77 // unloaded. If a Symbol* is copied out of the ConstantPool into Symbol* X,
coleenp@2497 78 // the Symbol* in the ConstantPool will in general out live X so the reference
coleenp@2497 79 // counting on X can be elided.
coleenp@2497 80 //
coleenp@2497 81 // For cases where the scope of A is not greater than the scope of B,
coleenp@2497 82 // the reference counting is explicitly done. See ciSymbol,
coleenp@2497 83 // ResolutionErrorEntry and ClassVerifier for examples.
coleenp@2497 84 //
coleenp@2497 85 // 3) When a Symbol K is created for temporary use, generally for substrings of
coleenp@2497 86 // an existing symbol or to create a new symbol, assign it to a
coleenp@2497 87 // TempNewSymbol. The SymbolTable methods new_symbol(), lookup()
coleenp@2497 88 // and probe() all potentially return a pointer to a new Symbol.
coleenp@2497 89 // The allocation (or lookup) of K increments the reference count for K
coleenp@2497 90 // and the destructor decrements the reference count.
coleenp@2497 91 //
coleenp@2497 92 // Another example of TempNewSymbol usage is parsed_name used in
coleenp@2497 93 // ClassFileParser::parseClassFile() where parsed_name is used in the cleanup
coleenp@2497 94 // after a failed attempt to load a class. Here parsed_name is a
coleenp@2497 95 // TempNewSymbol (passed in as a parameter) so the reference count on its symbol
coleenp@2497 96 // will be decremented when it goes out of scope.
coleenp@2497 97
coleenp@2497 98 class Symbol : public CHeapObj {
duke@435 99 friend class VMStructs;
coleenp@2497 100 friend class SymbolTable;
coleenp@2497 101 friend class MoveSymbols;
duke@435 102 private:
coleenp@2497 103 volatile int _refcount;
coleenp@2497 104 int _identity_hash;
duke@435 105 unsigned short _length; // number of UTF8 characters in the symbol
duke@435 106 jbyte _body[1];
duke@435 107
duke@435 108 enum {
duke@435 109 // max_symbol_length is constrained by type of _length
duke@435 110 max_symbol_length = (1 << 16) -1
duke@435 111 };
coleenp@2497 112
coleenp@2497 113 static int object_size(int length) {
coleenp@2497 114 size_t size = heap_word_size(sizeof(Symbol) + length);
coleenp@2497 115 return align_object_size(size);
coleenp@2497 116 }
coleenp@2497 117
coleenp@2497 118 void byte_at_put(int index, int value) {
coleenp@2497 119 assert(index >=0 && index < _length, "symbol index overflow");
coleenp@2497 120 _body[index] = value;
coleenp@2497 121 }
coleenp@2497 122
coleenp@2497 123 Symbol(const u1* name, int length);
coleenp@2497 124 void* operator new(size_t size, int len);
coleenp@2497 125
duke@435 126 public:
coleenp@2497 127 // Low-level access (used with care, since not GC-safe)
coleenp@2497 128 const jbyte* base() const { return &_body[0]; }
duke@435 129
coleenp@2497 130 int object_size() { return object_size(utf8_length()); }
duke@435 131
duke@435 132 // Returns the largest size symbol we can safely hold.
duke@435 133 static int max_length() {
duke@435 134 return max_symbol_length;
duke@435 135 }
duke@435 136
coleenp@2497 137 int identity_hash() {
coleenp@2497 138 return _identity_hash;
duke@435 139 }
duke@435 140
coleenp@2497 141 // Reference counting. See comments above this class for when to use.
coleenp@2497 142 int refcount() const { return _refcount; }
coleenp@2497 143 void increment_refcount();
coleenp@2497 144 void decrement_refcount();
duke@435 145
duke@435 146 int byte_at(int index) const {
duke@435 147 assert(index >=0 && index < _length, "symbol index overflow");
coleenp@2497 148 return base()[index];
duke@435 149 }
duke@435 150
coleenp@2497 151 const jbyte* bytes() const { return base(); }
duke@435 152
duke@435 153 int utf8_length() const { return _length; }
duke@435 154
twisti@1573 155 // Compares the symbol with a string.
duke@435 156 bool equals(const char* str, int len) const;
twisti@1573 157 bool equals(const char* str) const { return equals(str, (int) strlen(str)); }
twisti@1573 158
twisti@1573 159 // Tests if the symbol starts with the given prefix.
twisti@1573 160 bool starts_with(const char* prefix, int len) const;
twisti@1573 161 bool starts_with(const char* prefix) const {
twisti@1573 162 return starts_with(prefix, (int) strlen(prefix));
twisti@1573 163 }
twisti@1573 164
twisti@1573 165 // Tests if the symbol starts with the given prefix.
twisti@1573 166 int index_of_at(int i, const char* str, int len) const;
twisti@1573 167 int index_of_at(int i, const char* str) const {
twisti@1573 168 return index_of_at(i, str, (int) strlen(str));
twisti@1573 169 }
duke@435 170
duke@435 171 // Three-way compare for sorting; returns -1/0/1 if receiver is </==/> than arg
duke@435 172 // note that the ordering is not alfabetical
coleenp@2497 173 inline int fast_compare(Symbol* other) const;
duke@435 174
duke@435 175 // Returns receiver converted to null-terminated UTF-8 string; string is
duke@435 176 // allocated in resource area, or in the char buffer provided by caller.
duke@435 177 char* as_C_string() const;
duke@435 178 char* as_C_string(char* buf, int size) const;
duke@435 179 // Use buf if needed buffer length is <= size.
duke@435 180 char* as_C_string_flexible_buffer(Thread* t, char* buf, int size) const;
duke@435 181
duke@435 182
duke@435 183 // Returns a null terminated utf8 string in a resource array
duke@435 184 char* as_utf8() const { return as_C_string(); }
duke@435 185 char* as_utf8_flexible_buffer(Thread* t, char* buf, int size) const {
duke@435 186 return as_C_string_flexible_buffer(t, buf, size);
duke@435 187 }
duke@435 188
duke@435 189 jchar* as_unicode(int& length) const;
duke@435 190
duke@435 191 // Treating this symbol as a class name, returns the Java name for the class.
duke@435 192 // String is allocated in resource area if buffer is not provided.
duke@435 193 // See Klass::external_name()
duke@435 194 const char* as_klass_external_name() const;
duke@435 195 const char* as_klass_external_name(char* buf, int size) const;
duke@435 196
coleenp@2497 197 // Printing
coleenp@2497 198 void print_symbol_on(outputStream* st = NULL) const;
coleenp@2497 199 void print_on(outputStream* st) const; // First level print
coleenp@2497 200 void print_value_on(outputStream* st) const; // Second level print.
duke@435 201
coleenp@2497 202 // printing on default output stream
coleenp@2497 203 void print() { print_on(tty); }
coleenp@2497 204 void print_value() { print_value_on(tty); }
coleenp@2497 205
coleenp@2497 206 #ifndef PRODUCT
coleenp@2497 207 // Empty constructor to create a dummy symbol object on stack
coleenp@2497 208 // only for getting its vtable pointer.
coleenp@2497 209 Symbol() { }
coleenp@2497 210
coleenp@2497 211 static int _total_count;
coleenp@2497 212 #endif
duke@435 213 };
duke@435 214
duke@435 215 // Note: this comparison is used for vtable sorting only; it doesn't matter
duke@435 216 // what order it defines, as long as it is a total, time-invariant order
coleenp@2497 217 // Since Symbol*s are in C_HEAP, their relative order in memory never changes,
duke@435 218 // so use address comparison for speed
coleenp@2497 219 int Symbol::fast_compare(Symbol* other) const {
duke@435 220 return (((uintptr_t)this < (uintptr_t)other) ? -1
duke@435 221 : ((uintptr_t)this == (uintptr_t) other) ? 0 : 1);
duke@435 222 }
coleenp@2497 223 #endif // SHARE_VM_OOPS_SYMBOL_HPP

mercurial