Projects
openEuler:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:0017-8054889-Compiler-team-s-i...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0017-8054889-Compiler-team-s-implementation-task.patch of Package openjdk-1.8.0
Date: Tue, 6 Jun 2023 01:47:43 +0000 Subject: [PATCH 17/59] 8054889: Compiler team's implementation task Bug url: https://bugs.openjdk.org/browse/JDK-8054889 --- hotspot/src/share/vm/ci/ciEnv.cpp | 2 +- hotspot/src/share/vm/code/codeCache.cpp | 20 ++ hotspot/src/share/vm/code/codeCache.hpp | 4 + .../src/share/vm/compiler/compileBroker.cpp | 78 +++---- .../src/share/vm/compiler/compileBroker.hpp | 24 +-- hotspot/src/share/vm/runtime/globals.hpp | 2 +- .../src/share/vm/runtime/vm_operations.cpp | 12 ++ .../src/share/vm/runtime/vm_operations.hpp | 34 +++ .../share/vm/services/diagnosticCommand.cpp | 19 ++ .../share/vm/services/diagnosticCommand.hpp | 64 ++++++ .../serviceability/dcmd/CodeCacheTest.java | 139 +++++++++++++ .../serviceability/dcmd/CodelistTest.java | 97 +++++++++ .../dcmd/CompilerQueueTest.java | 108 ++++++++++ .../dcmd/MethodIdentifierParser.java | 196 ++++++++++++++++++ 14 files changed, 747 insertions(+), 52 deletions(-) create mode 100644 hotspot/test/serviceability/dcmd/CodeCacheTest.java create mode 100644 hotspot/test/serviceability/dcmd/CodelistTest.java create mode 100644 hotspot/test/serviceability/dcmd/CompilerQueueTest.java create mode 100644 hotspot/test/serviceability/dcmd/MethodIdentifierParser.java diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index e536c19d6..a27ca3254 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -952,7 +952,7 @@ void ciEnv::validate_compile_task_dependencies(ciMethod* target) { #ifdef ASSERT if (!counter_changed && !PrintCompilation) { // Print out the compile task that failed - _task->print_line(); + _task->print_tty(); } #endif assert(counter_changed, "failed dependencies, but counter didn't change"); diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index d0ab4f194..8df29d608 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -263,6 +263,7 @@ void CodeCache::flush() { #define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) ) #define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var))) #define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var))) +#define FOR_ALL_NMETHODS(var) for (nmethod *var = first_nmethod(); var != NULL; var = next_nmethod(var)) bool CodeCache::contains(void *p) { @@ -1007,6 +1008,25 @@ void CodeCache::print_summary(outputStream* st, bool detailed) { } } +void CodeCache::print_codelist(outputStream* st) { + assert_locked_or_safepoint(CodeCache_lock); + + FOR_ALL_NMETHODS(p) { + ResourceMark rm; + char *method_name = p->method()->name_and_sig_as_C_string(); + st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]", + p->compile_id(), p->comp_level(), method_name, (intptr_t)p->header_begin(), + (intptr_t)p->code_begin(), (intptr_t)p->code_end()); + } +} + +void CodeCache::print_layout(outputStream* st) { + assert_locked_or_safepoint(CodeCache_lock); + ResourceMark rm; + + print_summary(st, true); +} + void CodeCache::log_state(outputStream* st) { st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'", diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 415f67750..ab1417b19 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -159,6 +159,10 @@ class CodeCache : AllStatic { static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); + // Dcmd (Diagnostic commands) + static void print_codelist(outputStream* st); + static void print_layout(outputStream* st); + // The full limits of the codeCache static address low_bound() { return (address) _heap->low_boundary(); } static address high_bound() { return (address) _heap->high_boundary(); } diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 79636258a..63f7bde8f 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -193,7 +193,7 @@ class CompilationLog : public StringEventLog { StringLogMessage lm; stringStream sstr = lm.stream(); // msg.time_stamp().update_to(tty->time_stamp().ticks()); - task->print_compilation(&sstr, NULL, true); + task->print_compilation(&sstr, NULL, true, false); log(thread, "%s", (const char*)lm); } @@ -355,7 +355,6 @@ void CompileTask::set_code(nmethod* nm) { if (nm == NULL) _code_handle = NULL; // drop the handle also } - void CompileTask::mark_on_stack() { // Mark these methods as something redefine classes cannot remove. _method->set_on_stack(true); @@ -364,18 +363,6 @@ void CompileTask::mark_on_stack() { } } -// ------------------------------------------------------------------ -// CompileTask::print -void CompileTask::print() { - tty->print("<CompileTask compile_id=%d ", _compile_id); - tty->print("method="); - _method->print_name(tty); - tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>", - _osr_bci, bool_to_str(_is_blocking), - bool_to_str(_is_complete), bool_to_str(_is_success)); -} - - // ------------------------------------------------------------------ // CompileTask::print_line_on_error // @@ -394,11 +381,11 @@ void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { // ------------------------------------------------------------------ // CompileTask::print_line -void CompileTask::print_line() { +void CompileTask::print_tty() { ttyLocker ttyl; // keep the following output all in one block // print compiler name if requested if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level())); - print_compilation(); + print_compilation(tty); } @@ -406,7 +393,7 @@ void CompileTask::print_line() { // CompileTask::print_compilation_impl void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, bool is_osr_method, int osr_bci, bool is_blocking, - const char* msg, bool short_form) { + const char* msg, bool short_form, bool cr) { if (!short_form) { st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp } @@ -455,7 +442,7 @@ void CompileTask::print_compilation_impl(outputStream* st, Method* method, int c if (msg != NULL) { st->print(" %s", msg); } - if (!short_form) { + if (cr) { st->cr(); } } @@ -521,9 +508,9 @@ void CompileTask::print_inline_indent(int inline_level, outputStream* st) { // ------------------------------------------------------------------ // CompileTask::print_compilation -void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) { +void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) { bool is_osr_method = osr_bci() != InvocationEntryBci; - print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form); + print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr); } // ------------------------------------------------------------------ @@ -649,7 +636,9 @@ void CompileQueue::add(CompileTask* task) { // Mark the method as being in the compile queue. task->method()->set_queued_for_compilation(); - NOT_PRODUCT(print();) + if (CIPrintCompileQueue) { + print_tty(); + } if (LogCompilation && xtty != NULL) { task->log_task_queued(); @@ -816,24 +805,39 @@ void CompileQueue::mark_on_stack() { } } -#ifndef PRODUCT -/** - * Print entire compilation queue. - */ -void CompileQueue::print() { - if (CIPrintCompileQueue) { - ttyLocker ttyl; - tty->print_cr("Contents of %s", name()); - tty->print_cr("----------------------"); - CompileTask* task = _first; +CompileQueue* CompileBroker::compile_queue(int comp_level) { + if (is_c2_compile(comp_level)) return _c2_compile_queue; + if (is_c1_compile(comp_level)) return _c1_compile_queue; + return NULL; +} + + +void CompileBroker::print_compile_queues(outputStream* st) { + _c1_compile_queue->print(st); + _c2_compile_queue->print(st); +} + + +void CompileQueue::print(outputStream* st) { + assert_locked_or_safepoint(lock()); + st->print_cr("Contents of %s", name()); + st->print_cr("----------------------------"); + CompileTask* task = _first; + if (task == NULL) { + st->print_cr("Empty");; + } else { while (task != NULL) { - task->print_line(); + task->print_compilation(st, NULL, true, true); task = task->next(); } - tty->print_cr("----------------------"); } + st->print_cr("----------------------------"); +} + +void CompileQueue::print_tty() { + ttyLocker ttyl; + print(tty); } -#endif // PRODUCT CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) { @@ -1096,11 +1100,11 @@ void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler #endif // !ZERO && !SHARK // Initialize the compilation queue if (c2_compiler_count > 0) { - _c2_compile_queue = new CompileQueue("C2 CompileQueue", MethodCompileQueue_lock); + _c2_compile_queue = new CompileQueue("C2 compile queue", MethodCompileQueue_lock); _compilers[1]->set_num_compiler_threads(c2_compiler_count); } if (c1_compiler_count > 0) { - _c1_compile_queue = new CompileQueue("C1 CompileQueue", MethodCompileQueue_lock); + _c1_compile_queue = new CompileQueue("C1 compile queue", MethodCompileQueue_lock); _compilers[0]->set_num_compiler_threads(c1_compiler_count); } @@ -1927,7 +1931,7 @@ static void post_compilation_event(EventCompilation* event, CompileTask* task) { void CompileBroker::invoke_compiler_on_method(CompileTask* task) { if (PrintCompilation) { ResourceMark rm; - task->print_line(); + task->print_tty(); } elapsedTimer time; diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index 96d5e816b..a5bd806f6 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -111,14 +111,14 @@ class CompileTask : public CHeapObj<mtCompiler> { private: static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false, - const char* msg = NULL, bool short_form = false); + const char* msg = NULL, bool short_form = false, bool cr = true); public: - void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false); - static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) { + void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true); + static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) { print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, - msg, short_form); + msg, short_form, cr); } static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL); @@ -131,8 +131,7 @@ public: static void print_inline_indent(int inline_level, outputStream* st = tty); - void print(); - void print_line(); + void print_tty(); void print_line_on_error(outputStream* st, char* buf, int buflen); void log_task(xmlStream* log); @@ -235,7 +234,8 @@ class CompileQueue : public CHeapObj<mtCompiler> { // Redefine Classes support void mark_on_stack(); void free_all(); - NOT_PRODUCT (void print();) + void print_tty(); + void print(outputStream* st = tty); ~CompileQueue() { assert (is_empty(), " Compile Queue must be empty"); @@ -337,7 +337,7 @@ class CompileBroker: AllStatic { static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS); static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level); - static bool is_compile_blocking (); + static bool is_compile_blocking(); static void preload_classes (methodHandle method, TRAPS); static CompileTask* create_compile_task(CompileQueue* queue, @@ -365,11 +365,8 @@ class CompileBroker: AllStatic { int hot_count, const char* comment, Thread* thread); - static CompileQueue* compile_queue(int comp_level) { - if (is_c2_compile(comp_level)) return _c2_compile_queue; - if (is_c1_compile(comp_level)) return _c1_compile_queue; - return NULL; - } + + static CompileQueue* compile_queue(int comp_level); static bool init_compiler_runtime(); static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread); @@ -387,6 +384,7 @@ class CompileBroker: AllStatic { static bool compilation_is_complete(methodHandle method, int osr_bci, int comp_level); static bool compilation_is_in_queue(methodHandle method); + static void print_compile_queues(outputStream* st); static int queue_size(int comp_level) { CompileQueue *q = compile_queue(comp_level); return q != NULL ? q->size() : 0; diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 3b2776ce5..ac9165031 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2581,7 +2581,7 @@ class CommandLineFlags { develop(bool, CIPrintCompilerName, false, \ "when CIPrint is active, print the name of the active compiler") \ \ - develop(bool, CIPrintCompileQueue, false, \ + diagnostic(bool, CIPrintCompileQueue, false, \ "display the contents of the compile queue whenever a " \ "compilation is enqueued") \ \ diff --git a/hotspot/src/share/vm/runtime/vm_operations.cpp b/hotspot/src/share/vm/runtime/vm_operations.cpp index 03c424905..04e55cd73 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.cpp +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp @@ -476,3 +476,15 @@ void VM_Exit::wait_if_vm_exited() { ShouldNotReachHere(); } } + +void VM_PrintCompileQueue::doit() { + CompileBroker::print_compile_queues(_out); +} + +void VM_PrintCodeList::doit() { + CodeCache::print_codelist(_out); +} + +void VM_PrintCodeCache::doit() { + CodeCache::print_layout(_out); +} diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index baf604264..19463b137 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -102,6 +102,9 @@ template(JFROldObject) \ template(PrintClasses) \ template(PrintMetadata) \ + template(PrintCompileQueue) \ + template(PrintCodeList) \ + template(PrintCodeCache) \ class VM_Operation: public CHeapObj<mtInternal> { public: @@ -434,4 +437,35 @@ class VM_RotateGCLog: public VM_Operation { void doit() { gclog_or_tty->rotate_log(true, _out); } }; +class VM_PrintCompileQueue: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCompileQueue(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCompileQueue; } + void doit(); +}; + +class VM_PrintCodeList: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCodeList(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCodeList; } + void doit(); +}; + +class VM_PrintCodeCache: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCodeCache(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCodeCache; } + void doit(); +}; + + #endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index fb8e293e3..e37ba3cc8 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -73,6 +73,9 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RotateGCLogDCmd>(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderStatsDCmd>(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassLoaderHierarchyDCmd>(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false)); #ifdef LINUX DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TrimCLibcHeapDCmd>(full_export, true, false)); #endif // LINUX @@ -814,3 +817,19 @@ void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) { output()->print_cr("Target VM does not support GC log file rotation."); } } + +void CompileQueueDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCompileQueue printCompileQueueOp(output()); + VMThread::execute(&printCompileQueueOp); +} + +void CodeListDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCodeList printCodeListOp(output()); + VMThread::execute(&printCodeListOp); +} + +void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCodeCache printCodeCacheOp(output()); + VMThread::execute(&printCodeCacheOp); +} + diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 87bff52fe..65c04571b 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -509,4 +509,68 @@ public: virtual void execute(DCmdSource source, TRAPS); }; +class CompileQueueDCmd : public DCmd { +public: + CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.queue"; + } + static const char* description() { + return "Print methods queued for compilation."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + +class CodeListDCmd : public DCmd { +public: + CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.codelist"; + } + static const char* description() { + return "Print all compiled methods in code cache."; + } + static const char* impact() { + return "Medium"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + + +class CodeCacheDCmd : public DCmd { +public: + CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.codecache"; + } + static const char* description() { + return "Print code cache layout and bounds."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP diff --git a/hotspot/test/serviceability/dcmd/CodeCacheTest.java b/hotspot/test/serviceability/dcmd/CodeCacheTest.java new file mode 100644 index 000000000..aaedb210f --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CodeCacheTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CodeCacheTest + * @bug 8054889 + * @build DcmdUtil CodeCacheTest + * @run main CodeCacheTest + * @summary Test of diagnostic command Compiler.codecache + */ + +import java.io.BufferedReader; +import java.io.StringReader; +import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CodeCacheTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.codecache and then parses the output, + * making sure that all number look ok + * + * + * Expected output: + * + * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb + * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000] + * total_blobs=575 nmethods=69 adapters=423 + * compilation: enabled + */ + + static Pattern line1 = Pattern.compile("CodeCache: size=(\\p{Digit}*)Kb used=(\\p{Digit}*)Kb max_used=(\\p{Digit}*)Kb free=(\\p{Digit}*)Kb"); + static Pattern line2 = Pattern.compile(" bounds \\[0x(\\p{XDigit}*), 0x(\\p{XDigit}*), 0x(\\p{XDigit}*)\\]"); + static Pattern line3 = Pattern.compile(" total_blobs=(\\p{Digit}*) nmethods=(\\p{Digit}*) adapters=(\\p{Digit}*)"); + static Pattern line4 = Pattern.compile(" compilation: (\\w*)"); + + public static void main(String arg[]) throws Exception { + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.codecache"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + // Validate first line + String line; + line = r.readLine(); + Matcher m = line1.matcher(line); + if (m.matches()) { + for(int i = 1; i <= 4; i++) { + int val = Integer.parseInt(m.group(i)); + if (val < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } + } else { + throw new Exception("Regexp 1 failed"); + } + + // Validate second line + line = r.readLine(); + m = line2.matcher(line); + if (m.matches()) { + long start = Long.parseLong(m.group(1), 16); + if (start < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + long mark = Long.parseLong(m.group(2), 16); + if (mark < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + long top = Long.parseLong(m.group(3), 16); + if (top < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (start > mark) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (mark > top) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } else { + throw new Exception("Regexp 2 failed line: " + line); + } + + // Validate third line + line = r.readLine(); + m = line3.matcher(line); + if (m.matches()) { + int blobs = Integer.parseInt(m.group(1)); + if (blobs <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + int nmethods = Integer.parseInt(m.group(2)); + if (nmethods <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + int adapters = Integer.parseInt(m.group(3)); + if (adapters <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (blobs < (nmethods + adapters)) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } else { + throw new Exception("Regexp 3 failed"); + } + + // Validate fourth line + line = r.readLine(); + m = line4.matcher(line); + if (m.matches()) { + if (!m.group(1).equals("enabled")) { + throw new Exception("Invalid message: '" + m.group(1) + "'"); + } + } else { + throw new Exception("Regexp 4 failed"); + } + } +} \ No newline at end of file diff --git a/hotspot/test/serviceability/dcmd/CodelistTest.java b/hotspot/test/serviceability/dcmd/CodelistTest.java new file mode 100644 index 000000000..151a9ccfb --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CodelistTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CodelistTest + * @bug 8054889 + * @build DcmdUtil MethodIdentifierParser CodelistTest + * @run main CodelistTest + * @summary Test of diagnostic command Compiler.codelist + */ + +import java.io.BufferedReader; +import java.io.StringReader; +import java.lang.reflect.Method; + +public class CodelistTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.codelist and then parses the output, + * making sure that the first methods in the list is valid by reflection. + * + * Output example: + * + * 6 0 java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V [0x00007f7b49200910, 0x00007f7b49200aa0 - 0x00007f7b49200d30] + * 2 3 java.lang.String.indexOf(II)I [0x00007f7b49200d90, 0x00007f7b49200f60 - 0x00007f7b49201490] + * 7 3 java.lang.Math.min(II)I [0x00007f7b4922f010, 0x00007f7b4922f180 - 0x00007f7b4922f338] + * 8 3 java.lang.String.equals(Ljava/lang/Object;)Z [0x00007f7b4922fb10, 0x00007f7b4922fd40 - 0x00007f7b49230698] + * 9 3 java.lang.AbstractStringBuilder.ensureCapacityInternal(I)V [0x00007f7b49232010, 0x00007f7b492321a0 - 0x00007f7b49232510] + * 10 1 java.lang.Object.<init>()V [0x00007f7b49233e90, 0x00007f7b49233fe0 - 0x00007f7b49234118] + * + */ + + public static void main(String arg[]) throws Exception { + int ok = 0; + int fail = 0; + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.codelist"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + // Grab a method name from the output + String line; + int count = 0; + + while((line = r.readLine()) != null) { + count++; + + String[] parts = line.split(" "); + // int compileID = Integer.parseInt(parts[0]); + // int compileLevel = Integer.parseInt(parts[1]); + String methodPrintedInLogFormat = parts[2]; + + // skip inits and clinits - they can not be reflected + if (methodPrintedInLogFormat.contains("<init>")) { + continue; + } + if (methodPrintedInLogFormat.contains("<clinit>")) { + continue; + } + + MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat); + Method m; + try { + m = mf.getMethod(); + } catch (NoSuchMethodException e) { + m = null; + } + if (m == null) { + throw new Exception("Test failed"); + } + if (count > 10) { + // Testing 10 entries is enough. Lets not waste time. + break; + } + } + } +} \ No newline at end of file diff --git a/hotspot/test/serviceability/dcmd/CompilerQueueTest.java b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java new file mode 100644 index 000000000..661e7cb49 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CompilerQueueTest + * @bug 8054889 + * @build DcmdUtil CompilerQueueTest + * @run main CompilerQueueTest + * @summary Test of diagnostic command Compiler.queue + */ + +import java.io.BufferedReader; +import java.io.StringReader; + +public class CompilerQueueTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.queue and + * then parses the output, making sure that the output look ok. + * + * + * Output example: + * + * Contents of C1 compile queue + * ---------------------------- + * 73 3 java.lang.AbstractStringBuilder::append (50 bytes) + * 74 1 java.util.TreeMap::size (5 bytes) + * 75 3 java.lang.StringBuilder::append (8 bytes) + * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes) + * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes) + * ---------------------------- + * Contents of C2 compile queue + * ---------------------------- + * Empty + * ---------------------------- + * + **/ + + public static void main(String arg[]) throws Exception { + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.queue"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + String line; + match(r.readLine(), "Contents of C1 compile queue"); + match(r.readLine(), "----------------------------"); + String str = r.readLine(); + if (!str.equals("Empty")) { + while (str.charAt(0) != '-') { + validateMethodLine(str); + str = r.readLine(); + } + } else { + str = r.readLine(); + } + + match(str, "----------------------------"); + match(r.readLine(), "Contents of C2 compile queue"); + match(r.readLine(), "----------------------------"); + str = r.readLine(); + if (!str.equals("Empty")) { + while (str.charAt(0) != '-') { + validateMethodLine(str); + str = r.readLine(); + } + } else { + str = r.readLine(); + } + match(str, "----------------------------"); + } + + private static void validateMethodLine(String str) throws Exception { + String name = str.substring(19); + int sep = name.indexOf("::"); + try { + Class.forName(name.substring(0, sep)); + } catch (ClassNotFoundException e) { + throw new Exception("Failed parsing dcmd queue"); + } + } + + public static void match(String line, String str) throws Exception { + if (!line.equals(str)) { + throw new Exception("String equals: " + line + ", " + str); + } + } +} \ No newline at end of file diff --git a/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java new file mode 100644 index 000000000..0ad5d59e7 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Method; +import java.util.ArrayList; + +public class MethodIdentifierParser { + + private String logString; + private String className; + private String methodName; + private String methodDescriptor; + + /** + * This is a utility class for parsing the log entries for a method. It supplies + * a few select methods for reflecting the class and method from that information. + * + * Example log entries: + * "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;" + */ + + public MethodIdentifierParser(String logString) { + this.logString = logString; + + int i = logString.lastIndexOf("."); // find start of method name + className = logString.substring(0, i); // classname is everything before + int i2 = logString.indexOf("("); // Signature starts with an '(' + methodName = logString.substring(i+1, i2); + methodDescriptor = logString.substring(i2, logString.length()); + + // Add sanity check for extracted fields + } + + public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception { + try { + return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray()); + } catch (UnexpectedTokenException e) { + throw new Exception("Parse failed"); + } + } + + public Class<?>[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException { + ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor); + Class<?> paramType; + ArrayList<Class<?>> list = new ArrayList<Class<?>>(); + while ((paramType = s.nextParamType()) != null) { + list.add(paramType); + } + if (list.size() > 0) { + return list.toArray(new Class<?>[list.size()]); + } else { + return null; + } + } + + class ParameterDecriptorIterator { + + // This class uses charAt() indexing for startMark and i + // That is when i points to the last char it can be retrieved with + // charAt(i). Including the last char for a subString requires + // substring(startMark, i+1); + + private String methodDescriptor; + private int startMark; + + public ParameterDecriptorIterator(String signature) { + this.methodDescriptor = signature; + this.startMark = 0; + if (signature.charAt(0) == '(') { + this.startMark = 1; + } + } + + public Class<?> nextParamType() throws UnexpectedTokenException { + int i = startMark; + while (methodDescriptor.length() > i) { + switch (methodDescriptor.charAt(i)) { + case 'C': + case 'B': + case 'I': + case 'J': + case 'Z': + case 'F': + case 'D': + case 'S': + // Primitive class case, but we may have gotten here with [ as first token + break; + case 'L': + // Internal class name suffixed by ';' + while (methodDescriptor.charAt(i) != ';') { + i++; + } + break; + case '[': + i++; // arrays -> do another pass + continue; + case ')': + return null; // end found + case 'V': + case ';': + default: + throw new UnexpectedTokenException(methodDescriptor, i); + } + break; + } + if (i == startMark) { + // Single char -> primitive class case + startMark++; // Update for next iteration + switch (methodDescriptor.charAt(i)) { + case 'C': + return char.class; + case 'B': + return byte.class; + case 'I': + return int.class; + case 'J': + return long.class; + case 'F': + return float.class; + case 'D': + return double.class; + case 'S': + return short.class; + case 'Z': + return boolean.class; + default: + throw new UnexpectedTokenException(methodDescriptor, i); + } + } else { + // Multi char case + String nextParam; + if (methodDescriptor.charAt(startMark) == 'L') { + // When reflecting a class the leading 'L' and trailing';' must be removed. + // (When reflecting an array of classes, they must remain...) + nextParam = methodDescriptor.substring(startMark+1, i); + } else { + // Any kind of array - simple case, use whole descriptor when reflecting. + nextParam = methodDescriptor.substring(startMark, i+1); + } + startMark = ++i; // Update for next iteration + try { + // The parameter descriptor uses JVM internal class identifier with '/' as + // package separator, but Class.forName expects '.'. + nextParam = nextParam.replace('/', '.'); + return Class.forName(nextParam); + } catch (ClassNotFoundException e) { + System.out.println("Class not Found: " + nextParam); + return null; + } + } + } + } + + class UnexpectedTokenException extends Exception { + String descriptor; + int i; + public UnexpectedTokenException(String descriptor, int i) { + this.descriptor = descriptor; + this.i = i; + } + + @Override + public String toString() { + return "Unexpected token at: " + i + " in signature: " + descriptor; + } + + private static final long serialVersionUID = 1L; + } + + public void debugPrint() { + System.out.println("mlf in: " + logString); + System.out.println("mlf class: " + className); + System.out.println("mlf method: " + methodName); + System.out.println("mlf methodDescriptor: " + methodDescriptor); + } +} \ No newline at end of file -- 2.22.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2