Mon, 12 Nov 2012 14:03:53 -0800
6830717: replay of compilations would help with debugging
Summary: When java process crashed in compiler thread, repeat the compilation process will help finding root cause. This is done with using SA dump application class data and replay data from core dump, then use debug version of jvm to recompile the problematic java method.
Reviewed-by: kvn, twisti, sspitsyn
Contributed-by: yumin.qi@oracle.com
1 /*
2 * Copyright (c) 1997, 2012, 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 "classfile/altHashing.hpp"
28 #include "classfile/classLoaderData.hpp"
29 #include "oops/symbol.hpp"
30 #include "runtime/os.hpp"
31 #include "memory/allocation.inline.hpp"
32 #include "memory/resourceArea.hpp"
34 Symbol::Symbol(const u1* name, int length, int refcount) : _refcount(refcount), _length(length) {
35 _identity_hash = os::random();
36 for (int i = 0; i < _length; i++) {
37 byte_at_put(i, name[i]);
38 }
39 }
41 void* Symbol::operator new(size_t sz, int len, TRAPS) {
42 int alloc_size = size(len)*HeapWordSize;
43 address res = (address) AllocateHeap(alloc_size, mtSymbol);
44 return res;
45 }
47 void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) {
48 int alloc_size = size(len)*HeapWordSize;
49 address res = (address)arena->Amalloc(alloc_size);
50 return res;
51 }
53 void* Symbol::operator new(size_t sz, int len, ClassLoaderData* loader_data, TRAPS) {
54 address res;
55 int alloc_size = size(len)*HeapWordSize;
56 res = (address) Metaspace::allocate(loader_data, size(len), true,
57 Metaspace::NonClassType, CHECK_NULL);
58 return res;
59 }
61 void Symbol::operator delete(void *p) {
62 assert(((Symbol*)p)->refcount() == 0, "should not call this");
63 FreeHeap(p);
64 }
66 // ------------------------------------------------------------------
67 // Symbol::equals
68 //
69 // Compares the symbol with a string of the given length.
70 bool Symbol::equals(const char* str, int len) const {
71 int l = utf8_length();
72 if (l != len) return false;
73 while (l-- > 0) {
74 if (str[l] != (char) byte_at(l))
75 return false;
76 }
77 assert(l == -1, "we should be at the beginning");
78 return true;
79 }
82 // ------------------------------------------------------------------
83 // Symbol::starts_with
84 //
85 // Tests if the symbol starts with the specified prefix of the given
86 // length.
87 bool Symbol::starts_with(const char* prefix, int len) const {
88 if (len > utf8_length()) return false;
89 while (len-- > 0) {
90 if (prefix[len] != (char) byte_at(len))
91 return false;
92 }
93 assert(len == -1, "we should be at the beginning");
94 return true;
95 }
98 // ------------------------------------------------------------------
99 // Symbol::index_of
100 //
101 // Finds if the given string is a substring of this symbol's utf8 bytes.
102 // Return -1 on failure. Otherwise return the first index where str occurs.
103 int Symbol::index_of_at(int i, const char* str, int len) const {
104 assert(i >= 0 && i <= utf8_length(), "oob");
105 if (len <= 0) return 0;
106 char first_char = str[0];
107 address bytes = (address) ((Symbol*)this)->base();
108 address limit = bytes + utf8_length() - len; // inclusive limit
109 address scan = bytes + i;
110 if (scan > limit)
111 return -1;
112 for (; scan <= limit; scan++) {
113 scan = (address) memchr(scan, first_char, (limit + 1 - scan));
114 if (scan == NULL)
115 return -1; // not found
116 assert(scan >= bytes+i && scan <= limit, "scan oob");
117 if (memcmp(scan, str, len) == 0)
118 return (int)(scan - bytes);
119 }
120 return -1;
121 }
124 char* Symbol::as_C_string(char* buf, int size) const {
125 if (size > 0) {
126 int len = MIN2(size - 1, utf8_length());
127 for (int i = 0; i < len; i++) {
128 buf[i] = byte_at(i);
129 }
130 buf[len] = '\0';
131 }
132 return buf;
133 }
135 char* Symbol::as_C_string() const {
136 int len = utf8_length();
137 char* str = NEW_RESOURCE_ARRAY(char, len + 1);
138 return as_C_string(str, len + 1);
139 }
141 char* Symbol::as_C_string_flexible_buffer(Thread* t,
142 char* buf, int size) const {
143 char* str;
144 int len = utf8_length();
145 int buf_len = len + 1;
146 if (size < buf_len) {
147 str = NEW_RESOURCE_ARRAY(char, buf_len);
148 } else {
149 str = buf;
150 }
151 return as_C_string(str, buf_len);
152 }
154 void Symbol::print_symbol_on(outputStream* st) const {
155 st = st ? st : tty;
156 st->print("%s", as_quoted_ascii());
157 }
159 char* Symbol::as_quoted_ascii() const {
160 const char *ptr = (const char *)&_body[0];
161 int quoted_length = UTF8::quoted_ascii_length(ptr, utf8_length());
162 char* result = NEW_RESOURCE_ARRAY(char, quoted_length + 1);
163 UTF8::as_quoted_ascii(ptr, result, quoted_length + 1);
164 return result;
165 }
167 jchar* Symbol::as_unicode(int& length) const {
168 Symbol* this_ptr = (Symbol*)this;
169 length = UTF8::unicode_length((char*)this_ptr->bytes(), utf8_length());
170 jchar* result = NEW_RESOURCE_ARRAY(jchar, length);
171 if (length > 0) {
172 UTF8::convert_to_unicode((char*)this_ptr->bytes(), result, length);
173 }
174 return result;
175 }
177 const char* Symbol::as_klass_external_name(char* buf, int size) const {
178 if (size > 0) {
179 char* str = as_C_string(buf, size);
180 int length = (int)strlen(str);
181 // Turn all '/'s into '.'s (also for array klasses)
182 for (int index = 0; index < length; index++) {
183 if (str[index] == '/') {
184 str[index] = '.';
185 }
186 }
187 return str;
188 } else {
189 return buf;
190 }
191 }
193 const char* Symbol::as_klass_external_name() const {
194 char* str = as_C_string();
195 int length = (int)strlen(str);
196 // Turn all '/'s into '.'s (also for array klasses)
197 for (int index = 0; index < length; index++) {
198 if (str[index] == '/') {
199 str[index] = '.';
200 }
201 }
202 return str;
203 }
205 // Alternate hashing for unbalanced symbol tables.
206 unsigned int Symbol::new_hash(jint seed) {
207 ResourceMark rm;
208 // Use alternate hashing algorithm on this symbol.
209 return AltHashing::murmur3_32(seed, (const jbyte*)as_C_string(), utf8_length());
210 }
212 void Symbol::print_on(outputStream* st) const {
213 if (this == NULL) {
214 st->print_cr("NULL");
215 } else {
216 st->print("Symbol: '");
217 print_symbol_on(st);
218 st->print("'");
219 st->print(" count %d", refcount());
220 }
221 }
223 // The print_value functions are present in all builds, to support the
224 // disassembler and error reporting.
225 void Symbol::print_value_on(outputStream* st) const {
226 if (this == NULL) {
227 st->print("NULL");
228 } else {
229 st->print("'");
230 for (int i = 0; i < utf8_length(); i++) {
231 st->print("%c", byte_at(i));
232 }
233 st->print("'");
234 }
235 }
237 // SymbolTable prints this in its statistics
238 NOT_PRODUCT(int Symbol::_total_count = 0;)