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

     1 /*
     2  * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    26 #include "precompiled.hpp"
    27 #include "oops/oop.inline.hpp"
    28 #include "oops/symbol.hpp"
    29 #include "runtime/os.hpp"
    30 #include "memory/allocation.inline.hpp"
    32 Symbol::Symbol(const u1* name, int length) : _refcount(0), _length(length) {
    33   _identity_hash = os::random();
    34   for (int i = 0; i < _length; i++) {
    35     byte_at_put(i, name[i]);
    36   }
    37 }
    39 void* Symbol::operator new(size_t size, int len) {
    40   return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol");
    41 }
    43 // ------------------------------------------------------------------
    44 // Symbol::equals
    45 //
    46 // Compares the symbol with a string of the given length.
    47 bool Symbol::equals(const char* str, int len) const {
    48   int l = utf8_length();
    49   if (l != len) return false;
    50   while (l-- > 0) {
    51     if (str[l] != (char) byte_at(l))
    52       return false;
    53   }
    54   assert(l == -1, "we should be at the beginning");
    55   return true;
    56 }
    59 // ------------------------------------------------------------------
    60 // Symbol::starts_with
    61 //
    62 // Tests if the symbol starts with the specified prefix of the given
    63 // length.
    64 bool Symbol::starts_with(const char* prefix, int len) const {
    65   if (len > utf8_length()) return false;
    66   while (len-- > 0) {
    67     if (prefix[len] != (char) byte_at(len))
    68       return false;
    69   }
    70   assert(len == -1, "we should be at the beginning");
    71   return true;
    72 }
    75 // ------------------------------------------------------------------
    76 // Symbol::index_of
    77 //
    78 // Finds if the given string is a substring of this symbol's utf8 bytes.
    79 // Return -1 on failure.  Otherwise return the first index where str occurs.
    80 int Symbol::index_of_at(int i, const char* str, int len) const {
    81   assert(i >= 0 && i <= utf8_length(), "oob");
    82   if (len <= 0)  return 0;
    83   char first_char = str[0];
    84   address bytes = (address) ((Symbol*)this)->base();
    85   address limit = bytes + utf8_length() - len;  // inclusive limit
    86   address scan = bytes + i;
    87   if (scan > limit)
    88     return -1;
    89   for (;;) {
    90     scan = (address) memchr(scan, first_char, (limit + 1 - scan));
    91     if (scan == NULL)
    92       return -1;  // not found
    93     assert(scan >= bytes+i && scan <= limit, "scan oob");
    94     if (memcmp(scan, str, len) == 0)
    95       return (int)(scan - bytes);
    96   }
    97 }
   100 char* Symbol::as_C_string(char* buf, int size) const {
   101   if (size > 0) {
   102     int len = MIN2(size - 1, utf8_length());
   103     for (int i = 0; i < len; i++) {
   104       buf[i] = byte_at(i);
   105     }
   106     buf[len] = '\0';
   107   }
   108   return buf;
   109 }
   111 char* Symbol::as_C_string() const {
   112   int len = utf8_length();
   113   char* str = NEW_RESOURCE_ARRAY(char, len + 1);
   114   return as_C_string(str, len + 1);
   115 }
   117 char* Symbol::as_C_string_flexible_buffer(Thread* t,
   118                                                  char* buf, int size) const {
   119   char* str;
   120   int len = utf8_length();
   121   int buf_len = len + 1;
   122   if (size < buf_len) {
   123     str = NEW_RESOURCE_ARRAY(char, buf_len);
   124   } else {
   125     str = buf;
   126   }
   127   return as_C_string(str, buf_len);
   128 }
   130 void Symbol::print_symbol_on(outputStream* st) const {
   131   st = st ? st : tty;
   132   int length = UTF8::unicode_length((const char*)bytes(), utf8_length());
   133   const char *ptr = (const char *)bytes();
   134   jchar value;
   135   for (int index = 0; index < length; index++) {
   136     ptr = UTF8::next(ptr, &value);
   137     if (value >= 32 && value < 127 || value == '\'' || value == '\\') {
   138       st->put(value);
   139     } else {
   140       st->print("\\u%04x", value);
   141     }
   142   }
   143 }
   145 jchar* Symbol::as_unicode(int& length) const {
   146   Symbol* this_ptr = (Symbol*)this;
   147   length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
   148   jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
   149   if (length > 0) {
   150     UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
   151   }
   152   return result;
   153 }
   155 const char* Symbol::as_klass_external_name(char* buf, int size) const {
   156   if (size > 0) {
   157     char* str    = as_C_string(buf, size);
   158     int   length = (int)strlen(str);
   159     // Turn all '/'s into '.'s (also for array klasses)
   160     for (int index = 0; index < length; index++) {
   161       if (str[index] == '/') {
   162         str[index] = '.';
   163       }
   164     }
   165     return str;
   166   } else {
   167     return buf;
   168   }
   169 }
   171 const char* Symbol::as_klass_external_name() const {
   172   char* str    = as_C_string();
   173   int   length = (int)strlen(str);
   174   // Turn all '/'s into '.'s (also for array klasses)
   175   for (int index = 0; index < length; index++) {
   176     if (str[index] == '/') {
   177       str[index] = '.';
   178     }
   179   }
   180   return str;
   181 }
   184 void Symbol::print_on(outputStream* st) const {
   185   if (this == NULL) {
   186     st->print_cr("NULL");
   187   } else {
   188     st->print("Symbol: '");
   189     print_symbol_on(st);
   190     st->print("'");
   191     st->print(" count %d", refcount());
   192   }
   193 }
   195 // The print_value functions are present in all builds, to support the
   196 // disassembler and error reporting.
   197 void Symbol::print_value_on(outputStream* st) const {
   198   if (this == NULL) {
   199     st->print("NULL");
   200   } else {
   201     st->print("'");
   202     for (int i = 0; i < utf8_length(); i++) {
   203       st->print("%c", byte_at(i));
   204     }
   205     st->print("'");
   206   }
   207 }
   209 void Symbol::increment_refcount() {
   210   // Only increment the refcount if positive.  If negative either
   211   // overflow has occurred or it is a permanent symbol in a read only
   212   // shared archive.
   213   if (_refcount >= 0) {
   214     Atomic::inc(&_refcount);
   215     NOT_PRODUCT(Atomic::inc(&_total_count);)
   216   }
   217 }
   219 void Symbol::decrement_refcount() {
   220   if (_refcount >= 0) {
   221     Atomic::dec(&_refcount);
   222 #ifdef ASSERT
   223     if (_refcount < 0) {
   224       print();
   225       assert(false, "reference count underflow for symbol");
   226     }
   227 #endif
   228   }
   229 }
   231 NOT_PRODUCT(int Symbol::_total_count = 0;)

mercurial