1/*
2 * Copyright (c) 1997, 2019, 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 "classfile/altHashing.hpp"
28#include "classfile/classLoaderData.hpp"
29#include "gc/shared/collectedHeap.hpp"
30#include "logging/log.hpp"
31#include "logging/logStream.hpp"
32#include "memory/allocation.inline.hpp"
33#include "memory/resourceArea.hpp"
34#include "memory/universe.hpp"
35#include "oops/symbol.hpp"
36#include "runtime/atomic.hpp"
37#include "runtime/os.hpp"
38#include "utilities/utf8.hpp"
39
40uint32_t Symbol::pack_length_and_refcount(int length, int refcount) {
41 STATIC_ASSERT(max_symbol_length == ((1 << 16) - 1));
42 STATIC_ASSERT(PERM_REFCOUNT == ((1 << 16) - 1));
43 assert(length >= 0, "negative length");
44 assert(length <= max_symbol_length, "too long symbol");
45 assert(refcount >= 0, "negative refcount");
46 assert(refcount <= PERM_REFCOUNT, "invalid refcount");
47 uint32_t hi = length;
48 uint32_t lo = refcount;
49 return (hi << 16) | lo;
50}
51
52Symbol::Symbol(const u1* name, int length, int refcount) {
53 _length_and_refcount = pack_length_and_refcount(length, refcount);
54 _identity_hash = (short)os::random();
55 for (int i = 0; i < length; i++) {
56 byte_at_put(i, name[i]);
57 }
58}
59
60void* Symbol::operator new(size_t sz, int len) throw() {
61 int alloc_size = size(len)*wordSize;
62 address res = (address) AllocateHeap(alloc_size, mtSymbol);
63 return res;
64}
65
66void* Symbol::operator new(size_t sz, int len, Arena* arena) throw() {
67 int alloc_size = size(len)*wordSize;
68 address res = (address)arena->Amalloc_4(alloc_size);
69 return res;
70}
71
72void Symbol::operator delete(void *p) {
73 assert(((Symbol*)p)->refcount() == 0, "should not call this");
74 FreeHeap(p);
75}
76
77void Symbol::set_permanent() {
78 // This is called at a safepoint during dumping of a dynamic CDS archive.
79 assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint");
80 _length_and_refcount = pack_length_and_refcount(length(), PERM_REFCOUNT);
81}
82
83
84// ------------------------------------------------------------------
85// Symbol::starts_with
86//
87// Tests if the symbol starts with the specified prefix of the given
88// length.
89bool Symbol::starts_with(const char* prefix, int len) const {
90 if (len > utf8_length()) return false;
91 while (len-- > 0) {
92 if (prefix[len] != char_at(len))
93 return false;
94 }
95 assert(len == -1, "we should be at the beginning");
96 return true;
97}
98
99
100// ------------------------------------------------------------------
101// Symbol::index_of
102//
103// Finds if the given string is a substring of this symbol's utf8 bytes.
104// Return -1 on failure. Otherwise return the first index where str occurs.
105int Symbol::index_of_at(int i, const char* str, int len) const {
106 assert(i >= 0 && i <= utf8_length(), "oob");
107 if (len <= 0) return 0;
108 char first_char = str[0];
109 address bytes = (address) ((Symbol*)this)->base();
110 address limit = bytes + utf8_length() - len; // inclusive limit
111 address scan = bytes + i;
112 if (scan > limit)
113 return -1;
114 for (; scan <= limit; scan++) {
115 scan = (address) memchr(scan, first_char, (limit + 1 - scan));
116 if (scan == NULL)
117 return -1; // not found
118 assert(scan >= bytes+i && scan <= limit, "scan oob");
119 if (memcmp(scan, str, len) == 0)
120 return (int)(scan - bytes);
121 }
122 return -1;
123}
124
125
126char* Symbol::as_C_string(char* buf, int size) const {
127 if (size > 0) {
128 int len = MIN2(size - 1, utf8_length());
129 for (int i = 0; i < len; i++) {
130 buf[i] = char_at(i);
131 }
132 buf[len] = '\0';
133 }
134 return buf;
135}
136
137char* Symbol::as_C_string() const {
138 int len = utf8_length();
139 char* str = NEW_RESOURCE_ARRAY(char, len + 1);
140 return as_C_string(str, len + 1);
141}
142
143void Symbol::print_utf8_on(outputStream* st) const {
144 st->print("%s", as_C_string());
145}
146
147void Symbol::print_symbol_on(outputStream* st) const {
148 char *s;
149 st = st ? st : tty;
150 {
151 // ResourceMark may not affect st->print(). If st is a string
152 // stream it could resize, using the same resource arena.
153 ResourceMark rm;
154 s = as_quoted_ascii();
155 s = os::strdup(s);
156 }
157 if (s == NULL) {
158 st->print("(null)");
159 } else {
160 st->print("%s", s);
161 os::free(s);
162 }
163}
164
165char* Symbol::as_quoted_ascii() const {
166 const char *ptr = (const char *)&_body[0];
167 int quoted_length = UTF8::quoted_ascii_length(ptr, utf8_length());
168 char* result = NEW_RESOURCE_ARRAY(char, quoted_length + 1);
169 UTF8::as_quoted_ascii(ptr, utf8_length(), result, quoted_length + 1);
170 return result;
171}
172
173jchar* Symbol::as_unicode(int& length) const {
174 Symbol* this_ptr = (Symbol*)this;
175 length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
176 jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
177 if (length > 0) {
178 UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
179 }
180 return result;
181}
182
183const char* Symbol::as_klass_external_name(char* buf, int size) const {
184 if (size > 0) {
185 char* str = as_C_string(buf, size);
186 int length = (int)strlen(str);
187 // Turn all '/'s into '.'s (also for array klasses)
188 for (int index = 0; index < length; index++) {
189 if (str[index] == '/') {
190 str[index] = '.';
191 }
192 }
193 return str;
194 } else {
195 return buf;
196 }
197}
198
199const char* Symbol::as_klass_external_name() const {
200 char* str = as_C_string();
201 int length = (int)strlen(str);
202 // Turn all '/'s into '.'s (also for array klasses)
203 for (int index = 0; index < length; index++) {
204 if (str[index] == '/') {
205 str[index] = '.';
206 }
207 }
208 return str;
209}
210
211static void print_class(outputStream *os, char *class_str, int len) {
212 for (int i = 0; i < len; ++i) {
213 if (class_str[i] == '/') {
214 os->put('.');
215 } else {
216 os->put(class_str[i]);
217 }
218 }
219}
220
221static void print_array(outputStream *os, char *array_str, int len) {
222 int dimensions = 0;
223 for (int i = 0; i < len; ++i) {
224 if (array_str[i] == '[') {
225 dimensions++;
226 } else if (array_str[i] == 'L') {
227 // Expected format: L<type name>;. Skip 'L' and ';' delimiting the type name.
228 print_class(os, array_str+i+1, len-i-2);
229 break;
230 } else {
231 os->print("%s", type2name(char2type(array_str[i])));
232 }
233 }
234 for (int i = 0; i < dimensions; ++i) {
235 os->print("[]");
236 }
237}
238
239void Symbol::print_as_signature_external_return_type(outputStream *os) {
240 for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
241 if (ss.at_return_type()) {
242 if (ss.is_array()) {
243 print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
244 } else if (ss.is_object()) {
245 // Expected format: L<type name>;. Skip 'L' and ';' delimiting the class name.
246 print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
247 } else {
248 os->print("%s", type2name(ss.type()));
249 }
250 }
251 }
252}
253
254void Symbol::print_as_signature_external_parameters(outputStream *os) {
255 bool first = true;
256 for (SignatureStream ss(this); !ss.is_done(); ss.next()) {
257 if (ss.at_return_type()) break;
258 if (!first) { os->print(", "); }
259 if (ss.is_array()) {
260 print_array(os, (char*)ss.raw_bytes(), (int)ss.raw_length());
261 } else if (ss.is_object()) {
262 // Skip 'L' and ';'.
263 print_class(os, (char*)ss.raw_bytes()+1, (int)ss.raw_length()-2);
264 } else {
265 os->print("%s", type2name(ss.type()));
266 }
267 first = false;
268 }
269}
270
271// Increment refcount while checking for zero. If the Symbol's refcount becomes zero
272// a thread could be concurrently removing the Symbol. This is used during SymbolTable
273// lookup to avoid reviving a dead Symbol.
274bool Symbol::try_increment_refcount() {
275 uint32_t found = _length_and_refcount;
276 while (true) {
277 uint32_t old_value = found;
278 int refc = extract_refcount(old_value);
279 if (refc == PERM_REFCOUNT) {
280 return true; // sticky max or created permanent
281 } else if (refc == 0) {
282 return false; // dead, can't revive.
283 } else {
284 found = Atomic::cmpxchg(old_value + 1, &_length_and_refcount, old_value);
285 if (found == old_value) {
286 return true; // successfully updated.
287 }
288 // refcount changed, try again.
289 }
290 }
291}
292
293// The increment_refcount() is called when not doing lookup. It is assumed that you
294// have a symbol with a non-zero refcount and it can't become zero while referenced by
295// this caller.
296void Symbol::increment_refcount() {
297 if (!try_increment_refcount()) {
298#ifdef ASSERT
299 print();
300 fatal("refcount has gone to zero");
301#endif
302 }
303#ifndef PRODUCT
304 if (refcount() != PERM_REFCOUNT) { // not a permanent symbol
305 NOT_PRODUCT(Atomic::inc(&_total_count);)
306 }
307#endif
308}
309
310// Decrement refcount potentially while racing increment, so we need
311// to check the value after attempting to decrement so that if another
312// thread increments to PERM_REFCOUNT the value is not decremented.
313void Symbol::decrement_refcount() {
314 uint32_t found = _length_and_refcount;
315 while (true) {
316 uint32_t old_value = found;
317 int refc = extract_refcount(old_value);
318 if (refc == PERM_REFCOUNT) {
319 return; // refcount is permanent, permanent is sticky
320 } else if (refc == 0) {
321#ifdef ASSERT
322 print();
323 fatal("refcount underflow");
324#endif
325 return;
326 } else {
327 found = Atomic::cmpxchg(old_value - 1, &_length_and_refcount, old_value);
328 if (found == old_value) {
329 return; // successfully updated.
330 }
331 // refcount changed, try again.
332 }
333 }
334}
335
336void Symbol::make_permanent() {
337 uint32_t found = _length_and_refcount;
338 while (true) {
339 uint32_t old_value = found;
340 int refc = extract_refcount(old_value);
341 if (refc == PERM_REFCOUNT) {
342 return; // refcount is permanent, permanent is sticky
343 } else if (refc == 0) {
344#ifdef ASSERT
345 print();
346 fatal("refcount underflow");
347#endif
348 return;
349 } else {
350 int len = extract_length(old_value);
351 found = Atomic::cmpxchg(pack_length_and_refcount(len, PERM_REFCOUNT), &_length_and_refcount, old_value);
352 if (found == old_value) {
353 return; // successfully updated.
354 }
355 // refcount changed, try again.
356 }
357 }
358}
359
360void Symbol::metaspace_pointers_do(MetaspaceClosure* it) {
361 if (log_is_enabled(Trace, cds)) {
362 LogStream trace_stream(Log(cds)::trace());
363 trace_stream.print("Iter(Symbol): %p ", this);
364 print_value_on(&trace_stream);
365 trace_stream.cr();
366 }
367}
368
369void Symbol::print_on(outputStream* st) const {
370 st->print("Symbol: '");
371 print_symbol_on(st);
372 st->print("'");
373 st->print(" count %d", refcount());
374}
375
376void Symbol::print() const { print_on(tty); }
377
378// The print_value functions are present in all builds, to support the
379// disassembler and error reporting.
380void Symbol::print_value_on(outputStream* st) const {
381 st->print("'");
382 for (int i = 0; i < utf8_length(); i++) {
383 st->print("%c", char_at(i));
384 }
385 st->print("'");
386}
387
388void Symbol::print_value() const { print_value_on(tty); }
389
390bool Symbol::is_valid(Symbol* s) {
391 if (!is_aligned(s, sizeof(MetaWord))) return false;
392 if ((size_t)s < os::min_page_size()) return false;
393
394 if (!os::is_readable_range(s, s + 1)) return false;
395
396 // Symbols are not allocated in Java heap.
397 if (Universe::heap()->is_in_reserved(s)) return false;
398
399 int len = s->utf8_length();
400 if (len < 0) return false;
401
402 jbyte* bytes = (jbyte*) s->bytes();
403 return os::is_readable_range(bytes, bytes + len);
404}
405
406// SymbolTable prints this in its statistics
407NOT_PRODUCT(size_t Symbol::_total_count = 0;)
408