Bug Summary

File:jdk/src/hotspot/share/classfile/symbolTable.hpp
Warning:line 191, column 34
Null pointer passed to 1st parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name compilerOracle.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp

/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp

1/*
2 * Copyright (c) 1998, 2021, 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#include "precompiled.hpp"
26#include "jvm.h"
27#include "classfile/symbolTable.hpp"
28#include "compiler/compilerDirectives.hpp"
29#include "compiler/compilerOracle.hpp"
30#include "compiler/methodMatcher.hpp"
31#include "memory/allocation.inline.hpp"
32#include "memory/oopFactory.hpp"
33#include "memory/resourceArea.hpp"
34#include "oops/klass.hpp"
35#include "oops/method.inline.hpp"
36#include "oops/symbol.hpp"
37#include "runtime/globals_extension.hpp"
38#include "runtime/handles.inline.hpp"
39#include "runtime/jniHandles.hpp"
40#include "runtime/os.hpp"
41
42static const char* optiontype_names[] = {
43#define enum_of_types(type, name) name,
44 OPTION_TYPES(enum_of_types)enum_of_types(Intx, "intx") enum_of_types(Uintx, "uintx") enum_of_types
(Bool, "bool") enum_of_types(Ccstr, "ccstr") enum_of_types(Ccstrlist
, "ccstrlist") enum_of_types(Double, "double")
45#undef enum_of_types
46};
47
48const char* optiontype2name(enum OptionType type) {
49 return optiontype_names[static_cast<int>(type)];
50}
51
52static enum OptionType option_types[] = {
53#define enum_of_options(option, name, ctype) OptionType::ctype,
54 COMPILECOMMAND_OPTIONS(enum_of_options)enum_of_options(Help, "help", Unknown) enum_of_options(Quiet,
"quiet", Unknown) enum_of_options(Log, "log", Bool) enum_of_options
(Print, "print", Bool) enum_of_options(Inline, "inline", Bool
) enum_of_options(DontInline, "dontinline", Bool) enum_of_options
(Blackhole, "blackhole", Bool) enum_of_options(CompileOnly, "compileonly"
, Bool) enum_of_options(Exclude, "exclude", Bool) enum_of_options
(Break, "break", Bool) enum_of_options(BreakAtExecute, "BreakAtExecute"
, Bool) enum_of_options(BreakAtCompile, "BreakAtCompile", Bool
) enum_of_options(PrintAssembly, "PrintAssembly", Bool) enum_of_options
(PrintInlining, "PrintInlining", Bool) enum_of_options(PrintIntrinsics
, "PrintIntrinsics", Bool) enum_of_options(PrintNMethods, "PrintNMethods"
, Bool) enum_of_options(PrintOptoAssembly, "PrintOptoAssembly"
, Bool) enum_of_options(PrintDebugInfo, "PrintDebugInfo", Bool
) enum_of_options(PrintRelocations, "PrintRelocations", Bool)
enum_of_options(PrintDependencies, "PrintDependencies", Bool
) enum_of_options(BackgroundCompilation, "BackgroundCompilation"
, Bool) enum_of_options(RepeatCompilation, "RepeatCompilation"
, Intx) enum_of_options(ReplayInline, "ReplayInline", Bool) enum_of_options
(DumpReplay, "DumpReplay", Bool) enum_of_options(DumpInline, "DumpInline"
, Bool) enum_of_options(CompileThresholdScaling, "CompileThresholdScaling"
, Double) enum_of_options(ControlIntrinsic, "ControlIntrinsic"
, Ccstrlist) enum_of_options(DisableIntrinsic, "DisableIntrinsic"
, Ccstrlist) enum_of_options(NoRTMLockEliding, "NoRTMLockEliding"
, Bool) enum_of_options(UseRTMLockEliding, "UseRTMLockEliding"
, Bool) enum_of_options(BlockLayoutByFrequency, "BlockLayoutByFrequency"
, Bool) enum_of_options(TraceOptoPipelining, "TraceOptoPipelining"
, Bool) enum_of_options(TraceOptoOutput, "TraceOptoOutput", Bool
) enum_of_options(TraceSpilling, "TraceSpilling", Bool) enum_of_options
(PrintIdeal, "PrintIdeal", Bool) enum_of_options(IGVPrintLevel
, "IGVPrintLevel", Intx) enum_of_options(Vectorize, "Vectorize"
, Bool) enum_of_options(VectorizeDebug, "VectorizeDebug", Uintx
) enum_of_options(CloneMapDebug, "CloneMapDebug", Bool) enum_of_options
(IncrementalInlineForceCleanup, "IncrementalInlineForceCleanup"
, Bool) enum_of_options(MaxNodeLimit, "MaxNodeLimit", Intx) enum_of_options
(TestOptionInt, "TestOptionInt", Intx) enum_of_options(TestOptionUint
, "TestOptionUint", Uintx) enum_of_options(TestOptionBool, "TestOptionBool"
, Bool) enum_of_options(TestOptionBool2, "TestOptionBool2", Bool
) enum_of_options(TestOptionStr, "TestOptionStr", Ccstr) enum_of_options
(TestOptionList, "TestOptionList", Ccstrlist) enum_of_options
(TestOptionDouble, "TestOptionDouble", Double) enum_of_options
(Option, "option", Unknown) enum_of_options(Unknown, "unknown"
, Unknown)
55#undef enum_of_options
56};
57
58enum OptionType option2type(enum CompileCommand option) {
59 return option_types[static_cast<int>(option)];
60}
61
62static const char* option_names[] = {
63#define enum_of_options(option, name, ctype) name,
64 COMPILECOMMAND_OPTIONS(enum_of_options)enum_of_options(Help, "help", Unknown) enum_of_options(Quiet,
"quiet", Unknown) enum_of_options(Log, "log", Bool) enum_of_options
(Print, "print", Bool) enum_of_options(Inline, "inline", Bool
) enum_of_options(DontInline, "dontinline", Bool) enum_of_options
(Blackhole, "blackhole", Bool) enum_of_options(CompileOnly, "compileonly"
, Bool) enum_of_options(Exclude, "exclude", Bool) enum_of_options
(Break, "break", Bool) enum_of_options(BreakAtExecute, "BreakAtExecute"
, Bool) enum_of_options(BreakAtCompile, "BreakAtCompile", Bool
) enum_of_options(PrintAssembly, "PrintAssembly", Bool) enum_of_options
(PrintInlining, "PrintInlining", Bool) enum_of_options(PrintIntrinsics
, "PrintIntrinsics", Bool) enum_of_options(PrintNMethods, "PrintNMethods"
, Bool) enum_of_options(PrintOptoAssembly, "PrintOptoAssembly"
, Bool) enum_of_options(PrintDebugInfo, "PrintDebugInfo", Bool
) enum_of_options(PrintRelocations, "PrintRelocations", Bool)
enum_of_options(PrintDependencies, "PrintDependencies", Bool
) enum_of_options(BackgroundCompilation, "BackgroundCompilation"
, Bool) enum_of_options(RepeatCompilation, "RepeatCompilation"
, Intx) enum_of_options(ReplayInline, "ReplayInline", Bool) enum_of_options
(DumpReplay, "DumpReplay", Bool) enum_of_options(DumpInline, "DumpInline"
, Bool) enum_of_options(CompileThresholdScaling, "CompileThresholdScaling"
, Double) enum_of_options(ControlIntrinsic, "ControlIntrinsic"
, Ccstrlist) enum_of_options(DisableIntrinsic, "DisableIntrinsic"
, Ccstrlist) enum_of_options(NoRTMLockEliding, "NoRTMLockEliding"
, Bool) enum_of_options(UseRTMLockEliding, "UseRTMLockEliding"
, Bool) enum_of_options(BlockLayoutByFrequency, "BlockLayoutByFrequency"
, Bool) enum_of_options(TraceOptoPipelining, "TraceOptoPipelining"
, Bool) enum_of_options(TraceOptoOutput, "TraceOptoOutput", Bool
) enum_of_options(TraceSpilling, "TraceSpilling", Bool) enum_of_options
(PrintIdeal, "PrintIdeal", Bool) enum_of_options(IGVPrintLevel
, "IGVPrintLevel", Intx) enum_of_options(Vectorize, "Vectorize"
, Bool) enum_of_options(VectorizeDebug, "VectorizeDebug", Uintx
) enum_of_options(CloneMapDebug, "CloneMapDebug", Bool) enum_of_options
(IncrementalInlineForceCleanup, "IncrementalInlineForceCleanup"
, Bool) enum_of_options(MaxNodeLimit, "MaxNodeLimit", Intx) enum_of_options
(TestOptionInt, "TestOptionInt", Intx) enum_of_options(TestOptionUint
, "TestOptionUint", Uintx) enum_of_options(TestOptionBool, "TestOptionBool"
, Bool) enum_of_options(TestOptionBool2, "TestOptionBool2", Bool
) enum_of_options(TestOptionStr, "TestOptionStr", Ccstr) enum_of_options
(TestOptionList, "TestOptionList", Ccstrlist) enum_of_options
(TestOptionDouble, "TestOptionDouble", Double) enum_of_options
(Option, "option", Unknown) enum_of_options(Unknown, "unknown"
, Unknown)
65#undef enum_of_options
66};
67
68const char* option2name(enum CompileCommand option) {
69 return option_names[static_cast<int>(option)];
70}
71
72/* Methods to map real type names to OptionType */
73template<typename T>
74static OptionType get_type_for() {
75 return OptionType::Unknown;
76};
77
78template<> OptionType get_type_for<intx>() {
79 return OptionType::Intx;
80}
81
82template<> OptionType get_type_for<uintx>() {
83 return OptionType::Uintx;
84}
85
86template<> OptionType get_type_for<bool>() {
87 return OptionType::Bool;
88}
89
90template<> OptionType get_type_for<ccstr>() {
91 return OptionType::Ccstr;
92}
93
94template<> OptionType get_type_for<double>() {
95 return OptionType::Double;
96}
97
98class MethodMatcher;
99class TypedMethodOptionMatcher;
100
101static TypedMethodOptionMatcher* option_list = NULL__null;
102static bool any_set = false;
103
104// A filter for quick lookup if an option is set
105static bool option_filter[static_cast<int>(CompileCommand::Unknown) + 1] = { 0 };
106
107void command_set_in_filter(enum CompileCommand option) {
108 assert(option != CompileCommand::Unknown, "sanity")do { if (!(option != CompileCommand::Unknown)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 108, "assert(" "option != CompileCommand::Unknown" ") failed"
, "sanity"); ::breakpoint(); } } while (0)
;
109 assert(option2type(option) != OptionType::Unknown, "sanity")do { if (!(option2type(option) != OptionType::Unknown)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 109, "assert(" "option2type(option) != OptionType::Unknown"
") failed", "sanity"); ::breakpoint(); } } while (0)
;
110
111 if ((option != CompileCommand::DontInline) &&
112 (option != CompileCommand::Inline) &&
113 (option != CompileCommand::Log)) {
114 any_set = true;
115 }
116 option_filter[static_cast<int>(option)] = true;
117}
118
119bool has_command(enum CompileCommand option) {
120 return option_filter[static_cast<int>(option)];
121}
122
123class TypedMethodOptionMatcher : public MethodMatcher {
124 private:
125 TypedMethodOptionMatcher* _next;
126 enum CompileCommand _option;
127 public:
128
129 union {
130 bool bool_value;
131 intx intx_value;
132 uintx uintx_value;
133 double double_value;
134 ccstr ccstr_value;
135 } _u;
136
137 TypedMethodOptionMatcher() : MethodMatcher(),
138 _next(NULL__null),
139 _option(CompileCommand::Unknown) {
140 memset(&_u, 0, sizeof(_u));
141 }
142
143 ~TypedMethodOptionMatcher();
144 static TypedMethodOptionMatcher* parse_method_pattern(char*& line, char* errorbuf, const int buf_size);
145 TypedMethodOptionMatcher* match(const methodHandle &method, enum CompileCommand option);
146
147 void init(enum CompileCommand option, TypedMethodOptionMatcher* next) {
148 _next = next;
149 _option = option;
150 }
151
152 void init_matcher(Symbol* class_name, Mode class_mode,
153 Symbol* method_name, Mode method_mode,
154 Symbol* signature) {
155 MethodMatcher::init(class_name, class_mode, method_name, method_mode, signature);
156 }
157
158 void set_next(TypedMethodOptionMatcher* next) {_next = next; }
159 TypedMethodOptionMatcher* next() { return _next; }
160 enum CompileCommand option() { return _option; }
161 template<typename T> T value();
162 template<typename T> void set_value(T value);
163 void print();
164 void print_all();
165 TypedMethodOptionMatcher* clone();
166};
167
168// A few templated accessors instead of a full template class.
169template<> intx TypedMethodOptionMatcher::value<intx>() {
170 return _u.intx_value;
171}
172
173template<> uintx TypedMethodOptionMatcher::value<uintx>() {
174 return _u.uintx_value;
175}
176
177template<> bool TypedMethodOptionMatcher::value<bool>() {
178 return _u.bool_value;
179}
180
181template<> double TypedMethodOptionMatcher::value<double>() {
182 return _u.double_value;
183}
184
185template<> ccstr TypedMethodOptionMatcher::value<ccstr>() {
186 return _u.ccstr_value;
187}
188
189template<> void TypedMethodOptionMatcher::set_value(intx value) {
190 _u.intx_value = value;
191}
192
193template<> void TypedMethodOptionMatcher::set_value(uintx value) {
194 _u.uintx_value = value;
195}
196
197template<> void TypedMethodOptionMatcher::set_value(double value) {
198 _u.double_value = value;
199}
200
201template<> void TypedMethodOptionMatcher::set_value(bool value) {
202 _u.bool_value = value;
203}
204
205template<> void TypedMethodOptionMatcher::set_value(ccstr value) {
206 _u.ccstr_value = (const ccstr)os::strdup_check_oom(value);
207}
208
209void TypedMethodOptionMatcher::print() {
210 ttyLocker ttyl;
211 print_base(tty);
212 const char* name = option2name(_option);
213 enum OptionType type = option2type(_option);
214 switch (type) {
215 case OptionType::Intx:
216 tty->print_cr(" intx %s = " INTX_FORMAT"%" "l" "d", name, value<intx>());
217 break;
218 case OptionType::Uintx:
219 tty->print_cr(" uintx %s = " UINTX_FORMAT"%" "l" "u", name, value<uintx>());
220 break;
221 case OptionType::Bool:
222 tty->print_cr(" bool %s = %s", name, value<bool>() ? "true" : "false");
223 break;
224 case OptionType::Double:
225 tty->print_cr(" double %s = %f", name, value<double>());
226 break;
227 case OptionType::Ccstr:
228 case OptionType::Ccstrlist:
229 tty->print_cr(" const char* %s = '%s'", name, value<ccstr>());
230 break;
231 default:
232 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 232); ::breakpoint(); } while (0)
;
233 }
234}
235
236void TypedMethodOptionMatcher::print_all() {
237 print();
238 if (_next != NULL__null) {
239 tty->print(" ");
240 _next->print_all();
241 }
242 }
243
244TypedMethodOptionMatcher* TypedMethodOptionMatcher::clone() {
245 TypedMethodOptionMatcher* m = new TypedMethodOptionMatcher();
246 m->_class_mode = _class_mode;
247 m->_class_name = _class_name;
248 m->_method_mode = _method_mode;
249 m->_method_name = _method_name;
250 m->_signature = _signature;
251 // Need to ref count the symbols
252 if (_class_name != NULL__null) {
253 _class_name->increment_refcount();
254 }
255 if (_method_name != NULL__null) {
256 _method_name->increment_refcount();
257 }
258 if (_signature != NULL__null) {
259 _signature->increment_refcount();
260 }
261 return m;
262}
263
264TypedMethodOptionMatcher::~TypedMethodOptionMatcher() {
265 enum OptionType type = option2type(_option);
266 if (type == OptionType::Ccstr || type == OptionType::Ccstrlist) {
267 ccstr v = value<ccstr>();
268 os::free((void*)v);
269 }
270}
271
272TypedMethodOptionMatcher* TypedMethodOptionMatcher::parse_method_pattern(char*& line, char* errorbuf, const int buf_size) {
273 assert(*errorbuf == '\0', "Dont call here with error_msg already set")do { if (!(*errorbuf == '\0')) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 273, "assert(" "*errorbuf == '\\0'" ") failed", "Dont call here with error_msg already set"
); ::breakpoint(); } } while (0)
;
274 const char* error_msg = NULL__null;
275 TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
276 MethodMatcher::parse_method_pattern(line, error_msg, tom);
277 if (error_msg != NULL__null) {
278 jio_snprintf(errorbuf, buf_size, error_msg);
279 delete tom;
280 return NULL__null;
281 }
282 return tom;
283}
284
285TypedMethodOptionMatcher* TypedMethodOptionMatcher::match(const methodHandle& method, enum CompileCommand option) {
286 TypedMethodOptionMatcher* current = this;
287 while (current != NULL__null) {
288 if (current->_option == option) {
289 if (current->matches(method)) {
290 return current;
291 }
292 }
293 current = current->next();
294 }
295 return NULL__null;
296}
297
298template<typename T>
299static void register_command(TypedMethodOptionMatcher* matcher,
300 enum CompileCommand option,
301 T value) {
302 assert(matcher != option_list, "No circular lists please")do { if (!(matcher != option_list)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 302, "assert(" "matcher != option_list" ") failed", "No circular lists please"
); ::breakpoint(); } } while (0)
;
303 if (option == CompileCommand::Log && !LogCompilation) {
304 tty->print_cr("Warning: +LogCompilation must be enabled in order for individual methods to be logged with ");
305 tty->print_cr(" CompileCommand=log,<method pattern>");
306 }
307 assert(CompilerOracle::option_matches_type(option, value), "Value must match option type")do { if (!(CompilerOracle::option_matches_type(option, value)
)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 307, "assert(" "CompilerOracle::option_matches_type(option, value)"
") failed", "Value must match option type"); ::breakpoint();
} } while (0)
;
308
309 if (option == CompileCommand::Blackhole && !UnlockExperimentalVMOptions) {
310 warning("Blackhole compile option is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions");
311 return;
312 }
313
314 matcher->init(option, option_list);
315 matcher->set_value<T>(value);
316 option_list = matcher;
317 command_set_in_filter(option);
318
319 if (!CompilerOracle::be_quiet()) {
320 // Print out the successful registration of a compile command
321 ttyLocker ttyl;
322 tty->print("CompileCommand: %s ", option2name(option));
323 matcher->print();
324 }
325 return;
326}
327
328template<typename T>
329bool CompilerOracle::has_option_value(const methodHandle& method, enum CompileCommand option, T& value) {
330 assert(option_matches_type(option, value), "Value must match option type")do { if (!(option_matches_type(option, value))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 330, "assert(" "option_matches_type(option, value)" ") failed"
, "Value must match option type"); ::breakpoint(); } } while (
0)
;
331 if (!has_command(option)) {
332 return false;
333 }
334 if (option_list != NULL__null) {
335 TypedMethodOptionMatcher* m = option_list->match(method, option);
336 if (m != NULL__null) {
337 value = m->value<T>();
338 return true;
339 }
340 }
341 return false;
342}
343
344static bool resolve_inlining_predicate(enum CompileCommand option, const methodHandle& method) {
345 assert(option == CompileCommand::Inline || option == CompileCommand::DontInline, "Sanity")do { if (!(option == CompileCommand::Inline || option == CompileCommand
::DontInline)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 345, "assert(" "option == CompileCommand::Inline || option == CompileCommand::DontInline"
") failed", "Sanity"); ::breakpoint(); } } while (0)
;
346 bool v1 = false;
347 bool v2 = false;
348 bool has_inline = CompilerOracle::has_option_value(method, CompileCommand::Inline, v1);
349 bool has_dnotinline = CompilerOracle::has_option_value(method, CompileCommand::DontInline, v2);
350 if (has_inline && has_dnotinline) {
351 if (v1 && v2) {
352 // Conflict options detected
353 // Find the last one for that method and return the predicate accordingly
354 // option_list lists options in reverse order. So the first option we find is the last which was specified.
355 enum CompileCommand last_one = CompileCommand::Unknown;
356 TypedMethodOptionMatcher* current = option_list;
357 while (current != NULL__null) {
358 last_one = current->option();
359 if (last_one == CompileCommand::Inline || last_one == CompileCommand::DontInline) {
360 if (current->matches(method)) {
361 return last_one == option;
362 }
363 }
364 current = current->next();
365 }
366 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 366); ::breakpoint(); } while (0)
;
367 return false;
368 } else {
369 // No conflicts
370 return option == CompileCommand::Inline ? v1 : v2;
371 }
372 } else {
373 if (option == CompileCommand::Inline) {
374 return has_inline ? v1 : false;
375 } else {
376 return has_dnotinline ? v2 : false;
377 }
378 }
379}
380
381static bool check_predicate(enum CompileCommand option, const methodHandle& method) {
382 // Special handling for Inline and DontInline since conflict options may be specified
383 if (option == CompileCommand::Inline || option == CompileCommand::DontInline) {
384 return resolve_inlining_predicate(option, method);
385 }
386
387 bool value = false;
388 if (CompilerOracle::has_option_value(method, option, value)) {
389 return value;
390 }
391 return false;
392}
393
394bool CompilerOracle::has_any_command_set() {
395 return any_set;
396}
397
398// Explicit instantiation for all OptionTypes supported.
399template bool CompilerOracle::has_option_value<intx>(const methodHandle& method, enum CompileCommand option, intx& value);
400template bool CompilerOracle::has_option_value<uintx>(const methodHandle& method, enum CompileCommand option, uintx& value);
401template bool CompilerOracle::has_option_value<bool>(const methodHandle& method, enum CompileCommand option, bool& value);
402template bool CompilerOracle::has_option_value<ccstr>(const methodHandle& method, enum CompileCommand option, ccstr& value);
403template bool CompilerOracle::has_option_value<double>(const methodHandle& method, enum CompileCommand option, double& value);
404
405template<typename T>
406bool CompilerOracle::option_matches_type(enum CompileCommand option, T& value) {
407 enum OptionType option_type = option2type(option);
408 if (option_type == OptionType::Unknown) {
409 return false; // Can't query options with type Unknown.
410 }
411 if (option_type == OptionType::Ccstrlist) {
412 option_type = OptionType::Ccstr; // CCstrList type options are stored as Ccstr
413 }
414 return (get_type_for<T>() == option_type);
415}
416
417template bool CompilerOracle::option_matches_type<intx>(enum CompileCommand option, intx& value);
418template bool CompilerOracle::option_matches_type<uintx>(enum CompileCommand option, uintx& value);
419template bool CompilerOracle::option_matches_type<bool>(enum CompileCommand option, bool& value);
420template bool CompilerOracle::option_matches_type<ccstr>(enum CompileCommand option, ccstr& value);
421template bool CompilerOracle::option_matches_type<double>(enum CompileCommand option, double& value);
422
423bool CompilerOracle::has_option(const methodHandle& method, enum CompileCommand option) {
424 bool value = false;
425 has_option_value(method, option, value);
426 return value;
427}
428
429bool CompilerOracle::should_exclude(const methodHandle& method) {
430 if (check_predicate(CompileCommand::Exclude, method)) {
431 return true;
432 }
433 if (has_command(CompileCommand::CompileOnly)) {
434 return !check_predicate(CompileCommand::CompileOnly, method);
435 }
436 return false;
437}
438
439bool CompilerOracle::should_inline(const methodHandle& method) {
440 return (check_predicate(CompileCommand::Inline, method));
441}
442
443bool CompilerOracle::should_not_inline(const methodHandle& method) {
444 return check_predicate(CompileCommand::DontInline, method) || check_predicate(CompileCommand::Exclude, method);
445}
446
447bool CompilerOracle::should_print(const methodHandle& method) {
448 return check_predicate(CompileCommand::Print, method);
449}
450
451bool CompilerOracle::should_print_methods() {
452 return has_command(CompileCommand::Print);
453}
454
455bool CompilerOracle::should_log(const methodHandle& method) {
456 if (!LogCompilation) return false;
457 if (!has_command(CompileCommand::Log)) {
458 return true; // by default, log all
459 }
460 return (check_predicate(CompileCommand::Log, method));
461}
462
463bool CompilerOracle::should_break_at(const methodHandle& method) {
464 return check_predicate(CompileCommand::Break, method);
465}
466
467void CompilerOracle::tag_blackhole_if_possible(const methodHandle& method) {
468 if (!check_predicate(CompileCommand::Blackhole, method)) {
469 return;
470 }
471 guarantee(UnlockExperimentalVMOptions, "Checked during initial parsing")do { if (!(UnlockExperimentalVMOptions)) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 471, "guarantee(" "UnlockExperimentalVMOptions" ") failed",
"Checked during initial parsing"); ::breakpoint(); } } while
(0)
;
472 if (method->result_type() != T_VOID) {
473 warning("Blackhole compile option only works for methods with void type: %s",
474 method->name_and_sig_as_C_string());
475 return;
476 }
477 if (!method->is_empty_method()) {
478 warning("Blackhole compile option only works for empty methods: %s",
479 method->name_and_sig_as_C_string());
480 return;
481 }
482 if (!method->is_static()) {
483 warning("Blackhole compile option only works for static methods: %s",
484 method->name_and_sig_as_C_string());
485 return;
486 }
487 if (method->intrinsic_id() == vmIntrinsics::_blackhole) {
488 return;
489 }
490 if (method->intrinsic_id() != vmIntrinsics::_none) {
491 warning("Blackhole compile option only works for methods that do not have intrinsic set: %s, %s",
492 method->name_and_sig_as_C_string(), vmIntrinsics::name_at(method->intrinsic_id()));
493 return;
494 }
495 method->set_intrinsic_id(vmIntrinsics::_blackhole);
496}
497
498static enum CompileCommand match_option_name(const char* line, int* bytes_read, char* errorbuf, int bufsize) {
499 assert(ARRAY_SIZE(option_names) == static_cast<int>(CompileCommand::Count), "option_names size mismatch")do { if (!(sizeof(array_size_impl(option_names)) == static_cast
<int>(CompileCommand::Count))) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 499, "assert(" "sizeof(array_size_impl(option_names)) == static_cast<int>(CompileCommand::Count)"
") failed", "option_names size mismatch"); ::breakpoint(); }
} while (0)
;
500
501 *bytes_read = 0;
502 char option_buf[256];
503 int matches = sscanf(line, "%255[a-zA-Z0-9]%n", option_buf, bytes_read);
504 if (matches > 0 && strcasecmp(option_buf, "unknown") != 0) {
505 for (uint i = 0; i < ARRAY_SIZE(option_names)sizeof(array_size_impl(option_names)); i++) {
506 if (strcasecmp(option_buf, option_names[i]) == 0) {
507 return static_cast<enum CompileCommand>(i);
508 }
509 }
510 }
511 jio_snprintf(errorbuf, bufsize, "Unrecognized option '%s'", option_buf);
512 return CompileCommand::Unknown;
513}
514
515// match exactly and don't mess with errorbuf
516enum CompileCommand CompilerOracle::parse_option_name(const char* line) {
517 for (uint i = 0; i < ARRAY_SIZE(option_names)sizeof(array_size_impl(option_names)); i++) {
518 if (strcasecmp(line, option_names[i]) == 0) {
519 return static_cast<enum CompileCommand>(i);
520 }
521 }
522 return CompileCommand::Unknown;
523}
524
525enum OptionType CompilerOracle::parse_option_type(const char* type_str) {
526 for (uint i = 0; i < ARRAY_SIZE(optiontype_names)sizeof(array_size_impl(optiontype_names)); i++) {
527 if (strcasecmp(type_str, optiontype_names[i]) == 0) {
528 return static_cast<enum OptionType>(i);
529 }
530 }
531 return OptionType::Unknown;
532}
533
534void print_tip() { // CMH Update info
535 tty->cr();
536 tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>' - to set boolean option to true");
537 tty->print_cr("Usage: '-XX:CompileCommand=<option>,<method pattern>,<value>'");
538 tty->print_cr("Use: '-XX:CompileCommand=help' for more information and to list all option.");
539 tty->cr();
540}
541
542void print_option(enum CompileCommand option, const char* name, enum OptionType type) {
543 if (type != OptionType::Unknown) {
544 tty->print_cr(" %s (%s)", name, optiontype2name(type));
545 }
546}
547
548void print_commands() {
549 tty->cr();
550 tty->print_cr("All available options:");
551#define enum_of_options(option, name, ctype) print_option(CompileCommand::option, name, OptionType::ctype);
552 COMPILECOMMAND_OPTIONS(enum_of_options)enum_of_options(Help, "help", Unknown) enum_of_options(Quiet,
"quiet", Unknown) enum_of_options(Log, "log", Bool) enum_of_options
(Print, "print", Bool) enum_of_options(Inline, "inline", Bool
) enum_of_options(DontInline, "dontinline", Bool) enum_of_options
(Blackhole, "blackhole", Bool) enum_of_options(CompileOnly, "compileonly"
, Bool) enum_of_options(Exclude, "exclude", Bool) enum_of_options
(Break, "break", Bool) enum_of_options(BreakAtExecute, "BreakAtExecute"
, Bool) enum_of_options(BreakAtCompile, "BreakAtCompile", Bool
) enum_of_options(PrintAssembly, "PrintAssembly", Bool) enum_of_options
(PrintInlining, "PrintInlining", Bool) enum_of_options(PrintIntrinsics
, "PrintIntrinsics", Bool) enum_of_options(PrintNMethods, "PrintNMethods"
, Bool) enum_of_options(PrintOptoAssembly, "PrintOptoAssembly"
, Bool) enum_of_options(PrintDebugInfo, "PrintDebugInfo", Bool
) enum_of_options(PrintRelocations, "PrintRelocations", Bool)
enum_of_options(PrintDependencies, "PrintDependencies", Bool
) enum_of_options(BackgroundCompilation, "BackgroundCompilation"
, Bool) enum_of_options(RepeatCompilation, "RepeatCompilation"
, Intx) enum_of_options(ReplayInline, "ReplayInline", Bool) enum_of_options
(DumpReplay, "DumpReplay", Bool) enum_of_options(DumpInline, "DumpInline"
, Bool) enum_of_options(CompileThresholdScaling, "CompileThresholdScaling"
, Double) enum_of_options(ControlIntrinsic, "ControlIntrinsic"
, Ccstrlist) enum_of_options(DisableIntrinsic, "DisableIntrinsic"
, Ccstrlist) enum_of_options(NoRTMLockEliding, "NoRTMLockEliding"
, Bool) enum_of_options(UseRTMLockEliding, "UseRTMLockEliding"
, Bool) enum_of_options(BlockLayoutByFrequency, "BlockLayoutByFrequency"
, Bool) enum_of_options(TraceOptoPipelining, "TraceOptoPipelining"
, Bool) enum_of_options(TraceOptoOutput, "TraceOptoOutput", Bool
) enum_of_options(TraceSpilling, "TraceSpilling", Bool) enum_of_options
(PrintIdeal, "PrintIdeal", Bool) enum_of_options(IGVPrintLevel
, "IGVPrintLevel", Intx) enum_of_options(Vectorize, "Vectorize"
, Bool) enum_of_options(VectorizeDebug, "VectorizeDebug", Uintx
) enum_of_options(CloneMapDebug, "CloneMapDebug", Bool) enum_of_options
(IncrementalInlineForceCleanup, "IncrementalInlineForceCleanup"
, Bool) enum_of_options(MaxNodeLimit, "MaxNodeLimit", Intx) enum_of_options
(TestOptionInt, "TestOptionInt", Intx) enum_of_options(TestOptionUint
, "TestOptionUint", Uintx) enum_of_options(TestOptionBool, "TestOptionBool"
, Bool) enum_of_options(TestOptionBool2, "TestOptionBool2", Bool
) enum_of_options(TestOptionStr, "TestOptionStr", Ccstr) enum_of_options
(TestOptionList, "TestOptionList", Ccstrlist) enum_of_options
(TestOptionDouble, "TestOptionDouble", Double) enum_of_options
(Option, "option", Unknown) enum_of_options(Unknown, "unknown"
, Unknown)
553#undef enum_of_options
554 tty->cr();
555}
556
557static void usage() {
558 tty->cr();
559 tty->print_cr("The CompileCommand option enables the user of the JVM to control specific");
560 tty->print_cr("behavior of the dynamic compilers.");
561 tty->cr();
562 tty->print_cr("Compile commands has this general form:");
563 tty->print_cr("-XX:CompileCommand=<option><method pattern><value>");
564 tty->print_cr(" Sets <option> to the specified value for methods matching <method pattern>");
565 tty->print_cr(" All options are typed");
566 tty->cr();
567 tty->print_cr("-XX:CompileCommand=<option><method pattern>");
568 tty->print_cr(" Sets <option> to true for methods matching <method pattern>");
569 tty->print_cr(" Only applies to boolean options.");
570 tty->cr();
571 tty->print_cr("-XX:CompileCommand=quiet");
572 tty->print_cr(" Silence the compile command output");
573 tty->cr();
574 tty->print_cr("-XX:CompileCommand=help");
575 tty->print_cr(" Prints this help text");
576 tty->cr();
577 print_commands();
578 tty->cr();
579 tty->print_cr("Method patterns has the format:");
580 tty->print_cr(" package/Class.method()");
581 tty->cr();
582 tty->print_cr("For backward compatibility this form is also allowed:");
583 tty->print_cr(" package.Class::method()");
584 tty->cr();
585 tty->print_cr("The signature can be separated by an optional whitespace or comma:");
586 tty->print_cr(" package/Class.method ()");
587 tty->cr();
588 tty->print_cr("The class and method identifier can be used together with leading or");
589 tty->print_cr("trailing *'s for wildcard matching:");
590 tty->print_cr(" *ackage/Clas*.*etho*()");
591 tty->cr();
592 tty->print_cr("It is possible to use more than one CompileCommand on the command line:");
593 tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*");
594 tty->cr();
595 tty->print_cr("The CompileCommands can be loaded from a file with the flag");
596 tty->print_cr("-XX:CompileCommandFile=<file> or be added to the file '.hotspot_compiler'");
597 tty->print_cr("Use the same format in the file as the argument to the CompileCommand flag.");
598 tty->print_cr("Add one command on each line.");
599 tty->print_cr(" exclude java/*.*");
600 tty->print_cr(" option java/*.* ReplayInline");
601 tty->cr();
602 tty->print_cr("The following commands have conflicting behavior: 'exclude', 'inline', 'dontinline',");
603 tty->print_cr("and 'compileonly'. There is no priority of commands. Applying (a subset of) these");
604 tty->print_cr("commands to the same method results in undefined behavior.");
605 tty->cr();
606};
607
608int skip_whitespace(char* &line) {
609 // Skip any leading spaces
610 int whitespace_read = 0;
611 sscanf(line, "%*[ \t]%n", &whitespace_read);
612 line += whitespace_read;
613 return whitespace_read;
614}
615
616void skip_comma(char* &line) {
617 // Skip any leading spaces
618 if (*line == ',') {
619 line++;
620 }
621}
622
623static void scan_value(enum OptionType type, char* line, int& total_bytes_read,
624 TypedMethodOptionMatcher* matcher, enum CompileCommand option, char* errorbuf, const int buf_size) {
625 int bytes_read = 0;
626 const char* ccname = option2name(option);
627 const char* type_str = optiontype2name(type);
628 int skipped = skip_whitespace(line);
629 total_bytes_read += skipped;
630 if (type == OptionType::Intx) {
631 intx value;
632 if (sscanf(line, "" INTX_FORMAT"%" "l" "d" "%n", &value, &bytes_read) == 1) {
633 total_bytes_read += bytes_read;
634 line += bytes_read;
635 register_command(matcher, option, value);
636 return;
637 } else {
638 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
639 }
640 } else if (type == OptionType::Uintx) {
641 uintx value;
642 if (sscanf(line, "" UINTX_FORMAT"%" "l" "u" "%n", &value, &bytes_read) == 1) {
643 total_bytes_read += bytes_read;
644 line += bytes_read;
645 register_command(matcher, option, value);
646 return;
647 } else {
648 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
649 }
650 } else if (type == OptionType::Ccstr) {
651 ResourceMark rm;
652 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1)(char*) resource_allocate_bytes((strlen(line) + 1) * sizeof(char
))
;
653 if (sscanf(line, "%255[_a-zA-Z0-9]%n", value, &bytes_read) == 1) {
654 total_bytes_read += bytes_read;
655 line += bytes_read;
656 register_command(matcher, option, (ccstr) value);
657 return;
658 } else {
659 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
660 }
661 } else if (type == OptionType::Ccstrlist) {
662 // Accumulates several strings into one. The internal type is ccstr.
663 ResourceMark rm;
664 char* value = NEW_RESOURCE_ARRAY(char, strlen(line) + 1)(char*) resource_allocate_bytes((strlen(line) + 1) * sizeof(char
))
;
665 char* next_value = value;
666 if (sscanf(line, "%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
667 total_bytes_read += bytes_read;
668 line += bytes_read;
669 next_value += bytes_read + 1;
670 char* end_value = next_value - 1;
671 while (sscanf(line, "%*[ \t]%255[_a-zA-Z0-9+\\-]%n", next_value, &bytes_read) == 1) {
672 total_bytes_read += bytes_read;
673 line += bytes_read;
674 *end_value = ' '; // override '\0'
675 next_value += bytes_read;
676 end_value = next_value-1;
677 }
678
679 if (option == CompileCommand::ControlIntrinsic || option == CompileCommand::DisableIntrinsic) {
680 ControlIntrinsicValidator validator(value, (option == CompileCommand::DisableIntrinsic));
681
682 if (!validator.is_valid()) {
683 jio_snprintf(errorbuf, buf_size, "Unrecognized intrinsic detected in %s: %s", option2name(option), validator.what());
684 }
685 }
686
687 register_command(matcher, option, (ccstr) value);
688 return;
689 } else {
690 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
691 }
692 } else if (type == OptionType::Bool) {
693 char value[256];
694 if (*line == '\0') {
695 // Short version of a CompileCommand sets a boolean Option to true
696 // -XXCompileCommand=<Option>,<method pattern>
697 register_command(matcher, option, true);
698 return;
699 }
700 if (sscanf(line, "%255[a-zA-Z]%n", value, &bytes_read) == 1) {
701 if (strcasecmp(value, "true") == 0) {
702 total_bytes_read += bytes_read;
703 line += bytes_read;
704 register_command(matcher, option, true);
705 return;
706 } else if (strcasecmp(value, "false") == 0) {
707 total_bytes_read += bytes_read;
708 line += bytes_read;
709 register_command(matcher, option, false);
710 return;
711 } else {
712 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
713 }
714 } else {
715 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
716 }
717 } else if (type == OptionType::Double) {
718 char buffer[2][256];
719 // Decimal separator '.' has been replaced with ' ' or '/' earlier,
720 // so read integer and fraction part of double value separately.
721 if (sscanf(line, "%255[0-9]%*[ /\t]%255[0-9]%n", buffer[0], buffer[1], &bytes_read) == 2) {
722 char value[512] = "";
723 jio_snprintf(value, sizeof(value), "%s.%s", buffer[0], buffer[1]);
724 total_bytes_read += bytes_read;
725 line += bytes_read;
726 register_command(matcher, option, atof(value));
727 return;
728 } else {
729 jio_snprintf(errorbuf, buf_size, "Value cannot be read for option '%s' of type '%s'", ccname, type_str);
730 }
731 } else {
732 jio_snprintf(errorbuf, buf_size, "Type '%s' not supported ", type_str);
733 }
734}
735
736// Scan next option and value in line, return MethodMatcher object on success, NULL on failure.
737// On failure, error_msg contains description for the first error.
738// For future extensions: set error_msg on first error.
739static void scan_option_and_value(enum OptionType type, char* line, int& total_bytes_read,
740 TypedMethodOptionMatcher* matcher,
741 char* errorbuf, const int buf_size) {
742 total_bytes_read = 0;
743 int bytes_read = 0;
744 char option_buf[256];
745
746 // Read option name.
747 if (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option_buf, &bytes_read) == 1) {
748 line += bytes_read;
749 total_bytes_read += bytes_read;
750 int bytes_read2 = 0;
751 total_bytes_read += skip_whitespace(line);
752 enum CompileCommand option = match_option_name(option_buf, &bytes_read2, errorbuf, buf_size);
753 if (option == CompileCommand::Unknown) {
754 assert(*errorbuf != '\0', "error must have been set")do { if (!(*errorbuf != '\0')) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 754, "assert(" "*errorbuf != '\\0'" ") failed", "error must have been set"
); ::breakpoint(); } } while (0)
;
755 return;
756 }
757 enum OptionType optiontype = option2type(option);
758 if (option2type(option) != type) {
759 const char* optiontype_name = optiontype2name(optiontype);
760 const char* type_name = optiontype2name(type);
761 jio_snprintf(errorbuf, buf_size, "Option '%s' with type '%s' doesn't match supplied type '%s'", option_buf, optiontype_name, type_name);
762 return;
763 }
764 scan_value(type, line, total_bytes_read, matcher, option, errorbuf, buf_size);
765 } else {
766 const char* type_str = optiontype2name(type);
767 jio_snprintf(errorbuf, buf_size, "Option name for type '%s' should be alphanumeric ", type_str);
768 }
769 return;
770}
771
772void CompilerOracle::print_parse_error(char* error_msg, char* original_line) {
773 assert(*error_msg != '\0', "Must have error_message")do { if (!(*error_msg != '\0')) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 773, "assert(" "*error_msg != '\\0'" ") failed", "Must have error_message"
); ::breakpoint(); } } while (0)
;
774 ttyLocker ttyl;
775 tty->print_cr("CompileCommand: An error occurred during parsing");
776 tty->print_cr("Error: %s", error_msg);
777 tty->print_cr("Line: '%s'", original_line);
778 print_tip();
779}
780
781class LineCopy : StackObj {
782 const char* _copy;
783public:
784 LineCopy(char* line) {
785 _copy = os::strdup(line, mtInternal);
786 }
787 ~LineCopy() {
788 os::free((void*)_copy);
789 }
790 char* get() {
791 return (char*)_copy;
792 }
793};
794
795void CompilerOracle::parse_from_line(char* line) {
796 if (line[0] == '\0') return;
797 if (line[0] == '#') return;
798
799 LineCopy original(line);
800 int bytes_read;
801 char error_buf[1024] = {0};
802
803 enum CompileCommand option = match_option_name(line, &bytes_read, error_buf, sizeof(error_buf));
804 line += bytes_read;
805 ResourceMark rm;
806
807 if (option == CompileCommand::Unknown) {
808 print_parse_error(error_buf, original.get());
809 return;
810 }
811
812 if (option == CompileCommand::Quiet) {
813 _quiet = true;
814 return;
815 }
816
817 if (option == CompileCommand::Help) {
818 usage();
819 return;
820 }
821
822 if (option == CompileCommand::Option) {
823 // Look for trailing options.
824 //
825 // Two types of trailing options are
826 // supported:
827 //
828 // (1) CompileCommand=option,Klass::method,option
829 // (2) CompileCommand=option,Klass::method,type,option,value
830 //
831 // Type (1) is used to enable a boolean option for a method.
832 //
833 // Type (2) is used to support options with a value. Values can have the
834 // the following types: intx, uintx, bool, ccstr, ccstrlist, and double.
835
836 char option_type[256]; // stores option for Type (1) and type of Type (2)
837 skip_comma(line);
838 TypedMethodOptionMatcher* archetype = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
839 if (archetype == NULL__null) {
840 print_parse_error(error_buf, original.get());
841 return;
842 }
843
844 skip_whitespace(line);
845
846 // This is unnecessarily complex. Should retire multi-option lines and skip while loop
847 while (sscanf(line, "%255[a-zA-Z0-9]%n", option_type, &bytes_read) == 1) {
848 line += bytes_read;
849
850 // typed_matcher is used as a blueprint for each option, deleted at the end
851 TypedMethodOptionMatcher* typed_matcher = archetype->clone();
852 enum OptionType type = parse_option_type(option_type);
853 if (type != OptionType::Unknown) {
854 // Type (2) option: parse option name and value.
855 scan_option_and_value(type, line, bytes_read, typed_matcher, error_buf, sizeof(error_buf));
856 if (*error_buf != '\0') {
857 print_parse_error(error_buf, original.get());
858 return;
859 }
860 line += bytes_read;
861 } else {
862 // Type (1) option - option_type contains the option name -> bool value = true is implied
863 int bytes_read;
864 enum CompileCommand option = match_option_name(option_type, &bytes_read, error_buf, sizeof(error_buf));
865 if (option == CompileCommand::Unknown) {
866 print_parse_error(error_buf, original.get());
867 return;
868 }
869 if (option2type(option) == OptionType::Bool) {
870 register_command(typed_matcher, option, true);
871 } else {
872 jio_snprintf(error_buf, sizeof(error_buf), " Missing type '%s' before option '%s'",
873 optiontype2name(option2type(option)), option2name(option));
874 print_parse_error(error_buf, original.get());
875 return;
876 }
877 }
878 assert(typed_matcher != NULL, "sanity")do { if (!(typed_matcher != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 878, "assert(" "typed_matcher != __null" ") failed", "sanity"
); ::breakpoint(); } } while (0)
;
879 assert(*error_buf == '\0', "No error here")do { if (!(*error_buf == '\0')) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 879, "assert(" "*error_buf == '\\0'" ") failed", "No error here"
); ::breakpoint(); } } while (0)
;
880 skip_whitespace(line);
881 } // while(
882 delete archetype;
883 } else { // not an OptionCommand
884 // Command has the following form:
885 // CompileCommand=<option>,<method pattern><value>
886 // CompileCommand=<option>,<method pattern> (implies option is bool and value is true)
887 assert(*error_buf == '\0', "Don't call here with error_buf already set")do { if (!(*error_buf == '\0')) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 887, "assert(" "*error_buf == '\\0'" ") failed", "Don't call here with error_buf already set"
); ::breakpoint(); } } while (0)
;
888 enum OptionType type = option2type(option);
889 int bytes_read = 0;
890 skip_comma(line);
891 TypedMethodOptionMatcher* matcher = TypedMethodOptionMatcher::parse_method_pattern(line, error_buf, sizeof(error_buf));
892 if (matcher == NULL__null) {
893 print_parse_error(error_buf, original.get());
894 return;
895 }
896 skip_whitespace(line);
897 if (*line == '\0') {
898 // if this is a bool option this implies true
899 if (option2type(option) == OptionType::Bool) {
900 register_command(matcher, option, true);
901 return;
902 } else {
903 jio_snprintf(error_buf, sizeof(error_buf), " Option '%s' is not followed by a value", option2name(option));
904 print_parse_error(error_buf, original.get());
905 return;
906 }
907 }
908 scan_value(type, line, bytes_read, matcher, option, error_buf, sizeof(error_buf));
909 if (*error_buf != '\0') {
910 print_parse_error(error_buf, original.get());
911 return;
912 }
913 assert(matcher != NULL, "consistency")do { if (!(matcher != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 913, "assert(" "matcher != __null" ") failed", "consistency"
); ::breakpoint(); } } while (0)
;
914 }
915}
916
917static const char* default_cc_file = ".hotspot_compiler";
918
919static const char* cc_file() {
920#ifdef ASSERT1
921 if (CompileCommandFile == NULL__null)
922 return default_cc_file;
923#endif
924 return CompileCommandFile;
925}
926
927bool CompilerOracle::has_command_file() {
928 return cc_file() != NULL__null;
929}
930
931bool CompilerOracle::_quiet = false;
932
933void CompilerOracle::parse_from_file() {
934 assert(has_command_file(), "command file must be specified")do { if (!(has_command_file())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 934, "assert(" "has_command_file()" ") failed", "command file must be specified"
); ::breakpoint(); } } while (0)
;
935 FILE* stream = fopen(cc_file(), "rt");
936 if (stream == NULL__null) return;
937
938 char token[1024];
939 int pos = 0;
940 int c = getc(stream)_IO_getc (stream);
941 while(c != EOF(-1) && pos < (int)(sizeof(token)-1)) {
942 if (c == '\n') {
943 token[pos++] = '\0';
944 parse_from_line(token);
945 pos = 0;
946 } else {
947 token[pos++] = c;
948 }
949 c = getc(stream)_IO_getc (stream);
950 }
951 token[pos++] = '\0';
952 parse_from_line(token);
953
954 fclose(stream);
955}
956
957void CompilerOracle::parse_from_string(const char* str, void (*parse_line)(char*)) {
958 char token[1024];
959 int pos = 0;
960 const char* sp = str;
961 int c = *sp++;
962 while (c != '\0' && pos < (int)(sizeof(token)-1)) {
963 if (c == '\n') {
964 token[pos++] = '\0';
965 parse_line(token);
966 pos = 0;
967 } else {
968 token[pos++] = c;
969 }
970 c = *sp++;
971 }
972 token[pos++] = '\0';
973 parse_line(token);
974}
975
976void compilerOracle_init() {
977 CompilerOracle::parse_from_string(CompileCommand, CompilerOracle::parse_from_line);
978 CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
979 if (CompilerOracle::has_command_file()) {
980 CompilerOracle::parse_from_file();
981 } else {
982 struct stat buf;
983 if (os::stat(default_cc_file, &buf) == 0) {
984 warning("%s file is present but has been ignored. "
985 "Run with -XX:CompileCommandFile=%s to load the file.",
986 default_cc_file, default_cc_file);
987 }
988 }
989 if (has_command(CompileCommand::Print)) {
990 if (PrintAssembly) {
991 warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
992 }
993 }
994}
995
996void CompilerOracle::parse_compile_only(char* line) {
997 int i;
998 char name[1024];
999 const char* className = NULL__null;
1
'className' initialized to a null pointer value
1000 const char* methodName = NULL__null;
1001
1002 bool have_colon = (strstr(line, "::") != NULL__null);
2
Assuming the condition is false
1003 char method_sep = have_colon
2.1
'have_colon' is false
2.1
'have_colon' is false
? ':' : '.';
3
'?' condition is false
1004
1005 if (Verbose) {
4
Assuming 'Verbose' is false
5
Taking false branch
1006 tty->print_cr("%s", line);
1007 }
1008
1009 ResourceMark rm;
1010 while (*line != '\0') {
6
Assuming the condition is true
7
Loop condition is true. Entering loop body
1011 MethodMatcher::Mode c_match = MethodMatcher::Exact;
1012 MethodMatcher::Mode m_match = MethodMatcher::Exact;
1013
1014 for (i = 0;
1015 i
7.1
'i' is < 1024
7.1
'i' is < 1024
< 1024 && *line != '\0' && *line != method_sep && *line != ',' && !isspace(*line);
8
Assuming the condition is true
9
Assuming the condition is false
1016 line++, i++) {
1017 name[i] = *line;
1018 if (name[i] == '.') name[i] = '/'; // package prefix uses '/'
1019 }
1020
1021 if (i
9.1
'i' is <= 0
9.1
'i' is <= 0
> 0) {
10
Taking false branch
1022 char* newName = NEW_RESOURCE_ARRAY( char, i + 1)(char*) resource_allocate_bytes((i + 1) * sizeof(char));
1023 if (newName == NULL__null)
1024 return;
1025 strncpy(newName, name, i);
1026 newName[i] = '\0';
1027
1028 if (className == NULL__null) {
1029 className = newName;
1030 } else {
1031 methodName = newName;
1032 }
1033 }
1034
1035 if (*line == method_sep) {
11
Taking false branch
1036 if (className == NULL__null) {
1037 className = "";
1038 c_match = MethodMatcher::Any;
1039 }
1040 } else {
1041 // got foo or foo/bar
1042 if (className
11.1
'className' is equal to NULL
11.1
'className' is equal to NULL
== NULL__null) {
12
Taking true branch
1043 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/compiler/compilerOracle.cpp"
, 1043); ::breakpoint(); } while (0)
;
13
Loop condition is false. Exiting loop
1044 } else {
1045 // missing class name handled as "Any" class match
1046 if (className[0] == '\0') {
1047 c_match = MethodMatcher::Any;
1048 }
1049 }
1050 }
1051
1052 // each directive is terminated by , or NUL or . followed by NUL
1053 if (*line == ',' || *line == '\0' || (line[0] == '.' && line[1] == '\0')) {
1054 if (methodName
13.1
'methodName' is equal to NULL
13.1
'methodName' is equal to NULL
== NULL__null) {
14
Taking true branch
1055 methodName = "";
1056 if (*line != method_sep) {
15
Taking true branch
1057 m_match = MethodMatcher::Any;
1058 }
1059 }
1060
1061 EXCEPTION_MARKExceptionMark __em; JavaThread* __the_thread__ = __em.thread(
);
;
1062 Symbol* c_name = SymbolTable::new_symbol(className);
16
Passing null pointer value via 1st parameter 'name'
17
Calling 'SymbolTable::new_symbol'
1063 Symbol* m_name = SymbolTable::new_symbol(methodName);
1064 Symbol* signature = NULL__null;
1065
1066 TypedMethodOptionMatcher* tom = new TypedMethodOptionMatcher();
1067 tom->init_matcher(c_name, c_match, m_name, m_match, signature);
1068 register_command(tom, CompileCommand::CompileOnly, true);
1069 if (PrintVMOptions) {
1070 tty->print("CompileOnly: compileonly ");
1071 tom->print();
1072 }
1073
1074 className = NULL__null;
1075 methodName = NULL__null;
1076 }
1077
1078 line = *line == '\0' ? line : line + 1;
1079 }
1080}
1081
1082enum CompileCommand CompilerOracle::string_to_option(const char* name) {
1083 int bytes_read = 0;
1084 char errorbuf[1024] = {0};
1085 return match_option_name(name, &bytes_read, errorbuf, sizeof(errorbuf));
1086}

/home/daniel/Projects/java/jdk/src/hotspot/share/classfile/symbolTable.hpp

1/*
2 * Copyright (c) 1997, 2021, 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#ifndef SHARE_CLASSFILE_SYMBOLTABLE_HPP
26#define SHARE_CLASSFILE_SYMBOLTABLE_HPP
27
28#include "memory/allocation.hpp"
29#include "memory/padded.hpp"
30#include "oops/symbol.hpp"
31#include "utilities/tableStatistics.hpp"
32
33class JavaThread;
34template <typename T> class GrowableArray;
35
36// TempNewSymbol acts as a handle class in a handle/body idiom and is
37// responsible for proper resource management of the body (which is a Symbol*).
38// The body is resource managed by a reference counting scheme.
39// TempNewSymbol can therefore be used to properly hold a newly created or referenced
40// Symbol* temporarily in scope.
41//
42// Routines in SymbolTable will initialize the reference count of a Symbol* before
43// it becomes "managed" by TempNewSymbol instances. As a handle class, TempNewSymbol
44// needs to maintain proper reference counting in context of copy semantics.
45//
46// In SymbolTable, new_symbol() will create a Symbol* if not already in the
47// symbol table and add to the symbol's reference count.
48// probe() and lookup_only() will increment the refcount if symbol is found.
49class TempNewSymbol : public StackObj {
50 Symbol* _temp;
51
52public:
53 TempNewSymbol() : _temp(NULL__null) {}
54
55 // Conversion from a Symbol* to a TempNewSymbol.
56 // Does not increment the current reference count.
57 TempNewSymbol(Symbol *s) : _temp(s) {}
58
59 // Copy constructor increments reference count.
60 TempNewSymbol(const TempNewSymbol& rhs) : _temp(rhs._temp) {
61 if (_temp != NULL__null) {
62 _temp->increment_refcount();
63 }
64 }
65
66 // Assignment operator uses a c++ trick called copy and swap idiom.
67 // rhs is passed by value so within the scope of this method it is a copy.
68 // At method exit it contains the former value of _temp, triggering the correct refcount
69 // decrement upon destruction.
70 void operator=(TempNewSymbol rhs) {
71 Symbol* tmp = rhs._temp;
72 rhs._temp = _temp;
73 _temp = tmp;
74 }
75
76 // Decrement reference counter so it can go away if it's unused
77 ~TempNewSymbol() {
78 if (_temp != NULL__null) {
79 _temp->decrement_refcount();
80 }
81 }
82
83 // Symbol* conversion operators
84 Symbol* operator -> () const { return _temp; }
85 bool operator == (Symbol* o) const { return _temp == o; }
86 operator Symbol*() { return _temp; }
87};
88
89class CompactHashtableWriter;
90class SerializeClosure;
91
92class SymbolTableConfig;
93class SymbolTableCreateEntry;
94
95class constantPoolHandle;
96class SymbolClosure;
97
98class SymbolTable : public AllStatic {
99 friend class VMStructs;
100 friend class Symbol;
101 friend class ClassFileParser;
102 friend class SymbolTableConfig;
103 friend class SymbolTableCreateEntry;
104
105 private:
106 static volatile bool _has_work;
107
108 // Set if one bucket is out of balance due to hash algorithm deficiency
109 static volatile bool _needs_rehashing;
110
111 static void delete_symbol(Symbol* sym);
112 static void grow(JavaThread* jt);
113 static void clean_dead_entries(JavaThread* jt);
114
115 static double get_load_factor();
116
117 static void check_concurrent_work();
118
119 static void item_added();
120 static void item_removed();
121
122 // For cleaning
123 static void reset_has_items_to_clean();
124 static void mark_has_items_to_clean();
125 static bool has_items_to_clean();
126
127 static Symbol* allocate_symbol(const char* name, int len, bool c_heap); // Assumes no characters larger than 0x7F
128 static Symbol* do_lookup(const char* name, int len, uintx hash);
129 static Symbol* do_add_if_needed(const char* name, int len, uintx hash, bool heap);
130
131 // lookup only, won't add. Also calculate hash. Used by the ClassfileParser.
132 static Symbol* lookup_only(const char* name, int len, unsigned int& hash);
133 static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
134
135 // Adding elements
136 static void new_symbols(ClassLoaderData* loader_data,
137 const constantPoolHandle& cp, int names_count,
138 const char** name, int* lengths,
139 int* cp_indices, unsigned int* hashValues);
140
141 static Symbol* lookup_shared(const char* name, int len, unsigned int hash) NOT_CDS_RETURN_(NULL);
142 static Symbol* lookup_dynamic(const char* name, int len, unsigned int hash);
143 static Symbol* lookup_common(const char* name, int len, unsigned int hash);
144
145 // Arena for permanent symbols (null class loader) that are never unloaded
146 static Arena* _arena;
147 static Arena* arena() { return _arena; } // called for statistics
148
149 static void print_table_statistics(outputStream* st, const char* table_name);
150
151 static void try_rehash_table();
152 static bool do_rehash();
153
154public:
155 // The symbol table
156 static size_t table_size();
157 static TableStatistics get_table_statistics();
158
159 enum {
160 symbol_alloc_batch_size = 8,
161 // Pick initial size based on java -version size measurements
162 symbol_alloc_arena_size = 360*K // TODO (revisit)
163 };
164
165 static void create_table();
166
167 static void do_concurrent_work(JavaThread* jt);
168 static bool has_work() { return _has_work; }
169 static void trigger_cleanup();
170
171 // Probing
172 // Needed for preloading classes in signatures when compiling.
173 // Returns the symbol is already present in symbol table, otherwise
174 // NULL. NO ALLOCATION IS GUARANTEED!
175 static Symbol* probe(const char* name, int len) {
176 unsigned int ignore_hash;
177 return lookup_only(name, len, ignore_hash);
178 }
179 static Symbol* probe_unicode(const jchar* name, int len) {
180 unsigned int ignore_hash;
181 return lookup_only_unicode(name, len, ignore_hash);
182 }
183
184 // Symbol lookup and create if not found.
185 // jchar (UTF16) version of lookup
186 static Symbol* new_symbol(const jchar* name, int len);
187 // char (UTF8) versions
188 static Symbol* new_symbol(const Symbol* sym, int begin, int end);
189 static Symbol* new_symbol(const char* utf8_buffer, int length);
190 static Symbol* new_symbol(const char* name) {
191 return new_symbol(name, (int)strlen(name));
18
Null pointer passed to 1st parameter expecting 'nonnull'
192 }
193
194 // Create a symbol in the arena for symbols that are not deleted
195 static Symbol* new_permanent_symbol(const char* name);
196
197 // Rehash the string table if it gets out of balance
198 static void rehash_table();
199 static bool needs_rehashing() { return _needs_rehashing; }
200 static inline void update_needs_rehash(bool rehash) {
201 if (rehash) {
202 _needs_rehashing = true;
203 }
204 }
205
206 // Heap dumper and CDS
207 static void symbols_do(SymbolClosure *cl);
208
209 // Sharing
210 static void shared_symbols_do(SymbolClosure *cl); // no safepoint iteration.
211private:
212 static void copy_shared_symbol_table(GrowableArray<Symbol*>* symbols,
213 CompactHashtableWriter* ch_table);
214public:
215 static size_t estimate_size_for_archive() NOT_CDS_RETURN_(0);
216 static void write_to_archive(GrowableArray<Symbol*>* symbols) NOT_CDS_RETURN;
217 static void serialize_shared_table_header(SerializeClosure* soc,
218 bool is_static_archive = true) NOT_CDS_RETURN;
219
220 // Jcmd
221 static void dump(outputStream* st, bool verbose=false);
222 // Debugging
223 static void verify();
224
225 // Histogram
226 static void print_histogram() PRODUCT_RETURN;
227};
228
229#endif // SHARE_CLASSFILE_SYMBOLTABLE_HPP