src/share/vm/oops/symbol.cpp

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
stefank@2314 26 #include "precompiled.hpp"
stefank@2314 27 #include "oops/oop.inline.hpp"
coleenp@2497 28 #include "oops/symbol.hpp"
coleenp@2497 29 #include "runtime/os.hpp"
coleenp@2497 30 #include "memory/allocation.inline.hpp"
duke@435 31
coleenp@2497 32 Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) {
coleenp@2497 33 _identity_hash = os::random();
coleenp@2497 34 for (int i = 0; i < _length; i++) {
coleenp@2497 35 byte_at_put(i, name[i]);
coleenp@2497 36 }
coleenp@2497 37 }
coleenp@2497 38
coleenp@2497 39 void* Symbol::operator new(size_t size, int len) {
coleenp@2497 40 return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol");
coleenp@2497 41 }
twisti@1573 42
twisti@1573 43 // ------------------------------------------------------------------
coleenp@2497 44 // Symbol::equals
twisti@1573 45 //
twisti@1573 46 // Compares the symbol with a string of the given length.
coleenp@2497 47 bool Symbol::equals(const char* str, int len) const {
duke@435 48 int l = utf8_length();
duke@435 49 if (l != len) return false;
duke@435 50 while (l-- > 0) {
duke@435 51 if (str[l] != (char) byte_at(l))
duke@435 52 return false;
duke@435 53 }
duke@435 54 assert(l == -1, "we should be at the beginning");
duke@435 55 return true;
duke@435 56 }
duke@435 57
twisti@1573 58
twisti@1573 59 // ------------------------------------------------------------------
coleenp@2497 60 // Symbol::starts_with
twisti@1573 61 //
twisti@1573 62 // Tests if the symbol starts with the specified prefix of the given
twisti@1573 63 // length.
coleenp@2497 64 bool Symbol::starts_with(const char* prefix, int len) const {
twisti@1573 65 if (len > utf8_length()) return false;
twisti@1573 66 while (len-- > 0) {
twisti@1573 67 if (prefix[len] != (char) byte_at(len))
twisti@1573 68 return false;
twisti@1573 69 }
twisti@1573 70 assert(len == -1, "we should be at the beginning");
twisti@1573 71 return true;
twisti@1573 72 }
twisti@1573 73
twisti@1573 74
twisti@1573 75 // ------------------------------------------------------------------
coleenp@2497 76 // Symbol::index_of
twisti@1573 77 //
twisti@1573 78 // Finds if the given string is a substring of this symbol's utf8 bytes.
twisti@1573 79 // Return -1 on failure. Otherwise return the first index where str occurs.
coleenp@2497 80 int Symbol::index_of_at(int i, const char* str, int len) const {
twisti@1573 81 assert(i >= 0 && i <= utf8_length(), "oob");
twisti@1573 82 if (len <= 0) return 0;
twisti@1573 83 char first_char = str[0];
coleenp@2497 84 address bytes = (address) ((Symbol*)this)->base();
twisti@1573 85 address limit = bytes + utf8_length() - len; // inclusive limit
twisti@1573 86 address scan = bytes + i;
twisti@1573 87 if (scan > limit)
twisti@1573 88 return -1;
twisti@1573 89 for (;;) {
twisti@1573 90 scan = (address) memchr(scan, first_char, (limit + 1 - scan));
twisti@1573 91 if (scan == NULL)
twisti@1573 92 return -1; // not found
twisti@1573 93 assert(scan >= bytes+i && scan <= limit, "scan oob");
twisti@1573 94 if (memcmp(scan, str, len) == 0)
twisti@1573 95 return (int)(scan - bytes);
twisti@1573 96 }
twisti@1573 97 }
twisti@1573 98
twisti@1573 99
coleenp@2497 100 char* Symbol::as_C_string(char* buf, int size) const {
duke@435 101 if (size > 0) {
duke@435 102 int len = MIN2(size - 1, utf8_length());
duke@435 103 for (int i = 0; i < len; i++) {
duke@435 104 buf[i] = byte_at(i);
duke@435 105 }
duke@435 106 buf[len] = '\0';
duke@435 107 }
duke@435 108 return buf;
duke@435 109 }
duke@435 110
coleenp@2497 111 char* Symbol::as_C_string() const {
duke@435 112 int len = utf8_length();
duke@435 113 char* str = NEW_RESOURCE_ARRAY(char, len + 1);
duke@435 114 return as_C_string(str, len + 1);
duke@435 115 }
duke@435 116
coleenp@2497 117 char* Symbol::as_C_string_flexible_buffer(Thread* t,
duke@435 118 char* buf, int size) const {
duke@435 119 char* str;
duke@435 120 int len = utf8_length();
duke@435 121 int buf_len = len + 1;
duke@435 122 if (size < buf_len) {
duke@435 123 str = NEW_RESOURCE_ARRAY(char, buf_len);
duke@435 124 } else {
duke@435 125 str = buf;
duke@435 126 }
duke@435 127 return as_C_string(str, buf_len);
duke@435 128 }
duke@435 129
coleenp@2497 130 void Symbol::print_symbol_on(outputStream* st) const {
duke@435 131 st = st ? st : tty;
never@657 132 int length = UTF8::unicode_length((const char*)bytes(), utf8_length());
never@657 133 const char *ptr = (const char *)bytes();
never@657 134 jchar value;
never@657 135 for (int index = 0; index < length; index++) {
never@657 136 ptr = UTF8::next(ptr, &value);
never@657 137 if (value >= 32 && value < 127 || value == '\'' || value == '\\') {
never@657 138 st->put(value);
never@657 139 } else {
never@657 140 st->print("\\u%04x", value);
never@657 141 }
never@657 142 }
duke@435 143 }
duke@435 144
coleenp@2497 145 jchar* Symbol::as_unicode(int& length) const {
coleenp@2497 146 Symbol* this_ptr = (Symbol*)this;
duke@435 147 length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
duke@435 148 jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
duke@435 149 if (length > 0) {
duke@435 150 UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
duke@435 151 }
duke@435 152 return result;
duke@435 153 }
duke@435 154
coleenp@2497 155 const char* Symbol::as_klass_external_name(char* buf, int size) const {
duke@435 156 if (size > 0) {
duke@435 157 char* str = as_C_string(buf, size);
duke@435 158 int length = (int)strlen(str);
duke@435 159 // Turn all '/'s into '.'s (also for array klasses)
duke@435 160 for (int index = 0; index < length; index++) {
duke@435 161 if (str[index] == '/') {
duke@435 162 str[index] = '.';
duke@435 163 }
duke@435 164 }
duke@435 165 return str;
duke@435 166 } else {
duke@435 167 return buf;
duke@435 168 }
duke@435 169 }
duke@435 170
coleenp@2497 171 const char* Symbol::as_klass_external_name() const {
duke@435 172 char* str = as_C_string();
duke@435 173 int length = (int)strlen(str);
duke@435 174 // Turn all '/'s into '.'s (also for array klasses)
duke@435 175 for (int index = 0; index < length; index++) {
duke@435 176 if (str[index] == '/') {
duke@435 177 str[index] = '.';
duke@435 178 }
duke@435 179 }
duke@435 180 return str;
duke@435 181 }
coleenp@2497 182
coleenp@2497 183
coleenp@2497 184 void Symbol::print_on(outputStream* st) const {
coleenp@2497 185 if (this == NULL) {
coleenp@2497 186 st->print_cr("NULL");
coleenp@2497 187 } else {
coleenp@2497 188 st->print("Symbol: '");
coleenp@2497 189 print_symbol_on(st);
coleenp@2497 190 st->print("'");
coleenp@2497 191 st->print(" count %d", refcount());
coleenp@2497 192 }
coleenp@2497 193 }
coleenp@2497 194
coleenp@2497 195 // The print_value functions are present in all builds, to support the
coleenp@2497 196 // disassembler and error reporting.
coleenp@2497 197 void Symbol::print_value_on(outputStream* st) const {
coleenp@2497 198 if (this == NULL) {
coleenp@2497 199 st->print("NULL");
coleenp@2497 200 } else {
coleenp@2497 201 st->print("'");
coleenp@2497 202 for (int i = 0; i < utf8_length(); i++) {
coleenp@2497 203 st->print("%c", byte_at(i));
coleenp@2497 204 }
coleenp@2497 205 st->print("'");
coleenp@2497 206 }
coleenp@2497 207 }
coleenp@2497 208
coleenp@2497 209 void Symbol::increment_refcount() {
coleenp@2497 210 // Only increment the refcount if positive. If negative either
coleenp@2497 211 // overflow has occurred or it is a permanent symbol in a read only
coleenp@2497 212 // shared archive.
coleenp@2497 213 if (_refcount >= 0) {
coleenp@2497 214 Atomic::inc(&_refcount);
coleenp@2497 215 NOT_PRODUCT(Atomic::inc(&_total_count);)
coleenp@2497 216 }
coleenp@2497 217 }
coleenp@2497 218
coleenp@2497 219 void Symbol::decrement_refcount() {
coleenp@2497 220 if (_refcount >= 0) {
coleenp@2497 221 Atomic::dec(&_refcount);
coleenp@2497 222 #ifdef ASSERT
coleenp@2497 223 if (_refcount < 0) {
coleenp@2497 224 print();
coleenp@2497 225 assert(false, "reference count underflow for symbol");
coleenp@2497 226 }
coleenp@2497 227 #endif
coleenp@2497 228 }
coleenp@2497 229 }
coleenp@2497 230
coleenp@2497 231 NOT_PRODUCT(int Symbol::_total_count = 0;)

mercurial