From 824267a43a2cce8ab8234d9c49f06bc69d04c0d3 Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Fri, 31 Jul 2015 10:33:02 -0700 Subject: [PATCH 01/53] 8132214: [TESTBUG] Create basic shared strings test for CDS archive Created new test Reviewed-by: jiangli, ctornqvi --- .../SharedArchiveFile/BasicJarBuilder.java | 86 +++++++++++++++++++ .../SharedArchiveFile/SharedStrings.java | 79 +++++++++++++++++ .../SharedArchiveFile/SharedStringsWb.java | 49 +++++++++++ 3 files changed, 214 insertions(+) create mode 100644 hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java create mode 100644 hotspot/test/runtime/SharedArchiveFile/SharedStrings.java create mode 100644 hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java diff --git a/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java new file mode 100644 index 00000000000..0bb499590c5 --- /dev/null +++ b/hotspot/test/runtime/SharedArchiveFile/BasicJarBuilder.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015, 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. + */ + +/* + * @summary Simple jar builder + * Input: jarName className1 className2 ... + * do not specify extensions, just the names + * E.g. prot_domain ProtDomainA ProtDomainB + * Output: A jar containing compiled classes, placed in a test classes folder + */ + +import jdk.test.lib.*; + +import java.io.File; +import java.util.ArrayList; +import sun.tools.jar.Main; + +public class BasicJarBuilder { + private static final String classDir = System.getProperty("test.classes"); + + public static void build(String jarName, String ...classNames) + throws Exception { + + createSimpleJar(classDir, classDir + File.separator + jarName + + ".jar", classNames); + } + + private static void createSimpleJar(String jarclassDir, String jarName, + String[] classNames) throws Exception { + ArrayList args = new ArrayList(); + args.add("cf"); + args.add(jarName); + addClassArgs(args, jarclassDir, classNames); + createJar(args); + } + + private static void addClassArgs(ArrayList args, String jarclassDir, + String[] classNames) { + + for (String name : classNames) { + args.add("-C"); + args.add(jarclassDir); + args.add(name + ".class"); + } + } + + private static void createJar(ArrayList args) { + Main jarTool = new Main(System.out, System.err, "jar"); + if (!jarTool.run(args.toArray(new String[1]))) { + throw new RuntimeException("jar operation failed"); + } + } + + // helpers + public static String getTestJar(String jar) { + File dir = new File(System.getProperty("test.classes", ".")); + File jarFile = new File(dir, jar); + if (!jarFile.exists()) { + throw new RuntimeException("Cannot find " + jarFile.getPath()); + } + if (!jarFile.isFile()) { + throw new RuntimeException("Not a regular file: " + jarFile.getPath()); + } + return jarFile.getPath(); + } +} diff --git a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java new file mode 100644 index 00000000000..895f65261fc --- /dev/null +++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, 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 + * @summary Check to make sure that shared strings in the bootstrap CDS archive + * are actually shared + * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows + * @requires (sun.arch.data.model != "32") & (os.family != "windows") + * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) + * @requires (vm.gc=="G1" | vm.gc=="null") + * @library /testlibrary /../../test/lib + * @modules java.base/sun.misc + * java.management + * @build SharedStringsWb SharedStrings BasicJarBuilder + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main SharedStrings + */ + +import jdk.test.lib.*; + +public class SharedStrings { + public static void main(String[] args) throws Exception { + BasicJarBuilder.build("whitebox", "sun/hotspot/WhiteBox"); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./SharedStrings.jsa", + "-XX:+PrintSharedSpaces", + // Needed for bootclasspath match, for CDS to work with WhiteBox API + "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"), + "-Xshare:dump"); + + new OutputAnalyzer(pb.start()) + .shouldContain("Loading classes to share") + .shouldContain("Shared string table stats") + .shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./SharedStrings.jsa", + // these are required modes for shared strings + "-XX:+UseCompressedOops", "-XX:+UseG1GC", + // needed for access to white box test API + "-Xbootclasspath/a:" + BasicJarBuilder.getTestJar("whitebox.jar"), + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-Xshare:on", "-showversion", "SharedStringsWb"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + try { + output.shouldContain("sharing"); + output.shouldHaveExitValue(0); + } catch (RuntimeException e) { + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } +} diff --git a/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java b/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java new file mode 100644 index 00000000000..be5aeab412c --- /dev/null +++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsWb.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, 2015, 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 sun.hotspot.WhiteBox; + +// This class is used by the test SharedStrings.java +// It should be launched in CDS mode +public class SharedStringsWb { + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + + if (wb.areSharedStringsIgnored()) { + System.out.println("Shared strings are ignored, assuming PASS"); + return; + } + + // The string "java" is known to be interened and added to CDS archive + String s = "java"; + String internedS = s.intern(); + + if (wb.isShared(internedS)) { + System.out.println("Found shared string, result: PASS"); + } else { + throw new RuntimeException("String is not shared, result: FAIL"); + } + } +} + + From 82f9578bb38628c207bca6a9ebf9a17897b00697 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 4 Aug 2015 15:16:23 +0200 Subject: [PATCH 02/53] 8085919: OperatingSystemMXBean/TestTotalSwap.java failure : Total Swap Space figures mismatch Reviewed-by: dholmes --- .../OperatingSystemMXBean/TestTotalSwap.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java b/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java index 3bb1c714e60..8d5e7c919ba 100644 --- a/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java +++ b/jdk/test/com/sun/management/OperatingSystemMXBean/TestTotalSwap.java @@ -73,6 +73,8 @@ public class TestTotalSwap { private static final long MAX_SIZE_FOR_PASS = Long.MAX_VALUE; public static void main(String args[]) throws Throwable { + // yocto might ignore the request to report swap size in bytes + boolean swapInKB = mbean.getVersion().contains("yocto"); long expected_swap_size = getSwapSizeFromOs(); @@ -87,10 +89,13 @@ public class TestTotalSwap { if (expected_swap_size > -1) { if (size != expected_swap_size) { - throw new RuntimeException("Expected total swap size : " + - expected_swap_size + - " but getTotalSwapSpaceSize returned: " + - size); + // try the expected size in kiloBytes + if (!(swapInKB && expected_swap_size * 1024 == size)) { + throw new RuntimeException("Expected total swap size : " + + expected_swap_size + + " but getTotalSwapSpaceSize returned: " + + size); + } } } From 0d46ebff8f43954796e75a25f6caf252ca5a6d84 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 4 Aug 2015 06:52:46 -0700 Subject: [PATCH 03/53] 8132969: C++11 requires a space between literal and identifier Reviewed-by: simonis, ctornqvi --- hotspot/src/share/vm/interpreter/interpreterRuntime.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 42ff73ea491..d08c5ce8b78 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1303,7 +1303,7 @@ void SignatureHandlerLibrary::add(uint64_t fingerprint, address handler) { if (handler_index < 0) { if (PrintSignatureHandlers && (handler != Interpreter::slow_signature_handler())) { tty->cr(); - tty->print_cr("argument handler #%d at "PTR_FORMAT" for fingerprint " UINT64_FORMAT, + tty->print_cr("argument handler #%d at " PTR_FORMAT " for fingerprint " UINT64_FORMAT, _handlers->length(), handler, fingerprint); @@ -1313,7 +1313,7 @@ void SignatureHandlerLibrary::add(uint64_t fingerprint, address handler) { } else { if (PrintSignatureHandlers) { tty->cr(); - tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: "PTR_FORMAT", new : "PTR_FORMAT")", + tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: " PTR_FORMAT ", new : " PTR_FORMAT ")", _handlers->length(), fingerprint, _handlers->at(handler_index), From 9b98a06f7d437c527d19194e0df54aaf63f84c4f Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Tue, 4 Aug 2015 18:11:40 +0300 Subject: [PATCH 04/53] 8132648: sun/tools/jhsdb/BasicLauncherTest fails with java.lang.RuntimeException Added check for standard conditions causing attach to fail Reviewed-by: jbachorik, sspitsyn --- jdk/test/sun/tools/jhsdb/BasicLauncherTest.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java index 4d7a81c152b..7111598d316 100644 --- a/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java +++ b/jdk/test/sun/tools/jhsdb/BasicLauncherTest.java @@ -42,6 +42,7 @@ import jdk.testlibrary.Utils; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; import jdk.test.lib.apps.LingeredApp; +import jdk.testlibrary.Platform; public class BasicLauncherTest { @@ -131,10 +132,16 @@ public class BasicLauncherTest { public static void main(String[] args) throws IOException { + if (!Platform.shouldSAAttach()) { + // Silently skip the test if we don't have enough permissions to attach + System.err.println("Error! Insufficient permissions to attach."); + return; + } + launchCLHSDB(); launch("No deadlocks found", "jstack"); - launch("Server compiler detected", "jmap"); + launch("compiler detected", "jmap"); launch("Java System Properties", "jinfo"); // The test throws RuntimeException on error. From 8bfa163a6825f0d06bfb57ce4a356b1cf889159d Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 4 Aug 2015 17:26:14 -0400 Subject: [PATCH 05/53] 8132306: java/lang/ref/ReferenceEnqueue.java fails with "RuntimeException: Error: poll() returned null; expected ref object" Carefully order ref.queue and queue list updates to address races. Reviewed-by: dholmes, dfuchs, plevart --- .../share/classes/java/lang/ref/ReferenceQueue.java | 10 ++++++++-- jdk/test/java/lang/ref/ReferenceEnqueue.java | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java index bf1af798fd4..edf3e7bb62e 100644 --- a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java +++ b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java @@ -65,10 +65,13 @@ public class ReferenceQueue { return false; } assert queue == this; - r.queue = ENQUEUED; r.next = (head == null) ? r : head; head = r; queueLength++; + // Update r.queue *after* adding to list, to avoid race + // with concurrent enqueued checks and fast-path poll(). + // Volatiles ensure ordering. + r.queue = ENQUEUED; if (r instanceof FinalReference) { sun.misc.VM.addFinalRefCount(1); } @@ -80,10 +83,13 @@ public class ReferenceQueue { private Reference reallyPoll() { /* Must hold lock */ Reference r = head; if (r != null) { + r.queue = NULL; + // Update r.queue *before* removing from list, to avoid + // race with concurrent enqueued checks and fast-path + // poll(). Volatiles ensure ordering. @SuppressWarnings("unchecked") Reference rn = r.next; head = (rn == r) ? null : rn; - r.queue = NULL; r.next = r; queueLength--; if (r instanceof FinalReference) { diff --git a/jdk/test/java/lang/ref/ReferenceEnqueue.java b/jdk/test/java/lang/ref/ReferenceEnqueue.java index 25907a034cc..c246591f12a 100644 --- a/jdk/test/java/lang/ref/ReferenceEnqueue.java +++ b/jdk/test/java/lang/ref/ReferenceEnqueue.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4268317 + * @bug 4268317 8132306 * @summary Test if Reference.enqueue() works properly with GC */ From 47dd02d8471e772e420df201587ebdd0552219b6 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 5 Aug 2015 21:44:54 -0400 Subject: [PATCH 06/53] 8130212: Thread::current() might access freed memory on Solaris Reviewed-by: kvn, twisti, stuefe --- hotspot/src/os/solaris/vm/os_solaris.cpp | 130 -------------- .../os/solaris/vm/thread_solaris.inline.hpp | 19 +- .../vm/threadLS_solaris_sparc.cpp | 27 +-- .../vm/threadLS_solaris_sparc.hpp | 44 +---- .../solaris_x86/vm/assembler_solaris_x86.cpp | 119 +++---------- .../solaris_x86/vm/threadLS_solaris_x86.cpp | 164 ++---------------- .../solaris_x86/vm/threadLS_solaris_x86.hpp | 56 +----- .../share/vm/runtime/threadLocalStorage.cpp | 9 +- .../share/vm/runtime/threadLocalStorage.hpp | 14 +- 9 files changed, 88 insertions(+), 494 deletions(-) diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 5f060c30a95..e5b68dafb15 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -182,75 +182,6 @@ extern "C" { static void unpackTime(timespec* absTime, bool isAbsolute, jlong time); -// Thread Local Storage -// This is common to all Solaris platforms so it is defined here, -// in this common file. -// The declarations are in the os_cpu threadLS*.hpp files. -// -// Static member initialization for TLS -Thread* ThreadLocalStorage::_get_thread_cache[ThreadLocalStorage::_pd_cache_size] = {NULL}; - -#ifndef PRODUCT - #define _PCT(n,d) ((100.0*(double)(n))/(double)(d)) - -int ThreadLocalStorage::_tcacheHit = 0; -int ThreadLocalStorage::_tcacheMiss = 0; - -void ThreadLocalStorage::print_statistics() { - int total = _tcacheMiss+_tcacheHit; - tty->print_cr("Thread cache hits %d misses %d total %d percent %f\n", - _tcacheHit, _tcacheMiss, total, _PCT(_tcacheHit, total)); -} - #undef _PCT -#endif // PRODUCT - -Thread* ThreadLocalStorage::get_thread_via_cache_slowly(uintptr_t raw_id, - int index) { - Thread *thread = get_thread_slow(); - if (thread != NULL) { - address sp = os::current_stack_pointer(); - guarantee(thread->_stack_base == NULL || - (sp <= thread->_stack_base && - sp >= thread->_stack_base - thread->_stack_size) || - is_error_reported(), - "sp must be inside of selected thread stack"); - - thread->set_self_raw_id(raw_id); // mark for quick retrieval - _get_thread_cache[index] = thread; - } - return thread; -} - - -static const double all_zero[sizeof(Thread) / sizeof(double) + 1] = {0}; -#define NO_CACHED_THREAD ((Thread*)all_zero) - -void ThreadLocalStorage::pd_set_thread(Thread* thread) { - - // Store the new value before updating the cache to prevent a race - // between get_thread_via_cache_slowly() and this store operation. - os::thread_local_storage_at_put(ThreadLocalStorage::thread_index(), thread); - - // Update thread cache with new thread if setting on thread create, - // or NO_CACHED_THREAD (zeroed) thread if resetting thread on exit. - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - _get_thread_cache[ix] = thread == NULL ? NO_CACHED_THREAD : thread; -} - -void ThreadLocalStorage::pd_init() { - for (int i = 0; i < _pd_cache_size; i++) { - _get_thread_cache[i] = NO_CACHED_THREAD; - } -} - -// Invalidate all the caches (happens to be the same as pd_init). -void ThreadLocalStorage::pd_invalidate_all() { pd_init(); } - -#undef NO_CACHED_THREAD - -// END Thread Local Storage - static inline size_t adjust_stack_size(address base, size_t size) { if ((ssize_t)size < 0) { // 4759953: Compensate for ridiculous stack size. @@ -1289,67 +1220,6 @@ int os::current_process_id() { return (int)(_initial_pid ? _initial_pid : getpid()); } -int os::allocate_thread_local_storage() { - // %%% in Win32 this allocates a memory segment pointed to by a - // register. Dan Stein can implement a similar feature in - // Solaris. Alternatively, the VM can do the same thing - // explicitly: malloc some storage and keep the pointer in a - // register (which is part of the thread's context) (or keep it - // in TLS). - // %%% In current versions of Solaris, thr_self and TSD can - // be accessed via short sequences of displaced indirections. - // The value of thr_self is available as %g7(36). - // The value of thr_getspecific(k) is stored in %g7(12)(4)(k*4-4), - // assuming that the current thread already has a value bound to k. - // It may be worth experimenting with such access patterns, - // and later having the parameters formally exported from a Solaris - // interface. I think, however, that it will be faster to - // maintain the invariant that %g2 always contains the - // JavaThread in Java code, and have stubs simply - // treat %g2 as a caller-save register, preserving it in a %lN. - thread_key_t tk; - if (thr_keycreate(&tk, NULL)) { - fatal(err_msg("os::allocate_thread_local_storage: thr_keycreate failed " - "(%s)", strerror(errno))); - } - return int(tk); -} - -void os::free_thread_local_storage(int index) { - // %%% don't think we need anything here - // if (pthread_key_delete((pthread_key_t) tk)) { - // fatal("os::free_thread_local_storage: pthread_key_delete failed"); - // } -} - -// libthread allocate for tsd_common is a version specific -// small number - point is NO swap space available -#define SMALLINT 32 -void os::thread_local_storage_at_put(int index, void* value) { - // %%% this is used only in threadLocalStorage.cpp - if (thr_setspecific((thread_key_t)index, value)) { - if (errno == ENOMEM) { - vm_exit_out_of_memory(SMALLINT, OOM_MALLOC_ERROR, - "thr_setspecific: out of swap space"); - } else { - fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed " - "(%s)", strerror(errno))); - } - } else { - ThreadLocalStorage::set_thread_in_slot((Thread *) value); - } -} - -// This function could be called before TLS is initialized, for example, when -// VM receives an async signal or when VM causes a fatal error during -// initialization. Return NULL if thr_getspecific() fails. -void* os::thread_local_storage_at(int index) { - // %%% this is used only in threadLocalStorage.cpp - void* r = NULL; - return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r; -} - - // gethrtime() should be monotonic according to the documentation, // but some virtualized platforms are known to break this guarantee. // getTimeNanos() must be guaranteed not to move backwards, so we diff --git a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp index b5355335f39..fdbc553cd22 100644 --- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp +++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -39,19 +39,12 @@ // For SPARC, to avoid excessive register window spill-fill faults, // we aggressively inline these routines. -inline Thread* ThreadLocalStorage::thread() { - // don't use specialized code if +UseMallocOnly -- may confuse Purify et al. - debug_only(if (UseMallocOnly) return get_thread_slow();); +inline void ThreadLocalStorage::set_thread(Thread* thread) { + _thr_current = thread; +} - uintptr_t raw = pd_raw_thread_id(); - int ix = pd_cache_index(raw); - Thread* candidate = ThreadLocalStorage::_get_thread_cache[ix]; - if (candidate->self_raw_id() == raw) { - // hit - return candidate; - } else { - return ThreadLocalStorage::get_thread_via_cache_slowly(raw, ix); - } +inline Thread* ThreadLocalStorage::thread() { + return _thr_current; } #endif // OS_SOLARIS_VM_THREAD_SOLARIS_INLINE_HPP diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp index d07db6a5c60..30210a453cc 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -26,19 +26,26 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadLocalStorage.hpp" -// Provides an entry point we can link against and -// a buffer we can emit code into. The buffer is -// filled by ThreadLocalStorage::generate_code_for_get_thread -// and called from ThreadLocalStorage::thread() +// True thread-local variable +__thread Thread * ThreadLocalStorage::_thr_current = NULL; -#include +// Implementations needed to support the shared API -// The portable TLS mechanism (get_thread_via_cache) is enough on SPARC. -// There is no need for hand-assembling a special function. -void ThreadLocalStorage::generate_code_for_get_thread() { +void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do + +bool ThreadLocalStorage::_initialized = false; + +void ThreadLocalStorage::init() { + _initialized = true; } -void ThreadLocalStorage::set_thread_in_slot (Thread * self) {} +bool ThreadLocalStorage::is_initialized() { + return _initialized; +} + +Thread* ThreadLocalStorage::get_thread_slow() { + return thread(); +} extern "C" Thread* get_thread() { return ThreadLocalStorage::thread(); diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp index 98a8fc58c31..e3d96c87ae7 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/threadLS_solaris_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -25,47 +25,15 @@ #ifndef OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP #define OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP -public: - // Java Thread - force inlining - static inline Thread* thread() ; +// Solaris specific implementation involves simple, direct use +// of a compiler-based thread-local variable private: - static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] - static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index); + static __thread Thread * _thr_current; - NOT_PRODUCT(static int _tcacheHit;) - NOT_PRODUCT(static int _tcacheMiss;) + static bool _initialized; // needed for shared API public: - - // Print cache hit/miss statistics - static void print_statistics() PRODUCT_RETURN; - - enum Constants { - _pd_cache_size = 256*2 // projected typical # of threads * 2 - }; - - static void set_thread_in_slot (Thread *) ; - - static uintptr_t pd_raw_thread_id() { - return _raw_thread_id(); - } - - static int pd_cache_index(uintptr_t raw_id) { - // Hash function: From email from Dave: - // The hash function deserves an explanation. %g7 points to libthread's - // "thread" structure. On T1 the thread structure is allocated on the - // user's stack (yes, really!) so the ">>20" handles T1 where the JVM's - // stack size is usually >= 1Mb. The ">>9" is for T2 where Roger allocates - // globs of thread blocks contiguously. The "9" has to do with the - // expected size of the T2 thread structure. If these constants are wrong - // the worst thing that'll happen is that the hit rate for heavily threaded - // apps won't be as good as it could be. If you want to burn another - // shift+xor you could mix together _all of the %g7 bits to form the hash, - // but I think that's excessive. Making the change above changed the - // T$ miss rate on SpecJBB (on a 16X system) from about 3% to imperceptible. - uintptr_t ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size); - return ix; - } + static inline Thread* thread(); #endif // OS_CPU_SOLARIS_SPARC_VM_THREADLS_SOLARIS_SPARC_HPP diff --git a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp index 203da611c01..d4c0feccaa3 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/assembler_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, 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 @@ -23,11 +23,10 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "runtime/os.hpp" #include "runtime/threadLocalStorage.hpp" - +#include "runtime/thread.inline.hpp" void MacroAssembler::int3() { push(rax); @@ -39,98 +38,32 @@ void MacroAssembler::int3() { pop(rax); } -#define __ _masm-> -#ifndef _LP64 -static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) { - - // slow call to of thr_getspecific - // int thr_getspecific(thread_key_t key, void **value); - // Consider using pthread_getspecific instead. - -__ push(0); // allocate space for return value - if (thread != rax) __ push(rax); // save rax, if caller still wants it -__ push(rcx); // save caller save -__ push(rdx); // save caller save - if (thread != rax) { -__ lea(thread, Address(rsp, 3 * sizeof(int))); // address of return value - } else { -__ lea(thread, Address(rsp, 2 * sizeof(int))); // address of return value - } -__ push(thread); // and pass the address -__ push(ThreadLocalStorage::thread_index()); // the key -__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); -__ increment(rsp, 2 * wordSize); -__ pop(rdx); -__ pop(rcx); - if (thread != rax) __ pop(rax); -__ pop(thread); - -} -#else -static void slow_call_thr_specific(MacroAssembler* _masm, Register thread) { - // slow call to of thr_getspecific - // int thr_getspecific(thread_key_t key, void **value); - // Consider using pthread_getspecific instead. - - if (thread != rax) { -__ push(rax); - } -__ push(0); // space for return value -__ push(rdi); -__ push(rsi); -__ lea(rsi, Address(rsp, 16)); // pass return value address -__ push(rdx); -__ push(rcx); -__ push(r8); -__ push(r9); -__ push(r10); - // XXX -__ mov(r10, rsp); -__ andptr(rsp, -16); -__ push(r10); -__ push(r11); - -__ movl(rdi, ThreadLocalStorage::thread_index()); -__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, thr_getspecific))); - -__ pop(r11); -__ pop(rsp); -__ pop(r10); -__ pop(r9); -__ pop(r8); -__ pop(rcx); -__ pop(rdx); -__ pop(rsi); -__ pop(rdi); -__ pop(thread); // load return value - if (thread != rax) { -__ pop(rax); - } -} -#endif //LP64 - +// This is simply a call to ThreadLocalStorage::thread() void MacroAssembler::get_thread(Register thread) { - - int segment = NOT_LP64(Assembler::GS_segment) LP64_ONLY(Assembler::FS_segment); - // Try to emit a Solaris-specific fast TSD/TLS accessor. - ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_getTlsAccessMode (); - if (tlsMode == ThreadLocalStorage::pd_tlsAccessIndirect) { // T1 - // Use thread as a temporary: mov r, gs:[0]; mov r, [r+tlsOffset] - emit_int8 (segment); - // ExternalAddress doesn't work because it can't take NULL - AddressLiteral null(0, relocInfo::none); - movptr (thread, null); - movptr(thread, Address(thread, ThreadLocalStorage::pd_getTlsOffset())) ; - return ; - } else - if (tlsMode == ThreadLocalStorage::pd_tlsAccessDirect) { // T2 - // mov r, gs:[tlsOffset] - emit_int8 (segment); - AddressLiteral tls_off((address)ThreadLocalStorage::pd_getTlsOffset(), relocInfo::none); - movptr (thread, tls_off); - return ; + if (thread != rax) { + push(rax); } + push(rdi); + push(rsi); + push(rdx); + push(rcx); + push(r8); + push(r9); + push(r10); + push(r11); - slow_call_thr_specific(this, thread); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, ThreadLocalStorage::thread))); + pop(r11); + pop(r10); + pop(r9); + pop(r8); + pop(rcx); + pop(rdx); + pop(rsi); + pop(rdi); + if (thread != rax) { + movl(thread, rax); + pop(rax); + } } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp index e2ce144a3c7..30210a453cc 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -26,167 +26,27 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadLocalStorage.hpp" -#ifdef AMD64 -extern "C" Thread* fs_load(ptrdiff_t tlsOffset); -extern "C" intptr_t fs_thread(); -#else -// From solaris_i486.s -extern "C" Thread* gs_load(ptrdiff_t tlsOffset); -extern "C" intptr_t gs_thread(); -#endif // AMD64 +// True thread-local variable +__thread Thread * ThreadLocalStorage::_thr_current = NULL; -// tlsMode encoding: -// -// pd_tlsAccessUndefined : uninitialized -// pd_tlsAccessSlow : not available -// pd_tlsAccessIndirect : -// old-style indirect access - present in "T1" libthread. -// use thr_slot_sync_allocate() to attempt to allocate a slot. -// pd_tlsAccessDirect : -// new-style direct access - present in late-model "T2" libthread. -// Allocate the offset (slot) via _thr_slot_offset() or by -// defining an IE- or LE-mode TLS/TSD slot in the launcher and then passing -// that offset into libjvm.so. -// See http://sac.eng/Archives/CaseLog/arc/PSARC/2003/159/. -// -// Note that we have a capability gap - some early model T2 forms -// (e.g., unpatched S9) have neither _thr_slot_sync_allocate() nor -// _thr_slot_offset(). In that case we revert to the usual -// thr_getspecific accessor. -// +// Implementations needed to support the shared API -static ThreadLocalStorage::pd_tlsAccessMode tlsMode = ThreadLocalStorage::pd_tlsAccessUndefined ; -static ptrdiff_t tlsOffset = 0 ; -static thread_key_t tlsKey ; +void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do -typedef int (*TSSA_Entry) (ptrdiff_t *, int, int) ; -typedef ptrdiff_t (*TSO_Entry) (int) ; +bool ThreadLocalStorage::_initialized = false; -ThreadLocalStorage::pd_tlsAccessMode ThreadLocalStorage::pd_getTlsAccessMode () -{ - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - return tlsMode ; +void ThreadLocalStorage::init() { + _initialized = true; } -ptrdiff_t ThreadLocalStorage::pd_getTlsOffset () { - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - return tlsOffset ; +bool ThreadLocalStorage::is_initialized() { + return _initialized; } -// TODO: Consider the following improvements: -// -// 1. Convert from thr_*specific* to pthread_*specific*. -// The pthread_ forms are slightly faster. Also, the -// pthread_ forms have a pthread_key_delete() API which -// would aid in clean JVM shutdown and the eventual goal -// of permitting a JVM to reinstantiate itself withing a process. -// -// 2. See ThreadLocalStorage::init(). We end up allocating -// two TLS keys during VM startup. That's benign, but we could collapse -// down to one key without too much trouble. -// -// 3. MacroAssembler::get_thread() currently emits calls to thr_getspecific(). -// Modify get_thread() to call Thread::current() instead. -// -// 4. Thread::current() currently uses a cache keyed by %gs:[0]. -// (The JVM has PSARC permission to use %g7/%gs:[0] -// as an opaque temporally unique thread identifier). -// For C++ access to a thread's reflexive "self" pointer we -// should consider using one of the following: -// a. a radix tree keyed by %esp - as in EVM. -// This requires two loads (the 2nd dependent on the 1st), but -// is easily inlined and doesn't require a "miss" slow path. -// b. a fast TLS/TSD slot allocated by _thr_slot_offset -// or _thr_slot_sync_allocate. -// -// 5. 'generate_code_for_get_thread' is a misnomer. -// We should change it to something more general like -// pd_ThreadSelf_Init(), for instance. -// - -static void AllocateTLSOffset () -{ - int rslt ; - TSSA_Entry tssa ; - TSO_Entry tso ; - ptrdiff_t off ; - - guarantee (tlsMode == ThreadLocalStorage::pd_tlsAccessUndefined, "tlsMode not set") ; - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; - tlsOffset = 0 ; -#ifndef AMD64 - - tssa = (TSSA_Entry) dlsym (RTLD_DEFAULT, "thr_slot_sync_allocate") ; - if (tssa != NULL) { - off = -1 ; - rslt = (*tssa)(&off, NULL, NULL) ; // (off,dtor,darg) - if (off != -1) { - tlsOffset = off ; - tlsMode = ThreadLocalStorage::pd_tlsAccessIndirect ; - return ; - } - } - - rslt = thr_keycreate (&tlsKey, NULL) ; - if (rslt != 0) { - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; // revert to slow mode - return ; - } - - tso = (TSO_Entry) dlsym (RTLD_DEFAULT, "_thr_slot_offset") ; - if (tso != NULL) { - off = (*tso)(tlsKey) ; - if (off >= 0) { - tlsOffset = off ; - tlsMode = ThreadLocalStorage::pd_tlsAccessDirect ; - return ; - } - } - - // Failure: Too bad ... we've allocated a TLS slot we don't need and there's - // no provision in the ABI for returning the slot. - // - // If we didn't find a slot then then: - // 1. We might be on liblwp. - // 2. We might be on T2 libthread, but all "fast" slots are already - // consumed - // 3. We might be on T1, and all TSD (thr_slot_sync_allocate) slots are - // consumed. - // 4. We might be on T2 libthread, but it's be re-architected - // so that fast slots are no longer g7-relative. - // - - tlsMode = ThreadLocalStorage::pd_tlsAccessSlow ; - return ; -#endif // AMD64 +Thread* ThreadLocalStorage::get_thread_slow() { + return thread(); } -void ThreadLocalStorage::generate_code_for_get_thread() { - AllocateTLSOffset() ; -} - -void ThreadLocalStorage::set_thread_in_slot(Thread *thread) { - guarantee (tlsMode != pd_tlsAccessUndefined, "tlsMode not set") ; - if (tlsMode == pd_tlsAccessIndirect) { -#ifdef AMD64 - intptr_t tbase = fs_thread(); -#else - intptr_t tbase = gs_thread(); -#endif // AMD64 - *((Thread**) (tbase + tlsOffset)) = thread ; - } else - if (tlsMode == pd_tlsAccessDirect) { - thr_setspecific (tlsKey, (void *) thread) ; - // set with thr_setspecific and then readback with gs_load to validate. -#ifdef AMD64 - guarantee (thread == fs_load(tlsOffset), "tls readback failure") ; -#else - guarantee (thread == gs_load(tlsOffset), "tls readback failure") ; -#endif // AMD64 - } -} - - extern "C" Thread* get_thread() { return ThreadLocalStorage::thread(); } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp index 05a9e7c25dd..4f8da7bcb65 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/threadLS_solaris_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -25,61 +25,15 @@ #ifndef OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP #define OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP -// Processor dependent parts of ThreadLocalStorage +// Solaris specific implementation involves simple, direct use +// of a compiler-based thread-local variable private: - static Thread* _get_thread_cache[]; // index by [(raw_id>>9)^(raw_id>>20) % _pd_cache_size] - static Thread* get_thread_via_cache_slowly(uintptr_t raw_id, int index); + static __thread Thread * _thr_current; - NOT_PRODUCT(static int _tcacheHit;) - NOT_PRODUCT(static int _tcacheMiss;) + static bool _initialized; // needed for shared API public: - // Cache hit/miss statistics - static void print_statistics() PRODUCT_RETURN; - - enum Constants { -#ifdef AMD64 - _pd_cache_size = 256*2 // projected typical # of threads * 2 -#else - _pd_cache_size = 128*2 // projected typical # of threads * 2 -#endif // AMD64 - }; - - enum pd_tlsAccessMode { - pd_tlsAccessUndefined = -1, - pd_tlsAccessSlow = 0, - pd_tlsAccessIndirect = 1, - pd_tlsAccessDirect = 2 - } ; - - static void set_thread_in_slot (Thread *) ; - - static pd_tlsAccessMode pd_getTlsAccessMode () ; - static ptrdiff_t pd_getTlsOffset () ; - - static uintptr_t pd_raw_thread_id() { -#ifdef _GNU_SOURCE -#ifdef AMD64 - uintptr_t rv; - __asm__ __volatile__ ("movq %%fs:0, %0" : "=r"(rv)); - return rv; -#else - return gs_thread(); -#endif // AMD64 -#else //_GNU_SOURCE - return _raw_thread_id(); -#endif //_GNU_SOURCE - } - - static int pd_cache_index(uintptr_t raw_id) { - // Copied from the sparc version. Dave said it should also work fine - // for solx86. - int ix = (int) (((raw_id >> 9) ^ (raw_id >> 20)) % _pd_cache_size); - return ix; - } - - // Java Thread static inline Thread* thread(); #endif // OS_CPU_SOLARIS_X86_VM_THREADLS_SOLARIS_X86_HPP diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.cpp b/hotspot/src/share/vm/runtime/threadLocalStorage.cpp index e5271b6d7e3..61d40889615 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.cpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -27,6 +27,11 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadLocalStorage.hpp" +// Solaris no longer has this kind of ThreadLocalStorage implementation. +// This will be removed from all platforms in the near future. + +#ifndef SOLARIS + // static member initialization int ThreadLocalStorage::_thread_index = -1; @@ -54,3 +59,5 @@ void ThreadLocalStorage::init() { bool ThreadLocalStorage::is_initialized() { return (thread_index() != -1); } + +#endif // SOLARIS diff --git a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp index 9d6d9f6f8c2..128dd98067f 100644 --- a/hotspot/src/share/vm/runtime/threadLocalStorage.hpp +++ b/hotspot/src/share/vm/runtime/threadLocalStorage.hpp @@ -38,10 +38,14 @@ extern "C" Thread* get_thread(); extern "C" uintptr_t _raw_thread_id(); class ThreadLocalStorage : AllStatic { + + // Exported API public: static void set_thread(Thread* thread); static Thread* get_thread_slow(); static void invalidate_all() { pd_invalidate_all(); } + static void init(); + static bool is_initialized(); // Machine dependent stuff #ifdef TARGET_OS_ARCH_linux_x86 @@ -81,17 +85,12 @@ class ThreadLocalStorage : AllStatic { # include "threadLS_bsd_zero.hpp" #endif - +#ifndef SOLARIS public: // Accessor static inline int thread_index() { return _thread_index; } static inline void set_thread_index(int index) { _thread_index = index; } - // Initialization - // Called explicitly from VMThread::activate_system instead of init_globals. - static void init(); - static bool is_initialized(); - private: static int _thread_index; @@ -100,6 +99,9 @@ class ThreadLocalStorage : AllStatic { // Processor dependent parts of set_thread and initialization static void pd_set_thread(Thread* thread); static void pd_init(); + +#endif // SOLARIS + // Invalidate any thread cacheing or optimization schemes. static void pd_invalidate_all(); From 95fb9da9de60374382bbef95372bec1e0cdd4f2b Mon Sep 17 00:00:00 2001 From: Cheleswer Sahu Date: Thu, 6 Aug 2015 00:08:57 -0700 Subject: [PATCH 07/53] 8075773: jps running as root fails after the fix of JDK-8050807 Reviewed-by: sla, dsamersoff, gthornbr --- hotspot/src/os/linux/vm/perfMemory_linux.cpp | 6 +++--- hotspot/src/os/solaris/vm/perfMemory_solaris.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp index a6fd68ed3db..ab2bcfbfac0 100644 --- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp @@ -217,9 +217,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; diff --git a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp index 3c941eaeef4..3c9188d3000 100644 --- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp +++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp @@ -219,9 +219,9 @@ static bool is_statbuf_secure(struct stat *statp) { // return false; } - // See if the uid of the directory matches the effective uid of the process. - // - if (statp->st_uid != geteuid()) { + // If user is not root then see if the uid of the directory matches the effective uid of the process. + uid_t euid = geteuid(); + if ((euid != 0) && (statp->st_uid != euid)) { // The directory was not created by this user, declare it insecure. // return false; From e787253b192891a9877237dc610e892a5116282a Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Thu, 6 Aug 2015 01:48:27 -0700 Subject: [PATCH 08/53] 8060245: update bsd version of jhelper.d to be in sync with the fix of 8009204 on solaris Sync the bsd version of jhelper with the solaris version Reviewed-by: sla, jbachorik --- hotspot/src/os/bsd/dtrace/jhelper.d | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hotspot/src/os/bsd/dtrace/jhelper.d b/hotspot/src/os/bsd/dtrace/jhelper.d index c5fea81b8d8..dbe0a4a42f9 100644 --- a/hotspot/src/os/bsd/dtrace/jhelper.d +++ b/hotspot/src/os/bsd/dtrace/jhelper.d @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -49,7 +49,7 @@ extern pointer __1cJCodeCacheG_heaps_; extern pointer __1cIUniverseO_collectedHeap_; extern pointer __1cHnmethodG__vtbl_; -extern pointer __1cNMethodG__vtbl_; +extern pointer __1cGMethodG__vtbl_; extern pointer __1cKBufferBlobG__vtbl_; #define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer)) @@ -164,7 +164,7 @@ dtrace:helper:ustack: this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len); this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_; - + /* * Get Java heap bounds */ @@ -457,12 +457,15 @@ dtrace:helper:ustack: this->nameSymbol = copyin_ptr(this->constantPool + this->nameIndex * sizeof (pointer) + SIZE_ConstantPool); + /* The symbol is a CPSlot and has lower bit set to indicate metadata */ + this->nameSymbol &= (~1); /* remove metadata lsb */ this->nameSymbolLength = copyin_uint16(this->nameSymbol + OFFSET_Symbol_length); this->signatureSymbol = copyin_ptr(this->constantPool + this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool); + this->signatureSymbol &= (~1); /* remove metadata lsb */ this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + OFFSET_Symbol_length); From 6e3ffb1aaed103bcf29d501e0dc0534e38e242c5 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 6 Aug 2015 15:49:50 +0200 Subject: [PATCH 09/53] 8073052: Rename and clean up the allocation manager hierarchy in g1Allocator.?pp Fix naming of G1ParGCAllocator, decrease dependencies between G1CollectedHeap, G1Allocator and G1AllocRegion, additional documentation. Reviewed-by: mgerdin, jmasa, kbarrett --- hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp | 2 - hotspot/src/share/vm/gc/g1/g1Allocator.cpp | 98 ++++++++++++++++--- hotspot/src/share/vm/gc/g1/g1Allocator.hpp | 83 +++++++++++----- .../src/share/vm/gc/g1/g1Allocator.inline.hpp | 46 +++++++++ .../src/share/vm/gc/g1/g1Allocator_ext.cpp | 4 +- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 68 +++++++------ .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 45 ++------- .../share/vm/gc/g1/g1CollectedHeap.inline.hpp | 76 -------------- .../share/vm/gc/g1/g1CollectedHeap_ext.cpp | 6 ++ .../src/share/vm/gc/g1/g1CollectorPolicy.cpp | 1 + .../share/vm/gc/g1/g1OopClosures.inline.hpp | 1 + .../share/vm/gc/g1/g1ParScanThreadState.cpp | 21 ++-- .../share/vm/gc/g1/g1ParScanThreadState.hpp | 2 +- .../src/share/vm/gc/g1/g1RootProcessor.cpp | 1 + hotspot/src/share/vm/gc/g1/heapRegion.hpp | 16 +-- .../src/share/vm/gc/g1/heapRegion.inline.hpp | 16 ++- .../src/share/vm/gc/g1/heapRegionManager.cpp | 2 +- .../src/share/vm/gc/g1/vm_operations_g1.cpp | 10 +- 18 files changed, 281 insertions(+), 217 deletions(-) create mode 100644 hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp diff --git a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp index 02f948e597f..8633a9d3d23 100644 --- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp @@ -300,5 +300,3 @@ HeapRegion* OldGCAllocRegion::release() { } return G1AllocRegion::release(); } - - diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp index 9450d728671..02216782b9f 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/g1/g1Allocator.hpp" +#include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1MarkSweep.hpp" @@ -116,15 +116,85 @@ void G1DefaultAllocator::abandon_gc_alloc_regions() { G1PLAB::G1PLAB(size_t gclab_word_size) : PLAB(gclab_word_size), _retired(true) { } -HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest, - size_t word_sz, - AllocationContext_t context) { +size_t G1Allocator::unsafe_max_tlab_alloc(AllocationContext_t context) { + // Return the remaining space in the cur alloc region, but not less than + // the min TLAB size. + + // Also, this value can be at most the humongous object threshold, + // since we can't allow tlabs to grow big enough to accommodate + // humongous objects. + + HeapRegion* hr = mutator_alloc_region(context)->get(); + size_t max_tlab = _g1h->max_tlab_size() * wordSize; + if (hr == NULL) { + return max_tlab; + } else { + return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab); + } +} + +HeapWord* G1Allocator::par_allocate_during_gc(InCSetState dest, + size_t word_size, + AllocationContext_t context) { + switch (dest.value()) { + case InCSetState::Young: + return survivor_attempt_allocation(word_size, context); + case InCSetState::Old: + return old_attempt_allocation(word_size, context); + default: + ShouldNotReachHere(); + return NULL; // Keep some compilers happy + } +} + +HeapWord* G1Allocator::survivor_attempt_allocation(size_t word_size, + AllocationContext_t context) { + assert(!_g1h->is_humongous(word_size), + "we should not be seeing humongous-size allocations in this path"); + + HeapWord* result = survivor_gc_alloc_region(context)->attempt_allocation(word_size, + false /* bot_updates */); + if (result == NULL) { + MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); + result = survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size, + false /* bot_updates */); + } + if (result != NULL) { + _g1h->dirty_young_block(result, word_size); + } + return result; +} + +HeapWord* G1Allocator::old_attempt_allocation(size_t word_size, + AllocationContext_t context) { + assert(!_g1h->is_humongous(word_size), + "we should not be seeing humongous-size allocations in this path"); + + HeapWord* result = old_gc_alloc_region(context)->attempt_allocation(word_size, + true /* bot_updates */); + if (result == NULL) { + MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); + result = old_gc_alloc_region(context)->attempt_allocation_locked(word_size, + true /* bot_updates */); + } + return result; +} + +G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) : + _g1h(G1CollectedHeap::heap()), + _allocator(allocator), + _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { +} + +HeapWord* G1PLABAllocator::allocate_direct_or_new_plab(InCSetState dest, + size_t word_sz, + AllocationContext_t context) { size_t gclab_word_size = _g1h->desired_plab_sz(dest); if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { G1PLAB* alloc_buf = alloc_buffer(dest, context); alloc_buf->retire(); - HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context); + HeapWord* buf = _allocator->par_allocate_during_gc(dest, gclab_word_size, context); if (buf == NULL) { return NULL; // Let caller handle allocation failure. } @@ -136,14 +206,18 @@ HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest, assert(obj != NULL, "buffer was definitely big enough..."); return obj; } else { - return _g1h->par_allocate_during_gc(dest, word_sz, context); + return _allocator->par_allocate_during_gc(dest, word_sz, context); } } -G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) : - G1ParGCAllocator(g1h), - _surviving_alloc_buffer(g1h->desired_plab_sz(InCSetState::Young)), - _tenured_alloc_buffer(g1h->desired_plab_sz(InCSetState::Old)) { +void G1PLABAllocator::undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) { + alloc_buffer(dest, context)->undo_allocation(obj, word_sz); +} + +G1DefaultPLABAllocator::G1DefaultPLABAllocator(G1Allocator* allocator) : + G1PLABAllocator(allocator), + _surviving_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Young)), + _tenured_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Old)) { for (uint state = 0; state < InCSetState::Num; state++) { _alloc_buffers[state] = NULL; } @@ -151,7 +225,7 @@ G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) : _alloc_buffers[InCSetState::Old] = &_tenured_alloc_buffer; } -void G1DefaultParGCAllocator::retire_alloc_buffers() { +void G1DefaultPLABAllocator::retire_alloc_buffers() { for (uint state = 0; state < InCSetState::Num; state++) { G1PLAB* const buf = _alloc_buffers[state]; if (buf != NULL) { @@ -160,7 +234,7 @@ void G1DefaultParGCAllocator::retire_alloc_buffers() { } } -void G1DefaultParGCAllocator::waste(size_t& wasted, size_t& undo_wasted) { +void G1DefaultPLABAllocator::waste(size_t& wasted, size_t& undo_wasted) { wasted = 0; undo_wasted = 0; for (uint state = 0; state < InCSetState::Num; state++) { diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp index a5dfebed492..dc9bb16b620 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp @@ -33,17 +33,36 @@ class EvacuationInfo; -// Base class for G1 allocators. +// Interface to keep track of which regions G1 is currently allocating into. Provides +// some accessors (e.g. allocating into them, or getting their occupancy). +// Also keeps track of retained regions across GCs. class G1Allocator : public CHeapObj { friend class VMStructs; protected: G1CollectedHeap* _g1h; + virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0; + + // Accessors to the allocation regions. + virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0; + virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0; + + // Allocation attempt during GC for a survivor object / PLAB. + inline HeapWord* survivor_attempt_allocation(size_t word_size, + AllocationContext_t context); + // Allocation attempt during GC for an old object / PLAB. + inline HeapWord* old_attempt_allocation(size_t word_size, + AllocationContext_t context); public: G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { } + virtual ~G1Allocator() { } static G1Allocator* create_allocator(G1CollectedHeap* g1h); +#ifdef ASSERT + // Do we currently have an active mutator region to allocate into? + bool has_mutator_alloc_region(AllocationContext_t context) { return mutator_alloc_region(context)->get() != NULL; } +#endif virtual void init_mutator_alloc_region() = 0; virtual void release_mutator_alloc_region() = 0; @@ -51,24 +70,35 @@ public: virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0; virtual void abandon_gc_alloc_regions() = 0; - virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0; - virtual SurvivorGCAllocRegion* survivor_gc_alloc_region(AllocationContext_t context) = 0; - virtual OldGCAllocRegion* old_gc_alloc_region(AllocationContext_t context) = 0; - virtual size_t used_in_alloc_regions() = 0; - virtual bool is_retained_old_region(HeapRegion* hr) = 0; + // Management of retained regions. - void reuse_retained_old_region(EvacuationInfo& evacuation_info, - OldGCAllocRegion* old, - HeapRegion** retained); + virtual bool is_retained_old_region(HeapRegion* hr) = 0; + void reuse_retained_old_region(EvacuationInfo& evacuation_info, + OldGCAllocRegion* old, + HeapRegion** retained); - virtual HeapRegion* new_heap_region(uint hrs_index, - G1BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr) { - return new HeapRegion(hrs_index, sharedOffsetArray, mr); - } + // Allocate blocks of memory during mutator time. + + inline HeapWord* attempt_allocation(size_t word_size, AllocationContext_t context); + inline HeapWord* attempt_allocation_locked(size_t word_size, AllocationContext_t context); + inline HeapWord* attempt_allocation_force(size_t word_size, AllocationContext_t context); + + size_t unsafe_max_tlab_alloc(AllocationContext_t context); + + // Allocate blocks of memory during garbage collection. Will ensure an + // allocation region, either by picking one or expanding the + // heap, and then allocate a block of the given size. The block + // may not be a humongous - it must fit into a single heap region. + HeapWord* par_allocate_during_gc(InCSetState dest, + size_t word_size, + AllocationContext_t context); + + virtual size_t used_in_alloc_regions() = 0; }; -// The default allocator for G1. +// The default allocation region manager for G1. Provides a single mutator, survivor +// and old generation allocation region. +// Can retain the (single) old generation allocation region across GCs. class G1DefaultAllocator : public G1Allocator { protected: // Alloc region used to satisfy mutator allocation requests. @@ -152,10 +182,14 @@ public: } }; -class G1ParGCAllocator : public CHeapObj { +// Manages the PLABs used during garbage collection. Interface for allocation from PLABs. +// Needs to handle multiple contexts, extra alignment in any "survivor" area and some +// statistics. +class G1PLABAllocator : public CHeapObj { friend class G1ParScanThreadState; protected: G1CollectedHeap* _g1h; + G1Allocator* _allocator; // The survivor alignment in effect in bytes. // == 0 : don't align survivors @@ -182,11 +216,10 @@ protected: } public: - G1ParGCAllocator(G1CollectedHeap* g1h) : - _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()) { } - virtual ~G1ParGCAllocator() { } + G1PLABAllocator(G1Allocator* allocator); + virtual ~G1PLABAllocator() { } - static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h); + static G1PLABAllocator* create_allocator(G1Allocator* allocator); virtual void waste(size_t& wasted, size_t& undo_wasted) = 0; @@ -219,18 +252,18 @@ public: return allocate_direct_or_new_plab(dest, word_sz, context); } - void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) { - alloc_buffer(dest, context)->undo_allocation(obj, word_sz); - } + void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context); }; -class G1DefaultParGCAllocator : public G1ParGCAllocator { +// The default PLAB allocator for G1. Keeps the current (single) PLAB for survivor +// and old generation allocation. +class G1DefaultPLABAllocator : public G1PLABAllocator { G1PLAB _surviving_alloc_buffer; G1PLAB _tenured_alloc_buffer; G1PLAB* _alloc_buffers[InCSetState::Num]; public: - G1DefaultParGCAllocator(G1CollectedHeap* g1h); + G1DefaultPLABAllocator(G1Allocator* _allocator); virtual G1PLAB* alloc_buffer(InCSetState dest, AllocationContext_t context) { assert(dest.is_valid(), diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp new file mode 100644 index 00000000000..f39a4e74877 --- /dev/null +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.inline.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, 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. + * + */ + +#ifndef SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP +#define SHARE_VM_GC_G1_G1ALLOCATOR_INLINE_HPP + +#include "gc/g1/g1Allocator.hpp" +#include "gc/g1/g1AllocRegion.inline.hpp" + +HeapWord* G1Allocator::attempt_allocation(size_t word_size, AllocationContext_t context) { + return mutator_alloc_region(context)->attempt_allocation(word_size, false /* bot_updates */); +} + +HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size, AllocationContext_t context) { + HeapWord* result = mutator_alloc_region(context)->attempt_allocation_locked(word_size, false /* bot_updates */); + assert(result != NULL || mutator_alloc_region(context)->get() == NULL, + err_msg("Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, p2i(mutator_alloc_region(context)->get()))); + return result; +} + +HeapWord* G1Allocator::attempt_allocation_force(size_t word_size, AllocationContext_t context) { + return mutator_alloc_region(context)->attempt_allocation_force(word_size, false /* bot_updates */); +} + +#endif // SHARE_VM_GC_G1_G1ALLOCATOR_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp index 3491ece62ab..35ef20c1045 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator_ext.cpp @@ -30,6 +30,6 @@ G1Allocator* G1Allocator::create_allocator(G1CollectedHeap* g1h) { return new G1DefaultAllocator(g1h); } -G1ParGCAllocator* G1ParGCAllocator::create_allocator(G1CollectedHeap* g1h) { - return new G1DefaultParGCAllocator(g1h); +G1PLABAllocator* G1PLABAllocator::create_allocator(G1Allocator* allocator) { + return new G1DefaultPLABAllocator(allocator); } diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index a4f62735a5d..3bcc7fcebda 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -31,7 +31,7 @@ #include "gc/g1/concurrentG1Refine.hpp" #include "gc/g1/concurrentG1RefineThread.hpp" #include "gc/g1/concurrentMarkThread.inline.hpp" -#include "gc/g1/g1AllocRegion.inline.hpp" +#include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" @@ -815,22 +815,16 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, { MutexLockerEx x(Heap_lock); - result = _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size, - false /* bot_updates */); + result = _allocator->attempt_allocation_locked(word_size, context); if (result != NULL) { return result; } - // If we reach here, attempt_allocation_locked() above failed to - // allocate a new region. So the mutator alloc region should be NULL. - assert(_allocator->mutator_alloc_region(context)->get() == NULL, "only way to get here"); - if (GC_locker::is_active_and_needs_gc()) { if (g1_policy()->can_expand_young_list()) { // No need for an ergo verbose message here, // can_expand_young_list() does this when it returns true. - result = _allocator->mutator_alloc_region(context)->attempt_allocation_force(word_size, - false /* bot_updates */); + result = _allocator->attempt_allocation_force(word_size, context); if (result != NULL) { return result; } @@ -890,8 +884,7 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size, // first attempt (without holding the Heap_lock) here and the // follow-on attempt will be at the start of the next loop // iteration (after taking the Heap_lock). - result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size, - false /* bot_updates */); + result = _allocator->attempt_allocation(word_size, context); if (result != NULL) { return result; } @@ -1109,6 +1102,29 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) { } } +inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, + uint* gc_count_before_ret, + uint* gclocker_retry_count_ret) { + assert_heap_not_locked_and_not_at_safepoint(); + assert(!is_humongous(word_size), "attempt_allocation() should not " + "be called for humongous allocation requests"); + + AllocationContext_t context = AllocationContext::current(); + HeapWord* result = _allocator->attempt_allocation(word_size, context); + + if (result == NULL) { + result = attempt_allocation_slow(word_size, + context, + gc_count_before_ret, + gclocker_retry_count_ret); + } + assert_heap_not_locked(); + if (result != NULL) { + dirty_young_block(result, word_size); + } + return result; +} + HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size, uint* gc_count_before_ret, uint* gclocker_retry_count_ret) { @@ -1231,13 +1247,11 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size, AllocationContext_t context, bool expect_null_mutator_alloc_region) { assert_at_safepoint(true /* should_be_vm_thread */); - assert(_allocator->mutator_alloc_region(context)->get() == NULL || - !expect_null_mutator_alloc_region, + assert(!_allocator->has_mutator_alloc_region(context) || !expect_null_mutator_alloc_region, "the current alloc region was unexpectedly found to be non-NULL"); if (!is_humongous(word_size)) { - return _allocator->mutator_alloc_region(context)->attempt_allocation_locked(word_size, - false /* bot_updates */); + return _allocator->attempt_allocation_locked(word_size, context); } else { HeapWord* result = humongous_obj_allocate(word_size, context); if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) { @@ -2373,7 +2387,6 @@ void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, assert(!dcqs.completed_buffers_exist_dirty(), "Completed buffers exist!"); } - // Computes the sum of the storage used by the various regions. size_t G1CollectedHeap::used() const { size_t result = _summary_bytes_used + _allocator->used_in_alloc_regions(); @@ -2632,6 +2645,11 @@ bool G1CollectedHeap::is_in_exact(const void* p) const { } #endif +bool G1CollectedHeap::obj_in_cs(oop obj) { + HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj); + return r != NULL && r->in_collection_set(); +} + // Iteration functions. // Applies an ExtendedOopClosure onto all references of objects within a HeapRegion. @@ -2833,20 +2851,8 @@ size_t G1CollectedHeap::max_tlab_size() const { } size_t G1CollectedHeap::unsafe_max_tlab_alloc(Thread* ignored) const { - // Return the remaining space in the cur alloc region, but not less than - // the min TLAB size. - - // Also, this value can be at most the humongous object threshold, - // since we can't allow tlabs to grow big enough to accommodate - // humongous objects. - - HeapRegion* hr = _allocator->mutator_alloc_region(AllocationContext::current())->get(); - size_t max_tlab = max_tlab_size() * wordSize; - if (hr == NULL) { - return max_tlab; - } else { - return MIN2(MAX2(hr->free(), (size_t) MinTLABSize), max_tlab); - } + AllocationContext_t context = AllocationContext::current(); + return _allocator->unsafe_max_tlab_alloc(context); } size_t G1CollectedHeap::max_capacity() const { @@ -5009,7 +5015,7 @@ public: bool G1STWIsAliveClosure::do_object_b(oop p) { // An object is reachable if it is outside the collection set, // or is inside and copied. - return !_g1->obj_in_cs(p) || p->is_forwarded(); + return !_g1->is_in_cset(p) || p->is_forwarded(); } // Non Copying Keep Alive closure diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 7b52c34dc50..73f1f114566 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -27,7 +27,6 @@ #include "gc/g1/concurrentMark.hpp" #include "gc/g1/evacuationInfo.hpp" -#include "gc/g1/g1AllocRegion.hpp" #include "gc/g1/g1AllocationContext.hpp" #include "gc/g1/g1Allocator.hpp" #include "gc/g1/g1BiasedArray.hpp" @@ -193,7 +192,7 @@ class G1CollectedHeap : public CollectedHeap { // Closures used in implementation. friend class G1ParScanThreadState; friend class G1ParTask; - friend class G1ParGCAllocator; + friend class G1PLABAllocator; friend class G1PrepareCompactClosure; // Other related classes. @@ -248,7 +247,7 @@ private: // The sequence of all heap regions in the heap. HeapRegionManager _hrm; - // Class that handles the different kinds of allocations. + // Handles non-humongous allocations in the G1CollectedHeap. G1Allocator* _allocator; // Outside of GC pauses, the number of bytes used in all regions other @@ -280,22 +279,6 @@ private: // start of each GC. bool _expand_heap_after_alloc_failure; - // It resets the mutator alloc region before new allocations can take place. - void init_mutator_alloc_region(); - - // It releases the mutator alloc region. - void release_mutator_alloc_region(); - - // It initializes the GC alloc regions at the start of a GC. - void init_gc_alloc_regions(EvacuationInfo& evacuation_info); - - // It releases the GC alloc regions at the end of a GC. - void release_gc_alloc_regions(EvacuationInfo& evacuation_info); - - // It does any cleanup that needs to be done on the GC alloc regions - // before a Full GC. - void abandon_gc_alloc_regions(); - // Helper for monitoring and management support. G1MonitoringSupport* _g1mm; @@ -557,25 +540,6 @@ protected: // belongs to a young region. inline void dirty_young_block(HeapWord* start, size_t word_size); - // Allocate blocks during garbage collection. Will ensure an - // allocation region, either by picking one or expanding the - // heap, and then allocate a block of the given size. The block - // may not be a humongous - it must fit into a single heap region. - inline HeapWord* par_allocate_during_gc(InCSetState dest, - size_t word_size, - AllocationContext_t context); - // Ensure that no further allocations can happen in "r", bearing in mind - // that parallel threads might be attempting allocations. - void par_allocate_remaining_space(HeapRegion* r); - - // Allocation attempt during GC for a survivor object / PLAB. - inline HeapWord* survivor_attempt_allocation(size_t word_size, - AllocationContext_t context); - - // Allocation attempt during GC for an old object / PLAB. - inline HeapWord* old_attempt_allocation(size_t word_size, - AllocationContext_t context); - // These methods are the "callbacks" from the G1AllocRegion class. // For mutator alloc regions. @@ -725,6 +689,9 @@ public: G1HRPrinter* hr_printer() { return &_hr_printer; } + // Allocates a new heap region instance. + HeapRegion* new_heap_region(uint hrs_index, MemRegion mr); + // Frees a non-humongous region by initializing its contents and // adding it to the free list that's passed as a parameter (this is // usually a local list which will be appended to the master free @@ -1263,7 +1230,7 @@ public: // Return "TRUE" iff the given object address is within the collection // set. Slow implementation. - inline bool obj_in_cs(oop obj); + bool obj_in_cs(oop obj); inline bool is_in_cset(const HeapRegion *hr); inline bool is_in_cset(oop obj); diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index d35fcac0796..0911fe9f055 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -26,7 +26,6 @@ #define SHARE_VM_GC_G1_G1COLLECTEDHEAP_INLINE_HPP #include "gc/g1/concurrentMark.hpp" -#include "gc/g1/g1AllocRegion.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1CollectorState.hpp" @@ -57,20 +56,6 @@ size_t G1CollectedHeap::desired_plab_sz(InCSetState dest) { return MIN2(_humongous_object_threshold_in_words, gclab_word_size); } -HeapWord* G1CollectedHeap::par_allocate_during_gc(InCSetState dest, - size_t word_size, - AllocationContext_t context) { - switch (dest.value()) { - case InCSetState::Young: - return survivor_attempt_allocation(word_size, context); - case InCSetState::Old: - return old_attempt_allocation(word_size, context); - default: - ShouldNotReachHere(); - return NULL; // Keep some compilers happy - } -} - // Inline functions for G1CollectedHeap inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() { @@ -126,67 +111,6 @@ inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) { _old_set.remove(hr); } -inline bool G1CollectedHeap::obj_in_cs(oop obj) { - HeapRegion* r = _hrm.addr_to_region((HeapWord*) obj); - return r != NULL && r->in_collection_set(); -} - -inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, - uint* gc_count_before_ret, - uint* gclocker_retry_count_ret) { - assert_heap_not_locked_and_not_at_safepoint(); - assert(!is_humongous(word_size), "attempt_allocation() should not " - "be called for humongous allocation requests"); - - AllocationContext_t context = AllocationContext::current(); - HeapWord* result = _allocator->mutator_alloc_region(context)->attempt_allocation(word_size, - false /* bot_updates */); - if (result == NULL) { - result = attempt_allocation_slow(word_size, - context, - gc_count_before_ret, - gclocker_retry_count_ret); - } - assert_heap_not_locked(); - if (result != NULL) { - dirty_young_block(result, word_size); - } - return result; -} - -inline HeapWord* G1CollectedHeap::survivor_attempt_allocation(size_t word_size, - AllocationContext_t context) { - assert(!is_humongous(word_size), - "we should not be seeing humongous-size allocations in this path"); - - HeapWord* result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation(word_size, - false /* bot_updates */); - if (result == NULL) { - MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); - result = _allocator->survivor_gc_alloc_region(context)->attempt_allocation_locked(word_size, - false /* bot_updates */); - } - if (result != NULL) { - dirty_young_block(result, word_size); - } - return result; -} - -inline HeapWord* G1CollectedHeap::old_attempt_allocation(size_t word_size, - AllocationContext_t context) { - assert(!is_humongous(word_size), - "we should not be seeing humongous-size allocations in this path"); - - HeapWord* result = _allocator->old_gc_alloc_region(context)->attempt_allocation(word_size, - true /* bot_updates */); - if (result == NULL) { - MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); - result = _allocator->old_gc_alloc_region(context)->attempt_allocation_locked(word_size, - true /* bot_updates */); - } - return result; -} - // It dirties the cards that cover the block so that so that the post // write barrier never queues anything when updating objects on this // block. It is assumed (and in fact we assert) that the block diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp index 5c429bafda2..bb1dfc39893 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap_ext.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/heapRegion.inline.hpp" bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts, jlong* totals, @@ -31,3 +32,8 @@ bool G1CollectedHeap::copy_allocation_context_stats(const jint* contexts, jint len) { return false; } + +HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index, + MemRegion mr) { + return new HeapRegion(hrs_index, bot_shared(), mr); +} diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index cec6220d2e3..cae3e54bd3f 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -31,6 +31,7 @@ #include "gc/g1/g1ErgoVerbose.hpp" #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1Log.hpp" +#include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/gcPolicyCounters.hpp" #include "runtime/arguments.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp index e9e996c944b..a6f9ccafc35 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp @@ -31,6 +31,7 @@ #include "gc/g1/g1ParScanThreadState.inline.hpp" #include "gc/g1/g1RemSet.hpp" #include "gc/g1/g1RemSet.inline.hpp" +#include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "memory/iterator.inline.hpp" #include "runtime/prefetch.inline.hpp" diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index 75a512d0bd2..9b783fab8e4 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -59,7 +59,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM; memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t)); - _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h); + _plab_allocator = G1PLABAllocator::create_allocator(_g1h->allocator()); _dest[InCSetState::NotInCSet] = InCSetState::NotInCSet; // The dest for Young is used when the objects are aged enough to @@ -71,8 +71,8 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, } G1ParScanThreadState::~G1ParScanThreadState() { - _g1_par_allocator->retire_alloc_buffers(); - delete _g1_par_allocator; + _plab_allocator->retire_alloc_buffers(); + delete _plab_allocator; FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); } @@ -97,7 +97,7 @@ G1ParScanThreadState::print_termination_stats(int i, const double term_ms = term_time() * 1000.0; size_t alloc_buffer_waste = 0; size_t undo_waste = 0; - _g1_par_allocator->waste(alloc_buffer_waste, undo_waste); + _plab_allocator->waste(alloc_buffer_waste, undo_waste); st->print_cr("%3d %9.2f %9.2f %6.2f " "%9.2f %6.2f " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7), @@ -167,8 +167,9 @@ HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state, // Right now we only have two types of regions (young / old) so // let's keep the logic here simple. We can generalize it when necessary. if (dest->is_young()) { - HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old, - word_sz, context); + HeapWord* const obj_ptr = _plab_allocator->allocate(InCSetState::Old, + word_sz, + context); if (obj_ptr == NULL) { return NULL; } @@ -209,12 +210,12 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, uint age = 0; InCSetState dest_state = next_state(state, old_mark, age); - HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context); + HeapWord* obj_ptr = _plab_allocator->plab_allocate(dest_state, word_sz, context); // PLAB allocations should succeed most of the time, so we'll // normally check against NULL once and that's it. if (obj_ptr == NULL) { - obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context); + obj_ptr = _plab_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context); if (obj_ptr == NULL) { obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context); if (obj_ptr == NULL) { @@ -233,7 +234,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, if (_g1h->evacuation_should_fail()) { // Doing this after all the allocation attempts also tests the // undo_allocation() method too. - _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); + _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); return handle_evacuation_failure_par(old, old_mark); } #endif // !PRODUCT @@ -295,7 +296,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, } return obj; } else { - _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); + _plab_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); return forward_ptr; } } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp index d01517ff872..02ac3abc799 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp @@ -46,7 +46,7 @@ class G1ParScanThreadState : public StackObj { G1SATBCardTableModRefBS* _ct_bs; G1RemSet* _g1_rem; - G1ParGCAllocator* _g1_par_allocator; + G1PLABAllocator* _plab_allocator; ageTable _age_table; InCSetState _dest[InCSetState::Num]; diff --git a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp index f48a40da74b..fbe9aa743ff 100644 --- a/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RootProcessor.cpp @@ -34,6 +34,7 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1RemSet.inline.hpp" #include "gc/g1/g1RootProcessor.hpp" +#include "gc/g1/heapRegion.inline.hpp" #include "memory/allocation.inline.hpp" #include "runtime/fprofiler.hpp" #include "runtime/mutex.hpp" diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.hpp index 2b07a11bf5c..e7bccf0783a 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp @@ -497,20 +497,10 @@ class HeapRegion: public G1OffsetTableContigSpace { return _rem_set; } - bool in_collection_set() const; + inline bool in_collection_set() const; - HeapRegion* next_in_collection_set() { - assert(in_collection_set(), "should only invoke on member of CS."); - assert(_next_in_special_set == NULL || - _next_in_special_set->in_collection_set(), - "Malformed CS."); - return _next_in_special_set; - } - void set_next_in_collection_set(HeapRegion* r) { - assert(in_collection_set(), "should only invoke on member of CS."); - assert(r == NULL || r->in_collection_set(), "Malformed CS."); - _next_in_special_set = r; - } + inline HeapRegion* next_in_collection_set() const; + inline void set_next_in_collection_set(HeapRegion* r); void set_allocation_context(AllocationContext_t context) { _allocation_context = context; diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp index cd963a096d4..24c5b9783fa 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp @@ -26,7 +26,7 @@ #define SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP #include "gc/g1/g1BlockOffsetTable.inline.hpp" -#include "gc/g1/g1CollectedHeap.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/heapRegion.hpp" #include "gc/shared/space.hpp" #include "oops/oop.inline.hpp" @@ -200,4 +200,18 @@ inline bool HeapRegion::in_collection_set() const { return G1CollectedHeap::heap()->is_in_cset(this); } +inline HeapRegion* HeapRegion::next_in_collection_set() const { + assert(in_collection_set(), "should only invoke on member of CS."); + assert(_next_in_special_set == NULL || + _next_in_special_set->in_collection_set(), + "Malformed CS."); + return _next_in_special_set; +} + +void HeapRegion::set_next_in_collection_set(HeapRegion* r) { + assert(in_collection_set(), "should only invoke on member of CS."); + assert(r == NULL || r->in_collection_set(), "Malformed CS."); + _next_in_special_set = r; +} + #endif // SHARE_VM_GC_G1_HEAPREGION_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp index bdb82548871..0501f3237c2 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp @@ -70,7 +70,7 @@ HeapRegion* HeapRegionManager::new_heap_region(uint hrm_index) { HeapWord* bottom = g1h->bottom_addr_for_region(hrm_index); MemRegion mr(bottom, bottom + HeapRegion::GrainWords); assert(reserved().contains(mr), "invariant"); - return g1h->allocator()->new_heap_region(hrm_index, g1h->bot_shared(), mr); + return g1h->new_heap_region(hrm_index, mr); } void HeapRegionManager::commit_regions(uint index, size_t num_regions) { diff --git a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp index 90a74d367d5..316a14fbc72 100644 --- a/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc/g1/vm_operations_g1.cpp @@ -94,8 +94,9 @@ void VM_G1IncCollectionPause::doit() { if (_word_size > 0) { // An allocation has been requested. So, try to do that first. - _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(), - false /* expect_null_cur_alloc_region */); + _result = g1h->attempt_allocation_at_safepoint(_word_size, + allocation_context(), + false /* expect_null_cur_alloc_region */); if (_result != NULL) { // If we can successfully allocate before we actually do the // pause then we will consider this pause successful. @@ -147,8 +148,9 @@ void VM_G1IncCollectionPause::doit() { g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); if (_pause_succeeded && _word_size > 0) { // An allocation had been requested. - _result = g1h->attempt_allocation_at_safepoint(_word_size, allocation_context(), - true /* expect_null_cur_alloc_region */); + _result = g1h->attempt_allocation_at_safepoint(_word_size, + allocation_context(), + true /* expect_null_cur_alloc_region */); } else { assert(_result == NULL, "invariant"); if (!_pause_succeeded) { From 183850cec4dc479b49ff86f1f0fbe784cc7ebe46 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 6 Aug 2015 15:49:52 +0200 Subject: [PATCH 10/53] 8133043: Clean up code related to termination stats printing Reformat termination stats related code to make it look more similar to existing code. Reviewed-by: jwilhelm, jmasa --- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 14 +++++------- .../share/vm/gc/g1/g1ParScanThreadState.cpp | 22 ++++++------------- .../share/vm/gc/g1/g1ParScanThreadState.hpp | 5 ++++- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 3bcc7fcebda..d3d2314cf53 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4449,9 +4449,6 @@ protected: ParallelTaskTerminator _terminator; uint _n_workers; - Mutex _stats_lock; - Mutex* stats_lock() { return &_stats_lock; } - public: G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues, G1RootProcessor* root_processor, uint n_workers) : AbstractGangTask("G1 collection"), @@ -4459,8 +4456,7 @@ public: _queues(task_queues), _root_processor(root_processor), _terminator(n_workers, _queues), - _n_workers(n_workers), - _stats_lock(Mutex::leaf, "parallel G1 stats lock", true) + _n_workers(n_workers) {} RefToScanQueueSet* queues() { return _queues; } @@ -4587,8 +4583,8 @@ public: _g1h->update_surviving_young_words(pss.surviving_young_words()+1); if (PrintTerminationStats) { - MutexLocker x(stats_lock()); - pss.print_termination_stats(worker_id); + MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag); + pss.print_termination_stats(); } assert(pss.queue_is_empty(), "should be empty"); @@ -5504,7 +5500,9 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { } // The individual threads will set their evac-failure closures. - if (PrintTerminationStats) G1ParScanThreadState::print_termination_stats_hdr(); + if (PrintTerminationStats) { + G1ParScanThreadState::print_termination_stats_hdr(); + } workers()->run_task(&g1_par_task); end_par_time_sec = os::elapsedTime(); diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index 9b783fab8e4..49777178150 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -76,32 +76,24 @@ G1ParScanThreadState::~G1ParScanThreadState() { FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base); } -void -G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) -{ +void G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st) { st->print_raw_cr("GC Termination Stats"); - st->print_raw_cr(" elapsed --strong roots-- -------termination-------" - " ------waste (KiB)------"); - st->print_raw_cr("thr ms ms % ms % attempts" - " total alloc undo"); - st->print_raw_cr("--- --------- --------- ------ --------- ------ --------" - " ------- ------- -------"); + st->print_raw_cr(" elapsed --strong roots-- -------termination------- ------waste (KiB)------"); + st->print_raw_cr("thr ms ms % ms % attempts total alloc undo"); + st->print_raw_cr("--- --------- --------- ------ --------- ------ -------- ------- ------- -------"); } -void -G1ParScanThreadState::print_termination_stats(int i, - outputStream* const st) const -{ +void G1ParScanThreadState::print_termination_stats(outputStream* const st) const { const double elapsed_ms = elapsed_time() * 1000.0; const double s_roots_ms = strong_roots_time() * 1000.0; const double term_ms = term_time() * 1000.0; size_t alloc_buffer_waste = 0; size_t undo_waste = 0; _plab_allocator->waste(alloc_buffer_waste, undo_waste); - st->print_cr("%3d %9.2f %9.2f %6.2f " + st->print_cr("%3u %9.2f %9.2f %6.2f " "%9.2f %6.2f " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7), - i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, + _queue_num, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, term_ms, term_ms * 100 / elapsed_ms, term_attempts(), (alloc_buffer_waste + undo_waste) * HeapWordSize / K, alloc_buffer_waste * HeapWordSize / K, diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp index 02ac3abc799..59decc69eb3 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp @@ -139,8 +139,11 @@ class G1ParScanThreadState : public StackObj { return os::elapsedTime() - _start; } + // Print the header for the per-thread termination statistics. static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty); - void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const; + + // Print actual per-thread termination statistics. + void print_termination_stats(outputStream* const st = gclog_or_tty) const; size_t* surviving_young_words() { // We add on to hide entry 0 which accumulates surviving words for From c2d0a8dbd03ffc841945a45221ea77bef5ba72cf Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Thu, 6 Aug 2015 15:52:33 +0200 Subject: [PATCH 11/53] 8133047: Rename G1ParScanThreadState::_queue_num to _worker_id Reviewed-by: jmasa, jwilhelm --- hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 8 ++++---- hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp | 2 +- hotspot/src/share/vm/gc/g1/g1OopClosures.cpp | 2 +- hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp | 12 ++++++------ hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp | 7 +++---- .../share/vm/gc/g1/g1ParScanThreadState.inline.hpp | 4 ++-- 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index d3d2314cf53..47575010563 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -4285,18 +4285,18 @@ void G1CollectedHeap::remove_self_forwarding_pointers() { g1_policy()->phase_times()->record_evac_fail_remove_self_forwards((os::elapsedTime() - remove_self_forwards_start) * 1000.0); } -void G1CollectedHeap::preserve_mark_during_evac_failure(uint queue_num, oop obj, markOop m) { +void G1CollectedHeap::preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m) { if (!_evacuation_failed) { _evacuation_failed = true; } - _evacuation_failed_info_array[queue_num].register_copy_failure(obj->size()); + _evacuation_failed_info_array[worker_id].register_copy_failure(obj->size()); // We want to call the "for_promotion_failure" version only in the // case of a promotion failure. if (m->must_be_preserved_for_promotion_failure(obj)) { OopAndMarkOop elem(obj, m); - _preserved_objs[queue_num].push(elem); + _preserved_objs[worker_id].push(elem); } } @@ -4340,7 +4340,7 @@ void G1ParCopyClosure::do_oop_work(T* p) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - assert(_worker_id == _par_scan_state->queue_num(), "sanity"); + assert(_worker_id == _par_scan_state->worker_id(), "sanity"); const InCSetState state = _g1->in_cset_state(obj); if (state.is_in_cset()) { diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 73f1f114566..d17ee55b52c 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -854,7 +854,7 @@ protected: // Preserve the mark of "obj", if necessary, in preparation for its mark // word being overwritten with a self-forwarding-pointer. - void preserve_mark_during_evac_failure(uint queue, oop obj, markOop m); + void preserve_mark_during_evac_failure(uint worker_id, oop obj, markOop m); #ifndef PRODUCT // Support for forcing evacuation failures. Analogous to diff --git a/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp b/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp index b314e45627b..ba41f2c9b70 100644 --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.cpp @@ -48,7 +48,7 @@ void G1ParClosureSuper::set_par_scan_thread_state(G1ParScanThreadState* par_scan assert(par_scan_state != NULL, "Must set par_scan_state to non-NULL."); _par_scan_state = par_scan_state; - _worker_id = par_scan_state->queue_num(); + _worker_id = par_scan_state->worker_id(); assert(_worker_id < ParallelGCThreads, err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, ParallelGCThreads)); diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index 49777178150..87471f2ab99 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -31,13 +31,13 @@ #include "oops/oop.inline.hpp" #include "runtime/prefetch.inline.hpp" -G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp) +G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp) : _g1h(g1h), - _refs(g1h->task_queue(queue_num)), + _refs(g1h->task_queue(worker_id)), _dcq(&g1h->dirty_card_queue_set()), _ct_bs(g1h->g1_barrier_set()), _g1_rem(g1h->g1_rem_set()), - _hash_seed(17), _queue_num(queue_num), + _hash_seed(17), _worker_id(worker_id), _term_attempts(0), _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()), _age_table(false), _scanner(g1h, rp), @@ -93,7 +93,7 @@ void G1ParScanThreadState::print_termination_stats(outputStream* const st) const st->print_cr("%3u %9.2f %9.2f %6.2f " "%9.2f %6.2f " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7), - _queue_num, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, + _worker_id, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms, term_ms, term_ms * 100 / elapsed_ms, term_attempts(), (alloc_buffer_waste + undo_waste) * HeapWordSize / K, alloc_buffer_waste * HeapWordSize / K, @@ -267,7 +267,7 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, "sanity"); G1StringDedup::enqueue_from_evacuation(is_from_young, is_to_young, - queue_num(), + _worker_id, obj); } @@ -307,7 +307,7 @@ oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) { _g1h->hr_printer()->evac_failure(r); } - _g1h->preserve_mark_during_evac_failure(_queue_num, old, m); + _g1h->preserve_mark_during_evac_failure(_worker_id, old, m); _scanner.set_region(r); old->oop_iterate_backwards(&_scanner); diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp index 59decc69eb3..2652eda3388 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp @@ -55,7 +55,7 @@ class G1ParScanThreadState : public StackObj { G1ParScanClosure _scanner; int _hash_seed; - uint _queue_num; + uint _worker_id; size_t _term_attempts; @@ -85,7 +85,7 @@ class G1ParScanThreadState : public StackObj { } public: - G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); + G1ParScanThreadState(G1CollectedHeap* g1h, uint worker_id, ReferenceProcessor* rp); ~G1ParScanThreadState(); ageTable* age_table() { return &_age_table; } @@ -112,8 +112,7 @@ class G1ParScanThreadState : public StackObj { } } - int* hash_seed() { return &_hash_seed; } - uint queue_num() { return _queue_num; } + uint worker_id() { return _worker_id; } size_t term_attempts() const { return _term_attempts; } void note_term_attempt() { _term_attempts++; } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp index 0a1b3d055c2..c213745be4b 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.inline.hpp @@ -56,7 +56,7 @@ template void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from } assert(obj != NULL, "Must be"); - update_rs(from, p, queue_num()); + update_rs(from, p, _worker_id); } template inline void G1ParScanThreadState::push_on_queue(T* ref) { @@ -136,7 +136,7 @@ inline void G1ParScanThreadState::dispatch_reference(StarTask ref) { void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) { StarTask stolen_task; - while (task_queues->steal(queue_num(), hash_seed(), stolen_task)) { + while (task_queues->steal(_worker_id, &_hash_seed, stolen_task)) { assert(verify_task(stolen_task), "sanity"); dispatch_reference(stolen_task); From 7983a4235c25ccab161a0b659a9cac0f5c99ed0a Mon Sep 17 00:00:00 2001 From: Karen Kinnear Date: Thu, 6 Aug 2015 13:02:15 -0400 Subject: [PATCH 12/53] 8087342: Crash in klassItable::initialize_itable_for_interface Fix method searches to handle static, private instance and overpass Reviewed-by: lfoltan, dholmes, hseigel --- .../src/share/vm/interpreter/linkResolver.cpp | 7 +- hotspot/src/share/vm/oops/instanceKlass.cpp | 71 +++-- hotspot/src/share/vm/oops/instanceKlass.hpp | 37 ++- hotspot/src/share/vm/oops/klass.hpp | 1 + hotspot/src/share/vm/oops/klassVtable.cpp | 125 ++++---- .../TestStaticandInstance.java | 272 ++++++++++++++++++ 6 files changed, 435 insertions(+), 78 deletions(-) create mode 100644 hotspot/test/runtime/lambda-features/TestStaticandInstance.java diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index d3a97225c20..07c63c9b343 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -379,7 +379,8 @@ int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, if (!resolved_method->is_abstract() && (InstanceKlass::cast(klass())->default_methods() != NULL)) { int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), - name, signature, Klass::find_overpass, Klass::find_static); + name, signature, Klass::find_overpass, + Klass::find_static, Klass::find_private); if (index >= 0 ) { vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); } @@ -1189,7 +1190,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, assert(resolved_method->method_holder()->is_linked(), "must be linked"); // do lookup based on receiver klass using the vtable index - if (resolved_method->method_holder()->is_interface()) { // miranda method + if (resolved_method->method_holder()->is_interface()) { // default or miranda method vtable_index = vtable_index_of_interface_method(resolved_klass, resolved_method); assert(vtable_index >= 0 , "we should have valid vtable index at this point"); @@ -1198,7 +1199,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); } else { // at this point we are sure that resolved_method is virtual and not - // a miranda method; therefore, it must have a valid vtable index. + // a default or miranda method; therefore, it must have a valid vtable index. assert(!resolved_method->has_itable_index(), ""); vtable_index = resolved_method->vtable_index(); // We could get a negative vtable_index for final methods, diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 63a1b1fa4f3..0aa1c431bbb 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -1381,12 +1381,14 @@ static int binary_search(Array* methods, Symbol* name) { // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const { - return find_method_impl(name, signature, find_overpass, find_static); + return find_method_impl(name, signature, find_overpass, find_static, find_private); } Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, - OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const { - return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode); + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode) const { + return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode); } // find_instance_method looks up the name/signature in the local methods array @@ -1394,7 +1396,7 @@ Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, Method* InstanceKlass::find_instance_method( Array* methods, Symbol* name, Symbol* signature) { Method* meth = InstanceKlass::find_method_impl(methods, name, signature, - find_overpass, skip_static); + find_overpass, skip_static, find_private); assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics"); return meth; } @@ -1405,22 +1407,51 @@ Method* InstanceKlass::find_instance_method(Symbol* name, Symbol* signature) { return InstanceKlass::find_instance_method(methods(), name, signature); } +// Find looks up the name/signature in the local methods array +// and filters on the overpass, static and private flags +// This returns the first one found +// note that the local methods array can have up to one overpass, one static +// and one instance (private or not) with the same name/signature +Method* InstanceKlass::find_local_method(Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode) const { + return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode); +} + +// Find looks up the name/signature in the local methods array +// and filters on the overpass, static and private flags +// This returns the first one found +// note that the local methods array can have up to one overpass, one static +// and one instance (private or not) with the same name/signature +Method* InstanceKlass::find_local_method(Array* methods, + Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode) { + return InstanceKlass::find_method_impl(methods, name, signature, overpass_mode, static_mode, private_mode); +} + + // find_method looks up the name/signature in the local methods array Method* InstanceKlass::find_method( Array* methods, Symbol* name, Symbol* signature) { - return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static); + return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static, find_private); } Method* InstanceKlass::find_method_impl( - Array* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) { - int hit = find_method_index(methods, name, signature, overpass_mode, static_mode); + Array* methods, Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode, + PrivateLookupMode private_mode) { + int hit = find_method_index(methods, name, signature, overpass_mode, static_mode, private_mode); return hit >= 0 ? methods->at(hit): NULL; } -bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static) { - return (m->signature() == signature) && +bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private) { + return ((m->signature() == signature) && (!skipping_overpass || !m->is_overpass()) && - (!skipping_static || !m->is_static()); + (!skipping_static || !m->is_static()) && + (!skipping_private || !m->is_private())); } // Used directly for default_methods to find the index into the @@ -1430,17 +1461,25 @@ bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_o // the search continues to find a potential non-overpass match. This capability // is important during method resolution to prefer a static method, for example, // over an overpass method. +// There is the possibility in any _method's array to have the same name/signature +// for a static method, an overpass method and a local instance method +// To correctly catch a given method, the search criteria may need +// to explicitly skip the other two. For local instance methods, it +// is often necessary to skip private methods int InstanceKlass::find_method_index( - Array* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) { + Array* methods, Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, StaticLookupMode static_mode, + PrivateLookupMode private_mode) { bool skipping_overpass = (overpass_mode == skip_overpass); bool skipping_static = (static_mode == skip_static); + bool skipping_private = (private_mode == skip_private); int hit = binary_search(methods, name); if (hit != -1) { Method* m = methods->at(hit); // Do linear search to find matching signature. First, quick check // for common case, ignoring overpasses if requested. - if (method_matches(m, signature, skipping_overpass, skipping_static)) return hit; + if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return hit; // search downwards through overloaded methods int i; @@ -1448,18 +1487,18 @@ int InstanceKlass::find_method_index( Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (method_matches(m, signature, skipping_overpass, skipping_static)) return i; + if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i; } // search upwards for (i = hit + 1; i < methods->length(); ++i) { Method* m = methods->at(i); assert(m->is_method(), "must be method"); if (m->name() != name) break; - if (method_matches(m, signature, skipping_overpass, skipping_static)) return i; + if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i; } // not found #ifdef ASSERT - int index = (skipping_overpass || skipping_static) ? -1 : linear_search(methods, name, signature); + int index = (skipping_overpass || skipping_static || skipping_private) ? -1 : linear_search(methods, name, signature); assert(index == -1, err_msg("binary search should have found entry %d", index)); #endif } @@ -1489,7 +1528,7 @@ Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, O OverpassLookupMode overpass_local_mode = overpass_mode; Klass* klass = const_cast(this); while (klass != NULL) { - Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static); + Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static, find_private); if (method != NULL) { return method; } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 141ec1139e6..4529b40d390 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -503,12 +503,28 @@ class InstanceKlass: public Klass { Method* find_instance_method(Symbol* name, Symbol* signature); static Method* find_instance_method(Array* methods, Symbol* name, Symbol* signature); - // true if method matches signature and conforms to skipping_X conditions. - static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static); + // find a local method (returns NULL if not found) + Method* find_local_method(Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode) const; - // find a local method index in default_methods (returns -1 if not found) - static int find_method_index(Array* methods, Symbol* name, Symbol* signature, - OverpassLookupMode overpass_mode, StaticLookupMode static_mode); + // find a local method from given methods array (returns NULL if not found) + static Method* find_local_method(Array* methods, + Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode); + + // true if method matches signature and conforms to skipping_X conditions. + static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private); + + // find a local method index in methods or default_methods (returns -1 if not found) + static int find_method_index(Array* methods, + Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode); // lookup operation (returns NULL if not found) Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const; @@ -1153,9 +1169,14 @@ private: // find a local method (returns NULL if not found) Method* find_method_impl(Symbol* name, Symbol* signature, - OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const; - static Method* find_method_impl(Array* methods, Symbol* name, Symbol* signature, - OverpassLookupMode overpass_mode, StaticLookupMode static_mode); + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode) const; + static Method* find_method_impl(Array* methods, + Symbol* name, Symbol* signature, + OverpassLookupMode overpass_mode, + StaticLookupMode static_mode, + PrivateLookupMode private_mode); // Free CHeap allocated fields. void release_C_heap_structures(); diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 57648b363b6..48267d54ce2 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -161,6 +161,7 @@ protected: enum DefaultsLookupMode { find_defaults, skip_defaults }; enum OverpassLookupMode { find_overpass, skip_overpass }; enum StaticLookupMode { find_static, skip_static }; + enum PrivateLookupMode { find_private, skip_private }; bool is_klass() const volatile { return true; } diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index 54df450637b..545dbd467ae 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -683,7 +683,6 @@ bool klassVtable::is_miranda_entry_at(int i) { if (mhk->is_interface()) { assert(m->is_public(), "should be public"); assert(ik()->implements_interface(method_holder) , "this class should implement the interface"); - // the search could find a miranda or a default method if (is_miranda(m, ik()->methods(), ik()->default_methods(), ik()->super())) { return true; } @@ -691,25 +690,57 @@ bool klassVtable::is_miranda_entry_at(int i) { return false; } -// check if a method is a miranda method, given a class's methods table, -// its default_method table and its super -// Miranda methods are calculated twice: -// first: before vtable size calculation: including abstract and superinterface default +// Check if a method is a miranda method, given a class's methods array, +// its default_method table and its super class. +// "Miranda" means an abstract non-private method that would not be +// overridden for the local class. +// A "miranda" method should only include non-private interface +// instance methods, i.e. not private methods, not static methods, +// not default methods (concrete interface methods), not overpass methods. +// If a given class already has a local (including overpass) method, a +// default method, or any of its superclasses has the same which would have +// overridden an abstract method, then this is not a miranda method. +// +// Miranda methods are checked multiple times. +// Pass 1: during class load/class file parsing: before vtable size calculation: +// include superinterface abstract and default methods (non-private instance). // We include potential default methods to give them space in the vtable. -// During the first run, the default_methods list is empty -// This is seen by default method creation -// Second: recalculated during vtable initialization: only include abstract methods. +// During the first run, the current instanceKlass has not yet been +// created, the superclasses and superinterfaces do have instanceKlasses +// but may not have vtables, the default_methods list is empty, no overpasses. +// This is seen by default method creation. +// +// Pass 2: recalculated during vtable initialization: only include abstract methods. +// The goal of pass 2 is to walk through the superinterfaces to see if any of +// the superinterface methods (which were all abstract pre-default methods) +// need to be added to the vtable. +// With the addition of default methods, we have three new challenges: +// overpasses, static interface methods and private interface methods. +// Static and private interface methods do not get added to the vtable and +// are not seen by the method resolution process, so we skip those. +// Overpass methods are already in the vtable, so vtable lookup will +// find them and we don't need to add a miranda method to the end of +// the vtable. So we look for overpass methods and if they are found we +// return false. Note that we inherit our superclasses vtable, so +// the superclass' search also needs to use find_overpass so that if +// one is found we return false. +// False means - we don't need a miranda method added to the vtable. +// // During the second run, default_methods is set up, so concrete methods from // superinterfaces with matching names/signatures to default_methods are already // in the default_methods list and do not need to be appended to the vtable -// as mirandas -// This is seen by link resolution and selection. -// "miranda" means not static, not defined by this class. -// private methods in interfaces do not belong in the miranda list. -// the caller must make sure that the method belongs to an interface implemented by the class -// Miranda methods only include public interface instance methods -// Not private methods, not static methods, not default == concrete abstract -// Miranda methods also do not include overpass methods in interfaces +// as mirandas. Abstract methods may already have been handled via +// overpasses - either local or superclass overpasses, which may be +// in the vtable already. +// +// Pass 3: They are also checked by link resolution and selection, +// for invocation on a method (not interface method) reference that +// resolves to a method with an interface as its method_holder. +// Used as part of walking from the bottom of the vtable to find +// the vtable index for the miranda method. +// +// Part of the Miranda Rights in the US mean that if you do not have +// an attorney one will be appointed for you. bool klassVtable::is_miranda(Method* m, Array* class_methods, Array* default_methods, Klass* super) { if (m->is_static() || m->is_private() || m->is_overpass()) { @@ -717,44 +748,36 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods, } Symbol* name = m->name(); Symbol* signature = m->signature(); - Method* mo; - if ((mo = InstanceKlass::find_instance_method(class_methods, name, signature)) == NULL) { - // did not find it in the method table of the current class - if ((default_methods == NULL) || - InstanceKlass::find_method(default_methods, name, signature) == NULL) { - if (super == NULL) { - // super doesn't exist - return true; - } - - mo = InstanceKlass::cast(super)->lookup_method(name, signature); - while (mo != NULL && mo->access_flags().is_static() - && mo->method_holder() != NULL - && mo->method_holder()->super() != NULL) - { - mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::find_overpass); - } - if (mo == NULL || mo->access_flags().is_private() ) { - // super class hierarchy does not implement it or protection is different - return true; - } - } - } else { - // if the local class has a private method, the miranda will not - // override it, so a vtable slot is needed - if (mo->access_flags().is_private()) { - - // Second round, weed out any superinterface methods that turned - // into default methods, i.e. were concrete not abstract in the end - if ((default_methods == NULL) || - InstanceKlass::find_method(default_methods, name, signature) == NULL) { - return true; - } - } + // First look in local methods to see if already covered + if (InstanceKlass::find_local_method(class_methods, name, signature, + Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) + { + return false; } - return false; + // Check local default methods + if ((default_methods != NULL) && + (InstanceKlass::find_method(default_methods, name, signature) != NULL)) + { + return false; + } + + InstanceKlass* cursuper; + // Iterate on all superclasses, which should have instanceKlasses + // Note that we explicitly look for overpasses at each level. + // Overpasses may or may not exist for supers for pass 1, + // they should have been created for pass 2 and later. + + for (cursuper = InstanceKlass::cast(super); cursuper != NULL; cursuper = (InstanceKlass*)cursuper->super()) + { + if (cursuper->find_local_method(name, signature, + Klass::find_overpass, Klass::skip_static, Klass::skip_private) != NULL) { + return false; + } + } + + return true; } // Scans current_interface_methods for miranda methods that do not diff --git a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java new file mode 100644 index 00000000000..021ac48bf8a --- /dev/null +++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, 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 8087342 + * @summary Test linkresolver search static, instance and overpass duplicates + * @run main/othervm -Xverify:none TestStaticandInstance + */ + + +import java.util.*; +import jdk.internal.org.objectweb.asm.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +public class TestStaticandInstance { + static final String stringC = "C"; + static final String stringD = "D"; + static final String stringI = "I"; + + public static void main(String args[]) throws Throwable { + ClassLoader cl = new ClassLoader() { + public Class loadClass(String name) throws ClassNotFoundException { + Class retClass; + if ((retClass = findLoadedClass(name)) != null) { + return retClass; + } + if (stringC.equals(name)) { + byte[] classFile=dumpC(); + return defineClass(stringC, classFile, 0, classFile.length); + } + if (stringD.equals(name)) { + byte[] classFile=dumpD(); + return defineClass(stringD, classFile, 0, classFile.length); + } + if (stringI.equals(name)) { + byte[] classFile=dumpI(); + return defineClass(stringI, classFile, 0, classFile.length); + } + return super.loadClass(name); + } + }; + + Class classC = cl.loadClass(stringC); + Class classI = cl.loadClass(stringI); + + try { + int staticret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallStatic").invoke(null); + if (staticret != 1) { + throw new RuntimeException("invokestatic failed to call correct method"); + } + System.out.println("staticret: " + staticret); // should be 1 + + int invokeinterfaceret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallInterface").invoke(null); + if (invokeinterfaceret != 0) { + throw new RuntimeException(String.format("Expected java.lang.AbstractMethodError, got %d", invokeinterfaceret)); + } + System.out.println("invokeinterfaceret: AbstractMethodError"); + + int invokevirtualret = (Integer)cl.loadClass(stringD).getDeclaredMethod("CallVirtual").invoke(null); + if (invokevirtualret != 0) { + throw new RuntimeException(String.format("Expected java.lang.IncompatibleClassChangeError, got %d", invokevirtualret)); + } + System.out.println("invokevirtualret: IncompatibleClassChangeError"); + } catch (java.lang.Throwable e) { + throw new RuntimeException("Unexpected exception: " + e.getMessage()); + } + } + +/* +interface I { + public int m(); // abstract + default int q() { return 3; } // trigger defmeth processing: C gets AME overpass +} + +// C gets static, private and AME overpass m()I with -Xverify:none +class C implements I { + static int m() { return 1;} // javac with "n()" and patch to "m()" + private int m() { return 2;} // javac with public and patch to private +} + +public class D { + public static int CallStatic() { + int staticret = C.m(); // javac with "C.n" and patch to "C.m" + return staticret; + } + public static int CallInterface() throws AbstractMethodError{ + try { + I myI = new C(); + return myI.m(); + } catch (java.lang.AbstractMethodError e) { + return 0; // for success + } + } + public static int CallVirtual() { + try { + C myC = new C(); + return myC.m(); + } catch (java.lang.IncompatibleClassChangeError e) { + return 0; // for success + } + } +} +*/ + + public static byte[] dumpC() { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(52, ACC_SUPER, "C", null, "java/lang/Object", new String[] { "I" }); + + { + mv = cw.visitMethod(0, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_STATIC, "m", "()I", null, null); + mv.visitCode(); + mv.visitInsn(ICONST_1); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 0); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); + mv.visitCode(); + mv.visitInsn(ICONST_2); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + public static byte[] dumpD () { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(52, ACC_PUBLIC + ACC_SUPER, "D", null, "java/lang/Object", null); + + { + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallStatic", "()I", null, null); + mv.visitCode(); + mv.visitMethodInsn(INVOKESTATIC, "C", "m", "()I", false); + mv.visitVarInsn(ISTORE, 0); + mv.visitVarInsn(ILOAD, 0); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallInterface", "()I", null, new String[] { "java/lang/AbstractMethodError" }); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, "java/lang/AbstractMethodError"); + mv.visitLabel(l0); + mv.visitTypeInsn(NEW, "C"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "C", "", "()V", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEINTERFACE, "I", "m", "()I", true); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/AbstractMethodError"}); + mv.visitVarInsn(ASTORE, 0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "CallVirtual", "()I", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, "java/lang/IncompatibleClassChangeError"); + mv.visitLabel(l0); + mv.visitTypeInsn(NEW, "C"); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, "C", "", "()V", false); + mv.visitVarInsn(ASTORE, 0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKEVIRTUAL, "C", "m", "()I", false); + mv.visitLabel(l1); + mv.visitInsn(IRETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {"java/lang/IncompatibleClassChangeError"}); + mv.visitVarInsn(ASTORE, 0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } + + public static byte[] dumpI() { + + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + AnnotationVisitor av0; + + cw.visit(52, ACC_ABSTRACT + ACC_INTERFACE, "I", null, "java/lang/Object", null); + + { + mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "m", "()I", null, null); + mv.visitEnd(); + } + { + mv = cw.visitMethod(ACC_PUBLIC, "q", "()I", null, null); + mv.visitCode(); + mv.visitInsn(ICONST_3); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + cw.visitEnd(); + + return cw.toByteArray(); + } +} From bcca305c14cfb6aaeb152f6700e1c9a5a40d03c0 Mon Sep 17 00:00:00 2001 From: Eric Caspole Date: Fri, 7 Aug 2015 09:15:42 -0400 Subject: [PATCH 13/53] 8078904: CMS: Assert failed: Ctl pt invariant Survivor rescan array now baed on MinTLABSize so all entries will fit Reviewed-by: tschatzl, kbarrett --- .../vm/gc/cms/concurrentMarkSweepGeneration.cpp | 12 +++--------- .../vm/gc/cms/concurrentMarkSweepGeneration.hpp | 4 ---- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 831ddf581d7..87242cf495e 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -620,12 +620,12 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, // Support for parallelizing survivor space rescan if ((CMSParallelRemarkEnabled && CMSParallelSurvivorRemarkEnabled) || CMSParallelInitialMarkEnabled) { const size_t max_plab_samples = - ((DefNewGeneration*)_young_gen)->max_survivor_size() / plab_sample_minimum_size(); + _young_gen->max_survivor_size() / (ThreadLocalAllocBuffer::min_size() * HeapWordSize); _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC); - _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC); + _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC); _cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads, mtGC); - _survivor_chunk_capacity = 2*max_plab_samples; + _survivor_chunk_capacity = max_plab_samples; for (uint i = 0; i < ParallelGCThreads; i++) { HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC); ChunkArray* cur = ::new (&_survivor_plab_array[i]) ChunkArray(vec, max_plab_samples); @@ -641,12 +641,6 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _inter_sweep_timer.start(); // start of time } -size_t CMSCollector::plab_sample_minimum_size() { - // The default value of MinTLABSize is 2k, but there is - // no way to get the default value if the flag has been overridden. - return MAX2(ThreadLocalAllocBuffer::min_size() * HeapWordSize, 2 * K); -} - const char* ConcurrentMarkSweepGeneration::name() const { return "concurrent mark-sweep generation"; } diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp index ff4c5ea138d..36e2c2f65c9 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp @@ -739,10 +739,6 @@ class CMSCollector: public CHeapObj { size_t* _cursor; ChunkArray* _survivor_plab_array; - // A bounded minimum size of PLABs, should not return too small values since - // this will affect the size of the data structures used for parallel young gen rescan - size_t plab_sample_minimum_size(); - // Support for marking stack overflow handling bool take_from_overflow_list(size_t num, CMSMarkStack* to_stack); bool par_take_from_overflow_list(size_t num, From c6cfb3a7fddcea4d3c653e4b5aa0f72ca8520877 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Fri, 7 Aug 2015 15:37:07 +0200 Subject: [PATCH 14/53] 8133042: Remove some direct accesses of G1Allocator to G1CollectedHeap members Remove direct access to private members of G1CollectedHeap from G1Allocator and G1ArchiveAllocator. Allows removal of friend delcarations. Reviewed-by: kbarrett, jmasa, jwilhelm --- hotspot/src/share/vm/gc/g1/g1Allocator.cpp | 8 +++---- .../src/share/vm/gc/g1/g1CollectedHeap.cpp | 1 - .../src/share/vm/gc/g1/g1CollectedHeap.hpp | 23 +++++++++---------- .../share/vm/gc/g1/g1CollectedHeap.inline.hpp | 4 ++++ 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp index 02216782b9f..a32544f4eb2 100644 --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp @@ -67,11 +67,11 @@ void G1Allocator::reuse_retained_old_region(EvacuationInfo& evacuation_info, // retired. We have to remove it now, since we don't allow regions // we allocate to in the region sets. We'll re-add it later, when // it's retired again. - _g1h->_old_set.remove(retained_region); + _g1h->old_set_remove(retained_region); bool during_im = _g1h->collector_state()->during_initial_mark_pause(); retained_region->note_start_of_copying(during_im); old->set(retained_region); - _g1h->_hr_printer.reuse(retained_region); + _g1h->hr_printer()->reuse(retained_region); evacuation_info.set_alloc_regions_used_before(retained_region->used()); } } @@ -264,8 +264,8 @@ bool G1ArchiveAllocator::alloc_new_region() { } assert(hr->is_empty(), err_msg("expected empty region (index %u)", hr->hrm_index())); hr->set_archive(); - _g1h->_old_set.add(hr); - _g1h->_hr_printer.alloc(hr, G1HRPrinter::Archive); + _g1h->old_set_add(hr); + _g1h->hr_printer()->alloc(hr, G1HRPrinter::Archive); _allocated_regions.append(hr); _allocation_region = hr; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 47575010563..2fec93a7dfe 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -6495,7 +6495,6 @@ HeapRegion* G1CollectedHeap::alloc_highest_free_region() { return NULL; } - // Heap region set verification class VerifyRegionListsClosure : public HeapRegionClosure { diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index d17ee55b52c..e4b4045808d 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -186,8 +186,6 @@ class G1CollectedHeap : public CollectedHeap { friend class MutatorAllocRegion; friend class SurvivorGCAllocRegion; friend class OldGCAllocRegion; - friend class G1Allocator; - friend class G1ArchiveAllocator; // Closures used in implementation. friend class G1ParScanThreadState; @@ -534,12 +532,6 @@ protected: AllocationContext_t context, bool expect_null_mutator_alloc_region); - // It dirties the cards that cover the block so that so that the post - // write barrier never queues anything when updating objects on this - // block. It is assumed (and in fact we assert) that the block - // belongs to a young region. - inline void dirty_young_block(HeapWord* start, size_t word_size); - // These methods are the "callbacks" from the G1AllocRegion class. // For mutator alloc regions. @@ -553,10 +545,6 @@ protected: void retire_gc_alloc_region(HeapRegion* alloc_region, size_t allocated_bytes, InCSetState dest); - // Allocate the highest free region in the reserved heap. This will commit - // regions as necessary. - HeapRegion* alloc_highest_free_region(); - // - if explicit_gc is true, the GC is for a System.gc() or a heap // inspection request and should collect the entire heap // - if clear_all_soft_refs is true, all soft references should be @@ -692,6 +680,10 @@ public: // Allocates a new heap region instance. HeapRegion* new_heap_region(uint hrs_index, MemRegion mr); + // Allocate the highest free region in the reserved heap. This will commit + // regions as necessary. + HeapRegion* alloc_highest_free_region(); + // Frees a non-humongous region by initializing its contents and // adding it to the free list that's passed as a parameter (this is // usually a local list which will be appended to the master free @@ -705,6 +697,12 @@ public: bool par, bool locked = false); + // It dirties the cards that cover the block so that the post + // write barrier never queues anything when updating objects on this + // block. It is assumed (and in fact we assert) that the block + // belongs to a young region. + inline void dirty_young_block(HeapWord* start, size_t word_size); + // Frees a humongous region by collapsing it into individual regions // and calling free_region() for each of them. The freed regions // will be added to the free list that's passed as a parameter (this @@ -1183,6 +1181,7 @@ public: } } + inline void old_set_add(HeapRegion* hr); inline void old_set_remove(HeapRegion* hr); size_t non_young_capacity_bytes() { diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp index 0911fe9f055..e8d4b8ee160 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp @@ -107,6 +107,10 @@ inline void G1CollectedHeap::increment_gc_time_stamp() { OrderAccess::fence(); } +inline void G1CollectedHeap::old_set_add(HeapRegion* hr) { + _old_set.add(hr); +} + inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) { _old_set.remove(hr); } From 6ee89e55d57c132eba23c33220a6319538e49977 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Fri, 7 Aug 2015 09:21:32 -0700 Subject: [PATCH 15/53] 8033577: [parfait] warnings from b128 for hotspot/src/os/solaris/dtrace: Unportable format string argument mismatch Reduce the warnings Reviewed-by: sla, dsamersoff, coleenp --- hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp | 6 +++--- hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp index 8fd9e727b17..4d695aea251 100644 --- a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp @@ -108,7 +108,7 @@ StubQueue* AbstractInterpreter::_code = NULL; #define GEN_SIZE(Type) \ switch(gen_variant) { \ case GEN_OFFSET: \ - printf("#define SIZE_%-35s %ld\n", \ + printf("#define SIZE_%-35s %ld\n", \ #Type, sizeof(Type)); \ break; \ case GEN_INDEX: \ @@ -228,10 +228,10 @@ int generateJvmOffsets(GEN_variant gen_variant) { printf("\n"); GEN_OFFS(Method, _constMethod); - GEN_OFFS(Method, _constants); GEN_OFFS(Method, _access_flags); printf("\n"); + GEN_OFFS(ConstMethod, _constants); GEN_OFFS(ConstMethod, _flags); GEN_OFFS(ConstMethod, _code_size); GEN_OFFS(ConstMethod, _name_index); @@ -264,7 +264,7 @@ int generateJvmOffsets(GEN_variant gen_variant) { GEN_OFFS(nmethod, _method); GEN_OFFS(nmethod, _dependencies_offset); - GEN_OFFS(nmethod, _oops_offset); + GEN_OFFS(nmethod, _metadata_offset); GEN_OFFS(nmethod, _scopes_data_offset); GEN_OFFS(nmethod, _scopes_pcs_offset); GEN_OFFS(nmethod, _handler_table_offset); diff --git a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp index ac66ccba240..c145be3a85e 100644 --- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp @@ -85,7 +85,7 @@ StubQueue* AbstractInterpreter::_code = NULL; #define GEN_OFFS_NAME(Type,Name,OutputType) \ switch(gen_variant) { \ case GEN_OFFSET: \ - printf("#define OFFSET_%-33s %d\n", \ + printf("#define OFFSET_%-33s %ld\n", \ #OutputType #Name, offset_of(Type, Name)); \ break; \ case GEN_INDEX: \ @@ -103,7 +103,7 @@ StubQueue* AbstractInterpreter::_code = NULL; #define GEN_SIZE(Type) \ switch(gen_variant) { \ case GEN_OFFSET: \ - printf("#define SIZE_%-35s %d\n", \ + printf("#define SIZE_%-35s %ld\n", \ #Type, sizeof(Type)); \ break; \ case GEN_INDEX: \ @@ -211,7 +211,7 @@ int generateJvmOffsets(GEN_variant gen_variant) { GEN_OFFS(ConstantPool, _pool_holder); printf("\n"); - GEN_VALUE(OFFSET_HeapBlockHeader_used, offset_of(HeapBlock::Header, _used)); + GEN_VALUE(OFFSET_HeapBlockHeader_used, (int) offset_of(HeapBlock::Header, _used)); GEN_OFFS(oopDesc, _metadata); printf("\n"); @@ -275,7 +275,7 @@ int generateJvmOffsets(GEN_variant gen_variant) { GEN_OFFS(NarrowPtrStruct, _shift); printf("\n"); - GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header)); + GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header)); GEN_SIZE(oopDesc); GEN_SIZE(ConstantPool); printf("\n"); From 4f489580d7bec0b6dcf96cc4bf43183e697d8bbc Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Fri, 7 Aug 2015 09:22:29 -0700 Subject: [PATCH 16/53] 8080401: Uninitialised variable in hotspot/src/os/solaris/dtrace/ Reduce the warnings Reviewed-by: sla, dsamersoff --- hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp | 2 +- hotspot/src/os/bsd/dtrace/jvm_dtrace.c | 7 +++---- hotspot/src/os/bsd/dtrace/libjvm_db.c | 2 +- hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp | 2 +- hotspot/src/os/solaris/dtrace/jvm_dtrace.c | 7 +++---- hotspot/src/os/solaris/dtrace/libjvm_db.c | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp index 4d695aea251..6e012a9bee1 100644 --- a/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/bsd/dtrace/generateJvmOffsets.cpp @@ -134,7 +134,7 @@ StubQueue* AbstractInterpreter::_code = NULL; } void gen_prologue(GEN_variant gen_variant) { - const char *suffix; + const char *suffix = "Undefined-Suffix"; switch(gen_variant) { case GEN_OFFSET: suffix = ".h"; break; diff --git a/hotspot/src/os/bsd/dtrace/jvm_dtrace.c b/hotspot/src/os/bsd/dtrace/jvm_dtrace.c index 36d8b61b19f..58fc9197c7e 100644 --- a/hotspot/src/os/bsd/dtrace/jvm_dtrace.c +++ b/hotspot/src/os/bsd/dtrace/jvm_dtrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, 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 @@ -227,7 +227,7 @@ static void delete_attach_file(pid_t pid) { /* attach to given JVM */ jvm_t* jvm_attach(pid_t pid) { jvm_t* jvm; - int door_fd, attach_fd, i; + int door_fd, attach_fd, i = 0; jvm = (jvm_t*) calloc(1, sizeof(jvm_t)); if (jvm == NULL) { @@ -292,14 +292,13 @@ const char* jvm_get_last_error() { /* detach the givenb JVM */ int jvm_detach(jvm_t* jvm) { if (jvm) { - int res; + int res = 0; if (jvm->door_fd != -1) { if (file_close(jvm->door_fd) != 0) { set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR); res = -1; } else { clear_jvm_error(); - res = 0; } } free(jvm); diff --git a/hotspot/src/os/bsd/dtrace/libjvm_db.c b/hotspot/src/os/bsd/dtrace/libjvm_db.c index b483733f9ef..87a9afe24ff 100644 --- a/hotspot/src/os/bsd/dtrace/libjvm_db.c +++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c @@ -882,7 +882,7 @@ get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) /* Finds a PcDesc with real-pc equal to N->pc */ static int pc_desc_at(Nmethod_t *N) { - uint64_t pc_diff; + uint64_t pc_diff = 999; int32_t offs; int32_t err; diff --git a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp index c145be3a85e..ddd74b16d9e 100644 --- a/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp +++ b/hotspot/src/os/solaris/dtrace/generateJvmOffsets.cpp @@ -129,7 +129,7 @@ StubQueue* AbstractInterpreter::_code = NULL; } void gen_prologue(GEN_variant gen_variant) { - const char *suffix; + const char *suffix = "Undefined-Suffix"; switch(gen_variant) { case GEN_OFFSET: suffix = ".h"; break; diff --git a/hotspot/src/os/solaris/dtrace/jvm_dtrace.c b/hotspot/src/os/solaris/dtrace/jvm_dtrace.c index 36d8b61b19f..58fc9197c7e 100644 --- a/hotspot/src/os/solaris/dtrace/jvm_dtrace.c +++ b/hotspot/src/os/solaris/dtrace/jvm_dtrace.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2015, 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 @@ -227,7 +227,7 @@ static void delete_attach_file(pid_t pid) { /* attach to given JVM */ jvm_t* jvm_attach(pid_t pid) { jvm_t* jvm; - int door_fd, attach_fd, i; + int door_fd, attach_fd, i = 0; jvm = (jvm_t*) calloc(1, sizeof(jvm_t)); if (jvm == NULL) { @@ -292,14 +292,13 @@ const char* jvm_get_last_error() { /* detach the givenb JVM */ int jvm_detach(jvm_t* jvm) { if (jvm) { - int res; + int res = 0; if (jvm->door_fd != -1) { if (file_close(jvm->door_fd) != 0) { set_jvm_error(JVM_ERR_CANT_CLOSE_DOOR); res = -1; } else { clear_jvm_error(); - res = 0; } } free(jvm); diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c index 1f24b8719ad..6bad77b68bb 100644 --- a/hotspot/src/os/solaris/dtrace/libjvm_db.c +++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c @@ -882,7 +882,7 @@ get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) /* Finds a PcDesc with real-pc equal to N->pc */ static int pc_desc_at(Nmethod_t *N) { - uint64_t pc_diff; + uint64_t pc_diff = 999; int32_t offs; int32_t err; From 15b4d3eff9aa63d8d7d7cf72eb3c5a0361132259 Mon Sep 17 00:00:00 2001 From: Mikhailo Seledtsov Date: Fri, 7 Aug 2015 17:14:26 -0700 Subject: [PATCH 17/53] 8133222: [TESTBUG] Quarantine runtime/SharedArchiveFile/SharedStrings.java until the fix Quarantined using at-ingore tag Reviewed-by: dcubed --- hotspot/test/runtime/SharedArchiveFile/SharedStrings.java | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java index 895f65261fc..2078949d659 100644 --- a/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java +++ b/hotspot/test/runtime/SharedArchiveFile/SharedStrings.java @@ -32,6 +32,7 @@ * @library /testlibrary /../../test/lib * @modules java.base/sun.misc * java.management + * @ignore - 8133180 * @build SharedStringsWb SharedStrings BasicJarBuilder * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main SharedStrings From d364e5d1916f699254927026c0797ecb4315c512 Mon Sep 17 00:00:00 2001 From: Dmitry Dmitriev Date: Sun, 9 Aug 2015 13:38:24 +0300 Subject: [PATCH 18/53] 8132892: Memory must be freed after calling Arguments::set_sysclasspath function Free memory after calling set_sysclasspath Reviewed-by: dholmes, dcubed --- hotspot/src/share/vm/runtime/arguments.cpp | 4 +++- hotspot/src/share/vm/runtime/os.cpp | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 45043cc7371..e56a9f98ba3 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3305,7 +3305,9 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req if (scp_assembly_required) { // Assemble the bootclasspath elements into the final path. - Arguments::set_sysclasspath(scp_p->combined_path()); + char *combined_path = scp_p->combined_path(); + Arguments::set_sysclasspath(combined_path); + FREE_C_HEAP_ARRAY(char, combined_path); } // This must be done after all arguments have been processed. diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index bf10f5ab3c2..068bcacdc12 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1271,6 +1271,7 @@ bool os::set_boot_path(char fileSep, char pathSep) { bool has_jimage = (os::stat(jimage, &st) == 0); if (has_jimage) { Arguments::set_sysclasspath(jimage); + FREE_C_HEAP_ARRAY(char, jimage); return true; } FREE_C_HEAP_ARRAY(char, jimage); @@ -1282,6 +1283,7 @@ bool os::set_boot_path(char fileSep, char pathSep) { sysclasspath = expand_entries_to_path(modules_dir, fileSep, pathSep); } } + FREE_C_HEAP_ARRAY(char, modules_dir); // fallback to classes if (sysclasspath == NULL) @@ -1289,6 +1291,7 @@ bool os::set_boot_path(char fileSep, char pathSep) { if (sysclasspath == NULL) return false; Arguments::set_sysclasspath(sysclasspath); + FREE_C_HEAP_ARRAY(char, sysclasspath); return true; } From 27436603478b80002c5b0ccb68c8b789b482d0da Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Mon, 10 Aug 2015 13:08:53 +0200 Subject: [PATCH 19/53] 8076470: Remove the JVM TI hprof Agent Reviewed-by: sspitsyn, mchung, erikj --- common/bin/compare_exceptions.sh.incl | 21 --------------------- make/Images.gmk | 2 +- modules.xml | 4 ---- 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index 9c23a64222b..79ef2f2c6d9 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -42,7 +42,6 @@ STRIP_BEFORE_COMPARE=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -54,7 +53,6 @@ ACCEPTED_BIN_DIFF=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -62,9 +60,7 @@ ACCEPTED_BIN_DIFF=" ./lib/i386/client/libjvm.so ./lib/i386/libattach.so ./lib/i386/libdt_socket.so -./lib/i386/libhprof.so ./lib/i386/libinstrument.so -./lib/i386/libjava_crw_demo.so ./lib/i386/libjsdt.so ./lib/i386/libmanagement.so ./lib/i386/libnpt.so @@ -118,7 +114,6 @@ STRIP_BEFORE_COMPARE=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -130,16 +125,13 @@ ACCEPTED_BIN_DIFF=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so ./demo/jvmti/waiters/lib/libwaiters.so ./lib/amd64/libattach.so ./lib/amd64/libdt_socket.so -./lib/amd64/libhprof.so ./lib/amd64/libinstrument.so -./lib/amd64/libjava_crw_demo.so ./lib/amd64/libjsdt.so ./lib/amd64/libjsig.so ./lib/amd64/libmanagement.so @@ -197,7 +189,6 @@ STRIP_BEFORE_COMPARE=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -217,7 +208,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -232,7 +222,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./lib/amd64/libdcpr.so ./lib/amd64/libdt_socket.so ./lib/amd64/libfontmanager.so -./lib/amd64/libhprof.so ./lib/amd64/libinstrument.so ./lib/amd64/libj2gss.so ./lib/amd64/libj2pcsc.so @@ -240,7 +229,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./lib/amd64/libj2ucrypto.so ./lib/amd64/libjaas_unix.so ./lib/amd64/libjava.so -./lib/amd64/libjava_crw_demo.so ./lib/amd64/libjawt.so ./lib/amd64/libjdwp.so ./lib/amd64/libjfr.so @@ -330,7 +318,6 @@ STRIP_BEFORE_COMPARE=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -353,7 +340,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./demo/jvmti/gctest/lib/libgctest.so ./demo/jvmti/heapTracker/lib/libheapTracker.so ./demo/jvmti/heapViewer/lib/libheapViewer.so -./demo/jvmti/hprof/lib/libhprof.so ./demo/jvmti/minst/lib/libminst.so ./demo/jvmti/mtrace/lib/libmtrace.so ./demo/jvmti/versionCheck/lib/libversionCheck.so @@ -369,7 +355,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./lib/sparcv9/libdcpr.so ./lib/sparcv9/libdt_socket.so ./lib/sparcv9/libfontmanager.so -./lib/sparcv9/libhprof.so ./lib/sparcv9/libinstrument.so ./lib/sparcv9/libj2gss.so ./lib/sparcv9/libj2pcsc.so @@ -377,7 +362,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./lib/sparcv9/libj2ucrypto.so ./lib/sparcv9/libjaas_unix.so ./lib/sparcv9/libjava.so -./lib/sparcv9/libjava_crw_demo.so ./lib/sparcv9/libjawt.so ./lib/sparcv9/libjdwp.so ./lib/sparcv9/libjfr.so @@ -473,7 +457,6 @@ ACCEPTED_SMALL_SIZE_DIFF=" ./demo/jvmti/heapTracker/lib/heapTracker.dll ./demo/jvmti/minst/lib/minst.dll ./bin/attach.dll -./bin/java_crw_demo.dll ./bin/jsoundds.dll ./bin/server/jvm.dll ./bin/appletviewer.exe @@ -611,9 +594,7 @@ ACCEPTED_BIN_DIFF=" ./Contents/Home/lib/libawt_lwawt.dylib ./Contents/Home/lib/libdeploy.dylib ./Contents/Home/lib/libdt_socket.dylib -./Contents/Home/lib/libhprof.dylib ./Contents/Home/lib/libinstrument.dylib -./Contents/Home/lib/libjava_crw_demo.dylib ./Contents/Home/lib/libjdwp.dylib ./Contents/Home/lib/libjsdt.dylib ./Contents/Home/lib/libjsig.dylib @@ -635,9 +616,7 @@ ACCEPTED_BIN_DIFF=" ./lib/libawt_lwawt.dylib ./lib/libdeploy.dylib ./lib/libdt_socket.dylib -./lib/libhprof.dylib ./lib/libinstrument.dylib -./lib/libjava_crw_demo.dylib ./lib/libjdwp.dylib ./lib/libjsdt.dylib ./lib/libjsig.dylib diff --git a/make/Images.gmk b/make/Images.gmk index 0dfba0f509e..d26688cad3d 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -47,7 +47,7 @@ PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk # tools TOOLS_MODULES += jdk.attach jdk.compiler jdk.dev jdk.internal.le jdk.javadoc jdk.jcmd jdk.jconsole \ - jdk.hotspot.agent jdk.hprof.agent jdk.jartool jdk.jdeps jdk.jdi jdk.jdwp.agent \ + jdk.hotspot.agent jdk.jartool jdk.jdeps jdk.jdi jdk.jdwp.agent \ jdk.policytool jdk.rmic jdk.xml.bind jdk.xml.ws ifeq ($(OPENJDK_TARGET_OS), windows) diff --git a/modules.xml b/modules.xml index 5188fd4c42e..e6bdf1ef2a9 100644 --- a/modules.xml +++ b/modules.xml @@ -1622,10 +1622,6 @@ java.scripting jdk.jdi - - jdk.hprof.agent - java.base - jdk.httpserver java.base From 781b67580f801ec87375a8759d0264742b6bcec5 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Mon, 10 Aug 2015 13:08:54 +0200 Subject: [PATCH 20/53] 8076470: Remove the JVM TI hprof Agent Reviewed-by: sspitsyn, mchung, erikj --- hotspot/src/share/vm/runtime/arguments.cpp | 24 +++++++++------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index e56a9f98ba3..de5af848735 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -2295,13 +2295,13 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs *java_tool_options_args, } // Checks if name in command-line argument -agent{lib,path}:name[=options] -// represents a valid HPROF of JDWP agent. is_path==true denotes that we +// represents a valid JDWP agent. is_path==true denotes that we // are dealing with -agentpath (case where name is a path), otherwise with // -agentlib -bool valid_hprof_or_jdwp_agent(char *name, bool is_path) { +bool valid_jdwp_agent(char *name, bool is_path) { char *_name; - const char *_hprof = "hprof", *_jdwp = "jdwp"; - size_t _len_hprof, _len_jdwp, _len_prefix; + const char *_jdwp = "jdwp"; + size_t _len_jdwp, _len_prefix; if (is_path) { if ((_name = strrchr(name, (int) *os::file_separator())) == NULL) { @@ -2316,13 +2316,9 @@ bool valid_hprof_or_jdwp_agent(char *name, bool is_path) { } _name += _len_prefix; - _len_hprof = strlen(_hprof); _len_jdwp = strlen(_jdwp); - if (strncmp(_name, _hprof, _len_hprof) == 0) { - _name += _len_hprof; - } - else if (strncmp(_name, _jdwp, _len_jdwp) == 0) { + if (strncmp(_name, _jdwp, _len_jdwp) == 0) { _name += _len_jdwp; } else { @@ -2336,7 +2332,7 @@ bool valid_hprof_or_jdwp_agent(char *name, bool is_path) { return true; } - if (strcmp(name, _hprof) == 0 || strcmp(name, _jdwp) == 0) { + if (strcmp(name, _jdwp) == 0) { return true; } @@ -2427,9 +2423,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2); } #if !INCLUDE_JVMTI - if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) { + if (strcmp(name, "jdwp") == 0) { jio_fprintf(defaultStream::error_stream(), - "Profiling and debugging agents are not supported in this VM\n"); + "Debugging agents are not supported in this VM\n"); return JNI_ERR; } #endif // !INCLUDE_JVMTI @@ -2449,9 +2445,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, options = os::strdup_check_oom(pos + 1, mtInternal); } #if !INCLUDE_JVMTI - if (valid_hprof_or_jdwp_agent(name, is_absolute_path)) { + if (valid_jdwp_agent(name, is_absolute_path)) { jio_fprintf(defaultStream::error_stream(), - "Profiling and debugging agents are not supported in this VM\n"); + "Debugging agents are not supported in this VM\n"); return JNI_ERR; } #endif // !INCLUDE_JVMTI From de0713848b576beacabdea54bb88b76b47d85b71 Mon Sep 17 00:00:00 2001 From: Staffan Larsen Date: Mon, 10 Aug 2015 13:08:55 +0200 Subject: [PATCH 21/53] 8076470: Remove the JVM TI hprof Agent Reviewed-by: sspitsyn, mchung, erikj --- jdk/make/copy/Copy-jdk.hprof.agent.gmk | 37 - jdk/make/lib/Lib-jdk.hprof.agent.gmk | 94 - jdk/make/mapfiles/libhprof/mapfile-vers | 34 - .../mapfiles/libjava_crw_demo/mapfile-vers | 34 - .../classes/build/tools/module/boot.modules | 1 - jdk/src/java.base/share/native/libjli/java.c | 9 - .../aix/native/libhprof/porting_aix.c | 86 - .../aix/native/libhprof/porting_aix.h | 59 - .../com/sun/demo/jvmti/hprof/Tracker.java | 124 - .../share/native/libhprof/README.txt | 113 - .../share/native/libhprof/debug_malloc.c | 769 ------ .../share/native/libhprof/debug_malloc.h | 85 - .../share/native/libhprof/hprof.h | 401 --- .../share/native/libhprof/hprof_b_spec.h | 371 --- .../share/native/libhprof/hprof_blocks.c | 163 -- .../share/native/libhprof/hprof_blocks.h | 62 - .../share/native/libhprof/hprof_check.c | 1152 --------- .../share/native/libhprof/hprof_check.h | 58 - .../share/native/libhprof/hprof_class.c | 686 ------ .../share/native/libhprof/hprof_class.h | 77 - .../share/native/libhprof/hprof_cpu.c | 238 -- .../share/native/libhprof/hprof_cpu.h | 50 - .../share/native/libhprof/hprof_error.c | 215 -- .../share/native/libhprof/hprof_error.h | 102 - .../share/native/libhprof/hprof_event.c | 450 ---- .../share/native/libhprof/hprof_event.h | 60 - .../share/native/libhprof/hprof_frame.c | 210 -- .../share/native/libhprof/hprof_frame.h | 54 - .../share/native/libhprof/hprof_init.c | 2145 ----------------- .../share/native/libhprof/hprof_init.h | 47 - .../share/native/libhprof/hprof_io.c | 1980 --------------- .../share/native/libhprof/hprof_io.h | 169 -- .../share/native/libhprof/hprof_ioname.c | 71 - .../share/native/libhprof/hprof_ioname.h | 48 - .../share/native/libhprof/hprof_listener.c | 436 ---- .../share/native/libhprof/hprof_listener.h | 47 - .../share/native/libhprof/hprof_loader.c | 270 --- .../share/native/libhprof/hprof_loader.h | 51 - .../share/native/libhprof/hprof_md.h | 77 - .../share/native/libhprof/hprof_monitor.c | 442 ---- .../share/native/libhprof/hprof_monitor.h | 60 - .../share/native/libhprof/hprof_object.c | 324 --- .../share/native/libhprof/hprof_object.h | 62 - .../share/native/libhprof/hprof_reference.c | 814 ------- .../share/native/libhprof/hprof_reference.h | 57 - .../share/native/libhprof/hprof_site.c | 905 ------- .../share/native/libhprof/hprof_site.h | 56 - .../share/native/libhprof/hprof_stack.c | 170 -- .../share/native/libhprof/hprof_stack.h | 61 - .../share/native/libhprof/hprof_string.c | 115 - .../share/native/libhprof/hprof_string.h | 51 - .../share/native/libhprof/hprof_table.c | 954 -------- .../share/native/libhprof/hprof_table.h | 75 - .../share/native/libhprof/hprof_tag.c | 134 - .../share/native/libhprof/hprof_tag.h | 53 - .../share/native/libhprof/hprof_tls.c | 1190 --------- .../share/native/libhprof/hprof_tls.h | 89 - .../share/native/libhprof/hprof_trace.c | 869 ------- .../share/native/libhprof/hprof_trace.h | 74 - .../share/native/libhprof/hprof_tracker.c | 320 --- .../share/native/libhprof/hprof_tracker.h | 84 - .../share/native/libhprof/hprof_util.c | 1738 ------------- .../share/native/libhprof/hprof_util.h | 199 -- .../share/native/libhprof/jvm.hprof.txt | 86 - .../share/native/libhprof/manual.html | 1737 ------------- .../unix/native/libhprof/hprof_md.c | 453 ---- .../windows/native/libhprof/hprof_md.c | 450 ---- jdk/test/tools/pack200/CommandLineTests.java | 1 - 68 files changed, 22758 deletions(-) delete mode 100644 jdk/make/copy/Copy-jdk.hprof.agent.gmk delete mode 100644 jdk/make/lib/Lib-jdk.hprof.agent.gmk delete mode 100644 jdk/make/mapfiles/libhprof/mapfile-vers delete mode 100644 jdk/make/mapfiles/libjava_crw_demo/mapfile-vers delete mode 100644 jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c delete mode 100644 jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h delete mode 100644 jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_io.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_ioname.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_listener.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_loader.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_md.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_monitor.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_object.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_reference.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_site.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_stack.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_string.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_table.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tag.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tls.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_trace.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_tracker.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.c delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_util.h delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt delete mode 100644 jdk/src/jdk.hprof.agent/share/native/libhprof/manual.html delete mode 100644 jdk/src/jdk.hprof.agent/unix/native/libhprof/hprof_md.c delete mode 100644 jdk/src/jdk.hprof.agent/windows/native/libhprof/hprof_md.c diff --git a/jdk/make/copy/Copy-jdk.hprof.agent.gmk b/jdk/make/copy/Copy-jdk.hprof.agent.gmk deleted file mode 100644 index f738867240c..00000000000 --- a/jdk/make/copy/Copy-jdk.hprof.agent.gmk +++ /dev/null @@ -1,37 +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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -include CopyCommon.gmk - -################################################################################ - -HPROF_SRC := $(JDK_TOPDIR)/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt - -$(LIB_DST_DIR)/jvm.hprof.txt: $(HPROF_SRC) - $(call install-file) - -TARGETS := $(LIB_DST_DIR)/jvm.hprof.txt - -################################################################################ diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk deleted file mode 100644 index c6d1bbd1d04..00000000000 --- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk +++ /dev/null @@ -1,94 +0,0 @@ -# -# Copyright (c) 2011, 2015, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -include LibCommon.gmk - -################################################################################ - -BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof) - -BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \ - -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo - -BUILD_LIBHPROF_LDFLAGS := - -LIBHPROF_OPTIMIZATION := HIGHEST -ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), ) - ifeq ($(ENABLE_DEBUG_SYMBOLS), true) - LIBHPROF_OPTIMIZATION := LOW - endif -endif - -$(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \ - LIBRARY := hprof, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(BUILD_LIBHPROF_SRC), \ - OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(BUILD_LIBHPROF_CFLAGS), \ - CFLAGS_debug := -DHPROF_LOGGING, \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libhprof/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_windows := wsock32.lib winmm.lib advapi32.lib, \ - LDFLAGS_SUFFIX_linux := $(LIBDL), \ - LDFLAGS_SUFFIX_macosx := $(LIBDL), \ - LDFLAGS_SUFFIX_solaris := -lsocket -lnsl $(LIBDL) -lc, \ - VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=hprof.dll" \ - -D "JDK_INTERNAL_NAME=hprof" \ - -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libhprof_jvmti, \ - DEBUG_SYMBOLS := true)) - -TARGETS += $(BUILD_LIBHPROF) - -################################################################################ - -LIBJAVA_CRW_DEMO_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo - -$(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \ - LIBRARY := java_crw_demo, \ - OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(LIBJAVA_CRW_DEMO_SRC), \ - OPTIMIZATION := LOW, \ - CFLAGS := $(CFLAGS_JDKLIB) \ - $(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \ - MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjava_crw_demo/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ - $(call SET_SHARED_LIBRARY_ORIGIN), \ - LDFLAGS_SUFFIX_solaris := -lc, \ - VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=java_crw_demo.dll" \ - -D "JDK_INTERNAL_NAME=java_crw_demo" \ - -D "JDK_FTYPE=0x2L", \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava_crw_demo, \ - DEBUG_SYMBOLS := true)) - -TARGETS += $(BUILD_LIBJAVA_CRW_DEMO) - -################################################################################ diff --git a/jdk/make/mapfiles/libhprof/mapfile-vers b/jdk/make/mapfiles/libhprof/mapfile-vers deleted file mode 100644 index 1873c4f210a..00000000000 --- a/jdk/make/mapfiles/libhprof/mapfile-vers +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright (c) 2003, 2013, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# Define public interface. - -SUNWprivate_1.1 { - global: - Agent_OnLoad; - Agent_OnUnload; - local: - *; -}; diff --git a/jdk/make/mapfiles/libjava_crw_demo/mapfile-vers b/jdk/make/mapfiles/libjava_crw_demo/mapfile-vers deleted file mode 100644 index b9b31f7b106..00000000000 --- a/jdk/make/mapfiles/libjava_crw_demo/mapfile-vers +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright (c) 2004, 2013, 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# 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. -# - -# Define public interface. - -SUNWprivate_1.1 { - global: - java_crw_demo; - java_crw_demo_classname; - local: - *; -}; diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index b77e400e4ed..6830c6c8335 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -19,7 +19,6 @@ java.xml.crypto jdk.charsets jdk.deploy jdk.deploy.osx -jdk.hprof.agent jdk.httpserver jdk.jfr jdk.management diff --git a/jdk/src/java.base/share/native/libjli/java.c b/jdk/src/java.base/share/native/libjli/java.c index 64deecadec4..313f26b7c84 100644 --- a/jdk/src/java.base/share/native/libjli/java.c +++ b/jdk/src/java.base/share/native/libjli/java.c @@ -1082,15 +1082,6 @@ ParseArguments(int *pargc, char ***pargv, AddOption("-Xverify:remote", NULL); } else if (JLI_StrCmp(arg, "-noverify") == 0) { AddOption("-Xverify:none", NULL); - } else if (JLI_StrCCmp(arg, "-prof") == 0) { - char *p = arg + 5; - char *tmp = JLI_MemAlloc(JLI_StrLen(arg) + 50); - if (*p) { - sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1); - } else { - sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof"); - } - AddOption(tmp, NULL); } else if (JLI_StrCCmp(arg, "-ss") == 0 || JLI_StrCCmp(arg, "-oss") == 0 || JLI_StrCCmp(arg, "-ms") == 0 || diff --git a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c b/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c deleted file mode 100644 index 659d9c4c06b..00000000000 --- a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2012, 2013 SAP AG. 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. - * - */ - -#include -#include -#include - -#include "porting_aix.h" - -static unsigned char dladdr_buffer[0x4000]; - -static void fill_dll_info(void) { - int rc = loadquery(L_GETINFO,dladdr_buffer, sizeof(dladdr_buffer)); - if (rc == -1) { - fprintf(stderr, "loadquery failed (%d %s)", errno, strerror(errno)); - fflush(stderr); - } -} - -static int dladdr_dont_reload(void* addr, Dl_info* info) { - const struct ld_info* p = (struct ld_info*) dladdr_buffer; - info->dli_fbase = 0; info->dli_fname = 0; - info->dli_sname = 0; info->dli_saddr = 0; - for (;;) { - if (addr >= p->ldinfo_textorg && - addr < (((char*)p->ldinfo_textorg) + p->ldinfo_textsize)) { - info->dli_fname = p->ldinfo_filename; - info->dli_fbase = p->ldinfo_textorg; - return 1; /* [sic] */ - } - if (!p->ldinfo_next) { - break; - } - p = (struct ld_info*)(((char*)p) + p->ldinfo_next); - } - return 0; /* [sic] */ -} - -#ifdef __cplusplus -extern "C" -#endif -int dladdr(void *addr, Dl_info *info) { - static int loaded = 0; - if (!loaded) { - fill_dll_info(); - loaded = 1; - } - if (!addr) { - return 0; /* [sic] */ - } - /* Address could be AIX function descriptor? */ - void* const addr0 = *( (void**) addr ); - int rc = dladdr_dont_reload(addr, info); - if (rc == 0) { - rc = dladdr_dont_reload(addr0, info); - if (rc == 0) { /* [sic] */ - fill_dll_info(); /* refill, maybe loadquery info is outdated */ - rc = dladdr_dont_reload(addr, info); - if (rc == 0) { - rc = dladdr_dont_reload(addr0, info); - } - } - } - return rc; -} diff --git a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h b/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h deleted file mode 100644 index 79d1062dd67..00000000000 --- a/jdk/src/jdk.hprof.agent/aix/native/libhprof/porting_aix.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2012, 2013 SAP AG. 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. - * - */ - -/* - * Header file to contain porting-relevant code which does not have a - * home anywhere else. - * This is intially based on hotspot/src/os/aix/vm/{loadlib,porting}_aix.{hpp,cpp} - */ - -/* - * Aix' own version of dladdr(). - * This function tries to mimick dladdr(3) on Linux - * (see http://linux.die.net/man/3/dladdr) - * dladdr(3) is not POSIX but a GNU extension, and is not available on AIX. - * - * Differences between AIX dladdr and Linux dladdr: - * - * 1) Dl_info.dli_fbase: can never work, is disabled. - * A loaded image on AIX is divided in multiple segments, at least two - * (text and data) but potentially also far more. This is because the loader may - * load each member into an own segment, as for instance happens with the libC.a - * 2) Dl_info.dli_sname: This only works for code symbols (functions); for data, a - * zero-length string is returned (""). - * 3) Dl_info.dli_saddr: For code, this will return the entry point of the function, - * not the function descriptor. - */ - -typedef struct { - const char *dli_fname; /* file path of loaded library */ - void *dli_fbase; /* doesn't make sence on AIX */ - const char *dli_sname; /* symbol name; "" if not known */ - void *dli_saddr; /* address of *entry* of function; not function descriptor; */ -} Dl_info; - -#ifdef __cplusplus -extern "C" -#endif -int dladdr(void *addr, Dl_info *info); diff --git a/jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java b/jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java deleted file mode 100644 index dc3d61b5eb9..00000000000 --- a/jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof/Tracker.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.demo.jvmti.hprof; - -/* This class and it's methods are used by hprof when injecting bytecodes - * into class file images. - * See the directory src/share/demo/jvmti/hprof and the file README.txt - * for more details. - */ - -public class Tracker { - - /* Master switch that activates calls to native functions. */ - - private static int engaged = 0; - - /* To track memory allocated, we need to catch object init's and arrays. */ - - /* At the beginning of java.jang.Object.(), a call to - * Tracker.ObjectInit() is injected. - */ - - private static native void nativeObjectInit(Object thr, Object obj); - - public static void ObjectInit(Object obj) - { - if ( engaged != 0) { - if (obj == null) { - throw new IllegalArgumentException("Null object."); - } - nativeObjectInit(Thread.currentThread(), obj); - } - } - - /* Immediately following any of the newarray bytecodes, a call to - * Tracker.NewArray() is injected. - */ - - private static native void nativeNewArray(Object thr, Object obj); - - public static void NewArray(Object obj) - { - if ( engaged != 0) { - if (obj == null) { - throw new IllegalArgumentException("Null object."); - } - nativeNewArray(Thread.currentThread(), obj); - } - } - - /* For cpu time spent in methods, we need to inject for every method. */ - - /* At the very beginning of every method, a call to - * Tracker.CallSite() is injected. - */ - - private static native void nativeCallSite(Object thr, int cnum, int mnum); - - public static void CallSite(int cnum, int mnum) - { - if ( engaged != 0 ) { - if (cnum < 0) { - throw new IllegalArgumentException("Negative class index"); - } - - if (mnum < 0) { - throw new IllegalArgumentException("Negative method index"); - } - - nativeCallSite(Thread.currentThread(), cnum, mnum); - } - } - - /* Before any of the return bytecodes, a call to - * Tracker.ReturnSite() is injected. - */ - - private static native void nativeReturnSite(Object thr, int cnum, int mnum); - - public static void ReturnSite(int cnum, int mnum) - { - if ( engaged != 0 ) { - if (cnum < 0) { - throw new IllegalArgumentException("Negative class index"); - } - - if (mnum < 0) { - throw new IllegalArgumentException("Negative method index"); - } - - nativeReturnSite(Thread.currentThread(), cnum, mnum); - } - } - -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt b/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt deleted file mode 100644 index b57b287c634..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/README.txt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -README ------- - -Design and Implementation: - - * The Tracker Class (Tracker.java & hprof_tracker.c) - It was added to the sun.tools.hprof.Tracker in JDK 5.0 FCS, then - moved to a package that didn't cause classload errors due to - the security manager not liking the sun.* package name. - 5091195 detected that this class needs to be in com.sun.demo.jvmti.hprof. - The BCI code will call these static methods, which will in turn - (if engaged) call matching native methods in the hprof library, - with the additional current Thread argument (Thread.currentThread()). - Doing the currentThread call on the Java side was necessary due - to the difficulty of getting the current thread while inside one - of these Tracker native methods. This class lives in rt.jar. - - * Byte Code Instrumentation (BCI) - Using the ClassFileLoadHook feature and a C language - implementation of a byte code injection transformer, the following - bytecodes get injections: - - On entry to the java.lang.Object method, - a invokestatic call to - Tracker.ObjectInit(this); - is injected. - - On any newarray type opcode, immediately following it, - the array object is duplicated on the stack and an - invokestatic call to - Tracker.NewArray(obj); - is injected. - - On entry to all methods, a invokestatic call to - Tracker.CallSite(cnum,mnum); - is injected. The hprof agent can map the two integers - (cnum,mnum) to a method in a class. This is the BCI based - "method entry" event. - - On return from any method (any return opcode), - a invokestatic call to - Tracker.ReturnSite(cnum,mnum); - is injected. - All classes found via ClassFileLoadHook are injected with the - exception of some system class methods "" and "finalize" - whose length is 1 and system class methods with name "", - and also java.lang.Thread.currentThread() which is used in the - class Tracker (preventing nasty recursion issue). - System classes are currently defined as any class seen by the - ClassFileLoadHook prior to VM_INIT. This does mean that - objects created in the system classes inside might not - get tracked initially. - See the java_crw_demo source and documentation for more info. - The injections are based on what the hprof options - are requesting, e.g. if heap=sites or heap=all is requested, the - newarray and Object. method injections happen. - If cpu=times is requested, all methods get their entries and - returns tracked. Options like cpu=samples or monitor=y - do not require BCI. - - * BCI Allocation Tags (hprof_tag.c) - The current jlong tag being used on allocated objects - is an ObjectIndex, or an index into the object table inside - the hprof code. Depending on whether heap=sites or heap=dump - was asked for, these ObjectIndex's might represent unique - objects, or unique allocation sites for types of objects. - The heap=dump option requires considerable more space - due to the one jobject per ObjectIndex mapping. - - * BCI Performance - The cpu=times seems to have the most negative affect on - performance, this could be improved by not having the - Tracker class methods call native code directly, but accumulate - the data in a file or memory somehow and letting it buffer down - to the agent. The cpu=samples is probably a better way to - measure cpu usage, varying the interval as needed. - The heap=dump seems to use memory like crazy, but that's - partially the way it has always been. - - * Sources in the JDK workspace - The sources and Makefiles live in: - src/jdk.hprof.agent/* - src/share/demo/jvmti/java_crw_demo/* - make/lib/Lib-jdk.hprof.agent.gmk - --------- diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c deleted file mode 100644 index b130c166866..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.c +++ /dev/null @@ -1,769 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* ************************************************************************** - * - * Set of malloc/realloc/calloc/strdup/free replacement macros that - * insert some extra words around each allocation for debugging purposes - * and also attempt to detect invalid uses of the malloc heap through - * various tricks like inserting clobber words at the head and tail of - * the user's area, delayed free() calls, and setting the memory to - * a fixed pattern on allocation and when freed. The allocations also - * can include warrants so that when an area is clobbered, this - * package can report where the allocation took place. - * The macros included are: - * malloc(size) - * realloc(ptr,size) - * calloc(nelem,elsize) - * strdup(s1) - * free(ptr) - * malloc_police() <--- Not a system function - * The above macros match the standard behavior of the system functions. - * - * They should be used through the include file "debug_malloc.h". - * - * IMPORTANT: All source files that call any of these macros - * should include debug_malloc.h. This package will - * not work if the memory isn't allocated and freed - * by the macros in debug_malloc.h. The important issue - * is that any malloc() from debug_malloc.h must be - * freed by the free() in debug_malloc.h. - * - * The macros in debug_malloc.h will override the normal use of - * malloc, realloc, calloc, strdup, and free with the functions below. - * - * These functions include: - * void *debug_malloc(size_t, void*, int); - * void *debug_realloc(void*, size_t, void*, int); - * void *debug_calloc(size_t, size_t, void*, int); - * void debug_free(void *, void*, int); - * - * In addition the function debug_malloc_police() can be called to - * tell you what memory has not been freed. - * void debug_malloc_police(void*, int); - * The function debug_malloc_police() is available through the macro - * malloc_police(). Normally you would want to call this at exit() - * time to find out what memory is still allocated. - * - * The variable malloc_watch determines if the warrants are generated. - * warrants are structures that include the filename and line number - * of the caller who allocated the memory. This structure is stored - * at the tail of the malloc space, which is allocated large enough - * to hold some clobber words at the head and tail, the user's request - * and the warrant record (if malloc_watch is non-zero). - * - * The macro LEFT_OVER_CHAR is what the trailing bytes of an allocation - * are set to (when the allocation is not a multiple of 8) on allocation. - * At free(0 time, these bytes are double checked to make sure they were - * not clobbered. To remove this feature #undef LEFT_OVER_CHAR. - * - * The memory freed will have the FREED_CHAR put into it. To remove this - * feature #undef FREED_CHAR. - * - * The memory allocated (not calloc'd) will have the ALLOC_CHAR put into it - * at the time of allocation. To remove this feature #undef ALLOC_CHAR. - * - * The macro MAX_FREE_DELAY_COUNT controls how many free blocks will - * be kept around before being freed. This creates a delayed affect - * so that free space that gets clobbered just might get detected. - * The free() call will immediately set the user space to the FREED_CHAR, - * leaving the clobber words and warrant in place (making sure they - * haven't been clobbered). Then the free() pointer is added to a - * queue of MAX_FREE_DELAY_COUNT long, and if the queue was full, the - * oldest free()'d memory is actually freed, getting it's entire - * memory length set to the FREED_CHAR. - * - * WARNING: This can significantly slow down an application, depending - * on how many allocations are made. Also the additional memory - * needed for the clobber words and the warrants can be significant - * again, depending on how many allocations are made. - * In addition, the delayed free calls can create situations - * where you might run out of memory prematurely. - * - * ************************************************************************** - */ - -#ifdef DEBUG - -#include -#include -#include -#include -#include -#include "hprof.h" - -/* *************************************************************************** - * Space normally looks like (clobber Word is 64 bits and aligned to 8 bytes): - * - * ----------------- - * malloc/free get->| clobber Word | ---> contains -size requested by user - * ----------------- - * User gets --->| user space | - * | | - * | | left_over | ---> left_over bytes will be <= 7 - * ----------------- - * | clobber Word | ---> contains -size requested by user - * ----------------- - * | Warrant | ---> Optional (malloc_watch!=0) - * | | Contains filename and line number - * | | where allocation happened - * | | - * ----------------- - ***************************************************************************/ - -/* - * Flag that tells debug_malloc/debug_free/debug_realloc to police - * heap space usage. (This is a dynamic flag that can be turned on/off) - */ -static int malloc_watch = 1; - -/* Character to stuff into freed space */ -#define FREED_CHAR 'F' - -/* Character to stuff into allocated space */ -#define ALLOC_CHAR 'A' - -/* Character to stuff into left over trailing bytes */ -#define LEFT_OVER_CHAR 'Z' - -/* Number of 'free' calls that will be delayed until the end */ -#define MAX_FREE_DELAY_COUNT 1 -#undef MAX_FREE_DELAY_COUNT - -/* Maximum name of __FILE_ stored in each malloc'd area */ -#define WARRANT_NAME_MAX (32-1) /* 1 less than multiple of 8 is best */ - -/* Macro to convert a user pointer to the malloc pointer */ -#define user2malloc_(uptr) (((char*)(void*)uptr)-sizeof(Word)) - -/* Macro to convert a macro pointer to the user pointer */ -#define malloc2user_(mptr) (((char*)(void*)(mptr))+sizeof(Word)) - -/* Size of the warrant record (this is dynamic) */ -#define warrant_space ( malloc_watch?sizeof(Warrant_Record):0 ) - -/* Macro to round up a number of bytes to a multiple of sizeof(Word) bytes */ -#define round_up_(n) \ - ((n)==0?0:(sizeof(Word)+(((n)-1)/sizeof(Word))*sizeof(Word))) - -/* Macro to calculate the needed malloc bytes from the user's request. */ -#define rbytes_(nbytes) \ - (size_t)( sizeof(Word) + round_up_(nbytes) + sizeof(Word) + warrant_space ) - -/* Macro to get the -size stored in space through the malloc pointer */ -#define nsize1_(mptr) (((Word*)(void*)(mptr))->nsize1) -#define nsize2_(mptr) (((Word*)(void*)(mptr))->nsize2) - -/* Macro to get the -size stored in the tail of the space through */ -/* the malloc pointer */ -#define tail_nsize1_(mptr) \ - nsize1_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)) -#define tail_nsize2_(mptr) \ - nsize2_(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)) - -/* Macro to get the -size stored in space through the user pointer */ -#define user_nsize1_(uptr) nsize1_(user2malloc_(uptr)) -#define user_nsize2_(uptr) nsize2_(user2malloc_(uptr)) - -/* Macro to get the -size stored in the tail of the space through */ -/* the user pointer */ -#define user_tail_nsize1_(uptr) tail_nsize1_(user2malloc_(uptr)) -#define user_tail_nsize2_(uptr) tail_nsize2_(user2malloc_(uptr)) - -/* Macro to get the int* of the last 32bit word of user space */ -#define last_user_word_(mptr) \ - ((int*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr)))) - -/* Macros to get at the warrant contents from the malloc pointer */ -#define warrant_(mptr) \ - (*((Warrant_Record*)(void*)(((char*)(void*)(mptr))+round_up_(-nsize1_(mptr))+sizeof(Word)*2))) - -/* This struct is allocated after the tail clobber word if malloc_watch */ -/* is true. */ -typedef struct { - void *link; /* Next mptr in list */ - char name[WARRANT_NAME_MAX + 1]; /* Name of allocator */ - int line; /* Line number where allocated */ - int id; /* Nth allocation */ -} Warrant_Record; -#define warrant_link_(mptr) warrant_(mptr).link -#define warrant_name_(mptr) warrant_(mptr).name -#define warrant_line_(mptr) warrant_(mptr).line -#define warrant_id_(mptr) warrant_(mptr).id -#define MFILE(mptr) (malloc_watch?warrant_name_(mptr):"?") -#define MLINE(mptr) (malloc_watch?warrant_line_(mptr):0) -#define MID(mptr) (malloc_watch?warrant_id_(mptr):0) - -/* This should be one machine word and is also the clobber word struct */ -typedef struct { - int nsize1; - int nsize2; -} Word; /* Largest basic type , sizeof(double)? */ - -/* The first malloc pointer for the warrants */ -static void *first_warrant_mptr = NULL; - -/* Counter of allocations */ -static int id_counter = 0; -static int largest_size = 0; -static void * largest_addr = NULL; -static void * smallest_addr = NULL; - -/* Used to isolate what the error is */ -static char *debug_check; -static void *clobbered_ptr; - -/* Minimum macro */ -#define minimum(a,b) ((a)<(b)?(a):(b)) - -/* Message routine */ -static void -error_message(const char * format, ...) -{ - FILE *error_fp = stderr; /* All debug_malloc.c messages */ - va_list ap; - va_start(ap, format); - (void)fprintf(error_fp, "debug_malloc: "); - (void)vfprintf(error_fp, format, ap); - (void)fprintf(error_fp, "\n"); - (void)fflush(error_fp); - va_end(ap); -} - -/* This function prints out a memory error for the memory function - * 'name' which was called in file 'file' at line number 'line'. The malloc - * pointer with the error is in 'mptr'. - */ -static void -memory_error(void *mptr, const char *name, int mid, const char *mfile, int mline, const char *file, int line) -{ - char nice_words[512]; - char temp[256]; - int len; - void *mptr_walk; - - if (name == NULL) - name = "UNKNOWN_NAME"; - if (file == NULL) - file = "UNKNOWN_FILE"; - md_system_error(temp, (int)sizeof(temp)); - (void)strcpy(nice_words, temp); - if ( debug_check!=NULL ) { - (void)md_snprintf(nice_words, sizeof(nice_words), - "%s The %s at %p appears to have been hit.", - temp, debug_check, clobbered_ptr); - } - len = -nsize1_(mptr); - error_message("Error: " - "%s The malloc space #%d is at %p [user size=%d(0x%x)]," - " and was allocated from file \"%s\" at line %d." - " [The debug function %s() detected this error " - "in file \"%s\" at line %d.]", - nice_words, mid, mptr, len, len, mfile, mline, - name, file, line); - - /* Print out contents of this allocation */ - { - int i; - void *uptr = malloc2user_(mptr); - char *pmess; - pmess = temp; - for(i=0;i<(int)sizeof(temp);i++) { - int ch = ((unsigned char*)uptr)[i]; - if ( isprint(ch) ) { - *pmess++ = ch; - } else { - *pmess++ = '\\'; - *pmess++ = 'x'; - (void)sprintf(pmess,"%02x",ch); - pmess+=2; - } - } - *pmess = 0; - error_message("Error: %p contains user data: %s", uptr, temp); - } - - /* Try and print out table */ - if (!malloc_watch) { - return; - } - mptr_walk = first_warrant_mptr; - if (mptr_walk != NULL) { - error_message("Active allocations: " - "count=%d, largest_size=%d, address range (%p,%p)", - id_counter, largest_size, smallest_addr, largest_addr); - do { - int size1; - int size2; - char *mfile_walk; - - if ( mptr_walk > largest_addr || mptr_walk < smallest_addr ) { - error_message("Terminating list due to pointer corruption"); - break; - } - size1 = -nsize1_(mptr_walk); - size2 = -nsize2_(mptr_walk); - mfile_walk = MFILE(mptr_walk); - error_message("#%d: addr=%p size1=%d size2=%d file=\"%.*s\" line=%d", - MID(mptr_walk), mptr_walk, size1, size2, - WARRANT_NAME_MAX, mfile_walk, MLINE(mptr_walk)); - if ( size1 != size2 || size1 > largest_size || size1 < 0 ) { - error_message("Terminating list due to size corruption"); - break; - } - mptr_walk = warrant_link_(mptr_walk); - } while (mptr_walk != NULL); - } - abort(); -} - -/* This function sets the clobber word and sets up the warrant for the input - * malloc pointer "mptr". - */ -static void -setup_space_and_issue_warrant(void *mptr, size_t size, const char *file, int line) -{ - register int nbytes; - - /*LINTED*/ - nbytes = (int)size; - if ( nbytes > largest_size || largest_addr == NULL ) largest_size = nbytes; - /*LINTED*/ - if ( mptr > largest_addr ) largest_addr = mptr; - /*LINTED*/ - if ( mptr < smallest_addr || smallest_addr == NULL ) smallest_addr = mptr; - - /* Must be done first: */ - nsize1_(mptr) = -nbytes; - nsize2_(mptr) = -nbytes; - tail_nsize1_(mptr) = -nbytes; - tail_nsize2_(mptr) = -nbytes; - -#ifdef LEFT_OVER_CHAR - /* Fill in those few extra bytes just before the tail Word structure */ - { - register int trailing_extra_bytes; - /* LINTED */ - trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes); - if ( trailing_extra_bytes > 0 ) { - register char *p; - register int i; - p = ((char *) mptr) + sizeof(Word) + nbytes; - for (i = 0; i < trailing_extra_bytes; i++) - p[i] = LEFT_OVER_CHAR; - } - } -#endif - - /* Fill out warrant */ - if (malloc_watch) { - static Warrant_Record zero_warrant; - register void *p1, - *p2; - size_t len; - int start_pos = 0; - warrant_(mptr) = zero_warrant; - p1 = warrant_name_(mptr); - len = strlen(file); - if ( len > WARRANT_NAME_MAX ) { - /*LINTED*/ - start_pos = (int)len - WARRANT_NAME_MAX; - } - p2 = ((char*)file) + start_pos; - /*LINTED*/ - (void) memcpy(p1, p2, minimum(((int)len), WARRANT_NAME_MAX)); - warrant_line_(mptr) = line; - warrant_id_(mptr) = ++id_counter; - warrant_link_(mptr) = first_warrant_mptr; - first_warrant_mptr = mptr; - } -} - -/* This function checks the clobber words at the beginning and end of the - * allocated space. - */ -static void -memory_check(void *uptr, int mid, const char *mfile, int mline, const char *file, int line) -{ - int neg_nbytes; - int nbytes; - - debug_check = "pointer value itself"; - clobbered_ptr = uptr; - if (uptr == NULL) - memory_error((void *) NULL, "memory_check", mid, mfile, mline, file, line); - - /* Check both Word structures */ - - debug_check = "first beginning clobber word"; - clobbered_ptr = (char*)&user_nsize1_(uptr); - neg_nbytes = user_nsize1_(uptr); - if (neg_nbytes >= 0) - memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line); - - debug_check = "second beginning clobber word"; - clobbered_ptr = (char*)&user_nsize2_(uptr); - if (neg_nbytes != user_nsize2_(uptr)) - memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line); - - debug_check = "first ending clobber word"; - clobbered_ptr = (char*)&user_tail_nsize1_(uptr); - if (neg_nbytes != user_tail_nsize1_(uptr)) - memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line); - - debug_check = "second ending clobber word"; - clobbered_ptr = (char*)&user_tail_nsize2_(uptr); - if (neg_nbytes != user_tail_nsize2_(uptr)) - memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line); - - /* Get a positive count of bytes */ - nbytes = -neg_nbytes; - -#ifdef LEFT_OVER_CHAR - { - /* Check those few extra bytes just before the tail Word structure */ - register int trailing_extra_bytes; - register int i; - register char *p; - /* LINTED */ - trailing_extra_bytes = (int) (round_up_(nbytes) - nbytes); - p = ((char *) (uptr)) + nbytes; - debug_check = "trailing left over area"; - for (i = 0; i < trailing_extra_bytes; i++) { - clobbered_ptr = p+1; - if (p[i] != LEFT_OVER_CHAR) { - memory_error(user2malloc_(uptr), "memory_check", mid, mfile, mline, file, line); - } - } - } -#endif - - /* Make sure debug_check is cleared */ - debug_check = NULL; -} - -/* This function looks for the given malloc pointer in the police line up - * and removes it from the warrant list. - * mptr The pointer to the malloc space being removed - */ -static int -remove_warrant(void *mptr) -{ - void *mptr1, - *last_mptr1; - - /* Free it up from the list */ - if (malloc_watch && mptr != NULL) { - int found; - - found = 0; - last_mptr1 = NULL; - mptr1 = first_warrant_mptr; - while (mptr1 != NULL) { - if (mptr1 == mptr) { - if (last_mptr1 == NULL) - first_warrant_mptr = warrant_link_(mptr1); - else - warrant_link_(last_mptr1) = warrant_link_(mptr1); - found = 1; - break; - } - last_mptr1 = mptr1; - mptr1 = warrant_link_(mptr1); - } - return found; - } - return 1; -} - -static void -actual_free(void *uptr, const char *file, int line) -{ - void *mptr; - const char *mfile; - int mline; - int mid; - if ( uptr == NULL ) - return; - mptr = user2malloc_(uptr); - memory_check(uptr, (mid=MID(mptr)), (mfile=MFILE(mptr)), (mline=MLINE(mptr)), file, line); - if (malloc_watch && remove_warrant(mptr)==0 ) - memory_check(uptr, mid, mfile, mline, file, line); -#ifdef FREED_CHAR - if ( mptr!=NULL ) { - size_t nbytes = -nsize1_(mptr); - /* LINTED */ - (void)memset(mptr, FREED_CHAR, rbytes_(nbytes)); - } -#endif - free(mptr); -} - -#ifdef MAX_FREE_DELAY_COUNT - -static void *free_delay[MAX_FREE_DELAY_COUNT]; -static int free_delay_pos = 0; - -static void -delayed_free(void *uptr, const char* file, int line) -{ - void *mptr; - void *olduptr = free_delay[free_delay_pos]; - size_t nbytes; - if ( uptr==NULL ) - return; - mptr = user2malloc_(uptr); - memory_check(uptr, MID(mptr), MFILE(mptr), MLINE(mptr), file, line); - if ( olduptr!=NULL ) { - actual_free(olduptr, file, line); - } - free_delay[free_delay_pos] = uptr; - free_delay_pos++; - free_delay_pos = free_delay_pos % MAX_FREE_DELAY_COUNT; - nbytes = -user_nsize1_(uptr); -#ifdef FREED_CHAR - (void)memset(uptr, FREED_CHAR, (size_t)nbytes); -#endif -} - -static void -delayed_free_all(const char *file, int line) -{ - int i; - for ( i=0; i< MAX_FREE_DELAY_COUNT; i++) { - void *olduptr = free_delay[i]; - free_delay[i] = NULL; - if ( olduptr!=NULL ) { - actual_free(olduptr, file, line); - } - } -} - -#endif - -void -debug_free(void *uptr, const char *file, int line) -{ - int mid = 0; - - if (uptr == NULL) - memory_error((void *) NULL, "debug_free", mid, file, line, file, line); -#ifdef MAX_FREE_DELAY_COUNT - delayed_free(uptr, file, line); -#else - actual_free(uptr, file, line); -#endif -} - -/* This function calls malloc(). */ -void * -debug_malloc(size_t nbytes, const char *file, int line) -{ - void *mptr; - void *uptr; - int mid = id_counter; - - /*LINTED*/ - if ((int)nbytes <= 0) - memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line); - /* LINTED */ - mptr = malloc(rbytes_(nbytes)); - if (mptr == NULL) - memory_error((void *) NULL, "debug_malloc", mid, file, line, file, line); - setup_space_and_issue_warrant(mptr, nbytes, file, line); - uptr = malloc2user_(mptr); -#ifdef ALLOC_CHAR - (void)memset(uptr, ALLOC_CHAR, (size_t)nbytes); -#endif - return uptr; -} - -void * -debug_realloc(void *uptr, size_t nbytes, const char *file, int line) -{ - void *mptr; - void *oldmptr; - void *newuptr; - size_t oldnbytes; - int mid = id_counter; - - oldmptr = user2malloc_(uptr); - oldnbytes = 0; - if ((int)nbytes <= 0) - memory_error(oldmptr, "debug_realloc", mid, file, line, file, line); - if (uptr != NULL) { - memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line); - oldnbytes = -user_nsize1_(uptr); - if ( malloc_watch && remove_warrant(oldmptr)==0 ) - memory_check(uptr, MID(oldmptr), MFILE(oldmptr), MLINE(oldmptr), file, line); - } - if (uptr == NULL) { - /* LINTED */ - mptr = malloc(rbytes_(nbytes)); - } else { - /* LINTED */ - mptr = realloc(oldmptr, rbytes_(nbytes)); - } - if (mptr == NULL) - memory_error(oldmptr, "debug_realloc", mid, file, line, file, line); - setup_space_and_issue_warrant(mptr, nbytes, file, line); - newuptr = malloc2user_(mptr); -#ifdef ALLOC_CHAR - if (uptr == NULL) - (void)memset(newuptr, ALLOC_CHAR, (size_t)nbytes); - else if ( nbytes > oldnbytes ) - (void)memset(((char*)newuptr)+oldnbytes, ALLOC_CHAR, (size_t)nbytes-oldnbytes); -#endif - return newuptr; -} - -/* This function calls calloc(). */ -void * -debug_calloc(size_t nelem, size_t elsize, const char *file, int line) -{ - void *mptr; - size_t nbytes; - int mid = id_counter; - - nbytes = nelem*elsize; - /*LINTED*/ - if ((int)nbytes <= 0) - memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line); - /* LINTED */ - mptr = calloc(rbytes_(nbytes),1); - if (mptr == NULL) - memory_error((void *) NULL, "debug_calloc", mid, file, line, file, line); - setup_space_and_issue_warrant(mptr, nbytes, file, line); - return malloc2user_(mptr); -} - -/* This function replaces strdup(). */ -char * -debug_strdup(const char *s1, const char *file, int line) -{ - void *mptr; - void *uptr; - size_t nbytes; - int mid = id_counter; - - if (s1 == NULL) - memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line); - nbytes = strlen(s1)+1; - /*LINTED*/ - if ((int)nbytes < 0) - memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line); - /* LINTED */ - mptr = malloc(rbytes_(nbytes)); - if (mptr == NULL) - memory_error((void *) NULL, "debug_strdup", mid, file, line, file, line); - setup_space_and_issue_warrant(mptr, nbytes, file, line); - uptr = malloc2user_(mptr); - (void)strcpy((char*)uptr, s1); - return (char*)uptr; -} - -void -debug_malloc_verify(const char *file, int line) -{ - void *mptr; - -#ifdef MAX_FREE_DELAY_COUNT - delayed_free_all(file,line); -#endif - - if (!malloc_watch) { - return; - } - mptr = first_warrant_mptr; - if (mptr != NULL) { - /* Check all this memory first */ - do { - memory_check(malloc2user_(mptr), MID(mptr), MFILE(mptr), MLINE(mptr), file, line); - mptr = warrant_link_(mptr); - } while (mptr != NULL); - } -} - -/* Report outstanding space warrants to console. */ -void -debug_malloc_police(const char *file, int line) -{ - void *mptr; - -#ifdef MAX_FREE_DELAY_COUNT - delayed_free_all(file,line); -#endif - - if (!malloc_watch) { - return; - } - - mptr = first_warrant_mptr; - if (mptr != NULL) { - debug_malloc_verify(file, line); - /* Now issue warrants */ - mptr = first_warrant_mptr; - do { - error_message("Outstanding space warrant: %p (%d bytes) allocated by %s at line %d, allocation #%d", - mptr, -nsize1_(mptr), warrant_name_(mptr), - warrant_line_(mptr), warrant_id_(mptr)); - - mptr = warrant_link_(mptr); - } while (mptr != NULL); - } -} - -#else - -void -debug_malloc_verify(const char *file, int line) -{ - file = file; - line = line; -} - -void -debug_malloc_police(const char *file, int line) -{ - file = file; - line = line; -} - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h deleted file mode 100644 index 2b854770ff4..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/debug_malloc.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* *********************************************************************** - * - * The source file debug_malloc.c should be included with your sources. - * - * The object file debug_malloc.o should be included with your object files. - * - * WARNING: Any memory allocattion from things like memalign(), valloc(), - * or any memory not coming from these macros (malloc, realloc, - * calloc, and strdup) will fail miserably. - * - * *********************************************************************** - */ - -#ifndef _DEBUG_MALLOC_H -#define _DEBUG_MALLOC_H - -#ifdef DEBUG - -#include -#include - -/* Use THIS_FILE when it is available. */ -#ifndef THIS_FILE - #define THIS_FILE __FILE__ -#endif - -/* The real functions behind the macro curtains. */ - -void *debug_malloc(size_t, const char *, int); -void *debug_realloc(void *, size_t, const char *, int); -void *debug_calloc(size_t, size_t, const char *, int); -char *debug_strdup(const char *, const char *, int); -void debug_free(void *, const char *, int); - -#endif - -void debug_malloc_verify(const char*, int); -#undef malloc_verify -#define malloc_verify() debug_malloc_verify(THIS_FILE, __LINE__) - -void debug_malloc_police(const char*, int); -#undef malloc_police -#define malloc_police() debug_malloc_police(THIS_FILE, __LINE__) - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h deleted file mode 100644 index 696de3d3a26..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof.h +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* Primary hprof #include file, should be included by most if not - * all hprof source files. Gives access to the global data structure - * and all global macros, and everything declared in the #include - * files of each of the source files. - */ - -#ifndef HPROF_H -#define HPROF_H - -/* Standard C functions used throughout. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* General JVM/Java functions, types and macros. */ - -#include -#include "jni.h" -#include "jvmti.h" -#include "classfile_constants.h" -#include "jvm_md.h" - -/* Macros to extract the upper and lower 32 bits of a jlong */ - -#define jlong_high(a) ((jint)((a)>>32)) -#define jlong_low(a) ((jint)(a)) -#define jlong_to_jint(a) ((jint)(a)) -#define jint_to_jlong(a) ((jlong)(a)) - -#define jlong_add(a, b) ((a) + (b)) - - -/* The type used to contain a generic 32bit "serial number". */ - -typedef unsigned SerialNumber; - -/* How the options get to OnLoad: */ - -#define AGENTNAME "hprof" -#define XRUN "-Xrun" AGENTNAME -#define AGENTLIB "-agentlib:" AGENTNAME - -/* Name of prelude file, found at runtime relative to java binary location */ - -#define PRELUDE_FILE "jvm.hprof.txt" - -/* File I/O buffer size to be used with any file i/o operation */ - -#define FILE_IO_BUFFER_SIZE (1024*64) - -/* Machine dependent functions. */ - -#include "hprof_md.h" - -/* Table index types */ - -typedef unsigned TableIndex; -typedef TableIndex ClassIndex; -typedef TableIndex FrameIndex; -typedef TableIndex IoNameIndex; -typedef TableIndex MonitorIndex; -typedef TableIndex ObjectIndex; -typedef TableIndex LoaderIndex; -typedef TableIndex RefIndex; -typedef TableIndex SiteIndex; -typedef TableIndex StringIndex; -typedef TableIndex TlsIndex; -typedef TableIndex TraceIndex; - -/* Index for method tables in classes */ - -typedef int MethodIndex; - -/* The different kinds of class status bits. */ - -enum ClassStatus { - CLASS_PREPARED = 0x00000001, - CLASS_LOADED = 0x00000002, - CLASS_UNLOADED = 0x00000004, - CLASS_SPECIAL = 0x00000008, - CLASS_IN_LOAD_LIST = 0x00000010, - CLASS_SYSTEM = 0x00000020, - CLASS_DUMPED = 0x00000040 -}; -typedef jint ClassStatus; - -/* The different kind of objects we track with heap=dump */ - -typedef unsigned char ObjectKind; -enum { - OBJECT_NORMAL = 1, - OBJECT_CLASS = 2, - OBJECT_SYSTEM = 3, - OBJECT_HPROF = 4, - OBJECT_LOADER = 5 -}; - -/* Used by site_write() when writing out the heap=sites data. */ - -enum { - SITE_DUMP_INCREMENTAL = 0x01, - SITE_SORT_BY_ALLOC = 0x02, - SITE_FORCE_GC = 0x04 -}; - -/* Used to hold information about a field, and potentially a value too. */ - -typedef struct FieldInfo { - ClassIndex cnum; - StringIndex name_index; - StringIndex sig_index; - unsigned short modifiers; - unsigned char primType; - unsigned char primSize; -} FieldInfo; - -/* Used to hold information about a constant pool entry value for a class. */ - -typedef struct ConstantPoolValue { - unsigned constant_pool_index; - StringIndex sig_index; - jvalue value; -} ConstantPoolValue; - -/* All machine independent functions */ - -#include "hprof_error.h" -#include "hprof_util.h" -#include "hprof_blocks.h" -#include "hprof_stack.h" -#include "hprof_init.h" -#include "hprof_table.h" -#include "hprof_string.h" -#include "hprof_class.h" -#include "hprof_tracker.h" -#include "hprof_frame.h" -#include "hprof_monitor.h" -#include "hprof_trace.h" -#include "hprof_site.h" -#include "hprof_event.h" -#include "hprof_reference.h" -#include "hprof_object.h" -#include "hprof_loader.h" -#include "hprof_tls.h" -#include "hprof_check.h" -#include "hprof_io.h" -#include "hprof_listener.h" -#include "hprof_cpu.h" -#include "hprof_tag.h" - -/* Global data structure */ - -struct LineTable; - -typedef struct { - - jvmtiEnv *jvmti; /* JVMTI env for this session */ - JavaVM *jvm; /* JavaVM* for this session */ - jint cachedJvmtiVersion; /* JVMTI version number */ - - char *header; /* "JAVA PROFILE 1.0.[12]" */ - jboolean segmented; /* JNI_TRUE if 1.0.2 */ - jlong maxHeapSegment; - jlong maxMemory; - - /* Option settings */ - char * options; /* option string copy */ - char * utf8_output_filename;/* file=filename */ - int net_port; /* net=hostname:port */ - char * net_hostname; /* net=hostname:port */ - char output_format; /* format=a|b */ - int max_trace_depth; /* depth=max_trace_depth */ - int prof_trace_depth; /* max_trace_depth or 2 (old) */ - int sample_interval; /* interval=sample_interval (ms) */ - double cutoff_point; /* cutoff=cutoff_point */ - jboolean cpu_sampling; /* cpu=samples|y */ - jboolean cpu_timing; /* cpu=times */ - jboolean old_timing_format; /* cpu=old (old) output format */ - jboolean heap_dump; /* heap=dump|all */ - jboolean alloc_sites; /* heap=sites|all */ - jboolean thread_in_traces; /* thread=y|n */ - jboolean lineno_in_traces; /* lineno=y|n */ - jboolean dump_on_exit; /* doe=y|n */ - jboolean micro_state_accounting; /* msa=y|n */ - jboolean force_output; /* force=y|n */ - jboolean monitor_tracing; /* monitor=y|n */ - jboolean gc_okay; /* gc_okay=y|n (Not used) */ - - unsigned logflags; /* logflags=bitmask */ - - #define DEBUGFLAG_UNPREPARED_CLASSES 0x001 - unsigned debugflags; /* debugflags=bitmask */ - - jboolean coredump; /* coredump=y|n */ - jboolean errorexit; /* errorexit=y|n */ - jboolean pause; /* pause=y|n */ - jboolean debug; /* debug=y|n */ - jboolean verbose; /* verbose=y|n */ - jboolean primfields; /* primfields=y|n */ - jboolean primarrays; /* primarrays=y|n */ - jint experiment; /* X=NUMBER */ - - int fd; /* file or socket (net=addr). */ - jboolean socket; /* True if fd is a socket (net=addr). */ - jboolean bci; /* True if any kind of BCI being done */ - jboolean obj_watch; /* True if bci and watching allocs */ - - int bci_counter; /* Class BCI counter */ - - int heap_fd; - char *output_filename; /* file=filename */ - char *heapfilename; - - int check_fd; - char *checkfilename; - - volatile jboolean dump_in_process; /* Dump in process */ - volatile jboolean jvm_initializing; /* VMInit happening */ - volatile jboolean jvm_initialized; /* VMInit happened */ - volatile jboolean jvm_shut_down; /* VMDeath happened */ - jboolean vm_death_callback_active; /* VMDeath happening */ - - /* Stack of objects freed during GC */ - Stack * object_free_stack; - jrawMonitorID object_free_lock; - - /* Lock for debug_malloc() */ - jrawMonitorID debug_malloc_lock; - - /* Count of classes that JVMTI thinks are active */ - jint class_count; - - /* Used to track callbacks for VM_DEATH */ - jrawMonitorID callbackBlock; - jrawMonitorID callbackLock; - jint active_callbacks; - - /* Running totals on all bytes allocated */ - jlong total_alloced_bytes; - jlong total_alloced_instances; - jint total_live_bytes; - jint total_live_instances; - - /* Running total on all time spent in GC (very rough estimate) */ - jlong gc_start_time; - jlong time_in_gc; - - /* Global Data access Lock */ - jrawMonitorID data_access_lock; - - /* Global Dump lock */ - jrawMonitorID dump_lock; - - /* Milli-second clock when hprof onload started */ - jlong micro_sec_ticks; - - /* Thread class (for starting agent threads) */ - ClassIndex thread_cnum; - - /* Agent threads started information */ - jboolean listener_loop_running; - jrawMonitorID listener_loop_lock; - jboolean cpu_loop_running; - jrawMonitorID cpu_loop_lock; - jrawMonitorID cpu_sample_lock; /* cpu=samples loop */ - jint gc_finish; /* Count of GC finish events */ - jboolean gc_finish_active; /* True if thread active */ - jboolean gc_finish_stop_request; /* True if we want it to stop */ - jrawMonitorID gc_finish_lock; - - jboolean pause_cpu_sampling; /* temp pause in cpu sampling */ - - /* Output buffer, position, size, and position in dump if reading */ - char * write_buffer; - int write_buffer_index; - int write_buffer_size; - char * heap_buffer; - int heap_buffer_index; - int heap_buffer_size; - jlong heap_last_tag_position; - jlong heap_write_count; - char * check_buffer; - int check_buffer_index; - int check_buffer_size; - - /* Serial number counters for tables (see hprof_table.c), classes, - * tls (thread local storage), and traces. - */ - SerialNumber table_serial_number_start; - SerialNumber class_serial_number_start; - SerialNumber thread_serial_number_start; - SerialNumber trace_serial_number_start; - SerialNumber object_serial_number_start; - SerialNumber frame_serial_number_start; - SerialNumber gref_serial_number_start; - - SerialNumber table_serial_number_counter; - SerialNumber class_serial_number_counter; - SerialNumber thread_serial_number_counter; - SerialNumber trace_serial_number_counter; - SerialNumber object_serial_number_counter; - SerialNumber frame_serial_number_counter; - SerialNumber gref_serial_number_counter; - - /* The methodID for the Object method. */ - jmethodID object_init_method; - - /* Keeping track of the tracker class and it's methods */ - volatile jint tracking_engaged; /* !=0 means it's on */ - ClassIndex tracker_cnum; - int tracker_method_count; - struct { - StringIndex name; /* String index for name */ - StringIndex sig; /* String index for signature */ - jmethodID method; /* Method ID */ - } tracker_methods[12]; /* MAX 12 Tracker class methods */ - - /* Index to some common items */ - LoaderIndex system_loader; - SerialNumber unknown_thread_serial_num; - TraceIndex system_trace_index; - SiteIndex system_object_site_index; - jint system_class_size; - TraceIndex hprof_trace_index; - SiteIndex hprof_site_index; - - /* Tables for strings, classes, sites, etc. */ - struct LookupTable * string_table; - struct LookupTable * ioname_table; - struct LookupTable * class_table; - struct LookupTable * site_table; - struct LookupTable * object_table; - struct LookupTable * reference_table; - struct LookupTable * frame_table; - struct LookupTable * trace_table; - struct LookupTable * monitor_table; - struct LookupTable * tls_table; - struct LookupTable * loader_table; - - /* Handles to java_crw_demo library */ - void * java_crw_demo_library; - void * java_crw_demo_function; - void * java_crw_demo_classname_function; - - /* Indication that the agent has been loaded */ - jboolean isLoaded; - -} GlobalData; - -/* This should be the only 'extern' in the library (not exported). */ - -extern GlobalData * gdata; - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h deleted file mode 100644 index c9a2c346f4d..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_b_spec.h +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef HPROF_B_SPEC_H -#define HPROF_B_SPEC_H - -/* Hprof binary format enums and spec. */ - -/* Need to #define or typedef HprofId before including this file. - * hprof used ObjectIndex or 4 bytes, but it can be 4 or 8 byte type. - */ - -/* -------------------------------------------------------------------- */ -/* -------------------------------------------------------------------- */ -/* -------------------------------------------------------------------- */ - -/* - * hprof binary format: (result either written to a file or sent over - * the network). - * - * WARNING: This format is still under development, and is subject to - * change without notice. - * - * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated) - * u4 size of identifiers. Identifiers are used to represent - * UTF8 strings, objects, stack traces, etc. They usually - * have the same size as host pointers. For example, on - * Solaris and Win32, the size is 4. - * u4 high word - * u4 low word number of milliseconds since 0:00 GMT, 1/1/70 - * [record]* a sequence of records. - */ - -/* - * Record format: - * - * u1 a TAG denoting the type of the record - * u4 number of *microseconds* since the time stamp in the - * header. (wraps around in a little more than an hour) - * u4 number of bytes *remaining* in the record. Note that - * this number excludes the tag and the length field itself. - * [u1]* BODY of the record (a sequence of bytes) - */ - -/* - * The following TAGs are supported: - * - * TAG BODY notes - *---------------------------------------------------------- - * HPROF_UTF8 a UTF8-encoded name - * - * id name ID - * [u1]* UTF8 characters (no trailing zero) - * - * HPROF_LOAD_CLASS a newly loaded class - * - * u4 class serial number (> 0) - * id class object ID - * u4 stack trace serial number - * id class name ID - * - * HPROF_UNLOAD_CLASS an unloading class - * - * u4 class serial_number - * - * HPROF_FRAME a Java stack frame - * - * id stack frame ID - * id method name ID - * id method signature ID - * id source file name ID - * u4 class serial number - * i4 line number. >0: normal - * -1: unknown - * -2: compiled method - * -3: native method - * - * HPROF_TRACE a Java stack trace - * - * u4 stack trace serial number - * u4 thread serial number - * u4 number of frames - * [id]* stack frame IDs - * - * - * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC - * - * u2 flags 0x0001: incremental vs. complete - * 0x0002: sorted by allocation vs. live - * 0x0004: whether to force a GC - * u4 cutoff ratio - * u4 total live bytes - * u4 total live instances - * u8 total bytes allocated - * u8 total instances allocated - * u4 number of sites that follow - * [u1 is_array: 0: normal object - * 2: object array - * 4: boolean array - * 5: char array - * 6: float array - * 7: double array - * 8: byte array - * 9: short array - * 10: int array - * 11: long array - * u4 class serial number (may be zero during startup) - * u4 stack trace serial number - * u4 number of bytes alive - * u4 number of instances alive - * u4 number of bytes allocated - * u4]* number of instance allocated - * - * HPROF_START_THREAD a newly started thread. - * - * u4 thread serial number (> 0) - * id thread object ID - * u4 stack trace serial number - * id thread name ID - * id thread group name ID - * id thread group parent name ID - * - * HPROF_END_THREAD a terminating thread. - * - * u4 thread serial number - * - * HPROF_HEAP_SUMMARY heap summary - * - * u4 total live bytes - * u4 total live instances - * u8 total bytes allocated - * u8 total instances allocated - * - * HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT denote a heap dump - * - * [heap dump sub-records]* - * - * There are four kinds of heap dump sub-records: - * - * u1 sub-record type - * - * HPROF_GC_ROOT_UNKNOWN unknown root - * - * id object ID - * - * HPROF_GC_ROOT_THREAD_OBJ thread object - * - * id thread object ID (may be 0 for a - * thread newly attached through JNI) - * u4 thread sequence number - * u4 stack trace sequence number - * - * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root - * - * id object ID - * id JNI global ref ID - * - * HPROF_GC_ROOT_JNI_LOCAL JNI local ref - * - * id object ID - * u4 thread serial number - * u4 frame # in stack trace (-1 for empty) - * - * HPROF_GC_ROOT_JAVA_FRAME Java stack frame - * - * id object ID - * u4 thread serial number - * u4 frame # in stack trace (-1 for empty) - * - * HPROF_GC_ROOT_NATIVE_STACK Native stack - * - * id object ID - * u4 thread serial number - * - * HPROF_GC_ROOT_STICKY_CLASS System class - * - * id object ID - * - * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block - * - * id object ID - * u4 thread serial number - * - * HPROF_GC_ROOT_MONITOR_USED Busy monitor - * - * id object ID - * - * HPROF_GC_CLASS_DUMP dump of a class object - * - * id class object ID - * u4 stack trace serial number - * id super class object ID - * id class loader object ID - * id signers object ID - * id protection domain object ID - * id reserved - * id reserved - * - * u4 instance size (in bytes) - * - * u2 size of constant pool - * [u2, constant pool index, - * ty, type - * 2: object - * 4: boolean - * 5: char - * 6: float - * 7: double - * 8: byte - * 9: short - * 10: int - * 11: long - * vl]* and value - * - * u2 number of static fields - * [id, static field name, - * ty, type, - * vl]* and value - * - * u2 number of inst. fields (not inc. super) - * [id, instance field name, - * ty]* type - * - * HPROF_GC_INSTANCE_DUMP dump of a normal object - * - * id object ID - * u4 stack trace serial number - * id class object ID - * u4 number of bytes that follow - * [vl]* instance field values (class, followed - * by super, super's super ...) - * - * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array - * - * id array object ID - * u4 stack trace serial number - * u4 number of elements - * id array class ID - * [id]* elements - * - * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array - * - * id array object ID - * u4 stack trace serial number - * u4 number of elements - * u1 element type - * 4: boolean array - * 5: char array - * 6: float array - * 7: double array - * 8: byte array - * 9: short array - * 10: int array - * 11: long array - * [u1]* elements - * - * HPROF_HEAP_DUMP_END terminates series of heap dump segments - * - * HPROF_CPU_SAMPLES a set of sample traces of running threads - * - * u4 total number of samples - * u4 # of traces - * [u4 # of samples - * u4]* stack trace serial number - * - * HPROF_CONTROL_SETTINGS the settings of on/off switches - * - * u4 0x00000001: alloc traces on/off - * 0x00000002: cpu sampling on/off - * u2 stack trace depth - * - */ - -typedef enum HprofTag { - HPROF_UTF8 = 0x01, - HPROF_LOAD_CLASS = 0x02, - HPROF_UNLOAD_CLASS = 0x03, - HPROF_FRAME = 0x04, - HPROF_TRACE = 0x05, - HPROF_ALLOC_SITES = 0x06, - HPROF_HEAP_SUMMARY = 0x07, - HPROF_START_THREAD = 0x0A, - HPROF_END_THREAD = 0x0B, - HPROF_HEAP_DUMP = 0x0C, - HPROF_HEAP_DUMP_SEGMENT = 0x1C, /* 1.0.2 only */ - HPROF_HEAP_DUMP_END = 0x2C, /* 1.0.2 only */ - HPROF_CPU_SAMPLES = 0x0D, - HPROF_CONTROL_SETTINGS = 0x0E -} HprofTag; - -/* - * Heap dump constants - */ - -typedef enum HprofGcTag { - HPROF_GC_ROOT_UNKNOWN = 0xFF, - HPROF_GC_ROOT_JNI_GLOBAL = 0x01, - HPROF_GC_ROOT_JNI_LOCAL = 0x02, - HPROF_GC_ROOT_JAVA_FRAME = 0x03, - HPROF_GC_ROOT_NATIVE_STACK = 0x04, - HPROF_GC_ROOT_STICKY_CLASS = 0x05, - HPROF_GC_ROOT_THREAD_BLOCK = 0x06, - HPROF_GC_ROOT_MONITOR_USED = 0x07, - HPROF_GC_ROOT_THREAD_OBJ = 0x08, - HPROF_GC_CLASS_DUMP = 0x20, - HPROF_GC_INSTANCE_DUMP = 0x21, - HPROF_GC_OBJ_ARRAY_DUMP = 0x22, - HPROF_GC_PRIM_ARRAY_DUMP = 0x23 -} HprofGcTag; - -enum HprofType { - HPROF_ARRAY_OBJECT = 1, - HPROF_NORMAL_OBJECT = 2, - HPROF_BOOLEAN = 4, - HPROF_CHAR = 5, - HPROF_FLOAT = 6, - HPROF_DOUBLE = 7, - HPROF_BYTE = 8, - HPROF_SHORT = 9, - HPROF_INT = 10, - HPROF_LONG = 11 -}; -typedef unsigned char HprofType; - -#define HPROF_TYPE_SIZES \ - { \ - /*Object?*/ sizeof(HprofId), \ - /*Object?*/ sizeof(HprofId), \ - /*Array*/ sizeof(HprofId), \ - /*Object?*/ sizeof(HprofId), \ - /*jboolean*/ 1, \ - /*jchar*/ 2, \ - /*jfloat*/ 4, \ - /*jdouble*/ 8, \ - /*jbyte*/ 1, \ - /*jshort*/ 2, \ - /*jint*/ 4, \ - /*jlong*/ 8 \ - } - -#define HPROF_TYPE_IS_PRIMITIVE(ty) ((ty)>=HPROF_BOOLEAN) - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c deleted file mode 100644 index ce205bf2ce6..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* Allocations from large blocks, no individual free's */ - -#include "hprof.h" - -/* - * This file contains some allocation code that allows you - * to have space allocated via larger blocks of space. - * The only free allowed is of all the blocks and all the elements. - * Elements can be of different alignments and fixed or variable sized. - * The space allocated never moves. - * - */ - -/* Get the real size allocated based on alignment and bytes needed */ -static int -real_size(int alignment, int nbytes) -{ - if ( alignment > 1 ) { - int wasted; - - wasted = alignment - ( nbytes % alignment ); - if ( wasted != alignment ) { - nbytes += wasted; - } - } - return nbytes; -} - -/* Add a new current_block to the Blocks* chain, adjust size if nbytes big. */ -static void -add_block(Blocks *blocks, int nbytes) -{ - int header_size; - int block_size; - BlockHeader *block_header; - - HPROF_ASSERT(blocks!=NULL); - HPROF_ASSERT(nbytes>0); - - header_size = real_size(blocks->alignment, sizeof(BlockHeader)); - block_size = blocks->elem_size*blocks->population; - if ( nbytes > block_size ) { - block_size = real_size(blocks->alignment, nbytes); - } - block_header = (BlockHeader*)HPROF_MALLOC(block_size+header_size); - block_header->next = NULL; - block_header->bytes_left = block_size; - block_header->next_pos = header_size; - - /* Link in new block */ - if ( blocks->current_block != NULL ) { - blocks->current_block->next = block_header; - } - blocks->current_block = block_header; - if ( blocks->first_block == NULL ) { - blocks->first_block = block_header; - } -} - -/* Initialize a new Blocks */ -Blocks * -blocks_init(int alignment, int elem_size, int population) -{ - Blocks *blocks; - - HPROF_ASSERT(alignment>0); - HPROF_ASSERT(elem_size>0); - HPROF_ASSERT(population>0); - - blocks = (Blocks*)HPROF_MALLOC(sizeof(Blocks)); - blocks->alignment = alignment; - blocks->elem_size = elem_size; - blocks->population = population; - blocks->first_block = NULL; - blocks->current_block = NULL; - return blocks; -} - -/* Allocate bytes from a Blocks area. */ -void * -blocks_alloc(Blocks *blocks, int nbytes) -{ - BlockHeader *block; - int pos; - void *ptr; - - HPROF_ASSERT(blocks!=NULL); - HPROF_ASSERT(nbytes>=0); - if ( nbytes == 0 ) { - return NULL; - } - - block = blocks->current_block; - nbytes = real_size(blocks->alignment, nbytes); - if ( block == NULL || block->bytes_left < nbytes ) { - add_block(blocks, nbytes); - block = blocks->current_block; - } - pos = block->next_pos; - ptr = (void*)(((char*)block)+pos); - block->next_pos += nbytes; - block->bytes_left -= nbytes; - return ptr; -} - -/* Terminate the Blocks */ -void -blocks_term(Blocks *blocks) -{ - BlockHeader *block; - - HPROF_ASSERT(blocks!=NULL); - - block = blocks->first_block; - while ( block != NULL ) { - BlockHeader *next_block; - - next_block = block->next; - HPROF_FREE(block); - block = next_block; - } - HPROF_FREE(blocks); -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h deleted file mode 100644 index d6dd6d38091..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_blocks.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_BLOCKS_H -#define HPROF_BLOCKS_H - -typedef struct BlockHeader { - struct BlockHeader *next; - int bytes_left; - int next_pos; -} BlockHeader; - -typedef struct Blocks { - BlockHeader *first_block; /* Pointer to first BlockHeader */ - BlockHeader *current_block; /* Pointer to current BlockHeader */ - int alignment; /* Data alignment, 1, 2, 4, 8, 16 */ - int elem_size; /* Size in bytes, ==1 means variable sizes */ - int population; /* Number of elements to allow for per Block */ -} Blocks; - -Blocks * blocks_init(int alignment, int elem_size, int population); -void * blocks_alloc(Blocks *blocks, int nbytes); -void blocks_term(Blocks *blocks); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c deleted file mode 100644 index aef1eb90ef2..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.c +++ /dev/null @@ -1,1152 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* Functionality for checking hprof format=b output. */ - -/* ONLY used with logflags=4. */ - -/* Verifies and write a verbose textual version of a format=b file. - * Textual output file is gdata->checkfilename, fd is gdata->check_fd. - * Buffer is in gdata too, see gdata->check* variables. - * Could probably be isolated to a separate library or utility. - */ - -#include "hprof.h" - -typedef TableIndex HprofId; - -#include "hprof_b_spec.h" - -static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES; - -/* For map from HPROF_UTF8 to a string */ -typedef struct UmapInfo { - char *str; -} UmapInfo; - -/* Field information */ -typedef struct Finfo { - HprofId id; - HprofType ty; -} Finfo; - -/* Class information map from class ID (ClassIndex) to class information */ -typedef struct CmapInfo { - int max_finfo; - int n_finfo; - Finfo *finfo; - int inst_size; - HprofId sup; -} CmapInfo; - -/* Read raw bytes from the file image, update the pointer */ -static void -read_raw(unsigned char **pp, unsigned char *buf, int len) -{ - while ( len > 0 ) { - *buf = **pp; - buf++; - (*pp)++; - len--; - } -} - -/* Read various sized elements, properly converted from big to right endian. - * File will contain big endian format. - */ -static unsigned -read_u1(unsigned char **pp) -{ - unsigned char b; - - read_raw(pp, &b, 1); - return b; -} -static unsigned -read_u2(unsigned char **pp) -{ - unsigned short s; - - read_raw(pp, (void*)&s, 2); - return md_htons(s); -} -static unsigned -read_u4(unsigned char **pp) -{ - unsigned int u; - - read_raw(pp, (void*)&u, 4); - return md_htonl(u); -} -static jlong -read_u8(unsigned char **pp) -{ - unsigned int high; - unsigned int low; - jlong x; - - high = read_u4(pp); - low = read_u4(pp); - x = high; - x = (x << 32) | low; - return x; -} -static HprofId -read_id(unsigned char **pp) -{ - return (HprofId)read_u4(pp); -} - -/* System error routine */ -static void -system_error(const char *system_call, int rc, int errnum) -{ - char buf[256]; - char details[256]; - - details[0] = 0; - if ( errnum != 0 ) { - md_system_error(details, (int)sizeof(details)); - } else if ( rc >= 0 ) { - (void)strcpy(details,"Only part of buffer processed"); - } - if ( details[0] == 0 ) { - (void)strcpy(details,"Unknown system error condition"); - } - (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n", - system_call, details); - HPROF_ERROR(JNI_TRUE, buf); -} - -/* Write to a fd */ -static void -system_write(int fd, void *buf, int len) -{ - int res; - - HPROF_ASSERT(fd>=0); - res = md_write(fd, buf, len); - if (res < 0 || res!=len) { - system_error("write", res, errno); - } -} - -/* Flush check buffer */ -static void -check_flush(void) -{ - if ( gdata->check_fd < 0 ) { - return; - } - if (gdata->check_buffer_index) { - system_write(gdata->check_fd, gdata->check_buffer, gdata->check_buffer_index); - gdata->check_buffer_index = 0; - } -} - -/* Read out a given typed element */ -static jvalue -read_val(unsigned char **pp, HprofType ty) -{ - jvalue val; - static jvalue empty_val; - - val = empty_val; - switch ( ty ) { - case 0: - case HPROF_ARRAY_OBJECT: - case HPROF_NORMAL_OBJECT: - val.i = read_id(pp); - break; - case HPROF_BYTE: - case HPROF_BOOLEAN: - val.b = read_u1(pp); - break; - case HPROF_CHAR: - case HPROF_SHORT: - val.s = read_u2(pp); - break; - case HPROF_FLOAT: - case HPROF_INT: - val.i = read_u4(pp); - break; - case HPROF_DOUBLE: - case HPROF_LONG: - val.j = read_u8(pp); - break; - default: - HPROF_ERROR(JNI_TRUE, "bad type number"); - break; - } - return val; -} - -/* Move arbitrary byte stream into gdata->check_fd */ -static void -check_raw(void *buf, int len) -{ - if ( gdata->check_fd < 0 ) { - return; - } - - if ( len <= 0 ) { - return; - } - - if (gdata->check_buffer_index + len > gdata->check_buffer_size) { - check_flush(); - if (len > gdata->check_buffer_size) { - system_write(gdata->check_fd, buf, len); - return; - } - } - (void)memcpy(gdata->check_buffer + gdata->check_buffer_index, buf, len); - gdata->check_buffer_index += len; -} - -/* Printf for gdata->check_fd */ -static void -check_printf(char *fmt, ...) -{ - char buf[1024]; - va_list args; - - if ( gdata->check_fd < 0 ) { - return; - } - - va_start(args, fmt); - (void)md_vsnprintf(buf, sizeof(buf), fmt, args); - buf[sizeof(buf)-1] = 0; - check_raw(buf, (int)strlen(buf)); - va_end(args); -} - -/* Printf of an element for gdata->check_fd */ -static void -check_printf_val(HprofType ty, jvalue val, int long_form) -{ - jint low; - jint high; - - switch ( ty ) { - case HPROF_ARRAY_OBJECT: - check_printf("0x%08x", val.i); - break; - case HPROF_NORMAL_OBJECT: - check_printf("0x%08x", val.i); - break; - case HPROF_BOOLEAN: - check_printf("0x%02x", val.b); - break; - case HPROF_CHAR: - if ( long_form ) { - if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) { - check_printf("0x%04x", val.s); - } else { - check_printf("0x%04x(%c)", val.s, val.s); - } - } else { - if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) { - check_printf("\\u%04x", val.s); - } else { - check_printf("%c", val.s); - } - } - break; - case HPROF_FLOAT: - low = jlong_low(val.j); - check_printf("0x%08x(%f)", low, (double)val.f); - break; - case HPROF_DOUBLE: - high = jlong_high(val.j); - low = jlong_low(val.j); - check_printf("0x%08x%08x(%f)", high, low, val.d); - break; - case HPROF_BYTE: - check_printf("0x%02x", val.b); - break; - case HPROF_SHORT: - check_printf("0x%04x", val.s); - break; - case HPROF_INT: - check_printf("0x%08x", val.i); - break; - case HPROF_LONG: - high = jlong_high(val.j); - low = jlong_low(val.j); - check_printf("0x%08x%08x", high, low); - break; - } -} - -/* Printf of a string for gdata->check_fd */ -static void -check_printf_str(char *str) -{ - int len; - int i; - - if ( str == NULL ) { - check_printf(""); - } - check_printf("\""); - len = (int)strlen(str); - for (i = 0; i < len; i++) { - unsigned char c; - c = str[i]; - if ( isprint(c) ) { - check_printf("%c", c); - } else { - check_printf("\\x%02x", c); - } - } - check_printf("\""); -} - -/* Printf of a utf8 id for gdata->check_fd */ -static void -check_print_utf8(struct LookupTable *utab, char *prefix, HprofId id) -{ - TableIndex uindex; - - if ( id == 0 ) { - check_printf("%s0x%x", prefix, id); - } else { - uindex = table_find_entry(utab, &id, sizeof(id)); - if ( uindex == 0 ) { - check_printf("%s0x%x", prefix, id); - } else { - UmapInfo *umap; - - umap = (UmapInfo*)table_get_info(utab, uindex); - HPROF_ASSERT(umap!=NULL); - HPROF_ASSERT(umap->str!=NULL); - check_printf("%s0x%x->", prefix, id); - check_printf_str(umap->str); - } - } -} - -/* Add a instance field information to this cmap. */ -static void -add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty) -{ - int i; - - HPROF_ASSERT(cmap!=NULL); - i = cmap->n_finfo++; - if ( i+1 >= cmap->max_finfo ) { - int osize; - Finfo *new_finfo; - - osize = cmap->max_finfo; - cmap->max_finfo += 12; - new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo)); - (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo)); - if ( i == 0 ) { - cmap->finfo = new_finfo; - } else { - (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo)); - HPROF_FREE(cmap->finfo); - cmap->finfo = new_finfo; - } - } - cmap->finfo[i].id = id; - cmap->finfo[i].ty = ty; -} - -/* LookupTable callback for cmap entry cleanup */ -static void -cmap_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data) -{ - CmapInfo *cmap = info; - - if ( cmap == NULL ) { - return; - } - if ( cmap->finfo != NULL ) { - HPROF_FREE(cmap->finfo); - cmap->finfo = NULL; - } -} - -/* Case label for a switch on hprof heap dump elements */ -#define CASE_HEAP(name) case name: label = #name; - -/* Given the heap dump data and the utf8 map, check/write the heap dump. */ -static int -check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes) -{ - int nrecords; - unsigned char *p; - unsigned char *psave; - struct LookupTable *ctab; - CmapInfo cmap; - char *label; - unsigned tag; - HprofType ty; - HprofId id, id2, fr, sup; - int num_elements; - int num_bytes; - SerialNumber trace_serial_num; - SerialNumber thread_serial_num; - int npos; - int i; - int inst_size; - - ctab = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo)); - - /* First pass over heap records just fills in the CmapInfo table */ - nrecords = 0; - p = pstart; - while ( p < (pstart+nbytes) ) { - nrecords++; - /*LINTED*/ - npos = (int)(p - pstart); - tag = read_u1(&p); - switch ( tag ) { - CASE_HEAP(HPROF_GC_ROOT_UNKNOWN) - id = read_id(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL) - id = read_id(&p); - id2 = read_id(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL) - id = read_id(&p); - thread_serial_num = read_u4(&p); - fr = read_u4(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME) - id = read_id(&p); - thread_serial_num = read_u4(&p); - fr = read_u4(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK) - id = read_id(&p); - thread_serial_num = read_u4(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS) - id = read_id(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK) - id = read_id(&p); - thread_serial_num = read_u4(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED) - id = read_id(&p); - break; - CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ) - id = read_id(&p); - thread_serial_num = read_u4(&p); - trace_serial_num = read_u4(&p); - break; - CASE_HEAP(HPROF_GC_CLASS_DUMP) - (void)memset((void*)&cmap, 0, sizeof(cmap)); - id = read_id(&p); - trace_serial_num = read_u4(&p); - { - HprofId ld, si, pr, re1, re2; - - sup = read_id(&p); - ld = read_id(&p); - si = read_id(&p); - pr = read_id(&p); - re1 = read_id(&p); - re2 = read_id(&p); - cmap.sup = sup; - } - inst_size = read_u4(&p); - cmap.inst_size = inst_size; - num_elements = read_u2(&p); - for(i=0; i 0 ) { - TableIndex cindex; - int ifield; - CmapInfo *map; - - cindex = table_find_entry(ctab, &id2, sizeof(id2)); - HPROF_ASSERT(cindex!=0); - map = (CmapInfo*)table_get_info(ctab, cindex); - HPROF_ASSERT(map!=NULL); - HPROF_ASSERT(num_bytes==map->inst_size); - - psave = p; - ifield = 0; - - do { - for(i=0;in_finfo;i++) { - HprofType ty; - HprofId id; - jvalue val; - - ty = map->finfo[i].ty; - id = map->finfo[i].id; - HPROF_ASSERT(ty!=0); - HPROF_ASSERT(id!=0); - val = read_val(&p, ty); - check_printf(" field %d: ", ifield); - check_print_utf8(utab, "id=", id); - check_printf(", ty=%d, val=", ty); - check_printf_val(ty, val, 1); - check_printf("\n"); - ifield++; - } - id2 = map->sup; - map = NULL; - cindex = 0; - if ( id2 != 0 ) { - cindex = table_find_entry(ctab, &id2, sizeof(id2)); - HPROF_ASSERT(cindex!=0); - map = (CmapInfo*)table_get_info(ctab, cindex); - HPROF_ASSERT(map!=NULL); - } - } while ( map != NULL ); - HPROF_ASSERT(num_bytes==(p-psave)); - } - break; - CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP) - id = read_id(&p); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - num_elements = read_u4(&p); - id2 = read_id(&p); - check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n", - nrecords, npos, label, id, trace_serial_num, num_elements, id2); - for(i=0; i 0 ) { - int count; - int long_form; - int max_count; - char *quote; - - quote = ""; - long_form = 1; - max_count = 8; - count = 0; - switch ( ty ) { - case HPROF_CHAR: - long_form = 0; - max_count = 72; - quote = "\""; - /*FALLTHRU*/ - case HPROF_INT: - case HPROF_DOUBLE: - case HPROF_LONG: - case HPROF_BYTE: - case HPROF_BOOLEAN: - case HPROF_SHORT: - case HPROF_FLOAT: - check_printf(" val=%s", quote); - for(i=0; i 0 && count == 0 ) { - check_printf(" %s", quote); - } - val = read_val(&p, ty); - check_printf_val(ty, val, long_form); - count += 1; - if ( count >= max_count ) { - check_printf("\"\n"); - count = 0; - } - } - if ( count != 0 ) { - check_printf("%s\n", quote); - } - break; - } - } - HPROF_ASSERT(type_size[ty]*num_elements==(p-psave)); - break; - default: - label = "UNKNOWN"; - check_printf("H#%d@%d %s: ERROR!\n", - nrecords, npos, label); - HPROF_ERROR(JNI_TRUE, "unknown heap record type"); - break; - } - } - CHECK_FOR_ERROR(p==pstart+nbytes); - - table_cleanup(ctab, &cmap_cleanup, NULL); - - return nrecords; -} - -/* LookupTable cleanup callback for utab */ -static void -utab_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data) -{ - UmapInfo *umap = info; - - if ( umap == NULL ) { - return; - } - if ( umap->str != NULL ) { - HPROF_FREE(umap->str); - umap->str = NULL; - } -} - -/* Check all the heap tags in a heap dump */ -static int -check_tags(unsigned char *pstart, int nbytes) -{ - unsigned char *p; - int nrecord; - struct LookupTable *utab; - UmapInfo umap; - - check_printf("\nCHECK TAGS: starting\n"); - - utab = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo)); - - /* Walk the tags, assumes UTF8 tags are defined before used */ - p = pstart; - nrecord = 0; - while ( p < (pstart+nbytes) ) { - unsigned tag; - unsigned size; - int nheap_records; - int npos; - char *label; - HprofId id, nm, sg, so, gr, gn; - int i, li, num_elements; - HprofType ty; - SerialNumber trace_serial_num; - SerialNumber thread_serial_num; - SerialNumber class_serial_num; - unsigned flags; - unsigned depth; - float cutoff; - unsigned temp; - jint nblive; - jint nilive; - jlong tbytes; - jlong tinsts; - jint total_samples; - jint trace_count; - - nrecord++; - /*LINTED*/ - npos = (int)(p - pstart); - tag = read_u1(&p); - (void)read_u4(&p); /* microsecs */ - size = read_u4(&p); - #define CASE_TAG(name) case name: label = #name; - switch ( tag ) { - CASE_TAG(HPROF_UTF8) - CHECK_FOR_ERROR(size>=(int)sizeof(HprofId)); - id = read_id(&p); - check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"", - nrecord, npos, label, size, id); - num_elements = size-(int)sizeof(HprofId); - check_raw(p, num_elements); - check_printf("\"\n"); - /* Create entry in umap */ - umap.str = HPROF_MALLOC(num_elements+1); - (void)strncpy(umap.str, (char*)p, (size_t)num_elements); - umap.str[num_elements] = 0; - (void)table_create_entry(utab, &id, sizeof(id), &umap); - p += num_elements; - break; - CASE_TAG(HPROF_LOAD_CLASS) - CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId)); - class_serial_num = read_u4(&p); - CHECK_CLASS_SERIAL_NO(class_serial_num); - id = read_id(&p); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - nm = read_id(&p); - check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u," - " id=0x%x, trace_serial_num=%u, name_id=0x%x\n", - nrecord, npos, label, size, class_serial_num, - id, trace_serial_num, nm); - break; - CASE_TAG(HPROF_UNLOAD_CLASS) - CHECK_FOR_ERROR(size==4); - class_serial_num = read_u4(&p); - CHECK_CLASS_SERIAL_NO(class_serial_num); - check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n", - nrecord, npos, label, size, class_serial_num); - break; - CASE_TAG(HPROF_FRAME) - CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId)); - id = read_id(&p); - nm = read_id(&p); - sg = read_id(&p); - so = read_id(&p); - class_serial_num = read_u4(&p); - CHECK_CLASS_SERIAL_NO(class_serial_num); - li = read_u4(&p); - check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size); - check_print_utf8(utab, "id=", id); - check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x," - " class_serial_num=%u, lineno=%d\n", - nm, sg, so, class_serial_num, li); - break; - CASE_TAG(HPROF_TRACE) - CHECK_FOR_ERROR(size>=3*4); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - thread_serial_num = read_u4(&p); /* Can be 0 */ - num_elements = read_u4(&p); - check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u," - " thread_serial_num=%u, nelems=%d [", - nrecord, npos, label, size, - trace_serial_num, thread_serial_num, num_elements); - for(i=0; i< num_elements; i++) { - check_printf("0x%x,", read_id(&p)); - } - check_printf("]\n"); - break; - CASE_TAG(HPROF_ALLOC_SITES) - CHECK_FOR_ERROR(size>=2+4*4+2*8); - flags = read_u2(&p); - temp = read_u4(&p); - cutoff = *((float*)&temp); - nblive = read_u4(&p); - nilive = read_u4(&p); - tbytes = read_u8(&p); - tinsts = read_u8(&p); - num_elements = read_u4(&p); - check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g," - " nblive=%d, nilive=%d, tbytes=(%d,%d)," - " tinsts=(%d,%d), num_elements=%d\n", - nrecord, npos, label, size, - flags, cutoff, nblive, nilive, - jlong_high(tbytes), jlong_low(tbytes), - jlong_high(tinsts), jlong_low(tinsts), - num_elements); - for(i=0; i< num_elements; i++) { - ty = read_u1(&p); - class_serial_num = read_u4(&p); - CHECK_CLASS_SERIAL_NO(class_serial_num); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - nblive = read_u4(&p); - nilive = read_u4(&p); - tbytes = read_u4(&p); - tinsts = read_u4(&p); - check_printf("\t %d: ty=%d, class_serial_num=%u," - " trace_serial_num=%u, nblive=%d, nilive=%d," - " tbytes=%d, tinsts=%d\n", - i, ty, class_serial_num, trace_serial_num, - nblive, nilive, (jint)tbytes, (jint)tinsts); - } - break; - CASE_TAG(HPROF_HEAP_SUMMARY) - CHECK_FOR_ERROR(size==2*4+2*8); - nblive = read_u4(&p); - nilive = read_u4(&p); - tbytes = read_u8(&p); - tinsts = read_u8(&p); - check_printf("#%d@%d: %s, sz=%d," - " nblive=%d, nilive=%d, tbytes=(%d,%d)," - " tinsts=(%d,%d)\n", - nrecord, npos, label, size, - nblive, nilive, - jlong_high(tbytes), jlong_low(tbytes), - jlong_high(tinsts), jlong_low(tinsts)); - break; - CASE_TAG(HPROF_START_THREAD) - CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId)); - thread_serial_num = read_u4(&p); - CHECK_THREAD_SERIAL_NO(thread_serial_num); - id = read_id(&p); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - nm = read_id(&p); - gr = read_id(&p); - gn = read_id(&p); - check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u," - " id=0x%x, trace_serial_num=%u, ", - nrecord, npos, label, size, - thread_serial_num, id, trace_serial_num); - check_print_utf8(utab, "nm=", id); - check_printf(" trace_serial_num=%u, nm=0x%x," - " gr=0x%x, gn=0x%x\n", - trace_serial_num, nm, gr, gn); - break; - CASE_TAG(HPROF_END_THREAD) - CHECK_FOR_ERROR(size==4); - thread_serial_num = read_u4(&p); - CHECK_THREAD_SERIAL_NO(thread_serial_num); - check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n", - nrecord, npos, label, size, thread_serial_num); - break; - CASE_TAG(HPROF_HEAP_DUMP) - check_printf("#%d@%d: BEGIN: %s, sz=%d\n", - nrecord, npos, label, size); - nheap_records = check_heap_tags(utab, p, size); - check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n", - nrecord, npos, label, size, nheap_records); - p += size; - break; - CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */ - check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n", - nrecord, npos, label, size); - nheap_records = check_heap_tags(utab, p, size); - check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n", - nrecord, npos, label, size, nheap_records); - p += size; - break; - CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */ - check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n", - nrecord, npos, label, size); - break; - CASE_TAG(HPROF_CPU_SAMPLES) - CHECK_FOR_ERROR(size>=2*4); - total_samples = read_u4(&p); - trace_count = read_u4(&p); - check_printf("#%d@%d: %s, sz=%d, total_samples=%d," - " trace_count=%d\n", - nrecord, npos, label, size, - total_samples, trace_count); - for(i=0; i< trace_count; i++) { - num_elements = read_u4(&p); - trace_serial_num = read_u4(&p); - CHECK_TRACE_SERIAL_NO(trace_serial_num); - check_printf("\t %d: samples=%d, trace_serial_num=%u\n", - trace_serial_num, num_elements); - } - break; - CASE_TAG(HPROF_CONTROL_SETTINGS) - CHECK_FOR_ERROR(size==4+2); - flags = read_u4(&p); - depth = read_u2(&p); - check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n", - nrecord, npos, label, size, flags, depth); - break; - default: - label = "UNKNOWN"; - check_printf("#%d@%d: %s, sz=%d\n", - nrecord, npos, label, size); - HPROF_ERROR(JNI_TRUE, "unknown record type"); - p += size; - break; - } - CHECK_FOR_ERROR(p<=(pstart+nbytes)); - } - check_flush(); - CHECK_FOR_ERROR(p==(pstart+nbytes)); - table_cleanup(utab, &utab_cleanup, NULL); - return nrecord; -} - -/* Read the entire file into memory */ -static void * -get_binary_file_image(char *filename, int *pnbytes) -{ - unsigned char *image; - int fd; - jlong nbytes; - int nread; - - *pnbytes = 0; - fd = md_open_binary(filename); - CHECK_FOR_ERROR(fd>=0); - if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) { - HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file"); - } - CHECK_FOR_ERROR(((jint)nbytes)>512); - if ( md_seek(fd, (jlong)0) != (jlong)0 ) { - HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file"); - } - image = HPROF_MALLOC(((jint)nbytes)+1); - CHECK_FOR_ERROR(image!=NULL); - - /* Read the entire file image into memory */ - nread = md_read(fd, image, (jint)nbytes); - if ( nread <= 0 ) { - HPROF_ERROR(JNI_TRUE, "System read failed."); - } - CHECK_FOR_ERROR(((jint)nbytes)==nread); - md_close(fd); - *pnbytes = (jint)nbytes; - return image; -} - -/* ------------------------------------------------------------------ */ - -void -check_binary_file(char *filename) -{ - unsigned char *image; - unsigned char *p; - unsigned idsize; - int nbytes; - int nrecords; - - image = get_binary_file_image(filename, &nbytes); - if ( image == NULL ) { - check_printf("No file image: %s\n", filename); - return; - } - p = image; - CHECK_FOR_ERROR(strcmp((char*)p, gdata->header)==0); - check_printf("Filename=%s, nbytes=%d, header=\"%s\"\n", - filename, nbytes, p); - p+=((int)strlen((char*)p)+1); - idsize = read_u4(&p); - CHECK_FOR_ERROR(idsize==sizeof(HprofId)); - (void)read_u4(&p); - (void)read_u4(&p); - /* LINTED */ - nrecords = check_tags(p, nbytes - (int)( p - image ) ); - check_printf("#%d total records found in %d bytes\n", nrecords, nbytes); - HPROF_FREE(image); -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h deleted file mode 100644 index 02f470773bf..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_check.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_CHECK_H -#define HPROF_CHECK_H - -#define CHECK_FOR_ERROR(condition) \ - ( (condition) ? \ - (void)0 : \ - HPROF_ERROR(JNI_TRUE, #condition) ) -#define CHECK_SERIAL_NO(name, sno) \ - CHECK_FOR_ERROR( (sno) >= gdata->name##_serial_number_start && \ - (sno) < gdata->name##_serial_number_counter) -#define CHECK_CLASS_SERIAL_NO(sno) CHECK_SERIAL_NO(class,sno) -#define CHECK_THREAD_SERIAL_NO(sno) CHECK_SERIAL_NO(thread,sno) -#define CHECK_TRACE_SERIAL_NO(sno) CHECK_SERIAL_NO(trace,sno) -#define CHECK_OBJECT_SERIAL_NO(sno) CHECK_SERIAL_NO(object,sno) - -void check_binary_file(char *filename); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c deleted file mode 100644 index 3ebe0086685..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* Table of class information. - * - * Each element in this table is identified with a ClassIndex. - * Each element is uniquely identified by it's signature and loader. - * Every class load has a unique class serial number. - * While loaded, each element will have a cache of a global reference - * to it's jclass object, plus jmethodID's as needed. - * Method signatures and names are obtained via BCI. - * Methods can be identified with a ClassIndex and MethodIndex pair, - * where the MethodIndex matches the index of the method name and - * signature arrays obtained from the BCI pass. - * Strings are stored in the string table and a StringIndex is used. - * Class Loaders are stored in the loader table and a LoaderIndex is used. - * Since the jclass object is an object, at some point an object table - * entry may be allocated for the jclass as an ObjectIndex. - */ - -#include "hprof.h" - -/* Effectively represents a jclass object. */ - -/* These table elements are made unique by and sorted by signature name. */ - -typedef struct ClassKey { - StringIndex sig_string_index; /* Signature of class */ - LoaderIndex loader_index; /* Index for class loader */ -} ClassKey; - -/* Each class could contain method information, gotten from BCI callback */ - -typedef struct MethodInfo { - StringIndex name_index; /* Method name, index into string table */ - StringIndex sig_index; /* Method signature, index into string table */ - jmethodID method_id; /* Method ID, possibly NULL at first */ -} MethodInfo; - -/* The basic class information we save */ - -typedef struct ClassInfo { - jclass classref; /* Global ref to jclass */ - MethodInfo *method; /* Array of method data */ - int method_count; /* Count of methods */ - ObjectIndex object_index; /* Optional object index for jclass */ - SerialNumber serial_num; /* Unique to the actual class load */ - ClassStatus status; /* Current class status (bit mask) */ - ClassIndex super; /* Super class in this table */ - StringIndex name; /* Name of class */ - jint inst_size; /* #bytes needed for instance fields */ - jint field_count; /* Number of all fields */ - FieldInfo *field; /* Pointer to all FieldInfo's */ -} ClassInfo; - -/* Private interfaces */ - -static ClassKey* -get_pkey(ClassIndex index) -{ - void *key_ptr; - int key_len; - - table_get_key(gdata->class_table, index, (void*)&key_ptr, &key_len); - HPROF_ASSERT(key_len==sizeof(ClassKey)); - HPROF_ASSERT(key_ptr!=NULL); - return (ClassKey*)key_ptr; -} - -static void -fillin_pkey(const char *sig, LoaderIndex loader_index, ClassKey *pkey) -{ - static ClassKey empty_key; - - HPROF_ASSERT(loader_index!=0); - *pkey = empty_key; - pkey->sig_string_index = string_find_or_create(sig); - pkey->loader_index = loader_index; -} - -static ClassInfo * -get_info(ClassIndex index) -{ - ClassInfo *info; - - info = (ClassInfo*)table_get_info(gdata->class_table, index); - return info; -} - -static void -fill_info(TableIndex index, ClassKey *pkey) -{ - ClassInfo *info; - char *sig; - - info = get_info(index); - info->serial_num = gdata->class_serial_number_counter++; - info->method_count = 0; - info->inst_size = -1; - info->field_count = -1; - info->field = NULL; - sig = string_get(pkey->sig_string_index); - if ( sig[0] != JVM_SIGNATURE_CLASS ) { - info->name = pkey->sig_string_index; - } else { - int len; - - len = string_get_len(pkey->sig_string_index); - if ( len > 2 ) { - char *name; - - /* Class signature looks like "Lname;", we want "name" here. */ - name = HPROF_MALLOC(len-1); - (void)memcpy(name, sig+1, len-2); - name[len-2] = 0; - info->name = string_find_or_create(name); - HPROF_FREE(name); - } else { - /* This would be strange, a class signature not in "Lname;" form? */ - info->name = pkey->sig_string_index; - } - } -} - -static ClassIndex -find_entry(ClassKey *pkey) -{ - ClassIndex index; - - index = table_find_entry(gdata->class_table, - (void*)pkey, (int)sizeof(ClassKey)); - return index; -} - -static ClassIndex -create_entry(ClassKey *pkey) -{ - ClassIndex index; - - index = table_create_entry(gdata->class_table, - (void*)pkey, (int)sizeof(ClassKey), NULL); - fill_info(index, pkey); - return index; -} - -static ClassIndex -find_or_create_entry(ClassKey *pkey) -{ - ClassIndex index; - - HPROF_ASSERT(pkey!=NULL); - HPROF_ASSERT(pkey->loader_index!=0); - index = find_entry(pkey); - if ( index == 0 ) { - index = create_entry(pkey); - } - return index; -} - -static void -delete_classref(JNIEnv *env, ClassInfo *info, jclass klass) -{ - jclass ref; - int i; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(info!=NULL); - - for ( i = 0 ; i < info->method_count ; i++ ) { - info->method[i].method_id = NULL; - } - ref = info->classref; - if ( klass != NULL ) { - info->classref = newGlobalReference(env, klass); - } else { - info->classref = NULL; - } - if ( ref != NULL ) { - deleteGlobalReference(env, ref); - } -} - -static void -cleanup_item(TableIndex index, void *key_ptr, int key_len, - void *info_ptr, void *arg) -{ - ClassInfo *info; - - /* Cleanup any information in this ClassInfo structure. */ - HPROF_ASSERT(key_ptr!=NULL); - HPROF_ASSERT(key_len==sizeof(ClassKey)); - HPROF_ASSERT(info_ptr!=NULL); - info = (ClassInfo *)info_ptr; - if ( info->method_count > 0 ) { - HPROF_FREE((void*)info->method); - info->method_count = 0; - info->method = NULL; - } - if ( info->field != NULL ) { - HPROF_FREE((void*)info->field); - info->field_count = 0; - info->field = NULL; - } -} - -static void -delete_ref_item(TableIndex index, void *key_ptr, int key_len, - void *info_ptr, void *arg) -{ - delete_classref((JNIEnv*)arg, (ClassInfo*)info_ptr, NULL); -} - -static void -list_item(TableIndex index, void *key_ptr, int key_len, - void *info_ptr, void *arg) -{ - ClassInfo *info; - ClassKey key; - char *sig; - int i; - - HPROF_ASSERT(key_ptr!=NULL); - HPROF_ASSERT(key_len==sizeof(ClassKey)); - HPROF_ASSERT(info_ptr!=NULL); - key = *((ClassKey*)key_ptr); - sig = string_get(key.sig_string_index); - info = (ClassInfo *)info_ptr; - debug_message( - "0x%08x: Class %s, SN=%u, status=0x%08x, ref=%p," - " method_count=%d\n", - index, - (const char *)sig, - info->serial_num, - info->status, - (void*)info->classref, - info->method_count); - if ( info->method_count > 0 ) { - for ( i = 0 ; i < info->method_count ; i++ ) { - debug_message( - " Method %d: \"%s\", sig=\"%s\", method=%p\n", - i, - string_get(info->method[i].name_index), - string_get(info->method[i].sig_index), - (void*)info->method[i].method_id); - } - } -} - -static void -all_status_remove(TableIndex index, void *key_ptr, int key_len, - void *info_ptr, void *arg) -{ - ClassInfo *info; - ClassStatus status; - - HPROF_ASSERT(info_ptr!=NULL); - /*LINTED*/ - status = (ClassStatus)(long)(ptrdiff_t)arg; - info = (ClassInfo *)info_ptr; - info->status &= (~status); -} - -static void -unload_walker(TableIndex index, void *key_ptr, int key_len, - void *info_ptr, void *arg) -{ - ClassInfo *info; - - HPROF_ASSERT(info_ptr!=NULL); - info = (ClassInfo *)info_ptr; - if ( ! ( info->status & CLASS_IN_LOAD_LIST ) ) { - if ( ! (info->status & (CLASS_SPECIAL|CLASS_SYSTEM|CLASS_UNLOADED)) ) { - io_write_class_unload(info->serial_num, info->object_index); - info->status |= CLASS_UNLOADED; - delete_classref((JNIEnv*)arg, info, NULL); - } - } -} - -/* External interfaces */ - -void -class_init(void) -{ - HPROF_ASSERT(gdata->class_table==NULL); - gdata->class_table = table_initialize("Class", 512, 512, 511, - (int)sizeof(ClassInfo)); -} - -ClassIndex -class_find_or_create(const char *sig, LoaderIndex loader_index) -{ - ClassKey key; - - fillin_pkey(sig, loader_index, &key); - return find_or_create_entry(&key); -} - -ClassIndex -class_create(const char *sig, LoaderIndex loader_index) -{ - ClassKey key; - - fillin_pkey(sig, loader_index, &key); - return create_entry(&key); -} - -void -class_prime_system_classes(void) -{ - /* Prime System classes? Anything before VM_START is System class. - * Or classes loaded before env arg is non-NULL. - * Or any of the classes listed below. - */ - static const char * signatures[] = - { - "Ljava/lang/Object;", - "Ljava/io/Serializable;", - "Ljava/lang/String;", - "Ljava/lang/Class;", - "Ljava/lang/ClassLoader;", - "Ljava/lang/System;", - "Ljava/lang/Thread;", - "Ljava/lang/ThreadGroup;", - }; - int n_signatures; - int i; - LoaderIndex loader_index; - - n_signatures = (int)sizeof(signatures)/(int)sizeof(signatures[0]); - loader_index = loader_find_or_create(NULL, NULL); - for ( i = 0 ; i < n_signatures ; i++ ) { - ClassInfo *info; - ClassIndex index; - ClassKey key; - - fillin_pkey(signatures[i], loader_index, &key); - index = find_or_create_entry(&key); - info = get_info(index); - info->status |= CLASS_SYSTEM; - } -} - -void -class_add_status(ClassIndex index, ClassStatus status) -{ - ClassInfo *info; - - info = get_info(index); - info->status |= status; -} - -ClassStatus -class_get_status(ClassIndex index) -{ - ClassInfo *info; - - info = get_info(index); - return info->status; -} - -StringIndex -class_get_signature(ClassIndex index) -{ - ClassKey *pkey; - - pkey = get_pkey(index); - return pkey->sig_string_index; -} - -SerialNumber -class_get_serial_number(ClassIndex index) -{ - ClassInfo *info; - - if ( index == 0 ) { - return 0; - } - info = get_info(index); - return info->serial_num; -} - -void -class_all_status_remove(ClassStatus status) -{ - table_walk_items(gdata->class_table, &all_status_remove, - (void*)(ptrdiff_t)(long)status); -} - -void -class_do_unloads(JNIEnv *env) -{ - table_walk_items(gdata->class_table, &unload_walker, (void*)env); -} - -void -class_list(void) -{ - debug_message( - "--------------------- Class Table ------------------------\n"); - table_walk_items(gdata->class_table, &list_item, NULL); - debug_message( - "----------------------------------------------------------\n"); -} - -void -class_cleanup(void) -{ - table_cleanup(gdata->class_table, &cleanup_item, NULL); - gdata->class_table = NULL; -} - -void -class_delete_global_references(JNIEnv* env) -{ - table_walk_items(gdata->class_table, &delete_ref_item, (void*)env); -} - -void -class_set_methods(ClassIndex index, const char **name, const char **sig, - int count) -{ - ClassInfo *info; - int i; - - info = get_info(index); - if ( info->method_count > 0 ) { - HPROF_FREE((void*)info->method); - info->method_count = 0; - info->method = NULL; - } - info->method_count = count; - if ( count > 0 ) { - info->method = (MethodInfo *)HPROF_MALLOC(count*(int)sizeof(MethodInfo)); - for ( i = 0 ; i < count ; i++ ) { - info->method[i].name_index = string_find_or_create(name[i]); - info->method[i].sig_index = string_find_or_create(sig[i]); - info->method[i].method_id = NULL; - } - } -} - -jclass -class_new_classref(JNIEnv *env, ClassIndex index, jclass classref) -{ - ClassInfo *info; - - HPROF_ASSERT(classref!=NULL); - info = get_info(index); - if ( ! isSameObject(env, classref, info->classref) ) { - delete_classref(env, info, classref); - } - return info->classref; -} - -jclass -class_get_class(JNIEnv *env, ClassIndex index) -{ - ClassInfo *info; - jclass clazz; - - info = get_info(index); - clazz = info->classref; - if ( env != NULL && clazz == NULL ) { - WITH_LOCAL_REFS(env, 1) { - jclass new_clazz; - char *class_name; - - class_name = string_get(info->name); - /* This really only makes sense for the bootclass classes, - * since FindClass doesn't provide a way to load a class in - * a specific class loader. - */ - new_clazz = findClass(env, class_name); - if ( new_clazz == NULL ) { - HPROF_ERROR(JNI_TRUE, "Cannot load class with findClass"); - } - HPROF_ASSERT(new_clazz!=NULL); - clazz = class_new_classref(env, index, new_clazz); - } END_WITH_LOCAL_REFS; - HPROF_ASSERT(clazz!=NULL); - } - return clazz; -} - -jmethodID -class_get_methodID(JNIEnv *env, ClassIndex index, MethodIndex mnum) -{ - ClassInfo *info; - jmethodID method; - - info = get_info(index); - if (mnum >= info->method_count) { - jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); - (*env)->ThrowNew(env, newExcCls, "Illegal mnum"); - - return NULL; - } - method = info->method[mnum].method_id; - if ( method == NULL ) { - char * name; - char * sig; - jclass clazz; - - name = (char *)string_get(info->method[mnum].name_index); - if (name==NULL) { - jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); - (*env)->ThrowNew(env, newExcCls, "Name not found"); - - return NULL; - } - sig = (char *)string_get(info->method[mnum].sig_index); - HPROF_ASSERT(sig!=NULL); - clazz = class_get_class(env, index); - if ( clazz != NULL ) { - method = getMethodID(env, clazz, name, sig); - HPROF_ASSERT(method!=NULL); - info = get_info(index); - info->method[mnum].method_id = method; - } - } - return method; -} - -void -class_set_inst_size(ClassIndex index, jint inst_size) -{ - ClassInfo *info; - - info = get_info(index); - info->inst_size = inst_size; -} - -jint -class_get_inst_size(ClassIndex index) -{ - ClassInfo *info; - - info = get_info(index); - return info->inst_size; -} - -void -class_set_object_index(ClassIndex index, ObjectIndex object_index) -{ - ClassInfo *info; - - info = get_info(index); - info->object_index = object_index; -} - -ObjectIndex -class_get_object_index(ClassIndex index) -{ - ClassInfo *info; - - info = get_info(index); - return info->object_index; -} - -ClassIndex -class_get_super(ClassIndex index) -{ - ClassInfo *info; - - info = get_info(index); - return info->super; -} - -void -class_set_super(ClassIndex index, ClassIndex super) -{ - ClassInfo *info; - - info = get_info(index); - info->super = super; -} - -LoaderIndex -class_get_loader(ClassIndex index) -{ - ClassKey *pkey; - - pkey = get_pkey(index); - HPROF_ASSERT(pkey->loader_index!=0); - return pkey->loader_index; -} - -/* Get ALL class fields (supers too), return 1 on error, 0 if ok */ -jint -class_get_all_fields(JNIEnv *env, ClassIndex index, - jint *pfield_count, FieldInfo **pfield) -{ - ClassInfo *info; - FieldInfo *finfo; - jint count; - jint ret; - - count = 0; - finfo = NULL; - ret = 1; /* Default is to return an error condition */ - - info = get_info(index); - if ( info != NULL ) { - if ( info->field_count >= 0 ) { - /* Get cache */ - count = info->field_count; - finfo = info->field; - ret = 0; /* Return of cache data, no error */ - } else { - jclass klass; - - klass = info->classref; - if ( klass == NULL || isSameObject(env, klass, NULL) ) { - /* This is probably an error because this will cause the field - * index values to be off, but I'm hesitant to generate a - * fatal error here, so I will issue something and continue. - * I should have been holding a global reference to all the - * jclass, so I'm not sure how this could happen. - * Issuing a FindClass() here is just asking for trouble - * because if the class went away, we aren't even sure - * what ClassLoader to use. - */ - HPROF_ERROR(JNI_FALSE, "Missing jclass when fields needed"); - } else { - jint status; - - status = getClassStatus(klass); - if ( status & - (JVMTI_CLASS_STATUS_PRIMITIVE|JVMTI_CLASS_STATUS_ARRAY) ) { - /* Set cache */ - info->field_count = count; - info->field = finfo; - ret = 0; /* Primitive or array ok */ - } else if ( status & JVMTI_CLASS_STATUS_PREPARED ) { - /* Call JVMTI to get them */ - getAllClassFieldInfo(env, klass, &count, &finfo); - /* Set cache */ - info->field_count = count; - info->field = finfo; - ret = 0; - } - } - } - } - *pfield_count = count; - *pfield = finfo; - return ret; -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h deleted file mode 100644 index 6b4bc9c397d..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_class.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_CLASS_H -#define HPROF_CLASS_H - -void class_init(void); -ClassIndex class_find_or_create(const char *sig, LoaderIndex loader); -ClassIndex class_create(const char *sig, LoaderIndex loader); -SerialNumber class_get_serial_number(ClassIndex index); -StringIndex class_get_signature(ClassIndex index); -ClassStatus class_get_status(ClassIndex index); -void class_add_status(ClassIndex index, ClassStatus status); -void class_all_status_remove(ClassStatus status); -void class_do_unloads(JNIEnv *env); -void class_list(void); -void class_delete_global_references(JNIEnv* env); -void class_cleanup(void); -void class_set_methods(ClassIndex index, const char**name, - const char**descr, int count); -jmethodID class_get_methodID(JNIEnv *env, ClassIndex index, - MethodIndex mnum); -jclass class_new_classref(JNIEnv *env, ClassIndex index, - jclass classref); -void class_delete_classref(JNIEnv *env, ClassIndex index); -jclass class_get_class(JNIEnv *env, ClassIndex index); -void class_set_inst_size(ClassIndex index, jint inst_size); -jint class_get_inst_size(ClassIndex index); -void class_set_object_index(ClassIndex index, - ObjectIndex object_index); -ObjectIndex class_get_object_index(ClassIndex index); -ClassIndex class_get_super(ClassIndex index); -void class_set_super(ClassIndex index, ClassIndex super); -void class_set_loader(ClassIndex index, LoaderIndex loader); -LoaderIndex class_get_loader(ClassIndex index); -void class_prime_system_classes(void); -jint class_get_all_fields(JNIEnv *env, ClassIndex cnum, - jint *pfield_count, FieldInfo **pfield); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c deleted file mode 100644 index 5c1b953a401..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#include "hprof.h" - -/* This file contains the cpu loop for the option cpu=samples */ - -/* The cpu_loop thread basically waits for gdata->sample_interval millisecs - * then wakes up, and for each running thread it gets their stack trace, - * and updates the traces with 'hits'. - * - * No threads are suspended or resumed, and the thread sampling is in the - * file hprof_tls.c, which manages all active threads. The sampling - * technique (what is sampled) is also in hprof_tls.c. - * - * No adjustments are made to the pause time or sample interval except - * by the user via the interval=n option (default is 10ms). - * - * This thread can cause havoc when started prematurely or not terminated - * properly, see cpu_sample_init() and cpu_term(), and their calls in hprof_init.c. - * - * The listener loop (hprof_listener.c) can dynamically turn on or off the - * sampling of all or selected threads. - * - */ - -/* Private functions */ - -static void JNICALL -cpu_loop_function(jvmtiEnv *jvmti, JNIEnv *env, void *p) -{ - int loop_trip_counter; - jboolean cpu_loop_running; - - loop_trip_counter = 0; - - rawMonitorEnter(gdata->cpu_loop_lock); { - gdata->cpu_loop_running = JNI_TRUE; - cpu_loop_running = gdata->cpu_loop_running; - /* Notify cpu_sample_init() that we have started */ - rawMonitorNotifyAll(gdata->cpu_loop_lock); - } rawMonitorExit(gdata->cpu_loop_lock); - - rawMonitorEnter(gdata->cpu_sample_lock); /* Only waits inside loop let go */ - - while ( cpu_loop_running ) { - - ++loop_trip_counter; - - LOG3("cpu_loop()", "iteration", loop_trip_counter); - - /* If a dump is in progress, we pause sampling. */ - rawMonitorEnter(gdata->dump_lock); { - if (gdata->dump_in_process) { - gdata->pause_cpu_sampling = JNI_TRUE; - } - } rawMonitorExit(gdata->dump_lock); - - /* Check to see if we need to pause sampling (listener_loop command) */ - if (gdata->pause_cpu_sampling) { - - /* - * Pause sampling for now. Reset sample controls if - * sampling is resumed again. - */ - - rawMonitorWait(gdata->cpu_sample_lock, 0); - - rawMonitorEnter(gdata->cpu_loop_lock); { - cpu_loop_running = gdata->cpu_loop_running; - } rawMonitorExit(gdata->cpu_loop_lock); - - /* Continue the while loop, which will terminate if done. */ - continue; - } - - /* This is the normal short timed wait before getting a sample */ - rawMonitorWait(gdata->cpu_sample_lock, (jlong)gdata->sample_interval); - - /* Make sure we really want to continue */ - rawMonitorEnter(gdata->cpu_loop_lock); { - cpu_loop_running = gdata->cpu_loop_running; - } rawMonitorExit(gdata->cpu_loop_lock); - - /* Break out if we are done */ - if ( !cpu_loop_running ) { - break; - } - - /* - * If a dump request came in after we checked at the top of - * the while loop, then we catch that fact here. We - * don't want to perturb the data that is being dumped so - * we just ignore the data from this sampling loop. - */ - rawMonitorEnter(gdata->dump_lock); { - if (gdata->dump_in_process) { - gdata->pause_cpu_sampling = JNI_TRUE; - } - } rawMonitorExit(gdata->dump_lock); - - /* Sample all the threads and update trace costs */ - if ( !gdata->pause_cpu_sampling) { - tls_sample_all_threads(env); - } - - /* Check to see if we need to finish */ - rawMonitorEnter(gdata->cpu_loop_lock); { - cpu_loop_running = gdata->cpu_loop_running; - } rawMonitorExit(gdata->cpu_loop_lock); - - } - rawMonitorExit(gdata->cpu_sample_lock); - - rawMonitorEnter(gdata->cpu_loop_lock); { - /* Notify cpu_sample_term() that we are done. */ - rawMonitorNotifyAll(gdata->cpu_loop_lock); - } rawMonitorExit(gdata->cpu_loop_lock); - - LOG2("cpu_loop()", "clean termination"); -} - -/* External functions */ - -void -cpu_sample_init(JNIEnv *env) -{ - gdata->cpu_sampling = JNI_TRUE; - - /* Create the raw monitors needed */ - gdata->cpu_loop_lock = createRawMonitor("HPROF cpu loop lock"); - gdata->cpu_sample_lock = createRawMonitor("HPROF cpu sample lock"); - - rawMonitorEnter(gdata->cpu_loop_lock); { - createAgentThread(env, "HPROF cpu sampling thread", - &cpu_loop_function); - /* Wait for cpu_loop_function() to notify us it has started. */ - rawMonitorWait(gdata->cpu_loop_lock, 0); - } rawMonitorExit(gdata->cpu_loop_lock); -} - -void -cpu_sample_off(JNIEnv *env, ObjectIndex object_index) -{ - jint count; - - count = 1; - if (object_index != 0) { - tls_set_sample_status(object_index, 0); - count = tls_sum_sample_status(); - } - if ( count == 0 ) { - gdata->pause_cpu_sampling = JNI_TRUE; - } else { - gdata->pause_cpu_sampling = JNI_FALSE; - } -} - -void -cpu_sample_on(JNIEnv *env, ObjectIndex object_index) -{ - if ( gdata->cpu_loop_lock == NULL ) { - cpu_sample_init(env); - } - - if (object_index == 0) { - gdata->cpu_sampling = JNI_TRUE; - gdata->pause_cpu_sampling = JNI_FALSE; - } else { - jint count; - - tls_set_sample_status(object_index, 1); - count = tls_sum_sample_status(); - if ( count > 0 ) { - gdata->pause_cpu_sampling = JNI_FALSE; - } - } - - /* Notify the CPU sampling thread that sampling is on */ - rawMonitorEnter(gdata->cpu_sample_lock); { - rawMonitorNotifyAll(gdata->cpu_sample_lock); - } rawMonitorExit(gdata->cpu_sample_lock); - -} - -void -cpu_sample_term(JNIEnv *env) -{ - gdata->pause_cpu_sampling = JNI_FALSE; - rawMonitorEnter(gdata->cpu_sample_lock); { - /* Notify the CPU sampling thread to get out of any sampling Wait */ - rawMonitorNotifyAll(gdata->cpu_sample_lock); - } rawMonitorExit(gdata->cpu_sample_lock); - rawMonitorEnter(gdata->cpu_loop_lock); { - if ( gdata->cpu_loop_running ) { - gdata->cpu_loop_running = JNI_FALSE; - /* Wait for cpu_loop_function() thread to tell us it completed. */ - rawMonitorWait(gdata->cpu_loop_lock, 0); - } - } rawMonitorExit(gdata->cpu_loop_lock); -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h deleted file mode 100644 index e63747ec3dc..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_cpu.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_CPU_H -#define HPROF_CPU_H - -void cpu_sample_off(JNIEnv *env, ObjectIndex object_index); -void cpu_sample_on(JNIEnv *env, ObjectIndex object_index); - -void cpu_sample_init(JNIEnv *env); -void cpu_sample_term(JNIEnv *env); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c deleted file mode 100644 index 9776a1da4f0..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#include "hprof.h" - -/* The error handling logic. */ - -/* - * Most hprof error processing and error functions are kept here, along with - * termination functions and signal handling (used in debug version only). - * - */ - -#include - -static int p = 1; /* Used with pause=y|n option */ - -/* Private functions */ - -static void -error_message(const char * format, ...) -{ - va_list ap; - - va_start(ap, format); - (void)vfprintf(stderr, format, ap); - va_end(ap); -} - -static void -error_abort(void) -{ - /* Important to remove existing signal handler */ - (void)signal(SIGABRT, NULL); - error_message("HPROF DUMPING CORE\n"); - abort(); /* Sends SIGABRT signal, usually also caught by libjvm */ -} - -static void -signal_handler(int sig) -{ - /* Caught a signal, most likely a SIGABRT */ - error_message("HPROF SIGNAL %d TERMINATED PROCESS\n", sig); - error_abort(); -} - -static void -setup_signal_handler(int sig) -{ - /* Only if debug version or debug=y */ - if ( gdata->debug ) { - (void)signal(sig, (void(*)(int))(void*)&signal_handler); - } -} - -static void -terminate_everything(jint exit_code) -{ - if ( exit_code > 0 ) { - /* Could be a fatal error or assert error or a sanity error */ - error_message("HPROF TERMINATED PROCESS\n"); - if ( gdata->coredump || gdata->debug ) { - /* Core dump here by request */ - error_abort(); - } - } - /* Terminate the process */ - error_exit_process(exit_code); -} - -/* External functions */ - -void -error_setup(void) -{ - setup_signal_handler(SIGABRT); -} - -void -error_do_pause(void) -{ - int pid = md_getpid(); - int timeleft = 600; /* 10 minutes max */ - int interval = 10; /* 10 second message check */ - - /*LINTED*/ - error_message("\nHPROF pause for PID %d\n", (int)pid); - while ( p && timeleft > 0 ) { - md_sleep(interval); /* 'assign p=0' to stop pause loop */ - timeleft -= interval; - } - if ( timeleft <= 0 ) { - error_message("\n HPROF pause got tired of waiting and gave up.\n"); - } -} - -void -error_exit_process(int exit_code) -{ - exit(exit_code); -} - -static const char * -source_basename(const char *file) -{ - const char *p; - - if ( file == NULL ) { - return "UnknownSourceFile"; - } - p = strrchr(file, '/'); - if ( p == NULL ) { - p = strrchr(file, '\\'); - } - if ( p == NULL ) { - p = file; - } else { - p++; /* go past / */ - } - return p; -} - -void -error_assert(const char *condition, const char *file, int line) -{ - error_message("ASSERTION FAILURE: %s [%s:%d]\n", condition, - source_basename(file), line); - error_abort(); -} - -void -error_handler(jboolean fatal, jvmtiError error, - const char *message, const char *file, int line) -{ - char *error_name; - - if ( message==NULL ) { - message = ""; - } - if ( error != JVMTI_ERROR_NONE ) { - error_name = getErrorName(error); - if ( error_name == NULL ) { - error_name = "?"; - } - error_message("HPROF ERROR: %s (JVMTI Error %s(%d)) [%s:%d]\n", - message, error_name, error, - source_basename(file), line); - } else { - error_message("HPROF ERROR: %s [%s:%d]\n", message, - source_basename(file), line); - } - if ( fatal || gdata->errorexit ) { - /* If it's fatal, or the user wants termination on any error, die */ - terminate_everything(9); - } -} - -void -debug_message(const char * format, ...) -{ - va_list ap; - - va_start(ap, format); - (void)vfprintf(stderr, format, ap); - va_end(ap); -} - -void -verbose_message(const char * format, ...) -{ - if ( gdata->verbose ) { - va_list ap; - - va_start(ap, format); - (void)vfprintf(stderr, format, ap); - va_end(ap); - } -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h deleted file mode 100644 index 6dd06e02ec3..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_error.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_ERROR_H -#define HPROF_ERROR_H - -/* Use THIS_FILE when it is available. */ -#ifndef THIS_FILE - #define THIS_FILE __FILE__ -#endif - -/* Macros over assert and error functions so we can capture the source loc. */ - -#define HPROF_BOOL(x) ((jboolean)((x)==0?JNI_FALSE:JNI_TRUE)) - -#define HPROF_ERROR(fatal,msg) \ - error_handler(HPROF_BOOL(fatal), JVMTI_ERROR_NONE, msg, THIS_FILE, __LINE__) - -#define HPROF_JVMTI_ERROR(error,msg) \ - error_handler(HPROF_BOOL(error!=JVMTI_ERROR_NONE), \ - error, msg, THIS_FILE, __LINE__) - -#if defined(DEBUG) || !defined(NDEBUG) - #define HPROF_ASSERT(cond) \ - (((int)(cond))?(void)0:error_assert(#cond, THIS_FILE, __LINE__)) -#else - #define HPROF_ASSERT(cond) -#endif - -#define LOG_DUMP_MISC 0x1 /* Misc. logging info */ -#define LOG_DUMP_LISTS 0x2 /* Dump tables at vm init and death */ -#define LOG_CHECK_BINARY 0x4 /* If format=b, verify binary format */ - -#ifdef HPROF_LOGGING - #define LOG_STDERR(args) \ - { \ - if ( gdata != NULL && (gdata->logflags & LOG_DUMP_MISC) ) { \ - (void)fprintf args ; \ - } \ - } -#else - #define LOG_STDERR(args) -#endif - -#define LOG_FORMAT(format) "HPROF LOG: " format " [%s:%d]\n" - -#define LOG1(str1) LOG_STDERR((stderr, LOG_FORMAT("%s"), \ - str1, THIS_FILE, __LINE__ )) -#define LOG2(str1,str2) LOG_STDERR((stderr, LOG_FORMAT("%s %s"), \ - str1, str2, THIS_FILE, __LINE__ )) -#define LOG3(str1,str2,num) LOG_STDERR((stderr, LOG_FORMAT("%s %s 0x%x"), \ - str1, str2, num, THIS_FILE, __LINE__ )) - -#define LOG(str) LOG1(str) - -void error_handler(jboolean fatal, jvmtiError error, - const char *message, const char *file, int line); -void error_assert(const char *condition, const char *file, int line); -void error_exit_process(int exit_code); -void error_do_pause(void); -void error_setup(void); -void debug_message(const char * format, ...); -void verbose_message(const char * format, ...); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c deleted file mode 100644 index 194ef360e5a..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.c +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* This file contains all class, method and allocation event support functions, - * both JVMTI and BCI events. - * (See hprof_monitor.c for the monitor event handlers). - */ - -#include "hprof.h" - -/* Private internal functions. */ - -/* Return a TraceIndex for the given thread. */ -static TraceIndex -get_current(TlsIndex tls_index, JNIEnv *env, jboolean skip_init) -{ - TraceIndex trace_index; - - trace_index = tls_get_trace(tls_index, env, gdata->max_trace_depth, skip_init); - return trace_index; -} - -/* Return a ClassIndex for the given jclass, loader supplied or looked up. */ -static ClassIndex -find_cnum(JNIEnv *env, jclass klass, jobject loader) -{ - LoaderIndex loader_index; - ClassIndex cnum; - char * signature; - - HPROF_ASSERT(klass!=NULL); - - /* Get the loader index */ - loader_index = loader_find_or_create(env, loader); - - /* Get the signature for this class */ - getClassSignature(klass, &signature, NULL); - - /* Find the ClassIndex for this class */ - cnum = class_find_or_create(signature, loader_index); - - /* Free the signature space */ - jvmtiDeallocate(signature); - - /* Make sure we save a global reference to this class in the table */ - HPROF_ASSERT(cnum!=0); - (void)class_new_classref(env, cnum, klass); - return cnum; -} - -/* Get the ClassIndex for the superClass of this jclass. */ -static ClassIndex -get_super(JNIEnv *env, jclass klass) -{ - ClassIndex super_cnum; - - super_cnum = 0; - WITH_LOCAL_REFS(env, 1) { - jclass super_klass; - - super_klass = getSuperclass(env, klass); - if ( super_klass != NULL ) { - super_cnum = find_cnum(env, super_klass, - getClassLoader(super_klass)); - } - } END_WITH_LOCAL_REFS; - return super_cnum; -} - -/* Record an allocation. Could be jobject, jclass, jarray or primitive type. */ -static void -any_allocation(JNIEnv *env, SerialNumber thread_serial_num, - TraceIndex trace_index, jobject object) -{ - SiteIndex site_index; - ClassIndex cnum; - jint size; - jclass klass; - - /* NOTE: Normally the getObjectClass() and getClassLoader() - * would require a - * WITH_LOCAL_REFS(env, 1) { - * } END_WITH_LOCAL_REFS; - * but for performance reasons we skip it here. - */ - - /* Get and tag the klass */ - klass = getObjectClass(env, object); - cnum = find_cnum(env, klass, getClassLoader(klass)); - site_index = site_find_or_create(cnum, trace_index); - tag_class(env, klass, cnum, thread_serial_num, site_index); - - /* Tag the object */ - size = (jint)getObjectSize(object); - tag_new_object(object, OBJECT_NORMAL, thread_serial_num, size, site_index); -} - -/* Handle a java.lang.Object. object allocation. */ -void -event_object_init(JNIEnv *env, jthread thread, jobject object) -{ - /* Called via BCI Tracker class */ - - /* Be very careful what is called here, watch out for recursion. */ - - jint *pstatus; - TraceIndex trace_index; - SerialNumber thread_serial_num; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(object!=NULL); - - /* Prevent recursion into any BCI function for this thread (pstatus). */ - if ( tls_get_tracker_status(env, thread, JNI_TRUE, - &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) { - (*pstatus) = 1; - any_allocation(env, thread_serial_num, trace_index, object); - (*pstatus) = 0; - } -} - -/* Handle any newarray opcode allocation. */ -void -event_newarray(JNIEnv *env, jthread thread, jobject object) -{ - /* Called via BCI Tracker class */ - - /* Be very careful what is called here, watch out for recursion. */ - - jint *pstatus; - TraceIndex trace_index; - SerialNumber thread_serial_num; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(object!=NULL); - - /* Prevent recursion into any BCI function for this thread (pstatus). */ - if ( tls_get_tracker_status(env, thread, JNI_FALSE, - &pstatus, NULL, &thread_serial_num, &trace_index) == 0 ) { - (*pstatus) = 1; - any_allocation(env, thread_serial_num, trace_index, object); - (*pstatus) = 0; - } -} - -/* Handle tracking of a method call. */ -void -event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) -{ - /* Called via BCI Tracker class */ - - /* Be very careful what is called here, watch out for recursion. */ - - TlsIndex tls_index; - jint *pstatus; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - if (cnum == 0 || cnum == gdata->tracker_cnum) { - jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); - (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); - - return; - } - - /* Prevent recursion into any BCI function for this thread (pstatus). */ - if ( tls_get_tracker_status(env, thread, JNI_FALSE, - &pstatus, &tls_index, NULL, NULL) == 0 ) { - jmethodID method; - - (*pstatus) = 1; - method = class_get_methodID(env, cnum, mnum); - if (method != NULL) { - tls_push_method(tls_index, method); - } - - (*pstatus) = 0; - } -} - -/* Handle tracking of an exception catch */ -void -event_exception_catch(JNIEnv *env, jthread thread, jmethodID method, - jlocation location, jobject exception) -{ - /* Called via JVMTI_EVENT_EXCEPTION_CATCH callback */ - - /* Be very careful what is called here, watch out for recursion. */ - - TlsIndex tls_index; - jint *pstatus; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(method!=NULL); - - /* Prevent recursion into any BCI function for this thread (pstatus). */ - if ( tls_get_tracker_status(env, thread, JNI_FALSE, - &pstatus, &tls_index, NULL, NULL) == 0 ) { - (*pstatus) = 1; - tls_pop_exception_catch(tls_index, thread, method); - (*pstatus) = 0; - } -} - -/* Handle tracking of a method return pop one (maybe more) methods. */ -void -event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) -{ - /* Called via BCI Tracker class */ - - /* Be very careful what is called here, watch out for recursion. */ - - TlsIndex tls_index; - jint *pstatus; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - - if (cnum == 0 || cnum == gdata->tracker_cnum) { - jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); - (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); - - return; - } - - /* Prevent recursion into any BCI function for this thread (pstatus). */ - if ( tls_get_tracker_status(env, thread, JNI_FALSE, - &pstatus, &tls_index, NULL, NULL) == 0 ) { - jmethodID method; - - (*pstatus) = 1; - method = class_get_methodID(env, cnum, mnum); - if (method != NULL) { - tls_pop_method(tls_index, thread, method); - } - - (*pstatus) = 0; - } -} - -/* Handle a class prepare (should have been already loaded) */ -void -event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader) -{ - /* Called via JVMTI_EVENT_CLASS_PREPARE event */ - - ClassIndex cnum; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(klass!=NULL); - - /* Find the ClassIndex for this class */ - cnum = find_cnum(env, klass, loader); - class_add_status(cnum, CLASS_PREPARED); - -} - -/* Handle a class load (could have been already loaded) */ -void -event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader) -{ - /* Called via JVMTI_EVENT_CLASS_LOAD event or reset_class_load_status() */ - - ClassIndex cnum; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(klass!=NULL); - - /* Find the ClassIndex for this class */ - cnum = find_cnum(env, klass, loader); - - /* Always mark it as being in the load list */ - class_add_status(cnum, CLASS_IN_LOAD_LIST); - - /* If we are seeing this as a new loaded class, extra work */ - if ( ! ( class_get_status(cnum) & CLASS_LOADED ) ) { - TraceIndex trace_index; - SiteIndex site_index; - ClassIndex super; - SerialNumber class_serial_num; - SerialNumber trace_serial_num; - SerialNumber thread_serial_num; - ObjectIndex class_object_index; - char *signature; - - /* Get the TlsIndex and a TraceIndex for this location */ - if ( thread == NULL ) { - /* This should be very rare, but if this class load was simulated - * from hprof_init.c due to a reset of the class load status, - * and it originated from a pre-VM_INIT event, the jthread - * would be NULL, or it was a jclass created that didn't get - * reported to us, like an array class or a primitive class? - */ - trace_index = gdata->system_trace_index; - thread_serial_num = gdata->unknown_thread_serial_num; - } else { - TlsIndex tls_index; - - tls_index = tls_find_or_create(env, thread); - trace_index = get_current(tls_index, env, JNI_FALSE); - thread_serial_num = tls_get_thread_serial_number(tls_index); - } - - /* Get the SiteIndex for this location and a java.lang.Class object */ - /* Note that the target cnum, not the cnum for java.lang.Class. */ - site_index = site_find_or_create(cnum, trace_index); - - /* Tag this java.lang.Class object */ - tag_class(env, klass, cnum, thread_serial_num, site_index); - - class_add_status(cnum, CLASS_LOADED); - - class_serial_num = class_get_serial_number(cnum); - class_object_index = class_get_object_index(cnum); - trace_serial_num = trace_get_serial_number(trace_index); - signature = string_get(class_get_signature(cnum)); - - rawMonitorEnter(gdata->data_access_lock); { - io_write_class_load(class_serial_num, class_object_index, - trace_serial_num, signature); - } rawMonitorExit(gdata->data_access_lock); - - super = get_super(env, klass); - class_set_super(cnum, super); - } - -} - -/* Handle a thread start event */ -void -event_thread_start(JNIEnv *env, jthread thread) -{ - /* Called via JVMTI_EVENT_THREAD_START event */ - - TlsIndex tls_index; - ObjectIndex object_index; - TraceIndex trace_index; - jlong tag; - SerialNumber thread_serial_num; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - - tls_index = tls_find_or_create(env, thread); - thread_serial_num = tls_get_thread_serial_number(tls_index); - trace_index = get_current(tls_index, env, JNI_FALSE); - - tag = getTag(thread); - if ( tag == (jlong)0 ) { - SiteIndex site_index; - jint size; - - size = (jint)getObjectSize(thread); - site_index = site_find_or_create(gdata->thread_cnum, trace_index); - /* We create a new object with this thread's serial number */ - object_index = object_new(site_index, size, OBJECT_NORMAL, - thread_serial_num); - } else { - object_index = tag_extract(tag); - /* Normally the Thread object is created and tagged before we get - * here, but the thread_serial_number on this object isn't what - * we want. So we update it to the serial number of this thread. - */ - object_set_thread_serial_number(object_index, thread_serial_num); - } - tls_set_thread_object_index(tls_index, object_index); - - WITH_LOCAL_REFS(env, 1) { - jvmtiThreadInfo threadInfo; - jvmtiThreadGroupInfo threadGroupInfo; - jvmtiThreadGroupInfo parentGroupInfo; - - getThreadInfo(thread, &threadInfo); - getThreadGroupInfo(threadInfo.thread_group, &threadGroupInfo); - if ( threadGroupInfo.parent != NULL ) { - getThreadGroupInfo(threadGroupInfo.parent, &parentGroupInfo); - } else { - (void)memset(&parentGroupInfo, 0, sizeof(parentGroupInfo)); - } - - rawMonitorEnter(gdata->data_access_lock); { - io_write_thread_start(thread_serial_num, - object_index, trace_get_serial_number(trace_index), - threadInfo.name, threadGroupInfo.name, parentGroupInfo.name); - } rawMonitorExit(gdata->data_access_lock); - - jvmtiDeallocate(threadInfo.name); - jvmtiDeallocate(threadGroupInfo.name); - jvmtiDeallocate(parentGroupInfo.name); - - } END_WITH_LOCAL_REFS; -} - -void -event_thread_end(JNIEnv *env, jthread thread) -{ - /* Called via JVMTI_EVENT_THREAD_END event */ - TlsIndex tls_index; - - HPROF_ASSERT(env!=NULL); - HPROF_ASSERT(thread!=NULL); - - tls_index = tls_find_or_create(env, thread); - rawMonitorEnter(gdata->data_access_lock); { - io_write_thread_end(tls_get_thread_serial_number(tls_index)); - } rawMonitorExit(gdata->data_access_lock); - tls_thread_ended(env, tls_index); - setThreadLocalStorage(thread, (void*)NULL); -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h deleted file mode 100644 index ebc372e8511..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_event.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_EVENT_H -#define HPROF_EVENT_H - -/* From BCI: */ -void event_object_init(JNIEnv *env, jthread thread, jobject obj); -void event_newarray(JNIEnv *env, jthread thread, jobject obj); -void event_call(JNIEnv *env, jthread thread, - ClassIndex cnum, MethodIndex mnum); -void event_return(JNIEnv *env, jthread thread, - ClassIndex cnum, MethodIndex mnum); - -/* From JVMTI: */ -void event_class_load(JNIEnv *env, jthread thread, jclass klass, jobject loader); -void event_class_prepare(JNIEnv *env, jthread thread, jclass klass, jobject loader); -void event_thread_start(JNIEnv *env_id, jthread thread); -void event_thread_end(JNIEnv *env_id, jthread thread); -void event_exception_catch(JNIEnv *env, jthread thread, jmethodID method, - jlocation location, jobject exception); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c deleted file mode 100644 index df99d9aa9d7..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* This file contains support for handling frames, or (method,location) pairs. */ - -#include "hprof.h" - -/* - * Frames map 1-to-1 to (methodID,location) pairs. - * When no line number is known, -1 should be used. - * - * Frames are mostly used in traces (see hprof_trace.c) and will be marked - * with their status flag as they are written out to the hprof output file. - * - */ - -enum LinenoState { - LINENUM_UNINITIALIZED = 0, - LINENUM_AVAILABLE = 1, - LINENUM_UNAVAILABLE = 2 -}; - -typedef struct FrameKey { - jmethodID method; - jlocation location; -} FrameKey; - -typedef struct FrameInfo { - unsigned short lineno; - unsigned char lineno_state; /* LinenoState */ - unsigned char status; - SerialNumber serial_num; -} FrameInfo; - -static FrameKey* -get_pkey(FrameIndex index) -{ - void *key_ptr; - int key_len; - - table_get_key(gdata->frame_table, index, &key_ptr, &key_len); - HPROF_ASSERT(key_len==sizeof(FrameKey)); - HPROF_ASSERT(key_ptr!=NULL); - return (FrameKey*)key_ptr; -} - -static FrameInfo * -get_info(FrameIndex index) -{ - FrameInfo *info; - - info = (FrameInfo*)table_get_info(gdata->frame_table, index); - return info; -} - -static void -list_item(TableIndex i, void *key_ptr, int key_len, void *info_ptr, void *arg) -{ - FrameKey key; - FrameInfo *info; - - HPROF_ASSERT(key_ptr!=NULL); - HPROF_ASSERT(key_len==sizeof(FrameKey)); - HPROF_ASSERT(info_ptr!=NULL); - - key = *((FrameKey*)key_ptr); - info = (FrameInfo*)info_ptr; - debug_message( - "Frame 0x%08x: method=%p, location=%d, lineno=%d(%d), status=%d \n", - i, (void*)key.method, (jint)key.location, - info->lineno, info->lineno_state, info->status); -} - -void -frame_init(void) -{ - gdata->frame_table = table_initialize("Frame", - 1024, 1024, 1023, (int)sizeof(FrameInfo)); -} - -FrameIndex -frame_find_or_create(jmethodID method, jlocation location) -{ - FrameIndex index; - static FrameKey empty_key; - FrameKey key; - jboolean new_one; - - key = empty_key; - key.method = method; - key.location = location; - new_one = JNI_FALSE; - index = table_find_or_create_entry(gdata->frame_table, - &key, (int)sizeof(key), &new_one, NULL); - if ( new_one ) { - FrameInfo *info; - - info = get_info(index); - info->lineno_state = LINENUM_UNINITIALIZED; - if ( location < 0 ) { - info->lineno_state = LINENUM_UNAVAILABLE; - } - info->serial_num = gdata->frame_serial_number_counter++; - } - return index; -} - -void -frame_list(void) -{ - debug_message( - "--------------------- Frame Table ------------------------\n"); - table_walk_items(gdata->frame_table, &list_item, NULL); - debug_message( - "----------------------------------------------------------\n"); -} - -void -frame_cleanup(void) -{ - table_cleanup(gdata->frame_table, NULL, NULL); - gdata->frame_table = NULL; -} - -void -frame_set_status(FrameIndex index, jint status) -{ - FrameInfo *info; - - info = get_info(index); - info->status = (unsigned char)status; -} - -void -frame_get_location(FrameIndex index, SerialNumber *pserial_num, - jmethodID *pmethod, jlocation *plocation, jint *plineno) -{ - FrameKey *pkey; - FrameInfo *info; - jint lineno; - - pkey = get_pkey(index); - *pmethod = pkey->method; - *plocation = pkey->location; - info = get_info(index); - lineno = (jint)info->lineno; - if ( info->lineno_state == LINENUM_UNINITIALIZED ) { - info->lineno_state = LINENUM_UNAVAILABLE; - if ( gdata->lineno_in_traces ) { - if ( pkey->location >= 0 && !isMethodNative(pkey->method) ) { - lineno = getLineNumber(pkey->method, pkey->location); - if ( lineno >= 0 ) { - info->lineno = (unsigned short)lineno; /* save it */ - info->lineno_state = LINENUM_AVAILABLE; - } - } - } - } - if ( info->lineno_state == LINENUM_UNAVAILABLE ) { - lineno = -1; - } - *plineno = lineno; - *pserial_num = info->serial_num; -} - -jint -frame_get_status(FrameIndex index) -{ - FrameInfo *info; - - info = get_info(index); - return (jint)info->status; -} diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h deleted file mode 100644 index 5b94414291f..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_frame.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -#ifndef HPROF_FRAME_H -#define HPROF_FRAME_H - -void frame_init(void); -FrameIndex frame_find_or_create(jmethodID method, jlocation location); -void frame_list(void); -void frame_cleanup(void); -void frame_get_location(FrameIndex frame_num, SerialNumber *serial_num, - jmethodID *pmethod, - jlocation *plocation, jint *plineno); -void frame_set_status(FrameIndex frame_num, jint status); -jint frame_get_status(FrameIndex frame_num); - -#endif diff --git a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c b/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c deleted file mode 100644 index 6190e6a0ffa..00000000000 --- a/jdk/src/jdk.hprof.agent/share/native/libhprof/hprof_init.c +++ /dev/null @@ -1,2145 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -/* Main source file, the basic JVMTI connection/startup code. */ - -#include "hprof.h" - -#include "java_crw_demo.h" - -/* - * This file contains all the startup logic (Agent_Onload) and - * connection to the JVMTI interface. - * All JVMTI Event callbacks are in this file. - * All setting of global data (gdata) is done here. - * Options are parsed here. - * Option help messages are here. - * Termination handled here (VM_DEATH) and shutdown (Agent_OnUnload). - * Spawning of the cpu sample loop thread and listener thread is done here. - * - * Use of private 'static' data has been limited, most shared static data - * should be found in the GlobalData structure pointed to by gdata - * (see hprof.h). - * - */ - -/* The default output filenames. */ - -#define DEFAULT_TXT_SUFFIX ".txt" -#define DEFAULT_OUTPUTFILE "java.hprof" -#define DEFAULT_OUTPUTTEMP "java.hprof.temp" - -/* The only global variable, defined by this library */ -GlobalData *gdata; - -/* Experimental options */ -#define EXPERIMENT_NO_EARLY_HOOK 0x1 - -/* Default trace depth */ -#define DEFAULT_TRACE_DEPTH 4 - -/* Default sample interval */ -#define DEFAULT_SAMPLE_INTERVAL 10 - -/* Default cutoff */ -#define DEFAULT_CUTOFF_POINT 0.0001 - -/* Stringize macros for help. */ -#define _TO_STR(a) #a -#define TO_STR(a) _TO_STR(a) - -/* Macros to surround callback code (non-VM_DEATH callbacks). - * Note that this just keeps a count of the non-VM_DEATH callbacks that - * are currently active, it does not prevent these callbacks from - * operating in parallel. It's the VM_DEATH callback that will wait - * for all these callbacks to either complete and block, or just block. - * We need to hold back these threads so they don't die during the final - * VM_DEATH processing. - * If the VM_DEATH callback is active in the beginning, then this callback - * just blocks to prevent further execution of the thread. - * If the VM_DEATH callback is active at the end, then this callback - * will notify the VM_DEATH callback if it's the last one. - * In all cases, the last thing they do is Enter/Exit the monitor - * gdata->callbackBlock, which will block this callback if VM_DEATH - * is running. - * - * WARNING: No not 'return' or 'goto' out of the BEGIN_CALLBACK/END_CALLBACK - * block, this will mess up the count. - */ - -#define BEGIN_CALLBACK() \ -{ /* BEGIN OF CALLBACK */ \ - jboolean bypass; \ - rawMonitorEnter(gdata->callbackLock); \ - if (gdata->vm_death_callback_active) { \ - /* VM_DEATH is active, we will bypass the CALLBACK CODE */ \ - bypass = JNI_TRUE; \ - rawMonitorExit(gdata->callbackLock); \ - /* Bypassed CALLBACKS block here until VM_DEATH done */ \ - rawMonitorEnter(gdata->callbackBlock); \ - rawMonitorExit(gdata->callbackBlock); \ - } else { \ - /* We will be executing the CALLBACK CODE in this case */ \ - gdata->active_callbacks++; \ - bypass = JNI_FALSE; \ - rawMonitorExit(gdata->callbackLock); \ - } \ - if ( !bypass ) { \ - /* BODY OF CALLBACK CODE (with no callback locks held) */ - -#define END_CALLBACK() /* Part of bypass if body */ \ - rawMonitorEnter(gdata->callbackLock); \ - gdata->active_callbacks--; \ - /* If VM_DEATH is active, and last one, send notify. */ \ - if (gdata->vm_death_callback_active) { \ - if (gdata->active_callbacks == 0) { \ - rawMonitorNotifyAll(gdata->callbackLock); \ - } \ - } \ - rawMonitorExit(gdata->callbackLock); \ - /* Non-Bypassed CALLBACKS block here until VM_DEATH done */ \ - rawMonitorEnter(gdata->callbackBlock); \ - rawMonitorExit(gdata->callbackBlock); \ - } \ -} /* END OF CALLBACK */ - -/* Forward declarations */ -static void set_callbacks(jboolean on); - -/* ------------------------------------------------------------------- */ -/* Global data initialization */ - -/* Get initialized global data area */ -static GlobalData * -get_gdata(void) -{ - static GlobalData data; - - /* Create initial default values */ - (void)memset(&data, 0, sizeof(GlobalData)); - - data.fd = -1; /* Non-zero file or socket. */ - data.heap_fd = -1; /* For heap=dump, see hprof_io */ - data.check_fd = -1; /* For heap=dump, see hprof_io */ - data.max_trace_depth = DEFAULT_TRACE_DEPTH; - data.prof_trace_depth = DEFAULT_TRACE_DEPTH; - data.sample_interval = DEFAULT_SAMPLE_INTERVAL; - data.lineno_in_traces = JNI_TRUE; - data.output_format = 'a'; /* 'b' for binary */ - data.cutoff_point = DEFAULT_CUTOFF_POINT; - data.dump_on_exit = JNI_TRUE; - data.gc_start_time = -1L; -#ifdef DEBUG - data.debug = JNI_TRUE; - data.coredump = JNI_TRUE; -#endif - data.micro_state_accounting = JNI_FALSE; - data.force_output = JNI_TRUE; - data.verbose = JNI_TRUE; - data.primfields = JNI_TRUE; - data.primarrays = JNI_TRUE; - - data.table_serial_number_start = 1; - data.class_serial_number_start = 100000; - data.thread_serial_number_start = 200000; - data.trace_serial_number_start = 300000; - data.object_serial_number_start = 400000; - data.frame_serial_number_start = 500000; - data.gref_serial_number_start = 1; - - data.table_serial_number_counter = data.table_serial_number_start; - data.class_serial_number_counter = data.class_serial_number_start; - data.thread_serial_number_counter = data.thread_serial_number_start; - data.trace_serial_number_counter = data.trace_serial_number_start; - data.object_serial_number_counter = data.object_serial_number_start; - data.frame_serial_number_counter = data.frame_serial_number_start; - data.gref_serial_number_counter = data.gref_serial_number_start; - - data.unknown_thread_serial_num = data.thread_serial_number_counter++; - return &data; -} - -/* ------------------------------------------------------------------- */ -/* Error handler callback for the java_crw_demo (classfile read write) functions. */ - -static void -my_crw_fatal_error_handler(const char * msg, const char *file, int line) -{ - char errmsg[256]; - - (void)md_snprintf(errmsg, sizeof(errmsg), - "%s [%s:%d]", msg, file, line); - errmsg[sizeof(errmsg)-1] = 0; - HPROF_ERROR(JNI_TRUE, errmsg); -} - -static void -list_all_tables(void) -{ - string_list(); - class_list(); - frame_list(); - site_list(); - object_list(); - trace_list(); - monitor_list(); - tls_list(); - loader_list(); -} - -/* ------------------------------------------------------------------- */ -/* Option Parsing support */ - -/** - * Socket connection - */ - -/* - * Return a socket connect()ed to a "hostname" that is - * accept()ing heap profile data on "port." Return a value <= 0 if - * such a connection can't be made. - */ -static int -connect_to_socket(char *hostname, int port) -{ - int fd; - - if (port == 0 || port > 65535) { - HPROF_ERROR(JNI_FALSE, "invalid port number"); - return -1; - } - if (hostname == NULL) { - HPROF_ERROR(JNI_FALSE, "hostname is NULL"); - return -1; - } - - /* create a socket */ - fd = md_connect(hostname, (unsigned short)port); - return fd; -} - -/* Accept a filename, and adjust the name so that it is unique for this PID */ -static void -make_unique_filename(char **filename) -{ - int fd; - - /* Find a file that doesn't exist */ - fd = md_open(*filename); - if ( fd >= 0 ) { - int pid; - char *new_name; - char *old_name; - char *prefix; - char suffix[5]; - int new_len; - - /* Close the file. */ - md_close(fd); - - /* Make filename name.PID[.txt] */ - pid = md_getpid(); - old_name = *filename; - new_len = (int)strlen(old_name)+64; - new_name = HPROF_MALLOC(new_len); - prefix = old_name; - suffix[0] = 0; - - /* Look for .txt suffix if not binary output */ - if (gdata->output_format != 'b') { - char *dot; - char *format_suffix; - - format_suffix = DEFAULT_TXT_SUFFIX; - - (void)strcpy(suffix, format_suffix); - - dot = strrchr(old_name, '.'); - if ( dot != NULL ) { - int i; - int slen; - int match; - - slen = (int)strlen(format_suffix); - match = 1; - for ( i = 0; i < slen; i++ ) { - if ( dot[i]==0 || - tolower(format_suffix[i]) != tolower(dot[i]) ) { - match = 0; - break; - } - } - if ( match ) { - (void)strcpy(suffix, dot); - *dot = 0; /* truncates prefix and old_name */ - } - } - } - - /* Construct the name */ - (void)md_snprintf(new_name, new_len, - "%s.%d%s", prefix, pid, suffix); - *filename = new_name; - HPROF_FREE(old_name); - - /* Odds are with Windows, this file may not be so unique. */ - (void)remove(gdata->output_filename); - } -} - -static int -get_tok(char **src, char *buf, int buflen, int sep) -{ - int len; - char *p; - - buf[0] = 0; - if ( **src == 0 ) { - return 0; - } - p = strchr(*src, sep); - if ( p==NULL ) { - len = (int)strlen(*src); - p = (*src) + len; - } else { - /*LINTED*/ - len = (int)(p - (*src)); - } - if ( (len+1) > buflen ) { - return 0; - } - (void)memcpy(buf, *src, len); - buf[len] = 0; - if ( *p != 0 && *p == sep ) { - (*src) = p+1; - } else { - (*src) = p; - } - return len; -} - -static jboolean -setBinarySwitch(char **src, jboolean *ptr) -{ - char buf[80]; - - if (!get_tok(src, buf, (int)sizeof(buf), ',')) { - return JNI_FALSE; - } - if (strcmp(buf, "y") == 0) { - *ptr = JNI_TRUE; - } else if (strcmp(buf, "n") == 0) { - *ptr = JNI_FALSE; - } else { - return JNI_FALSE; - } - return JNI_TRUE; -} - -static void -print_usage(void) -{ - - (void)fprintf(stdout, -"\n" -" HPROF: Heap and CPU Profiling Agent (JVMTI Demonstration Code)\n" -"\n" -AGENTNAME " usage: java " AGENTLIB "=[help]|[