# HG changeset patch # User iveresov # Date 1412278263 25200 # Node ID 4c76a5021fe068ec47c886f04135986ba58db645 # Parent 03986a6d0e62b836c77b39fabed7cc816ba900f1# Parent 981df0f8be4eb63b118802412ef656caf7b8072a Merge diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/ci/ciEnv.cpp --- a/hotspot/src/share/vm/ci/ciEnv.cpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciEnv.cpp Thu Oct 02 12:31:03 2014 -0700 @@ -580,7 +580,12 @@ oop obj = cpool->resolved_references()->obj_at(cache_index); if (obj != NULL) { ciObject* ciobj = get_object(obj); - return ciConstant(T_OBJECT, ciobj); + if (ciobj->is_array()) { + return ciConstant(T_ARRAY, ciobj); + } else { + assert(ciobj->is_instance(), "should be an instance"); + return ciConstant(T_OBJECT, ciobj); + } } index = cpool->object_to_cp_index(cache_index); } @@ -607,8 +612,12 @@ } } ciObject* constant = get_object(string); - assert (constant->is_instance(), "must be an instance, or not? "); - return ciConstant(T_OBJECT, constant); + if (constant->is_array()) { + return ciConstant(T_ARRAY, constant); + } else { + assert (constant->is_instance(), "must be an instance, or not? "); + return ciConstant(T_OBJECT, constant); + } } else if (tag.is_klass() || tag.is_unresolved_klass()) { // 4881222: allow ldc to take a class type ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor); diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/ci/ciTypeFlow.cpp --- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp Thu Oct 02 12:31:03 2014 -0700 @@ -730,7 +730,7 @@ if (obj->is_null_object()) { push_null(); } else { - assert(obj->is_instance(), "must be java_mirror of klass"); + assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass"); push_object(obj->klass()); } } else { diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/code/codeCache.cpp Thu Oct 02 12:31:03 2014 -0700 @@ -347,8 +347,8 @@ CodeBlob* cb = NULL; // Get CodeHeap for the given CodeBlobType - CodeHeap* heap = get_code_heap(SegmentedCodeCache ? code_blob_type : CodeBlobType::All); - assert (heap != NULL, "heap is null"); + CodeHeap* heap = get_code_heap(code_blob_type); + assert(heap != NULL, "heap is null"); while (true) { cb = (CodeBlob*)heap->allocate(size, is_critical); @@ -734,6 +734,11 @@ return cap; } +size_t CodeCache::unallocated_capacity(int code_blob_type) { + CodeHeap* heap = get_code_heap(code_blob_type); + return (heap != NULL) ? heap->unallocated_capacity() : 0; +} + size_t CodeCache::unallocated_capacity() { size_t unallocated_cap = 0; FOR_ALL_HEAPS(heap) { @@ -1000,7 +1005,8 @@ // A CodeHeap is full. Print out warning and report event. void CodeCache::report_codemem_full(int code_blob_type, bool print) { // Get nmethod heap for the given CodeBlobType and build CodeCacheFull event - CodeHeap* heap = get_code_heap(SegmentedCodeCache ? code_blob_type : CodeBlobType::All); + CodeHeap* heap = get_code_heap(code_blob_type); + assert(heap != NULL, "heap is null"); if (!heap->was_full() || print) { // Not yet reported for this heap, report diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/code/codeCache.hpp --- a/hotspot/src/share/vm/code/codeCache.hpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/code/codeCache.hpp Thu Oct 02 12:31:03 2014 -0700 @@ -100,7 +100,7 @@ static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type); static CodeHeap* get_code_heap(CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType - static bool heap_available(int code_blob_type); // Returns true if a CodeHeap for the given CodeBlobType is available + static bool heap_available(int code_blob_type); // Returns true if an own CodeHeap for the given CodeBlobType is available static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps // Iteration @@ -175,11 +175,9 @@ static address high_bound() { return _high_bound; } // Profiling - static size_t capacity(int code_blob_type) { return heap_available(code_blob_type) ? get_code_heap(code_blob_type)->capacity() : 0; } static size_t capacity(); - static size_t unallocated_capacity(int code_blob_type) { return heap_available(code_blob_type) ? get_code_heap(code_blob_type)->unallocated_capacity() : 0; } + static size_t unallocated_capacity(int code_blob_type); static size_t unallocated_capacity(); - static size_t max_capacity(int code_blob_type) { return heap_available(code_blob_type) ? get_code_heap(code_blob_type)->max_capacity() : 0; } static size_t max_capacity(); static bool is_full(int* code_blob_type); diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/memory/heap.hpp --- a/hotspot/src/share/vm/memory/heap.hpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/memory/heap.hpp Thu Oct 02 12:31:03 2014 -0700 @@ -171,7 +171,8 @@ size_t unallocated_capacity() const { return max_capacity() - allocated_capacity(); } // Returns true if the CodeHeap contains CodeBlobs of the given type - bool accepts(int code_blob_type) const { return (_code_blob_type == code_blob_type); } + bool accepts(int code_blob_type) const { return (_code_blob_type == CodeBlobType::All) || + (_code_blob_type == code_blob_type); } int code_blob_type() const { return _code_blob_type; } // Debugging / Profiling diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Thu Oct 02 12:31:03 2014 -0700 @@ -879,7 +879,7 @@ call_does_dispatch, vtable_index); // out-parameters // We lack profiling at this call but type speculation may // provide us with a type - speculative_receiver_type = receiver_type->speculative_type(); + speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL; } CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Wed Oct 01 15:24:34 2014 -0700 +++ b/hotspot/test/TEST.groups Thu Oct 02 12:31:03 2014 -0700 @@ -489,6 +489,7 @@ compiler/uncommontrap/TestStackBangMonitorOwned.java \ compiler/uncommontrap/TestStackBangRbp.java \ compiler/unsafe/GetUnsafeObjectG1PreBarrier.java + hotspot_compiler_closed = \ closed/compiler/4292742/Test.java \ @@ -583,7 +584,8 @@ sanity/ExecuteInternalVMTests.java hotspot_serviceability = \ - sanity/ExecuteInternalVMTests.java + sanity/ExecuteInternalVMTests.java \ + serviceability/dcmd/compiler hotspot_all = \ :hotspot_compiler_1 \ diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/compiler/jsr292/NullConstantReceiver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jsr292/NullConstantReceiver.java Thu Oct 02 12:31:03 2014 -0700 @@ -0,0 +1,62 @@ +/* + * 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 + * @bug 8059556 + * @run main/othervm -Xbatch NullConstantReceiver + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class NullConstantReceiver { + static final MethodHandle target; + static { + try { + target = MethodHandles.lookup().findVirtual(NullConstantReceiver.class, "test", MethodType.methodType(void.class)); + } catch (ReflectiveOperationException e) { + throw new Error(e); + } + } + + public void test() {} + + static void run() throws Throwable { + target.invokeExact((NullConstantReceiver) null); + } + + public static void main(String[] args) throws Throwable { + for (int i = 0; i<15000; i++) { + try { + run(); + } catch (NullPointerException e) { + // expected + continue; + } + throw new AssertionError("NPE wasn't thrown"); + } + System.out.println("TEST PASSED"); + } +} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/compiler/jsr292/VMAnonymousClasses.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/jsr292/VMAnonymousClasses.java Thu Oct 02 12:31:03 2014 -0700 @@ -0,0 +1,125 @@ +/* + * 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 + * @bug 8058828 + * @run main/bootclasspath -Xbatch VMAnonymousClasses + */ + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import sun.misc.Unsafe; + +import java.lang.invoke.ConstantCallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.lang.invoke.VolatileCallSite; + +public class VMAnonymousClasses { + static final String TEST_METHOD_NAME = "constant"; + + static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + static int getConstantPoolSize(byte[] classFile) { + // The first few bytes: + // u4 magic; + // u2 minor_version; + // u2 major_version; + // u2 constant_pool_count; + return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF); + } + + static void test(Object value) throws ReflectiveOperationException { + System.out.printf("Test: %s", value != null ? value.getClass() : "null"); + + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, "Test", null, "java/lang/Object", null); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, TEST_METHOD_NAME, "()Ljava/lang/Object;", null, null); + + String placeholder = "CONSTANT"; + int index = cw.newConst(placeholder); + mv.visitLdcInsn(placeholder); + mv.visitInsn(Opcodes.ARETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + + byte[] classFile = cw.toByteArray(); + + Object[] cpPatches = new Object[getConstantPoolSize(classFile)]; + cpPatches[index] = value; + + Class test = UNSAFE.defineAnonymousClass(VMAnonymousClasses.class, classFile, cpPatches); + + Object expectedResult = (value != null) ? value : placeholder; + for (int i = 0; i<15000; i++) { + Object result = test.getMethod(TEST_METHOD_NAME).invoke(null); + if (result != expectedResult) { + throw new AssertionError(String.format("Wrong value returned: %s != %s", value, result)); + } + } + System.out.println(" PASSED"); + } + + public static void main(String[] args) throws ReflectiveOperationException { + // Objects + test(new Object()); + test("TEST"); + test(new VMAnonymousClasses()); + test(null); + + // Class + test(String.class); + + // Arrays + test(new boolean[0]); + test(new byte[0]); + test(new char[0]); + test(new short[0]); + test(new int[0]); + test(new long[0]); + test(new float[0]); + test(new double[0]); + test(new Object[0]); + + // Multi-dimensional arrays + test(new byte[0][0]); + test(new Object[0][0]); + + // MethodHandle-related + MethodType mt = MethodType.methodType(void.class, String[].class); + MethodHandle mh = MethodHandles.lookup().findStatic(VMAnonymousClasses.class, "main", mt); + test(mt); + test(mh); + test(new ConstantCallSite(mh)); + test(new MutableCallSite(MethodType.methodType(void.class))); + test(new VolatileCallSite(MethodType.methodType(void.class))); + + System.out.println("TEST PASSED"); + } +} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/CodeCacheTest.java --- a/hotspot/test/serviceability/dcmd/CodeCacheTest.java Wed Oct 01 15:24:34 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,174 +0,0 @@ -/* - * 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/othervm -XX:+SegmentedCodeCache CodeCacheTest - * @run main/othervm -XX:-SegmentedCodeCache 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 numbers look ok - * - * - * Expected output without code cache segmentation: - * - * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb - * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000] - * total_blobs=575 nmethods=69 adapters=423 - * compilation: enabled - * - * Expected output with code cache segmentation (number of segments may change): - * - * CodeHeap 'non-nmethods': size=5696Kb used=2236Kb max_used=2238Kb free=3459Kb - * bounds [0x00007fa0f0ffe000, 0x00007fa0f126e000, 0x00007fa0f158e000] - * CodeHeap 'profiled nmethods': size=120036Kb used=8Kb max_used=8Kb free=120027Kb - * bounds [0x00007fa0f158e000, 0x00007fa0f17fe000, 0x00007fa0f8ac7000] - * CodeHeap 'non-profiled nmethods': size=120036Kb used=2Kb max_used=2Kb free=120034Kb - * bounds [0x00007fa0f8ac7000, 0x00007fa0f8d37000, 0x00007fa100000000] - * total_blobs=486 nmethods=8 adapters=399 - * compilation: enabled - */ - - static Pattern line1 = Pattern.compile("(CodeCache|CodeHeap.*): 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: (.*)"); - - private static boolean getFlagBool(String flag, String where) { - Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where); - if (!m.find()) { - throw new RuntimeException("Could not find value for flag " + flag + " in output string"); - } - return m.group(1).equals("true"); - } - - private static int getFlagInt(String flag, String where) { - Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); - if (!m.find()) { - throw new RuntimeException("Could not find value for flag " + flag + " in output string"); - } - String match = m.group(); - return Integer.parseInt(match.substring(match.lastIndexOf(" ") + 1, match.length())); - } - - public static void main(String arg[]) throws Exception { - // Get number of code cache segments - int segmentsCount = 0; - String flags = DcmdUtil.executeDcmd("VM.flags", "-all"); - if (!getFlagBool("SegmentedCodeCache", flags) || !getFlagBool("UseCompiler", flags)) { - // No segmentation - segmentsCount = 1; - } else if (getFlagBool("TieredCompilation", flags) && getFlagInt("TieredStopAtLevel", flags) > 1) { - // Tiered compilation: use all segments - segmentsCount = 3; - } else { - // No TieredCompilation: only non-nmethod and non-profiled segment - segmentsCount = 2; - } - - // Get output from dcmd (diagnostic command) - String result = DcmdUtil.executeDcmd("Compiler.codecache"); - BufferedReader r = new BufferedReader(new StringReader(result)); - - // Validate code cache segments - String line; - Matcher m; - for (int s = 0; s < segmentsCount; ++s) { - // Validate first line - line = r.readLine(); - m = line1.matcher(line); - if (m.matches()) { - for (int i = 2; i <= 5; 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()) { - String start = m.group(1); - String mark = m.group(2); - String top = m.group(3); - - // Lexical compare of hex numbers to check that they look sane. - if (start.compareTo(mark) > 1) { - throw new Exception("Failed parsing dcmd codecache output"); - } - if (mark.compareTo(top) > 1) { - 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()) { - throw new Exception("Regexp 4 failed"); - } - } -} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/CodelistTest.java --- a/hotspot/test/serviceability/dcmd/CodelistTest.java Wed Oct 01 15:24:34 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * 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.()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("")) { - continue; - } - if (methodPrintedInLogFormat.contains("")) { - 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; - } - } - } -} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/CompilerQueueTest.java --- a/hotspot/test/serviceability/dcmd/CompilerQueueTest.java Wed Oct 01 15:24:34 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * 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); - } - } -} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/MethodIdentifierParser.java --- a/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java Wed Oct 01 15:24:34 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/* - * 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> list = new ArrayList>(); - 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); - } -} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/compiler/CodeCacheTest.java Thu Oct 02 12:31:03 2014 -0700 @@ -0,0 +1,176 @@ +/* + * 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 + * @library .. + * @build DcmdUtil CodeCacheTest + * @run main/othervm -XX:+SegmentedCodeCache CodeCacheTest + * @run main/othervm -XX:-SegmentedCodeCache CodeCacheTest + * @run main/othervm -Xint -XX:+SegmentedCodeCache 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 numbers look ok + * + * + * Expected output without code cache segmentation: + * + * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb + * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000] + * total_blobs=575 nmethods=69 adapters=423 + * compilation: enabled + * + * Expected output with code cache segmentation (number of segments may change): + * + * CodeHeap 'non-nmethods': size=5696Kb used=2236Kb max_used=2238Kb free=3459Kb + * bounds [0x00007fa0f0ffe000, 0x00007fa0f126e000, 0x00007fa0f158e000] + * CodeHeap 'profiled nmethods': size=120036Kb used=8Kb max_used=8Kb free=120027Kb + * bounds [0x00007fa0f158e000, 0x00007fa0f17fe000, 0x00007fa0f8ac7000] + * CodeHeap 'non-profiled nmethods': size=120036Kb used=2Kb max_used=2Kb free=120034Kb + * bounds [0x00007fa0f8ac7000, 0x00007fa0f8d37000, 0x00007fa100000000] + * total_blobs=486 nmethods=8 adapters=399 + * compilation: enabled + */ + + static Pattern line1 = Pattern.compile("(CodeCache|CodeHeap.*): 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: (.*)"); + + private static boolean getFlagBool(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + return m.group(1).equals("true"); + } + + private static int getFlagInt(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?=\\s+\\d+").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + String match = m.group(); + return Integer.parseInt(match.substring(match.lastIndexOf(" ") + 1, match.length())); + } + + public static void main(String arg[]) throws Exception { + // Get number of code cache segments + int segmentsCount = 0; + String flags = DcmdUtil.executeDcmd("VM.flags", "-all"); + if (!getFlagBool("SegmentedCodeCache", flags) || !getFlagBool("UseCompiler", flags)) { + // No segmentation + segmentsCount = 1; + } else if (getFlagBool("TieredCompilation", flags) && getFlagInt("TieredStopAtLevel", flags) > 1) { + // Tiered compilation: use all segments + segmentsCount = 3; + } else { + // No TieredCompilation: only non-nmethod and non-profiled segment + segmentsCount = 2; + } + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.codecache"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + // Validate code cache segments + String line; + Matcher m; + for (int s = 0; s < segmentsCount; ++s) { + // Validate first line + line = r.readLine(); + m = line1.matcher(line); + if (m.matches()) { + for (int i = 2; i <= 5; 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()) { + String start = m.group(1); + String mark = m.group(2); + String top = m.group(3); + + // Lexical compare of hex numbers to check that they look sane. + if (start.compareTo(mark) > 1) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (mark.compareTo(top) > 1) { + 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()) { + throw new Exception("Regexp 4 failed"); + } + } +} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/compiler/CodelistTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java Thu Oct 02 12:31:03 2014 -0700 @@ -0,0 +1,101 @@ +/* + * 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 + * @library .. + * @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.()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, clinits and methodHandles - they can not be reflected + if (methodPrintedInLogFormat.contains("")) { + continue; + } + if (methodPrintedInLogFormat.contains("")) { + continue; + } + if (methodPrintedInLogFormat.contains("MethodHandle")) { + 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 on: " + methodPrintedInLogFormat); + } + if (count > 10) { + // Testing 10 entries is enough. Lets not waste time. + break; + } + } + } +} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Thu Oct 02 12:31:03 2014 -0700 @@ -0,0 +1,107 @@ +/* + * 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 + * @library .. + * @build DcmdUtil CompilerQueueTest + * @run main CompilerQueueTest + * @run main/othervm -Xint 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 str = r.readLine(); + + while (str != null) { + if (str.startsWith("Contents of C")) { + 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,"----------------------------"); + str = r.readLine(); + } else { + throw new Exception("Failed parsing dcmd queue, line: " + str); + } + } + } + + private static void validateMethodLine(String str) throws Exception { + String name = str.substring(19); + int sep = name.indexOf("::"); + if (sep == -1) { + throw new Exception("Failed dcmd queue, didn't find separator :: in: " + name); + } + try { + Class.forName(name.substring(0, sep)); + } catch (ClassNotFoundException e) { + throw new Exception("Failed dcmd queue, Class for name: " + str); + } + } + + public static void match(String line, String str) throws Exception { + if (!line.equals(str)) { + throw new Exception("String equals: " + line + ", " + str); + } + } +} diff -r 03986a6d0e62 -r 4c76a5021fe0 hotspot/test/serviceability/dcmd/compiler/MethodIdentifierParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/serviceability/dcmd/compiler/MethodIdentifierParser.java Thu Oct 02 12:31:03 2014 -0700 @@ -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> list = new ArrayList>(); + 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); + } +}