hotspot/src/share/vm/oops/symbol.cpp
changeset 8076 96d498ec7ae1
parent 7397 5b173b4ca846
child 8921 14bfe81f2a9d
equal deleted inserted replaced
8075:582dd25571b2 8076:96d498ec7ae1
       
     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  */
       
    24 
       
    25 
       
    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"
       
    31 
       
    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 }
       
    38 
       
    39 void* Symbol::operator new(size_t size, int len) {
       
    40   return (void *) AllocateHeap(object_size(len) * HeapWordSize, "symbol");
       
    41 }
       
    42 
       
    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 }
       
    57 
       
    58 
       
    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 }
       
    73 
       
    74 
       
    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 }
       
    98 
       
    99 
       
   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 }
       
   110 
       
   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 }
       
   116 
       
   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 }
       
   129 
       
   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 }
       
   144 
       
   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 }
       
   154 
       
   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 }
       
   170 
       
   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 }
       
   182 
       
   183 
       
   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 }
       
   194 
       
   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 }
       
   208 
       
   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 }
       
   218 
       
   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 }
       
   230 
       
   231 NOT_PRODUCT(int Symbol::_total_count = 0;)