aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Dahlstrom <dahlstrom@google.com>2020-01-30 12:00:00 -0800
committerDana Dahlstrom <dahlstrom@google.com>2020-01-30 12:00:00 -0800
commit0c613a25e5e544c2743bbfe485295417b845284a (patch)
treed1462f8291586e98e8ef1b97990824fead595797
parent672904f8c32efa6df2c43470d9ed29c0f334c4af (diff)
parent9db779113bfae4bb0853a5d13c6114133ada6683 (diff)
downloadjdk8u_hotspot-0c613a25e5e544c2743bbfe485295417b845284a.tar.gz
Merge tag jb8u232-b1638.6
Change-Id: I9db779113bfae4bb0853a5d13c6114133ada6683
-rw-r--r--.hgtags21
-rw-r--r--THIRD_PARTY_README305
-rw-r--r--agent/src/os/linux/libproc_impl.c110
-rw-r--r--agent/src/os/linux/libproc_impl.h5
-rw-r--r--agent/src/os/linux/ps_core.c51
-rw-r--r--agent/src/os/linux/ps_proc.c178
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/HSDB.java18
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java36
-rw-r--r--agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js68
-rw-r--r--make/aix/makefiles/jsig.make7
-rw-r--r--make/bsd/makefiles/amd64.make15
-rw-r--r--make/bsd/makefiles/i486.make14
-rw-r--r--make/bsd/makefiles/jsig.make7
-rw-r--r--make/bsd/makefiles/ppc.make12
-rw-r--r--make/bsd/makefiles/zeroshark.make14
-rw-r--r--make/linux/makefiles/amd64.make14
-rw-r--r--make/linux/makefiles/i486.make14
-rw-r--r--make/linux/makefiles/jsig.make7
-rw-r--r--make/linux/makefiles/ppc64.make11
-rw-r--r--make/linux/makefiles/zeroshark.make30
-rw-r--r--make/solaris/makefiles/jsig.make7
-rw-r--r--src/cpu/ppc/vm/assembler_ppc.hpp59
-rw-r--r--src/cpu/ppc/vm/assembler_ppc.inline.hpp58
-rw-r--r--src/cpu/ppc/vm/frame_ppc.cpp9
-rw-r--r--src/cpu/ppc/vm/globals_ppc.hpp17
-rw-r--r--src/cpu/ppc/vm/interpreter_ppc.cpp11
-rw-r--r--src/cpu/ppc/vm/macroAssembler_ppc.cpp34
-rw-r--r--src/cpu/ppc/vm/macroAssembler_ppc.hpp38
-rw-r--r--src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp1136
-rw-r--r--src/cpu/ppc/vm/register_ppc.cpp24
-rw-r--r--src/cpu/ppc/vm/register_ppc.hpp174
-rw-r--r--src/cpu/ppc/vm/sharedRuntime_ppc.cpp11
-rw-r--r--src/cpu/ppc/vm/stubGenerator_ppc.cpp705
-rw-r--r--src/cpu/ppc/vm/stubRoutines_ppc_64.hpp2
-rw-r--r--src/cpu/ppc/vm/vm_version_ppc.cpp154
-rw-r--r--src/cpu/ppc/vm/vm_version_ppc.hpp20
-rw-r--r--src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp2
-rw-r--r--src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp4
-rw-r--r--src/cpu/sparc/vm/jniFastGetField_sparc.cpp5
-rw-r--r--src/cpu/sparc/vm/sharedRuntime_sparc.cpp31
-rw-r--r--src/cpu/sparc/vm/stubGenerator_sparc.cpp4
-rw-r--r--src/cpu/sparc/vm/templateInterpreter_sparc.cpp24
-rw-r--r--src/cpu/x86/vm/c1_LIRAssembler_x86.cpp4
-rw-r--r--src/cpu/x86/vm/c1_LIRGenerator_x86.cpp4
-rw-r--r--src/cpu/x86/vm/jniFastGetField_x86_32.cpp25
-rw-r--r--src/cpu/x86/vm/jniFastGetField_x86_64.cpp20
-rw-r--r--src/cpu/x86/vm/macroAssembler_x86.cpp36
-rw-r--r--src/cpu/x86/vm/macroAssembler_x86.hpp3
-rw-r--r--src/cpu/x86/vm/sharedRuntime_x86_32.cpp11
-rw-r--r--src/cpu/x86/vm/sharedRuntime_x86_64.cpp11
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86_64.hpp2
-rw-r--r--src/cpu/x86/vm/templateInterpreter_x86_32.cpp15
-rw-r--r--src/cpu/x86/vm/templateInterpreter_x86_64.cpp12
-rw-r--r--src/cpu/x86/vm/x86_64.ad61
-rw-r--r--src/cpu/zero/vm/cppInterpreter_zero.cpp10
-rw-r--r--src/os/aix/vm/os_aix.cpp7
-rw-r--r--src/os/aix/vm/os_aix.inline.hpp35
-rw-r--r--src/os/aix/vm/perfMemory_aix.cpp13
-rw-r--r--src/os/bsd/vm/os_bsd.cpp7
-rw-r--r--src/os/bsd/vm/os_bsd.inline.hpp33
-rw-r--r--src/os/bsd/vm/perfMemory_bsd.cpp13
-rw-r--r--src/os/linux/vm/os_linux.cpp31
-rw-r--r--src/os/linux/vm/os_linux.hpp1
-rw-r--r--src/os/linux/vm/os_linux.inline.hpp38
-rw-r--r--src/os/linux/vm/perfMemory_linux.cpp14
-rw-r--r--src/os/posix/vm/os_posix.cpp21
-rw-r--r--src/os/solaris/vm/os_solaris.cpp27
-rw-r--r--src/os/solaris/vm/os_solaris.hpp5
-rw-r--r--src/os/solaris/vm/os_solaris.inline.hpp31
-rw-r--r--src/os/solaris/vm/perfMemory_solaris.cpp13
-rw-r--r--src/os/windows/vm/os_windows.cpp37
-rw-r--r--src/os/windows/vm/os_windows.inline.hpp8
-rw-r--r--src/os/windows/vm/perfMemory_windows.cpp12
-rw-r--r--src/share/vm/adlc/adlparse.cpp6
-rw-r--r--src/share/vm/adlc/dfa.cpp22
-rw-r--r--src/share/vm/adlc/formssel.cpp9
-rw-r--r--src/share/vm/c1/c1_LIRGenerator.cpp8
-rw-r--r--src/share/vm/c1/c1_Optimizer.cpp8
-rw-r--r--src/share/vm/ci/bcEscapeAnalyzer.cpp42
-rw-r--r--src/share/vm/ci/bcEscapeAnalyzer.hpp4
-rw-r--r--src/share/vm/ci/ciStreams.cpp9
-rw-r--r--src/share/vm/ci/ciStreams.hpp4
-rw-r--r--src/share/vm/classfile/vmSymbols.hpp12
-rw-r--r--src/share/vm/code/codeCache.cpp58
-rw-r--r--src/share/vm/code/codeCache.hpp16
-rw-r--r--src/share/vm/code/nmethod.cpp2
-rw-r--r--src/share/vm/compiler/compileBroker.cpp6
-rw-r--r--src/share/vm/compiler/compileBroker.hpp4
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp5
-rw-r--r--src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp6
-rw-r--r--src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp6
-rw-r--r--src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp6
-rw-r--r--src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp6
-rw-r--r--src/share/vm/gc_implementation/g1/g1MarkSweep.cpp8
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp9
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp9
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp8
-rw-r--r--src/share/vm/memory/genCollectedHeap.cpp14
-rw-r--r--src/share/vm/memory/genCollectedHeap.hpp4
-rw-r--r--src/share/vm/memory/iterator.hpp15
-rw-r--r--src/share/vm/memory/metaspace.cpp32
-rw-r--r--src/share/vm/memory/metaspace.hpp5
-rw-r--r--src/share/vm/memory/referenceProcessor.cpp8
-rw-r--r--src/share/vm/oops/instanceKlass.cpp17
-rw-r--r--src/share/vm/oops/instanceKlass.hpp5
-rw-r--r--src/share/vm/oops/klass.hpp3
-rw-r--r--src/share/vm/oops/klassVtable.cpp22
-rw-r--r--src/share/vm/opto/addnode.cpp8
-rw-r--r--src/share/vm/opto/connode.cpp6
-rw-r--r--src/share/vm/opto/divnode.cpp2
-rw-r--r--src/share/vm/opto/graphKit.cpp9
-rw-r--r--src/share/vm/opto/graphKit.hpp2
-rw-r--r--src/share/vm/opto/ifnode.cpp2
-rw-r--r--src/share/vm/opto/library_call.cpp20
-rw-r--r--src/share/vm/opto/loopPredicate.cpp18
-rw-r--r--src/share/vm/opto/loopTransform.cpp24
-rw-r--r--src/share/vm/opto/loopnode.hpp2
-rw-r--r--src/share/vm/opto/matcher.cpp13
-rw-r--r--src/share/vm/opto/memnode.cpp21
-rw-r--r--src/share/vm/opto/mulnode.cpp103
-rw-r--r--src/share/vm/opto/reg_split.cpp3
-rw-r--r--src/share/vm/opto/runtime.cpp22
-rw-r--r--src/share/vm/opto/subnode.cpp8
-rw-r--r--src/share/vm/opto/superword.cpp4
-rw-r--r--src/share/vm/opto/type.cpp22
-rw-r--r--src/share/vm/prims/jni.cpp8
-rw-r--r--src/share/vm/prims/jvmtiEnv.cpp9
-rw-r--r--src/share/vm/prims/jvmtiEnvBase.hpp10
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.cpp84
-rw-r--r--src/share/vm/prims/jvmtiRedefineClasses.hpp4
-rw-r--r--src/share/vm/prims/jvmtiTagMap.cpp6
-rw-r--r--src/share/vm/prims/whitebox.cpp51
-rw-r--r--src/share/vm/runtime/advancedThresholdPolicy.cpp19
-rw-r--r--src/share/vm/runtime/arguments.cpp12
-rw-r--r--src/share/vm/runtime/compilationPolicy.cpp2
-rw-r--r--src/share/vm/runtime/java.cpp1
-rw-r--r--src/share/vm/runtime/javaCalls.cpp116
-rw-r--r--src/share/vm/runtime/javaCalls.hpp95
-rw-r--r--src/share/vm/runtime/jniHandles.cpp55
-rw-r--r--src/share/vm/runtime/jniHandles.hpp108
-rw-r--r--src/share/vm/runtime/mutexLocker.cpp2
-rw-r--r--src/share/vm/runtime/mutexLocker.hpp1
-rw-r--r--src/share/vm/runtime/os.cpp2
-rw-r--r--src/share/vm/runtime/os.hpp7
-rw-r--r--src/share/vm/runtime/simpleThresholdPolicy.cpp2
-rw-r--r--src/share/vm/runtime/stubRoutines.cpp6
-rw-r--r--src/share/vm/runtime/thread.cpp1
-rw-r--r--src/share/vm/runtime/vmThread.cpp1
-rw-r--r--src/share/vm/services/classLoadingService.cpp4
-rw-r--r--src/share/vm/services/heapDumper.cpp10
-rw-r--r--src/share/vm/services/memReporter.cpp12
-rw-r--r--src/share/vm/services/memoryManager.cpp31
-rw-r--r--src/share/vm/services/memoryManager.hpp20
-rw-r--r--src/share/vm/services/memoryService.cpp41
-rw-r--r--src/share/vm/services/memoryService.hpp27
-rw-r--r--src/share/vm/shark/sharkNativeWrapper.cpp3
-rw-r--r--src/share/vm/utilities/bitMap.cpp26
-rw-r--r--src/share/vm/utilities/bitMap.hpp6
-rw-r--r--src/share/vm/utilities/bitMap.inline.hpp2
-rw-r--r--src/share/vm/utilities/globalDefinitions.cpp63
-rw-r--r--src/share/vm/utilities/globalDefinitions.hpp99
-rw-r--r--src/share/vm/utilities/hashtable.cpp2
-rw-r--r--src/share/vm/utilities/taskqueue.hpp3
-rw-r--r--src/share/vm/utilities/vmError.cpp4
-rw-r--r--test/Makefile6
-rw-r--r--test/TEST.groups6
-rw-r--r--test/compiler/8209951/TestCipherBlockChainingEncrypt.java136
-rw-r--r--test/compiler/c1/TestGotoIf.jasm171
-rw-r--r--test/compiler/c1/TestGotoIfMain.java46
-rw-r--r--test/compiler/c2/Test8202414.java117
-rw-r--r--test/compiler/c2/Test8217359.java74
-rw-r--r--test/compiler/c2/TestIfWithDeadRegion.java57
-rw-r--r--test/compiler/escapeAnalysis/TestGetClass.java52
-rw-r--r--test/compiler/integerArithmetic/MultiplyByConstantLongMax.java45
-rw-r--r--test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java64
-rw-r--r--test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java3
-rw-r--r--test/compiler/loopopts/superword/TestNegBaseOffset.java59
-rw-r--r--test/compiler/rangechecks/RangeCheckEliminationScaleNotOne.java100
-rw-r--r--test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java24
-rw-r--r--test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java3
-rw-r--r--test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java16
-rw-r--r--test/compiler/tiered/ConstantGettersTransitionsTest.java193
-rw-r--r--test/compiler/tiered/Level2RecompilationTest.java92
-rw-r--r--test/compiler/tiered/LevelTransitionTest.java247
-rw-r--r--test/compiler/tiered/NonTieredLevelsTest.java4
-rw-r--r--test/compiler/tiered/TieredLevelsTest.java16
-rw-r--r--test/compiler/tiered/TransitionsTestExecutor.java66
-rw-r--r--test/compiler/whitebox/CompilerWhiteBoxTest.java52
-rw-r--r--test/gc/TestMemoryMXBeansAndPoolsPresence.java101
-rw-r--r--test/gc/arguments/TestMaxHeapSizeTools.java16
-rw-r--r--test/gc/g1/mixedgc/TestOldGenCollectionUsage.java231
-rw-r--r--test/jbProblemsList.txt3
-rw-r--r--test/runtime/6981737/Test6981737.java2
-rw-r--r--test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java2
-rw-r--r--test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java2
-rw-r--r--test/runtime/NMT/JcmdDetailDiff.java1
-rw-r--r--test/runtime/NMT/MallocSiteTypeChange.java69
-rw-r--r--test/runtime/NMT/NMTWithCDS.java5
-rw-r--r--test/runtime/RedefineTests/RedefineDoubleDelete.java85
-rw-r--r--test/runtime/RedefineTests/libRedefineDoubleDelete.c164
-rw-r--r--test/runtime/VtableTests/VTableTest.java50
-rw-r--r--test/runtime/VtableTests/pkg/A.java28
-rw-r--r--test/runtime/containers/docker/TestCPUAwareness.java5
-rw-r--r--test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.c142
-rw-r--r--test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java63
-rw-r--r--test/runtime/jni/CallWithJNIWeak/test.sh93
-rw-r--r--test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.c52
-rw-r--r--test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java122
-rw-r--r--test/runtime/jni/ReturnJNIWeak/test.sh93
-rw-r--r--test/testlibrary/whitebox/sun/hotspot/WhiteBox.java4
-rw-r--r--test/testlibrary/whitebox/sun/hotspot/code/NMethod.java11
211 files changed, 7147 insertions, 1514 deletions
diff --git a/.hgtags b/.hgtags
index c231965b5..a933d7c01 100644
--- a/.hgtags
+++ b/.hgtags
@@ -1296,3 +1296,24 @@ c0836eee40e5cfc7b3eebbb7a53bfcd98bc66278 jdk8u202-b03
96fec237fcc0acfcacea0a2bac07bf8ca919e64b jdk8u212-b03
b2000ea410b0aa80d94a89105ba3dc8bdebd80b7 jdk8u212-b04
96fec237fcc0acfcacea0a2bac07bf8ca919e64b jdk8u212-ga
+7fe2cda84af1feec9dd512fd7d17f70bfe91a9d0 jdk8u222-b01
+32bc598624bd33a1a8847e84f791559f18a69a49 jdk8u222-b02
+af43bab3c5d022f0e0b7890f732d8b365b4364cc jdk8u222-b03
+d690709cc3398f8cfd6ffebb89a229105fb3e69a jdk8u222-b04
+1ec20e8a3d8a7a29e9113b14567abec9f0240e9d jdk8u222-b05
+17778f8991c83d794897f05210dce2d2a7b4eb2d jdk8u222-b06
+75f4e02f1113bc353fc60df7330dd5456efc49a3 jdk8u222-b07
+36a743eee6721b423b7c21a3ba28ac8d906a5386 jdk8u222-b08
+55f693ba975d445d83a59cc32367ec4c2452b0c5 jdk8u222-b09
+adfdce09acc32a691145a67792d47ab637159776 jdk8u222-b10
+adfdce09acc32a691145a67792d47ab637159776 jdk8u222-ga
+afa42cf8d060a12fe2fd24210cac6c46252fcd53 jdk8u232-b01
+c963a2881865f6fab5b49a31d22651e8e1b4bf46 jdk8u232-b02
+fa7fe6dae563edaae8a8bbe8ac4bd4fa942bde0c jdk8u232-b03
+921c5ee7965fdfde75f578ddda24d5cd16f124dc jdk8u232-b04
+b13d7942036329f64c77a93cffc25e1b52523a3c jdk8u232-b05
+fea2c7f50ce8e6aee1e946eaec7b834193747d82 jdk8u232-b06
+c751303497d539aa85c6373aa0fa85580d3f3044 jdk8u232-b07
+4170228e11e6313e948e6ddcae9af3eed06b1fbe jdk8u232-b08
+12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-b09
+12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-ga
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index f9268adbe..7dc54a057 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -1096,33 +1096,6 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
--- end of LICENSE ---
-%% This notice is provided with respect to FontConfig 2.5, which may be
-included with JRE 8, JDK 8, and OpenJDK 8 source distributions on
-Linux and Solaris.
-
---- begin of LICENSE ---
-
-Copyright ?? 2001,2003 Keith Packard
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that the
-above copyright notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting documentation, and that
-the name of Keith Packard not be used in advertising or publicity pertaining
-to distribution of the software without specific, written prior permission.
-Keith Packard makes no representations about the suitability of this software
-for any purpose. It is provided "as is" without express or implied warranty.
-
-KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL KEITH
-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-
---- end of LICENSE ---
-
-------------------------------------------------------------------------------
%% This notice is provided with respect to freebXML Registry 3.0 & 3.1,
@@ -1497,60 +1470,90 @@ included with JDK 8 and OpenJDK 8 source distributions.
-------------------------------------------------------------------------------
-%% This notice is provided with respect to libpng 1.6.35, which may be
+%% This notice is provided with respect to libpng 1.6.37, which may be
included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
-This copy of the libpng notices is provided for your convenience. In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+PNG Reference Library License version 2
+---------------------------------------
-If you modify libpng you may insert additional notices immediately following
-this sentence.
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-This code is released under the libpng license.
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement. In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
-libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you
+ use this software in a product, an acknowledgment in the product
+ documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
- Simon-Pierre Cadieux
- Eric S. Raymond
- Mans Rullgard
- Cosmin Truta
- Gilles Vollant
- James Yu
- Mandar Sahastrabuddhe
- Google Inc.
- Vadim Barkov
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
+ Gilles Vollant
+ James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
- There is no warranty against interference with your enjoyment of the
- library or against infringement. There is no warranty that our
- efforts or the library will fulfill any of your particular purposes
- or needs. This library is provided with all faults, and the entire
- risk of satisfactory quality, performance, accuracy, and effort is with
- the user.
+ There is no warranty against interference with your enjoyment of
+ the library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is
+ with the user.
Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners and
+files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
- Tom Lane
- Glenn Randers-Pehrson
- Willem van Schaik
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -1558,14 +1561,14 @@ and are distributed according to the same disclaimer and license as
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
- John Bowler
- Kevin Bracey
- Sam Bushell
- Magnus Holmgren
- Greg Roelofs
- Tom Tanner
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
-Some files in the "scripts" directory have other copyright owners
+Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -1574,39 +1577,38 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
- Andreas Dilger
- Dave Martindale
- Guy Eric Schalnat
- Paul Schmidt
- Tim Wegner
-
-The PNG Reference Library is supplied "AS IS". The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose. The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose. The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
+ 1. The origin of this source code must not be misrepresented.
- 3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products. If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products. If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
TRADEMARK:
@@ -1639,7 +1641,7 @@ July 15, 2018
-------------------------------------------------------------------------------
-%% This notice is provided with respect to GIFLIB 5.1.1 & libungif 4.1.3,
+%% This notice is provided with respect to GIFLIB 5.1.8 & libungif 4.1.3,
which may be included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
@@ -1709,7 +1711,7 @@ which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions.
--- begin of LICENSE ---
Mesa 3-D graphics library
- Version: 4.1
+ Version: 5.0
Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
@@ -2128,13 +2130,13 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice
-------------------------------------------------------------------------------
-%% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1,
+%% This notice is provided with respect to PC/SC Lite v1.8.24,
which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris.
--- begin of LICENSE ---
-Copyright (c) 1999-2004 David Corcoran <corcoran@linuxnet.com>
-Copyright (c) 1999-2004 Ludovic Rousseau <ludovic.rousseau (at) free.fr>
+Copyright (c) 1999-2003 David Corcoran <corcoran@linuxnet.com>
+Copyright (c) 2001-2011 Ludovic Rousseau <ludovic.rousseau@free.fr>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -2146,15 +2148,10 @@ are met:
2. 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.
-3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by:
- David Corcoran <corcoran@linuxnet.com>
- http://www.linuxnet.com (MUSCLE)
-4. The name of the author may not be used to endorse or promote products
+3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
-Changes to this license can be made only by the copyright author with
+Changes to this license can be made only by the copyright author with
explicit written consent.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -2824,61 +2821,8 @@ Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.
-___________________________
-The files in motif/lib/Xm/util included this copyright:mkdirhier.man,
-xmkmf.man, chownxterm.c, makeg.man, mergelib.cpp, lndir.man, makestrs.man,
-checktree.c, lndir.c, makestrs.c
-Copyright (c) 1993, 1994 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not
-be used in advertising or otherwise to promote the sale, use or other
-dealing in this Software without prior written authorization from the
-X Consortium.
-_____________________________
-Xmos_r.h:
-/*
-Copyright (c) 1996 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-*/
+--- end of LICENSE ---
_____________________________
Copyright notice for HPkeysym.h:
/*
@@ -2933,55 +2877,6 @@ consequential damages in connection with the furnishing,
performance, or use of this material.
*/
-_____________________________________
-Copyright notice in keysym2ucs.h:
-
-Copyright 1987, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
-
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
--- end of LICENSE ---
@@ -3027,7 +2922,7 @@ included with JRE 8, JDK 8, and OpenJDK 8.
Apache Jakarta BCEL 5.1
Apache Jakarta Regexp 1.4
Apache Santuario XML Security for Java 1.5.4
- Apache Xalan-Java 2.7.1
+ Apache Xalan-Java 2.7.2
Apache Xerces Java 2.10.0
Apache XML Resolver 1.1
diff --git a/agent/src/os/linux/libproc_impl.c b/agent/src/os/linux/libproc_impl.c
index 2ea0d0f88..ca791c95d 100644
--- a/agent/src/os/linux/libproc_impl.c
+++ b/agent/src/os/linux/libproc_impl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -29,54 +29,51 @@
#include <thread_db.h>
#include "libproc_impl.h"
-static const char* alt_root = NULL;
-static int alt_root_len = -1;
-
#define SA_ALTROOT "SA_ALTROOT"
-static void init_alt_root() {
- if (alt_root_len == -1) {
- alt_root = getenv(SA_ALTROOT);
- if (alt_root) {
- alt_root_len = strlen(alt_root);
- } else {
- alt_root_len = 0;
- }
- }
-}
-
int pathmap_open(const char* name) {
- int fd;
- char alt_path[PATH_MAX + 1];
-
- init_alt_root();
-
- if (alt_root_len > 0) {
- strcpy(alt_path, alt_root);
- strcat(alt_path, name);
- fd = open(alt_path, O_RDONLY);
- if (fd >= 0) {
- print_debug("path %s substituted for %s\n", alt_path, name);
- return fd;
- }
+ static const char *alt_root = NULL;
+ static int alt_root_initialized = 0;
- if (strrchr(name, '/')) {
- strcpy(alt_path, alt_root);
- strcat(alt_path, strrchr(name, '/'));
- fd = open(alt_path, O_RDONLY);
- if (fd >= 0) {
- print_debug("path %s substituted for %s\n", alt_path, name);
- return fd;
- }
- }
- } else {
- fd = open(name, O_RDONLY);
- if (fd >= 0) {
- return fd;
- }
- }
+ int fd;
+ char alt_path[PATH_MAX + 1], *alt_path_end;
+ const char *s;
- return -1;
+ if (!alt_root_initialized) {
+ alt_root_initialized = -1;
+ alt_root = getenv(SA_ALTROOT);
+ }
+
+ if (alt_root == NULL) {
+ return open(name, O_RDONLY);
+ }
+
+ strcpy(alt_path, alt_root);
+ alt_path_end = alt_path + strlen(alt_path);
+
+ // Strip path items one by one and try to open file with alt_root prepended
+ s = name;
+ while (1) {
+ strcat(alt_path, s);
+ s += 1;
+
+ fd = open(alt_path, O_RDONLY);
+ if (fd >= 0) {
+ print_debug("path %s substituted for %s\n", alt_path, name);
+ return fd;
+ }
+
+ // Linker always put full path to solib to process, so we can rely
+ // on presence of /. If slash is not present, it means, that SOlib doesn't
+ // physically exist (e.g. linux-gate.so) and we fail opening it anyway
+ if ((s = strchr(s, '/')) == NULL) {
+ break;
+ }
+
+ *alt_path_end = 0;
+ }
+
+ return -1;
}
static bool _libsaproc_debug;
@@ -259,6 +256,26 @@ thread_info* add_thread_info(struct ps_prochandle* ph, pthread_t pthread_id, lwp
return newthr;
}
+void delete_thread_info(struct ps_prochandle* ph, thread_info* thr_to_be_removed) {
+ thread_info* current_thr = ph->threads;
+
+ if (thr_to_be_removed == ph->threads) {
+ ph->threads = ph->threads->next;
+ } else {
+ thread_info* previous_thr;
+ while (current_thr && current_thr != thr_to_be_removed) {
+ previous_thr = current_thr;
+ current_thr = current_thr->next;
+ }
+ if (current_thr == NULL) {
+ print_error("Could not find the thread to be removed");
+ return;
+ }
+ previous_thr->next = current_thr->next;
+ }
+ ph->num_threads--;
+ free(current_thr);
+}
// struct used for client data from thread_db callback
struct thread_db_client_data {
@@ -281,6 +298,11 @@ static int thread_db_callback(const td_thrhandle_t *th_p, void *data) {
print_debug("thread_db : pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
+ if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) {
+ print_debug("Skipping pthread %d (lwp %d)\n", ti.ti_tid, ti.ti_lid);
+ return TD_OK;
+ }
+
if (ptr->callback(ptr->ph, ti.ti_tid, ti.ti_lid) != true)
return TD_ERR;
diff --git a/agent/src/os/linux/libproc_impl.h b/agent/src/os/linux/libproc_impl.h
index bc907a970..1d25a0922 100644
--- a/agent/src/os/linux/libproc_impl.h
+++ b/agent/src/os/linux/libproc_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -113,6 +113,9 @@ typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lw
// reads thread info using libthread_db and calls above callback for each thread
bool read_thread_info(struct ps_prochandle* ph, thread_info_callback cb);
+// deletes a thread from the thread list
+void delete_thread_info(struct ps_prochandle* ph, thread_info* thr);
+
// adds a new shared object to lib list, returns NULL on failure
lib_info* add_lib_info(struct ps_prochandle* ph, const char* libname, uintptr_t base);
diff --git a/agent/src/os/linux/ps_core.c b/agent/src/os/linux/ps_core.c
index 541c857b5..c62e58d0f 100644
--- a/agent/src/os/linux/ps_core.c
+++ b/agent/src/os/linux/ps_core.c
@@ -865,8 +865,51 @@ err:
#define LD_BASE_OFFSET offsetof(struct r_debug, r_ldbase)
#define LINK_MAP_ADDR_OFFSET offsetof(struct link_map, l_addr)
#define LINK_MAP_NAME_OFFSET offsetof(struct link_map, l_name)
+#define LINK_MAP_LD_OFFSET offsetof(struct link_map, l_ld)
#define LINK_MAP_NEXT_OFFSET offsetof(struct link_map, l_next)
+// Calculate the load address of shared library
+// on prelink-enabled environment.
+//
+// In case of GDB, it would be calculated by offset of link_map.l_ld
+// and the address of .dynamic section.
+// See GDB implementation: lm_addr_check @ solib-svr4.c
+static uintptr_t calc_prelinked_load_address(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* elf_ehdr, uintptr_t link_map_addr) {
+ ELF_PHDR *phbuf;
+ uintptr_t lib_ld;
+ uintptr_t lib_dyn_addr = 0L;
+ uintptr_t load_addr;
+ int i;
+
+ phbuf = read_program_header_table(lib_fd, elf_ehdr);
+ if (phbuf == NULL) {
+ print_debug("can't read program header of shared object\n");
+ return 0L;
+ }
+
+ // Get the address of .dynamic section from shared library.
+ for (i = 0; i < elf_ehdr->e_phnum; i++) {
+ if (phbuf[i].p_type == PT_DYNAMIC) {
+ lib_dyn_addr = phbuf[i].p_vaddr;
+ break;
+ }
+ }
+
+ free(phbuf);
+
+ if (ps_pdread(ph, (psaddr_t)link_map_addr + LINK_MAP_LD_OFFSET,
+ &lib_ld, sizeof(uintptr_t)) != PS_OK) {
+ print_debug("can't read address of dynamic section in shared object\n");
+ return 0L;
+ }
+
+ // Return the load address which is calculated by the address of .dynamic
+ // and link_map.l_ld .
+ load_addr = lib_ld - lib_dyn_addr;
+ print_debug("lib_ld = 0x%lx, lib_dyn_addr = 0x%lx -> lib_base_diff = 0x%lx\n", lib_ld, lib_dyn_addr, load_addr);
+ return load_addr;
+}
+
// read shared library info from runtime linker's data structures.
// This work is done by librtlb_db in Solaris
static bool read_shared_lib_info(struct ps_prochandle* ph) {
@@ -968,6 +1011,14 @@ static bool read_shared_lib_info(struct ps_prochandle* ph) {
// continue with other libraries...
} else {
if (read_elf_header(lib_fd, &elf_ehdr)) {
+ if (lib_base_diff == 0x0L) {
+ lib_base_diff = calc_prelinked_load_address(ph, lib_fd, &elf_ehdr, link_map_addr);
+ if (lib_base_diff == 0x0L) {
+ close(lib_fd);
+ return false;
+ }
+ }
+
lib_base = lib_base_diff + find_base_address(lib_fd, &elf_ehdr);
print_debug("reading library %s @ 0x%lx [ 0x%lx ]\n",
lib_name, lib_base, lib_base_diff);
diff --git a/agent/src/os/linux/ps_proc.c b/agent/src/os/linux/ps_proc.c
index 1516842e4..c4d6a9ecc 100644
--- a/agent/src/os/linux/ps_proc.c
+++ b/agent/src/os/linux/ps_proc.c
@@ -28,6 +28,7 @@
#include <signal.h>
#include <errno.h>
#include <elf.h>
+#include <ctype.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
@@ -45,6 +46,12 @@
// This file has the libproc implementation specific to live process
// For core files, refer to ps_core.c
+typedef enum {
+ ATTACH_SUCCESS,
+ ATTACH_FAIL,
+ ATTACH_THREAD_DEAD
+} attach_state_t;
+
static inline uintptr_t align(uintptr_t ptr, size_t size) {
return (ptr & ~(size - 1));
}
@@ -167,9 +174,10 @@ static bool ptrace_continue(pid_t pid, int signal) {
// waits until the ATTACH has stopped the process
// by signal SIGSTOP
-static bool ptrace_waitpid(pid_t pid) {
+static attach_state_t ptrace_waitpid(pid_t pid) {
int ret;
int status;
+ errno = 0;
while (true) {
// Wait for debuggee to stop.
ret = waitpid(pid, &status, 0);
@@ -184,15 +192,15 @@ static bool ptrace_waitpid(pid_t pid) {
// will go to sleep.
if (WSTOPSIG(status) == SIGSTOP) {
// Debuggee stopped by SIGSTOP.
- return true;
+ return ATTACH_SUCCESS;
}
if (!ptrace_continue(pid, WSTOPSIG(status))) {
print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
- return false;
+ return ATTACH_FAIL;
}
} else {
- print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
- return false;
+ print_debug("waitpid(): Child process %d exited/terminated (status = 0x%x)\n", pid, status);
+ return ATTACH_THREAD_DEAD;
}
} else {
switch (errno) {
@@ -201,29 +209,89 @@ static bool ptrace_waitpid(pid_t pid) {
break;
case ECHILD:
print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
- break;
+ return ATTACH_THREAD_DEAD;
case EINVAL:
- print_debug("waitpid() failed. Invalid options argument.\n");
- break;
+ print_error("waitpid() failed. Invalid options argument.\n");
+ return ATTACH_FAIL;
default:
- print_debug("waitpid() failed. Unexpected error %d\n",errno);
- break;
+ print_error("waitpid() failed. Unexpected error %d\n",errno);
+ return ATTACH_FAIL;
}
- return false;
+ } // else
+ } // while
+}
+
+// checks the state of the thread/process specified by "pid", by reading
+// in the 'State:' value from the /proc/<pid>/status file. From the proc
+// man page, "Current state of the process. One of "R (running)",
+// "S (sleeping)", "D (disk sleep)", "T (stopped)", "T (tracing stop)",
+// "Z (zombie)", or "X (dead)"." Assumes that the thread is dead if we
+// don't find the status file or if the status is 'X' or 'Z'.
+static bool process_doesnt_exist(pid_t pid) {
+ char fname[32];
+ char buf[30];
+ FILE *fp = NULL;
+ const char state_string[] = "State:";
+
+ sprintf(fname, "/proc/%d/status", pid);
+ fp = fopen(fname, "r");
+ if (fp == NULL) {
+ print_debug("can't open /proc/%d/status file\n", pid);
+ // Assume the thread does not exist anymore.
+ return true;
+ }
+ bool found_state = false;
+ size_t state_len = strlen(state_string);
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ char *state = NULL;
+ if (strncmp (buf, state_string, state_len) == 0) {
+ found_state = true;
+ state = buf + state_len;
+ // Skip the spaces
+ while (isspace(*state)) {
+ state++;
+ }
+ // A state value of 'X' indicates that the thread is dead. 'Z'
+ // indicates that the thread is a zombie.
+ if (*state == 'X' || *state == 'Z') {
+ fclose (fp);
+ return true;
+ }
+ break;
}
}
+ // If the state value is not 'X' or 'Z', the thread exists.
+ if (!found_state) {
+ // We haven't found the line beginning with 'State:'.
+ // Assuming the thread exists.
+ print_error("Could not find the 'State:' string in the /proc/%d/status file\n", pid);
+ }
+ fclose (fp);
+ return false;
}
// attach to a process/thread specified by "pid"
-static bool ptrace_attach(pid_t pid, char* err_buf, size_t err_buf_len) {
+static attach_state_t ptrace_attach(pid_t pid, char* err_buf, size_t err_buf_len) {
+ errno = 0;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
+ if (errno == EPERM || errno == ESRCH) {
+ // Check if the process/thread is exiting or is a zombie
+ if (process_doesnt_exist(pid)) {
+ print_debug("Thread with pid %d does not exist\n", pid);
+ return ATTACH_THREAD_DEAD;
+ }
+ }
char buf[200];
char* msg = strerror_r(errno, buf, sizeof(buf));
snprintf(err_buf, err_buf_len, "ptrace(PTRACE_ATTACH, ..) failed for %d: %s", pid, msg);
- print_debug("%s\n", err_buf);
- return false;
+ print_error("%s\n", err_buf);
+ return ATTACH_FAIL;
} else {
- return ptrace_waitpid(pid);
+ attach_state_t wait_ret = ptrace_waitpid(pid);
+ if (wait_ret == ATTACH_THREAD_DEAD) {
+ print_debug("Thread with pid %d does not exist\n", pid);
+ }
+ return wait_ret;
}
}
@@ -277,7 +345,7 @@ static bool add_new_thread(struct ps_prochandle* ph, pthread_t pthread_id, lwpid
static bool read_lib_info(struct ps_prochandle* ph) {
char fname[32];
- char buf[256];
+ char buf[PATH_MAX];
FILE *fp = NULL;
sprintf(fname, "/proc/%d/maps", ph->pid);
@@ -287,10 +355,41 @@ static bool read_lib_info(struct ps_prochandle* ph) {
return false;
}
- while(fgets_no_cr(buf, 256, fp)){
- char * word[6];
- int nwords = split_n_str(buf, 6, word, ' ', '\0');
- if (nwords > 5 && find_lib(ph, word[5]) == false) {
+ while(fgets_no_cr(buf, PATH_MAX, fp)){
+ char * word[7];
+ int nwords = split_n_str(buf, 7, word, ' ', '\0');
+
+ if (nwords < 6) {
+ // not a shared library entry. ignore.
+ continue;
+ }
+
+ // SA does not handle the lines with patterns:
+ // "[stack]", "[heap]", "[vdso]", "[vsyscall]", etc.
+ if (word[5][0] == '[') {
+ // not a shared library entry. ignore.
+ continue;
+ }
+
+ if (nwords > 6) {
+ // prelink altered mapfile when the program is running.
+ // Entries like one below have to be skipped
+ // /lib64/libc-2.15.so (deleted)
+ // SO name in entries like one below have to be stripped.
+ // /lib64/libpthread-2.15.so.#prelink#.EECVts
+ char *s = strstr(word[5],".#prelink#");
+ if (s == NULL) {
+ // No prelink keyword. skip deleted library
+ print_debug("skip shared object %s deleted by prelink\n", word[5]);
+ continue;
+ }
+
+ // Fall through
+ print_debug("rectifying shared object name %s changed by prelink\n", word[5]);
+ *s = 0;
+ }
+
+ if (find_lib(ph, word[5]) == false) {
intptr_t base;
lib_info* lib;
#ifdef _LP64
@@ -345,16 +444,20 @@ static ps_prochandle_ops process_ops = {
struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
struct ps_prochandle* ph = NULL;
thread_info* thr = NULL;
+ attach_state_t attach_status = ATTACH_SUCCESS;
if ( (ph = (struct ps_prochandle*) calloc(1, sizeof(struct ps_prochandle))) == NULL) {
- snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
- print_debug("%s\n", err_buf);
- return NULL;
+ snprintf(err_buf, err_buf_len, "can't allocate memory for ps_prochandle");
+ print_debug("%s\n", err_buf);
+ return NULL;
}
- if (ptrace_attach(pid, err_buf, err_buf_len) != true) {
- free(ph);
- return NULL;
+ if ((attach_status = ptrace_attach(pid, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
+ if (attach_status == ATTACH_THREAD_DEAD) {
+ print_error("The process with pid %d does not exist.\n", pid);
+ }
+ free(ph);
+ return NULL;
}
// initialize ps_prochandle
@@ -373,14 +476,23 @@ struct ps_prochandle* Pgrab(pid_t pid, char* err_buf, size_t err_buf_len) {
// attach to the threads
thr = ph->threads;
+
while (thr) {
- // don't attach to the main thread again
- if (ph->pid != thr->lwp_id && ptrace_attach(thr->lwp_id, err_buf, err_buf_len) != true) {
- // even if one attach fails, we get return NULL
- Prelease(ph);
- return NULL;
- }
- thr = thr->next;
+ thread_info* current_thr = thr;
+ thr = thr->next;
+ // don't attach to the main thread again
+ if (ph->pid != current_thr->lwp_id) {
+ if ((attach_status = ptrace_attach(current_thr->lwp_id, err_buf, err_buf_len)) != ATTACH_SUCCESS) {
+ if (attach_status == ATTACH_THREAD_DEAD) {
+ // Remove this thread from the threads list
+ delete_thread_info(ph, current_thr);
+ }
+ else {
+ Prelease(ph);
+ return NULL;
+ } // ATTACH_THREAD_DEAD
+ } // !ATTACH_SUCCESS
+ }
}
return ph;
}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java
index 97726c4e6..30d1f6b95 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/HSDB.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/HSDB.java
@@ -128,10 +128,14 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
}
}
- // close this tool without calling System.exit
- protected void closeUI() {
- workerThread.shutdown();
- frame.dispose();
+ private class CloseUI extends WindowAdapter {
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ workerThread.shutdown();
+ frame.dispose();
+ }
+
}
public void run() {
@@ -147,7 +151,8 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
frame = new JFrame("HSDB - HotSpot Debugger");
frame.setSize(800, 600);
- frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+ frame.addWindowListener(new CloseUI());
JMenuBar menuBar = new JMenuBar();
@@ -210,7 +215,8 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
item = createMenuItem("Exit",
new ActionListener() {
public void actionPerformed(ActionEvent e) {
- closeUI();
+ workerThread.shutdown();
+ frame.dispose();
}
});
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.ALT_MASK));
diff --git a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
index f2d947493..91d47c60e 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
+++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
@@ -55,31 +55,21 @@ class LinuxCDebugger implements CDebugger {
if (pc == null) {
return null;
}
+
+ /* Typically we have about ten loaded objects here. So no reason to do
+ sort/binary search here. Linear search gives us acceptable performance.*/
+
List objs = getLoadObjectList();
- Object[] arr = objs.toArray();
- // load objects are sorted by base address, do binary search
- int mid = -1;
- int low = 0;
- int high = arr.length - 1;
-
- while (low <= high) {
- mid = (low + high) >> 1;
- LoadObject midVal = (LoadObject) arr[mid];
- long cmp = pc.minus(midVal.getBase());
- if (cmp < 0) {
- high = mid - 1;
- } else if (cmp > 0) {
- long size = midVal.getSize();
- if (cmp >= size) {
- low = mid + 1;
- } else {
- return (LoadObject) arr[mid];
- }
- } else { // match found
- return (LoadObject) arr[mid];
- }
+
+ for (int i = 0; i < objs.size(); i++) {
+ LoadObject ob = (LoadObject) objs.get(i);
+ Address base = ob.getBase();
+ long size = ob.getSize();
+ if ( pc.greaterThanOrEqual(base) && pc.lessThan(base.addOffsetTo(size))) {
+ return ob;
+ }
}
- // no match found.
+
return null;
}
diff --git a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
index 94f95ff3d..b60654f48 100644
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
+++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js
@@ -371,19 +371,23 @@ function sym2addr(dso, sym) {
return sa.dbg.lookup(dso, sym);
}
-// returns the ClosestSymbol or null
-function closestSymbolFor(addr) {
- if (sa.cdbg == null) {
+function loadObjectContainingPC(addr) {
+ if (sa.cdbg == null) {
// no CDebugger support, return null
return null;
- } else {
- var dso = sa.cdbg.loadObjectContainingPC(addr);
- if (dso != null) {
- return dso.closestSymbolToPC(addr);
- } else {
- return null;
- }
- }
+ }
+
+ return sa.cdbg.loadObjectContainingPC(addr);
+}
+
+// returns the ClosestSymbol or null
+function closestSymbolFor(addr) {
+ var dso = loadObjectContainingPC(addr);
+ if (dso != null) {
+ return dso.closestSymbolToPC(addr);
+ }
+
+ return null;
}
// Address-to-symbol
@@ -884,21 +888,29 @@ function isOop(addr) {
// returns description of given pointer as a String
function whatis(addr) {
- addr = any2addr(addr);
- var ptrLoc = findPtr(addr);
- if (ptrLoc.isUnknown()) {
- var vmType = vmTypeof(addr);
- if (vmType != null) {
- return "pointer to " + vmType.name;
- } else {
- var sym = closestSymbolFor(addr);
- if (sym != null) {
- return sym.name + '+' + sym.offset;
- } else {
- return ptrLoc.toString();
- }
- }
- } else {
- return ptrLoc.toString();
- }
+ addr = any2addr(addr);
+ var ptrLoc = findPtr(addr);
+ if (!ptrLoc.isUnknown()) {
+ return ptrLoc.toString();
+ }
+
+ var vmType = vmTypeof(addr);
+ if (vmType != null) {
+ return "pointer to " + vmType.name;
+ }
+
+ var dso = loadObjectContainingPC(addr);
+ if (dso == null) {
+ return ptrLoc.toString();
+ }
+
+ var sym = dso.closestSymbolToPC(addr);
+ if (sym != null) {
+ return sym.name + '+' + sym.offset;
+ }
+
+ var s = dso.getName();
+ var p = s.lastIndexOf("/");
+ var base = dso.getBase();
+ return s.substring(p+1, s.length) + '+' + addr.minus(base);
}
diff --git a/make/aix/makefiles/jsig.make b/make/aix/makefiles/jsig.make
index f8bf93872..ae453f2d9 100644
--- a/make/aix/makefiles/jsig.make
+++ b/make/aix/makefiles/jsig.make
@@ -54,10 +54,15 @@ ifeq ($(DEBUG_BINARIES), true)
JSIG_DEBUG_CFLAGS = -g
endif
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+ JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
@echo Making signal interposition lib...
$(QUIETLY) $(CXX) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
- $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) -o $@ $< -ldl
+ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) -o $@ $< -ldl
#ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
# $(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
diff --git a/make/bsd/makefiles/amd64.make b/make/bsd/makefiles/amd64.make
index ecdac17ee..6ff63ec29 100644
--- a/make/bsd/makefiles/amd64.make
+++ b/make/bsd/makefiles/amd64.make
@@ -22,11 +22,16 @@
#
#
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
-# Must also specify if CPU is little endian
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
CFLAGS += -DVM_LITTLE_ENDIAN
CFLAGS += -D_LP64=1
diff --git a/make/bsd/makefiles/i486.make b/make/bsd/makefiles/i486.make
index 86e825d3e..eac85d233 100644
--- a/make/bsd/makefiles/i486.make
+++ b/make/bsd/makefiles/i486.make
@@ -24,10 +24,16 @@
# TLS helper, assembled from .s file
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Must also specify if CPU is little endian
CFLAGS += -DVM_LITTLE_ENDIAN
diff --git a/make/bsd/makefiles/jsig.make b/make/bsd/makefiles/jsig.make
index 29779b002..b5860bfd8 100644
--- a/make/bsd/makefiles/jsig.make
+++ b/make/bsd/makefiles/jsig.make
@@ -59,10 +59,15 @@ ifeq ($(DEBUG_BINARIES), true)
JSIG_DEBUG_CFLAGS = -g
endif
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+ JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
@echo Making signal interposition lib...
$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
- $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $<
+ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) $(EXTRA_CFLAGS) -o $@ $<
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
ifeq ($(OS_VENDOR), Darwin)
$(DSYMUTIL) $@
diff --git a/make/bsd/makefiles/ppc.make b/make/bsd/makefiles/ppc.make
index 92957f963..4c361df11 100644
--- a/make/bsd/makefiles/ppc.make
+++ b/make/bsd/makefiles/ppc.make
@@ -22,8 +22,16 @@
#
#
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Must also specify if CPU is big endian
CFLAGS += -DVM_BIG_ENDIAN
diff --git a/make/bsd/makefiles/zeroshark.make b/make/bsd/makefiles/zeroshark.make
index 12c419819..e7335694b 100644
--- a/make/bsd/makefiles/zeroshark.make
+++ b/make/bsd/makefiles/zeroshark.make
@@ -25,10 +25,16 @@
# Setup common to Zero (non-Shark) and Shark versions of VM
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Specify that the CPU is little endian, if necessary
ifeq ($(ZERO_ENDIANNESS), little)
diff --git a/make/linux/makefiles/amd64.make b/make/linux/makefiles/amd64.make
index 2b77dbab6..28761af9f 100644
--- a/make/linux/makefiles/amd64.make
+++ b/make/linux/makefiles/amd64.make
@@ -22,10 +22,16 @@
#
#
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Must also specify if CPU is little endian
CFLAGS += -DVM_LITTLE_ENDIAN
diff --git a/make/linux/makefiles/i486.make b/make/linux/makefiles/i486.make
index 86e825d3e..eac85d233 100644
--- a/make/linux/makefiles/i486.make
+++ b/make/linux/makefiles/i486.make
@@ -24,10 +24,16 @@
# TLS helper, assembled from .s file
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Must also specify if CPU is little endian
CFLAGS += -DVM_LITTLE_ENDIAN
diff --git a/make/linux/makefiles/jsig.make b/make/linux/makefiles/jsig.make
index 9bf3b738b..6290db5af 100644
--- a/make/linux/makefiles/jsig.make
+++ b/make/linux/makefiles/jsig.make
@@ -51,10 +51,15 @@ ifeq ($(DEBUG_BINARIES), true)
JSIG_DEBUG_CFLAGS = -g
endif
+# Optimize jsig lib at level -O3 unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+ JSIG_OPT_FLAGS = $(OPT_CFLAGS)
+endif
+
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
@echo Making signal interposition lib...
$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
- $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(EXTRA_CFLAGS) -o $@ $< -ldl
+ $(LFLAGS_JSIG) $(JSIG_DEBUG_CFLAGS) $(JSIG_OPT_FLAGS) $(EXTRA_CFLAGS) -o $@ $< -ldl
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
ifneq ($(STRIP_POLICY),no_strip)
$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
diff --git a/make/linux/makefiles/ppc64.make b/make/linux/makefiles/ppc64.make
index f3392de49..6c0931223 100644
--- a/make/linux/makefiles/ppc64.make
+++ b/make/linux/makefiles/ppc64.make
@@ -49,3 +49,14 @@ else
# Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
CFLAGS += -mcpu=power7 -mtune=power8 -minsert-sched-nops=regroup_exact -mno-multiple -mno-string
endif
+
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
diff --git a/make/linux/makefiles/zeroshark.make b/make/linux/makefiles/zeroshark.make
index 3c10770d4..de1fcb353 100644
--- a/make/linux/makefiles/zeroshark.make
+++ b/make/linux/makefiles/zeroshark.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
# Copyright 2007, 2008 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
@@ -25,13 +25,27 @@
# Setup common to Zero (non-Shark) and Shark versions of VM
-# override this from the main file because some version of llvm do not like -Wundef
-WARNING_FLAGS = -Wpointer-arith -Wsign-compare -Wunused-function -Wunused-value
+# Some versions of llvm do not like -Wundef
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ WARNING_FLAGS += -Wno-undef
+endif
+# Suppress some warning flags that are normally turned on for hotspot,
+# because some of the zero code has not been updated accordingly.
+WARNING_FLAGS += -Wno-return-type \
+ -Wno-format-nonliteral -Wno-format-security \
+ -Wno-maybe-uninitialized
+
-# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
-# The copied fdlibm routines in sharedRuntimeTrans.o must not be optimized
-OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+# If FDLIBM_CFLAGS is non-empty it holds CFLAGS needed to be passed to
+# the compiler so as to be able to produce optimized objects
+# without losing precision.
+ifneq ($(FDLIBM_CFLAGS),)
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/SPEED) $(FDLIBM_CFLAGS)
+else
+ OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
+ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
+endif
# Specify that the CPU is little endian, if necessary
ifeq ($(ZERO_ENDIANNESS), little)
@@ -42,5 +56,3 @@ endif
ifeq ($(ARCH_DATA_MODEL), 64)
CFLAGS += -D_LP64=1
endif
-
-OPT_CFLAGS/compactingPermGenGen.o = -O1
diff --git a/make/solaris/makefiles/jsig.make b/make/solaris/makefiles/jsig.make
index bbc098245..74b07214b 100644
--- a/make/solaris/makefiles/jsig.make
+++ b/make/solaris/makefiles/jsig.make
@@ -47,10 +47,15 @@ else
LFLAGS_JSIG += -mt -xnolib
endif
+# Optimize jsig lib unless it's a slowdebug build
+ifneq ($(DEBUG_LEVEL), slowdebug)
+ JSIG_OPT_FLAGS = -xO4 -g
+endif
+
$(LIBJSIG): $(JSIGSRCDIR)/jsig.c $(LIBJSIG_MAPFILE)
@echo Making signal interposition lib...
$(QUIETLY) $(CC) $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \
- $(LFLAGS_JSIG) -o $@ $(JSIGSRCDIR)/jsig.c -ldl
+ $(LFLAGS_JSIG) $(JSIG_OPT_FLAGS) -o $@ $(JSIGSRCDIR)/jsig.c -ldl
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJSIG_DEBUGINFO)
$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJSIG_DEBUGINFO) $@
diff --git a/src/cpu/ppc/vm/assembler_ppc.hpp b/src/cpu/ppc/vm/assembler_ppc.hpp
index ddd07518a..88ac813a1 100644
--- a/src/cpu/ppc/vm/assembler_ppc.hpp
+++ b/src/cpu/ppc/vm/assembler_ppc.hpp
@@ -469,8 +469,15 @@ class Assembler : public AbstractAssembler {
LVSR_OPCODE = (31u << OPCODE_SHIFT | 38u << 1),
// Vector-Scalar (VSX) instruction support.
+ LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1),
+ STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1),
MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1),
+ MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 243u << 1),
MFVSRD_OPCODE = (31u << OPCODE_SHIFT | 51u << 1),
+ MFVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 115u << 1),
+ XXPERMDI_OPCODE= (60u << OPCODE_SHIFT | 10u << 3),
+ XXMRGHW_OPCODE = (60u << OPCODE_SHIFT | 18u << 3),
+ XXMRGLW_OPCODE = (60u << OPCODE_SHIFT | 50u << 3),
// Vector Permute and Formatting
VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ),
@@ -520,6 +527,7 @@ class Assembler : public AbstractAssembler {
VADDUBM_OPCODE = (4u << OPCODE_SHIFT | 0u ),
VADDUWM_OPCODE = (4u << OPCODE_SHIFT | 128u ),
VADDUHM_OPCODE = (4u << OPCODE_SHIFT | 64u ),
+ VADDUDM_OPCODE = (4u << OPCODE_SHIFT | 192u ),
VADDUBS_OPCODE = (4u << OPCODE_SHIFT | 512u ),
VADDUWS_OPCODE = (4u << OPCODE_SHIFT | 640u ),
VADDUHS_OPCODE = (4u << OPCODE_SHIFT | 576u ),
@@ -670,8 +678,10 @@ class Assembler : public AbstractAssembler {
// Atomics.
LWARX_OPCODE = (31u << OPCODE_SHIFT | 20u << 1),
LDARX_OPCODE = (31u << OPCODE_SHIFT | 84u << 1),
+ LQARX_OPCODE = (31u << OPCODE_SHIFT | 276u << 1),
STWCX_OPCODE = (31u << OPCODE_SHIFT | 150u << 1),
- STDCX_OPCODE = (31u << OPCODE_SHIFT | 214u << 1)
+ STDCX_OPCODE = (31u << OPCODE_SHIFT | 214u << 1),
+ STQCX_OPCODE = (31u << OPCODE_SHIFT | 182u << 1)
};
@@ -1052,6 +1062,22 @@ class Assembler : public AbstractAssembler {
static int vrs( VectorRegister r) { return vrs(r->encoding());}
static int vrt( VectorRegister r) { return vrt(r->encoding());}
+ // Only used on SHA sigma instructions (VX-form)
+ static int vst( int x) { return opp_u_field(x, 16, 16); }
+ static int vsix( int x) { return opp_u_field(x, 20, 17); }
+
+ // Support Vector-Scalar (VSX) instructions.
+ static int vsra( int x) { return opp_u_field(x & 0x1F, 15, 11) | opp_u_field((x & 0x20) >> 5, 29, 29); }
+ static int vsrb( int x) { return opp_u_field(x & 0x1F, 20, 16) | opp_u_field((x & 0x20) >> 5, 30, 30); }
+ static int vsrs( int x) { return opp_u_field(x & 0x1F, 10, 6) | opp_u_field((x & 0x20) >> 5, 31, 31); }
+ static int vsrt( int x) { return vsrs(x); }
+ static int vsdm( int x) { return opp_u_field(x, 23, 22); }
+
+ static int vsra( VectorSRegister r) { return vsra(r->encoding());}
+ static int vsrb( VectorSRegister r) { return vsrb(r->encoding());}
+ static int vsrs( VectorSRegister r) { return vsrs(r->encoding());}
+ static int vsrt( VectorSRegister r) { return vsrt(r->encoding());}
+
static int vsplt_uim( int x) { return opp_u_field(x, 15, 12); } // for vsplt* instructions
static int vsplti_sim(int x) { return opp_u_field(x, 15, 11); } // for vsplti* instructions
static int vsldoi_shb(int x) { return opp_u_field(x, 25, 22); } // for vsldoi instruction
@@ -1663,11 +1689,14 @@ class Assembler : public AbstractAssembler {
// atomics
inline void lwarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
inline void ldarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
+ inline void lqarx_unchecked(Register d, Register a, Register b, int eh1 = 0);
inline bool lxarx_hint_exclusive_access();
inline void lwarx( Register d, Register a, Register b, bool hint_exclusive_access = false);
inline void ldarx( Register d, Register a, Register b, bool hint_exclusive_access = false);
+ inline void lqarx( Register d, Register a, Register b, bool hint_exclusive_access = false);
inline void stwcx_( Register s, Register a, Register b);
inline void stdcx_( Register s, Register a, Register b);
+ inline void stqcx_( Register s, Register a, Register b);
// Instructions for adjusting thread priority for simultaneous
// multithreading (SMT) on Power5.
@@ -1849,6 +1878,7 @@ class Assembler : public AbstractAssembler {
inline void vaddubm( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vadduwm( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vadduhm( VectorRegister d, VectorRegister a, VectorRegister b);
+ inline void vaddudm( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vaddubs( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vadduws( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vadduhs( VectorRegister d, VectorRegister a, VectorRegister b);
@@ -1924,6 +1954,7 @@ class Assembler : public AbstractAssembler {
inline void vandc( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vnor( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vor( VectorRegister d, VectorRegister a, VectorRegister b);
+ inline void vmr( VectorRegister d, VectorRegister a);
inline void vxor( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vrld( VectorRegister d, VectorRegister a, VectorRegister b);
inline void vrlb( VectorRegister d, VectorRegister a, VectorRegister b);
@@ -1943,8 +1974,23 @@ class Assembler : public AbstractAssembler {
inline void mfvscr( VectorRegister d);
// Vector-Scalar (VSX) instructions.
+ inline void lxvd2x( VectorSRegister d, Register a);
+ inline void lxvd2x( VectorSRegister d, Register a, Register b);
+ inline void stxvd2x( VectorSRegister d, Register a);
+ inline void stxvd2x( VectorSRegister d, Register a, Register b);
+ inline void mtvrwz( VectorRegister d, Register a);
+ inline void mfvrwz( Register a, VectorRegister d);
inline void mtvrd( VectorRegister d, Register a);
inline void mfvrd( Register a, VectorRegister d);
+ inline void xxpermdi( VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm);
+ inline void xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b);
+ inline void xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b);
+
+ // VSX Extended Mnemonics
+ inline void xxspltd( VectorSRegister d, VectorSRegister a, int x);
+ inline void xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b);
+ inline void xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b);
+ inline void xxswapd( VectorSRegister d, VectorSRegister a);
// AES (introduced with Power 8)
inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b);
@@ -1954,7 +2000,8 @@ class Assembler : public AbstractAssembler {
inline void vsbox( VectorRegister d, VectorRegister a);
// SHA (introduced with Power 8)
- // Not yet implemented.
+ inline void vshasigmad(VectorRegister d, VectorRegister a, bool st, int six);
+ inline void vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six);
// Vector Binary Polynomial Multiplication (introduced with Power 8)
inline void vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b);
@@ -2022,10 +2069,13 @@ class Assembler : public AbstractAssembler {
// Atomics: use ra0mem to disallow R0 as base.
inline void lwarx_unchecked(Register d, Register b, int eh1);
inline void ldarx_unchecked(Register d, Register b, int eh1);
+ inline void lqarx_unchecked(Register d, Register b, int eh1);
inline void lwarx( Register d, Register b, bool hint_exclusive_access);
inline void ldarx( Register d, Register b, bool hint_exclusive_access);
+ inline void lqarx( Register d, Register b, bool hint_exclusive_access);
inline void stwcx_(Register s, Register b);
inline void stdcx_(Register s, Register b);
+ inline void stqcx_(Register s, Register b);
inline void lfs( FloatRegister d, int si16);
inline void lfsx( FloatRegister d, Register b);
inline void lfd( FloatRegister d, int si16);
@@ -2047,6 +2097,11 @@ class Assembler : public AbstractAssembler {
inline void lvsl( VectorRegister d, Register s2);
inline void lvsr( VectorRegister d, Register s2);
+ // Endianess specific concatenation of 2 loaded vectors.
+ inline void load_perm(VectorRegister perm, Register addr);
+ inline void vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm);
+ inline void vec_perm(VectorRegister dest, VectorRegister first, VectorRegister second, VectorRegister perm);
+
// RegisterOrConstant versions.
// These emitters choose between the versions using two registers and
// those with register and immediate, depending on the content of roc.
diff --git a/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/src/cpu/ppc/vm/assembler_ppc.inline.hpp
index 3c66cbb54..5d8066372 100644
--- a/src/cpu/ppc/vm/assembler_ppc.inline.hpp
+++ b/src/cpu/ppc/vm/assembler_ppc.inline.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, SAP SE. 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
@@ -504,11 +504,14 @@ inline void Assembler::elemental_membar(int e) { assert(0 < e && e < 16, "invali
// Use ra0mem to disallow R0 as base.
inline void Assembler::lwarx_unchecked(Register d, Register a, Register b, int eh1) { emit_int32( LWARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
inline void Assembler::ldarx_unchecked(Register d, Register a, Register b, int eh1) { emit_int32( LDARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
+inline void Assembler::lqarx_unchecked(Register d, Register a, Register b, int eh1) { emit_int32( LQARX_OPCODE | rt(d) | ra0mem(a) | rb(b) | eh(eh1)); }
inline bool Assembler::lxarx_hint_exclusive_access() { return VM_Version::has_lxarxeh(); }
inline void Assembler::lwarx( Register d, Register a, Register b, bool hint_exclusive_access) { lwarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
inline void Assembler::ldarx( Register d, Register a, Register b, bool hint_exclusive_access) { ldarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::lqarx( Register d, Register a, Register b, bool hint_exclusive_access) { lqarx_unchecked(d, a, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
inline void Assembler::stwcx_(Register s, Register a, Register b) { emit_int32( STWCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
inline void Assembler::stdcx_(Register s, Register a, Register b) { emit_int32( STDCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
+inline void Assembler::stqcx_(Register s, Register a, Register b) { emit_int32( STQCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
// Instructions for adjusting thread priority
// for simultaneous multithreading (SMT) on POWER5.
@@ -624,8 +627,23 @@ inline void Assembler::lvsl( VectorRegister d, Register s1, Register s2) { emit
inline void Assembler::lvsr( VectorRegister d, Register s1, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); }
// Vector-Scalar (VSX) instructions.
-inline void Assembler::mtvrd( VectorRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec).
-inline void Assembler::mfvrd( Register a, VectorRegister d) { emit_int32( MFVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec).
+inline void Assembler::lxvd2x( VectorSRegister d, Register s1) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); }
+inline void Assembler::lxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); }
+inline void Assembler::stxvd2x( VectorSRegister d, Register s1) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); }
+inline void Assembler::stxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); }
+inline void Assembler::mtvrd( VectorRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mfvrd( Register a, VectorRegister d) { emit_int32( MFVSRD_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mtvrwz( VectorRegister d, Register a) { emit_int32( MTVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::mfvrwz( Register a, VectorRegister d) { emit_int32( MFVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
+inline void Assembler::xxpermdi(VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm) { emit_int32( XXPERMDI_OPCODE | vsrt(d) | vsra(a) | vsrb(b) | vsdm(dm)); }
+inline void Assembler::xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
+inline void Assembler::xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
+
+// VSX Extended Mnemonics
+inline void Assembler::xxspltd( VectorSRegister d, VectorSRegister a, int x) { xxpermdi(d, a, a, x ? 3 : 0); }
+inline void Assembler::xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 0); }
+inline void Assembler::xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 3); }
+inline void Assembler::xxswapd( VectorSRegister d, VectorSRegister a) { xxpermdi(d, a, a, 2); }
inline void Assembler::vpkpx( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKPX_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vpkshss( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSHSS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -668,6 +686,7 @@ inline void Assembler::vaddsws( VectorRegister d, VectorRegister a, VectorRegist
inline void Assembler::vaddubm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vadduwm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vadduhm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
+inline void Assembler::vaddudm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUDM_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vaddubs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vadduws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vadduhs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHS_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -744,6 +763,7 @@ inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegist
inline void Assembler::vandc( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vnor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(b)); }
+inline void Assembler::vmr( VectorRegister d, VectorRegister a) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(a)); }
inline void Assembler::vxor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VXOR_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vrld( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLD_OPCODE | vrt(d) | vra(a) | vrb(b)); }
inline void Assembler::vrlb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLB_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -769,7 +789,8 @@ inline void Assembler::vncipherlast(VectorRegister d, VectorRegister a, VectorRe
inline void Assembler::vsbox( VectorRegister d, VectorRegister a) { emit_int32( VSBOX_OPCODE | vrt(d) | vra(a) ); }
// SHA (introduced with Power 8)
-// Not yet implemented.
+inline void Assembler::vshasigmad(VectorRegister d, VectorRegister a, bool st, int six) { emit_int32( VSHASIGMAD_OPCODE | vrt(d) | vra(a) | vst(st) | vsix(six)); }
+inline void Assembler::vshasigmaw(VectorRegister d, VectorRegister a, bool st, int six) { emit_int32( VSHASIGMAW_OPCODE | vrt(d) | vra(a) | vst(st) | vsix(six)); }
// Vector Binary Polynomial Multiplication (introduced with Power 8)
inline void Assembler::vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMB_OPCODE | vrt(d) | vra(a) | vrb(b)); }
@@ -833,10 +854,13 @@ inline void Assembler::dcbtstct(Register s2, int ct) { emit_int32( DCBTST_OPCOD
// ra0 version
inline void Assembler::lwarx_unchecked(Register d, Register b, int eh1) { emit_int32( LWARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
inline void Assembler::ldarx_unchecked(Register d, Register b, int eh1) { emit_int32( LDARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
+inline void Assembler::lqarx_unchecked(Register d, Register b, int eh1) { emit_int32( LQARX_OPCODE | rt(d) | rb(b) | eh(eh1)); }
inline void Assembler::lwarx( Register d, Register b, bool hint_exclusive_access){ lwarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
inline void Assembler::ldarx( Register d, Register b, bool hint_exclusive_access){ ldarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
+inline void Assembler::lqarx( Register d, Register b, bool hint_exclusive_access){ lqarx_unchecked(d, b, (hint_exclusive_access && lxarx_hint_exclusive_access() && UseExtendedLoadAndReserveInstructionsPPC64) ? 1 : 0); }
inline void Assembler::stwcx_(Register s, Register b) { emit_int32( STWCX_OPCODE | rs(s) | rb(b) | rc(1)); }
inline void Assembler::stdcx_(Register s, Register b) { emit_int32( STDCX_OPCODE | rs(s) | rb(b) | rc(1)); }
+inline void Assembler::stqcx_(Register s, Register b) { emit_int32( STQCX_OPCODE | rs(s) | rb(b) | rc(1)); }
// ra0 version
inline void Assembler::lfs( FloatRegister d, int si16) { emit_int32( LFS_OPCODE | frt(d) | simm(si16,16)); }
@@ -864,6 +888,30 @@ inline void Assembler::stvxl( VectorRegister d, Register s2) { emit_int32( STVXL
inline void Assembler::lvsl( VectorRegister d, Register s2) { emit_int32( LVSL_OPCODE | vrt(d) | rb(s2)); }
inline void Assembler::lvsr( VectorRegister d, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | rb(s2)); }
+inline void Assembler::load_perm(VectorRegister perm, Register addr) {
+#if defined(VM_LITTLE_ENDIAN)
+ lvsr(perm, addr);
+#else
+ lvsl(perm, addr);
+#endif
+}
+
+inline void Assembler::vec_perm(VectorRegister first_dest, VectorRegister second, VectorRegister perm) {
+#if defined(VM_LITTLE_ENDIAN)
+ vperm(first_dest, second, first_dest, perm);
+#else
+ vperm(first_dest, first_dest, second, perm);
+#endif
+}
+
+inline void Assembler::vec_perm(VectorRegister dest, VectorRegister first, VectorRegister second, VectorRegister perm) {
+#if defined(VM_LITTLE_ENDIAN)
+ vperm(dest, second, first, perm);
+#else
+ vperm(dest, first, second, perm);
+#endif
+}
+
inline void Assembler::load_const(Register d, void* x, Register tmp) {
load_const(d, (long)x, tmp);
}
diff --git a/src/cpu/ppc/vm/frame_ppc.cpp b/src/cpu/ppc/vm/frame_ppc.cpp
index a4f7bedb0..d56eeb2b3 100644
--- a/src/cpu/ppc/vm/frame_ppc.cpp
+++ b/src/cpu/ppc/vm/frame_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 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
@@ -190,10 +190,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result)
switch (method->result_type()) {
case T_OBJECT:
case T_ARRAY: {
- oop* obj_p = *(oop**)lresult;
- oop obj = (obj_p == NULL) ? (oop)NULL : *obj_p;
- assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check");
- *oop_result = obj;
+ *oop_result = JNIHandles::resolve(*(jobject*)lresult);
break;
}
// We use std/stfd to store the values.
diff --git a/src/cpu/ppc/vm/globals_ppc.hpp b/src/cpu/ppc/vm/globals_ppc.hpp
index 386bae680..28ca2c0c8 100644
--- a/src/cpu/ppc/vm/globals_ppc.hpp
+++ b/src/cpu/ppc/vm/globals_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2018 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
@@ -81,6 +81,19 @@ define_pd_global(uintx, TypeProfileLevel, 0);
product(bool, ReoptimizeCallSequences, true, \
"Reoptimize code-sequences of calls at runtime.") \
\
+ /* Power 8: Configure Data Stream Control Register. */ \
+ product(uint64_t,DSCR_PPC64, (uintx)-1, \
+ "Power8 or later: Specify encoded value for Data Stream Control " \
+ "Register") \
+ product(uint64_t,DSCR_DPFD_PPC64, 8, \
+ "Power8 or later: DPFD (default prefetch depth) value of the " \
+ "Data Stream Control Register." \
+ " 0: hardware default, 1: none, 2-7: min-max, 8: don't touch") \
+ product(uint64_t,DSCR_URG_PPC64, 8, \
+ "Power8 or later: URG (depth attainment urgency) value of the " \
+ "Data Stream Control Register." \
+ " 0: hardware default, 1: none, 2-7: min-max, 8: don't touch") \
+ \
product(bool, UseLoadInstructionsForStackBangingPPC64, false, \
"Use load instructions for stack banging.") \
\
diff --git a/src/cpu/ppc/vm/interpreter_ppc.cpp b/src/cpu/ppc/vm/interpreter_ppc.cpp
index b6b9907df..3505ce734 100644
--- a/src/cpu/ppc/vm/interpreter_ppc.cpp
+++ b/src/cpu/ppc/vm/interpreter_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2015 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017 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
@@ -413,11 +413,8 @@ address AbstractInterpreterGenerator::generate_result_handler_for(BasicType type
case T_LONG:
break;
case T_OBJECT:
- // unbox result if not null
- __ cmpdi(CCR0, R3_RET, 0);
- __ beq(CCR0, done);
- __ ld(R3_RET, 0, R3_RET);
- __ verify_oop(R3_RET);
+ // JNIHandles::resolve result.
+ __ resolve_jobject(R3_RET, R11_scratch1, R12_scratch2, /* needs_frame */ true); // kills R31
break;
case T_FLOAT:
break;
diff --git a/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/src/cpu/ppc/vm/macroAssembler_ppc.cpp
index a140b36bd..d70312706 100644
--- a/src/cpu/ppc/vm/macroAssembler_ppc.cpp
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, SAP SE. 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
@@ -2220,6 +2220,34 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base, Register Rtmp, Regis
stbx(R0, Rtmp, Robj);
}
+// Kills R31 if value is a volatile register.
+void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame) {
+ Label done;
+ cmpdi(CCR0, value, 0);
+ beq(CCR0, done); // Use NULL as-is.
+
+ clrrdi(tmp1, value, JNIHandles::weak_tag_size);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) { andi_(tmp2, value, JNIHandles::weak_tag_mask); }
+#endif
+ ld(value, 0, tmp1); // Resolve (untagged) jobject.
+
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ Label not_weak;
+ beq(CCR0, not_weak); // Test for jweak tag.
+ verify_oop(value);
+ g1_write_barrier_pre(noreg, // obj
+ noreg, // offset
+ value, // pre_val
+ tmp1, tmp2, needs_frame);
+ bind(not_weak);
+ }
+#endif // INCLUDE_ALL_GCS
+ verify_oop(value);
+ bind(done);
+}
+
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
// Goal: record the previous value if it is not null.
@@ -2281,7 +2309,7 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offs
bind(runtime);
- // VM call need frame to access(write) O register.
+ // May need to preserve LR. Also needed if current frame is not compatible with C calling convention.
if (needs_frame) {
save_LR_CR(Rtmp1);
push_frame_reg_args(0, Rtmp2);
diff --git a/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/src/cpu/ppc/vm/macroAssembler_ppc.hpp
index 0f4e8da72..afcec9a47 100644
--- a/src/cpu/ppc/vm/macroAssembler_ppc.hpp
+++ b/src/cpu/ppc/vm/macroAssembler_ppc.hpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2017 SAP AG. All rights reserved.
+ * Copyright (c) 2012, 2017 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
@@ -516,6 +516,8 @@ class MacroAssembler: public Assembler {
void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp);
void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj);
+ void resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame);
+
#if INCLUDE_ALL_GCS
// General G1 pre-barrier generator.
void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
@@ -665,6 +667,40 @@ class MacroAssembler: public Assembler {
void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp);
+ // SHA-2 auxiliary functions and public interfaces
+ private:
+ void sha256_deque(const VectorRegister src,
+ const VectorRegister dst1, const VectorRegister dst2, const VectorRegister dst3);
+ void sha256_load_h_vec(const VectorRegister a, const VectorRegister e, const Register hptr);
+ void sha256_round(const VectorRegister* hs, const int total_hs, int& h_cnt, const VectorRegister kpw);
+ void sha256_load_w_plus_k_vec(const Register buf_in, const VectorRegister* ws,
+ const int total_ws, const Register k, const VectorRegister* kpws,
+ const int total_kpws);
+ void sha256_calc_4w(const VectorRegister w0, const VectorRegister w1,
+ const VectorRegister w2, const VectorRegister w3, const VectorRegister kpw0,
+ const VectorRegister kpw1, const VectorRegister kpw2, const VectorRegister kpw3,
+ const Register j, const Register k);
+ void sha256_update_sha_state(const VectorRegister a, const VectorRegister b,
+ const VectorRegister c, const VectorRegister d, const VectorRegister e,
+ const VectorRegister f, const VectorRegister g, const VectorRegister h,
+ const Register hptr);
+
+ void sha512_load_w_vec(const Register buf_in, const VectorRegister* ws, const int total_ws);
+ void sha512_update_sha_state(const Register state, const VectorRegister* hs, const int total_hs);
+ void sha512_round(const VectorRegister* hs, const int total_hs, int& h_cnt, const VectorRegister kpw);
+ void sha512_load_h_vec(const Register state, const VectorRegister* hs, const int total_hs);
+ void sha512_calc_2w(const VectorRegister w0, const VectorRegister w1,
+ const VectorRegister w2, const VectorRegister w3,
+ const VectorRegister w4, const VectorRegister w5,
+ const VectorRegister w6, const VectorRegister w7,
+ const VectorRegister kpw0, const VectorRegister kpw1, const Register j,
+ const VectorRegister vRb, const Register k);
+
+ public:
+ void sha256(bool multi_block);
+ void sha512(bool multi_block);
+
+
//
// Debugging
//
diff --git a/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp b/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp
new file mode 100644
index 000000000..7a82ed3f9
--- /dev/null
+++ b/src/cpu/ppc/vm/macroAssembler_ppc_sha.cpp
@@ -0,0 +1,1136 @@
+// Copyright (c) 2017 Instituto de Pesquisas Eldorado. 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.
+
+// Implemented according to "Descriptions of SHA-256, SHA-384, and SHA-512"
+// (http://www.iwar.org.uk/comsec/resources/cipher/sha256-384-512.pdf).
+
+#include "asm/macroAssembler.inline.hpp"
+#include "runtime/stubRoutines.hpp"
+
+/**********************************************************************
+ * SHA 256
+ *********************************************************************/
+
+void MacroAssembler::sha256_deque(const VectorRegister src,
+ const VectorRegister dst1,
+ const VectorRegister dst2,
+ const VectorRegister dst3) {
+ vsldoi (dst1, src, src, 12);
+ vsldoi (dst2, src, src, 8);
+ vsldoi (dst3, src, src, 4);
+}
+
+void MacroAssembler::sha256_round(const VectorRegister* hs,
+ const int total_hs,
+ int& h_cnt,
+ const VectorRegister kpw) {
+ // convenience registers: cycle from 0-7 downwards
+ const VectorRegister a = hs[(total_hs + 0 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister b = hs[(total_hs + 1 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister c = hs[(total_hs + 2 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister d = hs[(total_hs + 3 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister e = hs[(total_hs + 4 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister f = hs[(total_hs + 5 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister g = hs[(total_hs + 6 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister h = hs[(total_hs + 7 - (h_cnt % total_hs)) % total_hs];
+ // temporaries
+ VectorRegister ch = VR0;
+ VectorRegister maj = VR1;
+ VectorRegister bsa = VR2;
+ VectorRegister bse = VR3;
+ VectorRegister vt0 = VR4;
+ VectorRegister vt1 = VR5;
+ VectorRegister vt2 = VR6;
+ VectorRegister vt3 = VR7;
+
+ vsel (ch, g, f, e);
+ vxor (maj, a, b);
+ vshasigmaw (bse, e, 1, 0xf);
+ vadduwm (vt2, ch, kpw);
+ vadduwm (vt1, h, bse);
+ vsel (maj, b, c, maj);
+ vadduwm (vt3, vt1, vt2);
+ vshasigmaw (bsa, a, 1, 0);
+ vadduwm (vt0, bsa, maj);
+
+ vadduwm (d, d, vt3);
+ vadduwm (h, vt3, vt0);
+
+ // advance vector pointer to the next iteration
+ h_cnt++;
+}
+
+void MacroAssembler::sha256_load_h_vec(const VectorRegister a,
+ const VectorRegister e,
+ const Register hptr) {
+ // temporaries
+ Register tmp = R8;
+ VectorRegister vt0 = VR0;
+ VectorRegister vRb = VR6;
+ // labels
+ Label sha256_aligned;
+
+ andi_ (tmp, hptr, 0xf);
+ lvx (a, hptr);
+ addi (tmp, hptr, 16);
+ lvx (e, tmp);
+ beq (CCR0, sha256_aligned);
+
+ // handle unaligned accesses
+ load_perm(vRb, hptr);
+ addi (tmp, hptr, 32);
+ vec_perm(a, e, vRb);
+
+ lvx (vt0, tmp);
+ vec_perm(e, vt0, vRb);
+
+ // aligned accesses
+ bind(sha256_aligned);
+}
+
+void MacroAssembler::sha256_load_w_plus_k_vec(const Register buf_in,
+ const VectorRegister* ws,
+ const int total_ws,
+ const Register k,
+ const VectorRegister* kpws,
+ const int total_kpws) {
+ Label w_aligned, after_w_load;
+
+ Register tmp = R8;
+ VectorRegister vt0 = VR0;
+ VectorRegister vt1 = VR1;
+ VectorRegister vRb = VR6;
+
+ andi_ (tmp, buf_in, 0xF);
+ beq (CCR0, w_aligned); // address ends with 0x0, not 0x8
+
+ // deal with unaligned addresses
+ lvx (ws[0], buf_in);
+ load_perm(vRb, buf_in);
+
+ for (int n = 1; n < total_ws; n++) {
+ VectorRegister w_cur = ws[n];
+ VectorRegister w_prev = ws[n-1];
+
+ addi (tmp, buf_in, n * 16);
+ lvx (w_cur, tmp);
+ vec_perm(w_prev, w_cur, vRb);
+ }
+ addi (tmp, buf_in, total_ws * 16);
+ lvx (vt0, tmp);
+ vec_perm(ws[total_ws-1], vt0, vRb);
+ b (after_w_load);
+
+ bind(w_aligned);
+
+ // deal with aligned addresses
+ lvx(ws[0], buf_in);
+ for (int n = 1; n < total_ws; n++) {
+ VectorRegister w = ws[n];
+ addi (tmp, buf_in, n * 16);
+ lvx (w, tmp);
+ }
+
+ bind(after_w_load);
+
+#if defined(VM_LITTLE_ENDIAN)
+ // Byte swapping within int values
+ li (tmp, 8);
+ lvsl (vt0, tmp);
+ vspltisb (vt1, 0xb);
+ vxor (vt1, vt0, vt1);
+ for (int n = 0; n < total_ws; n++) {
+ VectorRegister w = ws[n];
+ vec_perm(w, w, vt1);
+ }
+#endif
+
+ // Loading k, which is always aligned to 16-bytes
+ lvx (kpws[0], k);
+ for (int n = 1; n < total_kpws; n++) {
+ VectorRegister kpw = kpws[n];
+ addi (tmp, k, 16 * n);
+ lvx (kpw, tmp);
+ }
+
+ // Add w to K
+ assert(total_ws == total_kpws, "Redesign the loop below");
+ for (int n = 0; n < total_kpws; n++) {
+ VectorRegister kpw = kpws[n];
+ VectorRegister w = ws[n];
+
+ vadduwm (kpw, kpw, w);
+ }
+}
+
+void MacroAssembler::sha256_calc_4w(const VectorRegister w0,
+ const VectorRegister w1,
+ const VectorRegister w2,
+ const VectorRegister w3,
+ const VectorRegister kpw0,
+ const VectorRegister kpw1,
+ const VectorRegister kpw2,
+ const VectorRegister kpw3,
+ const Register j,
+ const Register k) {
+ // Temporaries
+ const VectorRegister vt0 = VR0;
+ const VectorRegister vt1 = VR1;
+ const VectorSRegister vsrt1 = vt1->to_vsr();
+ const VectorRegister vt2 = VR2;
+ const VectorRegister vt3 = VR3;
+ const VectorSRegister vst3 = vt3->to_vsr();
+ const VectorRegister vt4 = VR4;
+
+ // load to k[j]
+ lvx (vt0, j, k);
+
+ // advance j
+ addi (j, j, 16); // 16 bytes were read
+
+#if defined(VM_LITTLE_ENDIAN)
+ // b = w[j-15], w[j-14], w[j-13], w[j-12]
+ vsldoi (vt1, w1, w0, 12);
+
+ // c = w[j-7], w[j-6], w[j-5], w[j-4]
+ vsldoi (vt2, w3, w2, 12);
+
+#else
+ // b = w[j-15], w[j-14], w[j-13], w[j-12]
+ vsldoi (vt1, w0, w1, 4);
+
+ // c = w[j-7], w[j-6], w[j-5], w[j-4]
+ vsldoi (vt2, w2, w3, 4);
+#endif
+
+ // d = w[j-2], w[j-1], w[j-4], w[j-3]
+ vsldoi (vt3, w3, w3, 8);
+
+ // b = s0(w[j-15]) , s0(w[j-14]) , s0(w[j-13]) , s0(w[j-12])
+ vshasigmaw (vt1, vt1, 0, 0);
+
+ // d = s1(w[j-2]) , s1(w[j-1]) , s1(w[j-4]) , s1(w[j-3])
+ vshasigmaw (vt3, vt3, 0, 0xf);
+
+ // c = s0(w[j-15]) + w[j-7],
+ // s0(w[j-14]) + w[j-6],
+ // s0(w[j-13]) + w[j-5],
+ // s0(w[j-12]) + w[j-4]
+ vadduwm (vt2, vt1, vt2);
+
+ // c = s0(w[j-15]) + w[j-7] + w[j-16],
+ // s0(w[j-14]) + w[j-6] + w[j-15],
+ // s0(w[j-13]) + w[j-5] + w[j-14],
+ // s0(w[j-12]) + w[j-4] + w[j-13]
+ vadduwm (vt2, vt2, w0);
+
+ // e = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+ // s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+ // s0(w[j-13]) + w[j-5] + w[j-14] + s1(w[j-4]), // UNDEFINED
+ // s0(w[j-12]) + w[j-4] + w[j-13] + s1(w[j-3]) // UNDEFINED
+ vadduwm (vt4, vt2, vt3);
+
+ // At this point, e[0] and e[1] are the correct values to be stored at w[j]
+ // and w[j+1].
+ // e[2] and e[3] are not considered.
+ // b = s1(w[j]) , s1(s(w[j+1]) , UNDEFINED , UNDEFINED
+ vshasigmaw (vt1, vt4, 0, 0xf);
+
+ // v5 = s1(w[j-2]) , s1(w[j-1]) , s1(w[j]) , s1(w[j+1])
+#if defined(VM_LITTLE_ENDIAN)
+ xxmrgld (vst3, vsrt1, vst3);
+#else
+ xxmrghd (vst3, vst3, vsrt1);
+#endif
+
+ // c = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+ // s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+ // s0(w[j-13]) + w[j-5] + w[j-14] + s1(w[j]), // w[j+2]
+ // s0(w[j-12]) + w[j-4] + w[j-13] + s1(w[j+1]) // w[j+4]
+ vadduwm (vt2, vt2, vt3);
+
+ // Updating w0 to w3 to hold the new previous 16 values from w.
+ vmr (w0, w1);
+ vmr (w1, w2);
+ vmr (w2, w3);
+ vmr (w3, vt2);
+
+ // store k + w to v9 (4 values at once)
+#if defined(VM_LITTLE_ENDIAN)
+ vadduwm (kpw0, vt2, vt0);
+
+ vsldoi (kpw1, kpw0, kpw0, 12);
+ vsldoi (kpw2, kpw0, kpw0, 8);
+ vsldoi (kpw3, kpw0, kpw0, 4);
+#else
+ vadduwm (kpw3, vt2, vt0);
+
+ vsldoi (kpw2, kpw3, kpw3, 12);
+ vsldoi (kpw1, kpw3, kpw3, 8);
+ vsldoi (kpw0, kpw3, kpw3, 4);
+#endif
+}
+
+void MacroAssembler::sha256_update_sha_state(const VectorRegister a,
+ const VectorRegister b_,
+ const VectorRegister c,
+ const VectorRegister d,
+ const VectorRegister e,
+ const VectorRegister f,
+ const VectorRegister g,
+ const VectorRegister h,
+ const Register hptr) {
+ // temporaries
+ VectorRegister vt0 = VR0;
+ VectorRegister vt1 = VR1;
+ VectorRegister vt2 = VR2;
+ VectorRegister vt3 = VR3;
+ VectorRegister vt4 = VR4;
+ VectorRegister vt5 = VR5;
+ VectorRegister vaux = VR6;
+ VectorRegister vRb = VR6;
+ Register tmp = R8;
+ Register of16 = R8;
+ Register of32 = R9;
+ Label state_load_aligned;
+
+ // Load hptr
+ andi_ (tmp, hptr, 0xf);
+ li (of16, 16);
+ lvx (vt0, hptr);
+ lvx (vt5, of16, hptr);
+ beq (CCR0, state_load_aligned);
+
+ // handle unaligned accesses
+ li (of32, 32);
+ load_perm(vRb, hptr);
+
+ vec_perm(vt0, vt5, vRb); // vt0 = hptr[0]..hptr[3]
+
+ lvx (vt1, hptr, of32);
+ vec_perm(vt5, vt1, vRb); // vt5 = hptr[4]..hptr[7]
+
+ // aligned accesses
+ bind(state_load_aligned);
+
+#if defined(VM_LITTLE_ENDIAN)
+ vmrglw (vt1, b_, a); // vt1 = {a, b, ?, ?}
+ vmrglw (vt2, d, c); // vt2 = {c, d, ?, ?}
+ vmrglw (vt3, f, e); // vt3 = {e, f, ?, ?}
+ vmrglw (vt4, h, g); // vt4 = {g, h, ?, ?}
+ xxmrgld (vt1->to_vsr(), vt2->to_vsr(), vt1->to_vsr()); // vt1 = {a, b, c, d}
+ xxmrgld (vt3->to_vsr(), vt4->to_vsr(), vt3->to_vsr()); // vt3 = {e, f, g, h}
+ vadduwm (a, vt0, vt1); // a = {a+hptr[0], b+hptr[1], c+hptr[2], d+hptr[3]}
+ vadduwm (e, vt5, vt3); // e = {e+hptr[4], f+hptr[5], g+hptr[6], h+hptr[7]}
+
+ // Save hptr back, works for any alignment
+ xxswapd (vt0->to_vsr(), a->to_vsr());
+ stxvd2x (vt0->to_vsr(), hptr);
+ xxswapd (vt5->to_vsr(), e->to_vsr());
+ stxvd2x (vt5->to_vsr(), of16, hptr);
+#else
+ vmrglw (vt1, a, b_); // vt1 = {a, b, ?, ?}
+ vmrglw (vt2, c, d); // vt2 = {c, d, ?, ?}
+ vmrglw (vt3, e, f); // vt3 = {e, f, ?, ?}
+ vmrglw (vt4, g, h); // vt4 = {g, h, ?, ?}
+ xxmrgld (vt1->to_vsr(), vt1->to_vsr(), vt2->to_vsr()); // vt1 = {a, b, c, d}
+ xxmrgld (vt3->to_vsr(), vt3->to_vsr(), vt4->to_vsr()); // vt3 = {e, f, g, h}
+ vadduwm (d, vt0, vt1); // d = {a+hptr[0], b+hptr[1], c+hptr[2], d+hptr[3]}
+ vadduwm (h, vt5, vt3); // h = {e+hptr[4], f+hptr[5], g+hptr[6], h+hptr[7]}
+
+ // Save hptr back, works for any alignment
+ stxvd2x (d->to_vsr(), hptr);
+ stxvd2x (h->to_vsr(), of16, hptr);
+#endif
+}
+
+static const uint32_t sha256_round_table[64] __attribute((aligned(16))) = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
+};
+static const uint32_t *sha256_round_consts = sha256_round_table;
+
+// R3_ARG1 - byte[] Input string with padding but in Big Endian
+// R4_ARG2 - int[] SHA.state (at first, the root of primes)
+// R5_ARG3 - int offset
+// R6_ARG4 - int limit
+//
+// Internal Register usage:
+// R7 - k
+// R8 - tmp | j | of16
+// R9 - of32
+// VR0-VR8 - ch, maj, bsa, bse, vt0-vt3 | vt0-vt5, vaux/vRb
+// VR9-VR16 - a-h
+// VR17-VR20 - w0-w3
+// VR21-VR23 - vRb | vaux0-vaux2
+// VR24-VR27 - kpw0-kpw3
+void MacroAssembler::sha256(bool multi_block) {
+ static const ssize_t buf_size = 64;
+ static const uint8_t w_size = sizeof(sha256_round_table)/sizeof(uint32_t);
+#ifdef AIX
+ // malloc provides 16 byte alignment
+ if (((uintptr_t)sha256_round_consts & 0xF) != 0) {
+ uint32_t *new_round_consts = (uint32_t*)malloc(sizeof(sha256_round_table));
+ guarantee(new_round_consts, "oom");
+ memcpy(new_round_consts, sha256_round_consts, sizeof(sha256_round_table));
+ sha256_round_consts = (const uint32_t*)new_round_consts;
+ }
+#endif
+
+ Register buf_in = R3_ARG1;
+ Register state = R4_ARG2;
+ Register ofs = R5_ARG3;
+ Register limit = R6_ARG4;
+
+ Label sha_loop, core_loop;
+
+ // Save non-volatile vector registers in the red zone
+ static const VectorRegister nv[] = {
+ VR20, VR21, VR22, VR23, VR24, VR25, VR26, VR27/*, VR28, VR29, VR30, VR31*/
+ };
+ static const uint8_t nv_size = sizeof(nv) / sizeof (VectorRegister);
+
+ for (int c = 0; c < nv_size; c++) {
+ Register tmp = R8;
+ li (tmp, (c - (nv_size)) * 16);
+ stvx(nv[c], tmp, R1);
+ }
+
+ // Load hash state to registers
+ VectorRegister a = VR9;
+ VectorRegister b = VR10;
+ VectorRegister c = VR11;
+ VectorRegister d = VR12;
+ VectorRegister e = VR13;
+ VectorRegister f = VR14;
+ VectorRegister g = VR15;
+ VectorRegister h = VR16;
+ static const VectorRegister hs[] = {a, b, c, d, e, f, g, h};
+ static const int total_hs = sizeof(hs)/sizeof(VectorRegister);
+ // counter for cycling through hs vector to avoid register moves between iterations
+ int h_cnt = 0;
+
+ // Load a-h registers from the memory pointed by state
+#if defined(VM_LITTLE_ENDIAN)
+ sha256_load_h_vec(a, e, state);
+#else
+ sha256_load_h_vec(d, h, state);
+#endif
+
+ // keep k loaded also during MultiBlock loops
+ Register k = R7;
+ assert(((uintptr_t)sha256_round_consts & 0xF) == 0, "k alignment");
+ load_const_optimized(k, (address)sha256_round_consts, R0);
+
+ // Avoiding redundant loads
+ if (multi_block) {
+ align(OptoLoopAlignment);
+ }
+ bind(sha_loop);
+#if defined(VM_LITTLE_ENDIAN)
+ sha256_deque(a, b, c, d);
+ sha256_deque(e, f, g, h);
+#else
+ sha256_deque(d, c, b, a);
+ sha256_deque(h, g, f, e);
+#endif
+
+ // Load 16 elements from w out of the loop.
+ // Order of the int values is Endianess specific.
+ VectorRegister w0 = VR17;
+ VectorRegister w1 = VR18;
+ VectorRegister w2 = VR19;
+ VectorRegister w3 = VR20;
+ static const VectorRegister ws[] = {w0, w1, w2, w3};
+ static const int total_ws = sizeof(ws)/sizeof(VectorRegister);
+
+ VectorRegister kpw0 = VR24;
+ VectorRegister kpw1 = VR25;
+ VectorRegister kpw2 = VR26;
+ VectorRegister kpw3 = VR27;
+ static const VectorRegister kpws[] = {kpw0, kpw1, kpw2, kpw3};
+ static const int total_kpws = sizeof(kpws)/sizeof(VectorRegister);
+
+ sha256_load_w_plus_k_vec(buf_in, ws, total_ws, k, kpws, total_kpws);
+
+ // Cycle through the first 16 elements
+ assert(total_ws == total_kpws, "Redesign the loop below");
+ for (int n = 0; n < total_ws; n++) {
+ VectorRegister vaux0 = VR21;
+ VectorRegister vaux1 = VR22;
+ VectorRegister vaux2 = VR23;
+
+ sha256_deque(kpws[n], vaux0, vaux1, vaux2);
+
+#if defined(VM_LITTLE_ENDIAN)
+ sha256_round(hs, total_hs, h_cnt, kpws[n]);
+ sha256_round(hs, total_hs, h_cnt, vaux0);
+ sha256_round(hs, total_hs, h_cnt, vaux1);
+ sha256_round(hs, total_hs, h_cnt, vaux2);
+#else
+ sha256_round(hs, total_hs, h_cnt, vaux2);
+ sha256_round(hs, total_hs, h_cnt, vaux1);
+ sha256_round(hs, total_hs, h_cnt, vaux0);
+ sha256_round(hs, total_hs, h_cnt, kpws[n]);
+#endif
+ }
+
+ Register tmp = R8;
+ // loop the 16th to the 64th iteration by 8 steps
+ li (tmp, (w_size - 16) / total_hs);
+ mtctr(tmp);
+
+ // j will be aligned to 4 for loading words.
+ // Whenever read, advance the pointer (e.g: when j is used in a function)
+ Register j = R8;
+ li (j, 16*4);
+
+ align(OptoLoopAlignment);
+ bind(core_loop);
+
+ // due to VectorRegister rotate, always iterate in multiples of total_hs
+ for (int n = 0; n < total_hs/4; n++) {
+ sha256_calc_4w(w0, w1, w2, w3, kpw0, kpw1, kpw2, kpw3, j, k);
+ sha256_round(hs, total_hs, h_cnt, kpw0);
+ sha256_round(hs, total_hs, h_cnt, kpw1);
+ sha256_round(hs, total_hs, h_cnt, kpw2);
+ sha256_round(hs, total_hs, h_cnt, kpw3);
+ }
+
+ bdnz (core_loop);
+
+ // Update hash state
+ sha256_update_sha_state(a, b, c, d, e, f, g, h, state);
+
+ if (multi_block) {
+ addi(buf_in, buf_in, buf_size);
+ addi(ofs, ofs, buf_size);
+ cmplw(CCR0, ofs, limit);
+ ble(CCR0, sha_loop);
+
+ // return ofs
+ mr(R3_RET, ofs);
+ }
+
+ // Restore non-volatile registers
+ for (int c = 0; c < nv_size; c++) {
+ Register tmp = R8;
+ li (tmp, (c - (nv_size)) * 16);
+ lvx(nv[c], tmp, R1);
+ }
+}
+
+
+/**********************************************************************
+ * SHA 512
+ *********************************************************************/
+
+void MacroAssembler::sha512_load_w_vec(const Register buf_in,
+ const VectorRegister* ws,
+ const int total_ws) {
+ Register tmp = R8;
+ VectorRegister vRb = VR8;
+ VectorRegister aux = VR9;
+ Label is_aligned, after_alignment;
+
+ andi_ (tmp, buf_in, 0xF);
+ beq (CCR0, is_aligned); // address ends with 0x0, not 0x8
+
+ // deal with unaligned addresses
+ lvx (ws[0], buf_in);
+ load_perm(vRb, buf_in);
+
+ for (int n = 1; n < total_ws; n++) {
+ VectorRegister w_cur = ws[n];
+ VectorRegister w_prev = ws[n-1];
+ addi (tmp, buf_in, n * 16);
+ lvx (w_cur, tmp);
+ vec_perm(w_prev, w_cur, vRb);
+ }
+ addi (tmp, buf_in, total_ws * 16);
+ lvx (aux, tmp);
+ vec_perm(ws[total_ws-1], aux, vRb);
+ b (after_alignment);
+
+ bind(is_aligned);
+ lvx (ws[0], buf_in);
+ for (int n = 1; n < total_ws; n++) {
+ VectorRegister w = ws[n];
+ addi (tmp, buf_in, n * 16);
+ lvx (w, tmp);
+ }
+
+ bind(after_alignment);
+}
+
+// Update hash state
+void MacroAssembler::sha512_update_sha_state(const Register state,
+ const VectorRegister* hs,
+ const int total_hs) {
+
+#if defined(VM_LITTLE_ENDIAN)
+ int start_idx = 0;
+#else
+ int start_idx = 1;
+#endif
+
+ // load initial hash from the memory pointed by state
+ VectorRegister ini_a = VR10;
+ VectorRegister ini_c = VR12;
+ VectorRegister ini_e = VR14;
+ VectorRegister ini_g = VR16;
+ static const VectorRegister inis[] = {ini_a, ini_c, ini_e, ini_g};
+ static const int total_inis = sizeof(inis)/sizeof(VectorRegister);
+
+ Label state_save_aligned, after_state_save_aligned;
+
+ Register addr = R7;
+ Register tmp = R8;
+ VectorRegister vRb = VR8;
+ VectorRegister aux = VR9;
+
+ andi_(tmp, state, 0xf);
+ beq(CCR0, state_save_aligned);
+ // deal with unaligned addresses
+
+ {
+ VectorRegister a = hs[0];
+ VectorRegister b_ = hs[1];
+ VectorRegister c = hs[2];
+ VectorRegister d = hs[3];
+ VectorRegister e = hs[4];
+ VectorRegister f = hs[5];
+ VectorRegister g = hs[6];
+ VectorRegister h = hs[7];
+ load_perm(vRb, state);
+ lvx (ini_a, state);
+ addi (addr, state, 16);
+
+ lvx (ini_c, addr);
+ addi (addr, state, 32);
+ vec_perm(ini_a, ini_c, vRb);
+
+ lvx (ini_e, addr);
+ addi (addr, state, 48);
+ vec_perm(ini_c, ini_e, vRb);
+
+ lvx (ini_g, addr);
+ addi (addr, state, 64);
+ vec_perm(ini_e, ini_g, vRb);
+
+ lvx (aux, addr);
+ vec_perm(ini_g, aux, vRb);
+
+#if defined(VM_LITTLE_ENDIAN)
+ xxmrgld(a->to_vsr(), b_->to_vsr(), a->to_vsr());
+ xxmrgld(c->to_vsr(), d->to_vsr(), c->to_vsr());
+ xxmrgld(e->to_vsr(), f->to_vsr(), e->to_vsr());
+ xxmrgld(g->to_vsr(), h->to_vsr(), g->to_vsr());
+#else
+ xxmrgld(b_->to_vsr(), a->to_vsr(), b_->to_vsr());
+ xxmrgld(d->to_vsr(), c->to_vsr(), d->to_vsr());
+ xxmrgld(f->to_vsr(), e->to_vsr(), f->to_vsr());
+ xxmrgld(h->to_vsr(), g->to_vsr(), h->to_vsr());
+#endif
+
+ for (int n = start_idx; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+ VectorRegister ini_cur = inis[n/2];
+
+ vaddudm(h_cur, ini_cur, h_cur);
+ }
+
+ for (int n = start_idx; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+
+ mfvrd (tmp, h_cur);
+#if defined(VM_LITTLE_ENDIAN)
+ std (tmp, 8*n + 8, state);
+#else
+ std (tmp, 8*n - 8, state);
+#endif
+ vsldoi (aux, h_cur, h_cur, 8);
+ mfvrd (tmp, aux);
+ std (tmp, 8*n + 0, state);
+ }
+
+ b (after_state_save_aligned);
+ }
+
+ bind(state_save_aligned);
+ {
+ for (int n = 0; n < total_hs; n += 2) {
+#if defined(VM_LITTLE_ENDIAN)
+ VectorRegister h_cur = hs[n];
+ VectorRegister h_next = hs[n+1];
+#else
+ VectorRegister h_cur = hs[n+1];
+ VectorRegister h_next = hs[n];
+#endif
+ VectorRegister ini_cur = inis[n/2];
+
+ if (n/2 == 0) {
+ lvx(ini_cur, state);
+ } else {
+ addi(addr, state, (n/2) * 16);
+ lvx(ini_cur, addr);
+ }
+ xxmrgld(h_cur->to_vsr(), h_next->to_vsr(), h_cur->to_vsr());
+ }
+
+ for (int n = start_idx; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+ VectorRegister ini_cur = inis[n/2];
+
+ vaddudm(h_cur, ini_cur, h_cur);
+ }
+
+ for (int n = start_idx; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+
+ if (n/2 == 0) {
+ stvx(h_cur, state);
+ } else {
+ addi(addr, state, (n/2) * 16);
+ stvx(h_cur, addr);
+ }
+ }
+ }
+
+ bind(after_state_save_aligned);
+}
+
+// Use h_cnt to cycle through hs elements but also increment it at the end
+void MacroAssembler::sha512_round(const VectorRegister* hs,
+ const int total_hs, int& h_cnt,
+ const VectorRegister kpw) {
+
+ // convenience registers: cycle from 0-7 downwards
+ const VectorRegister a = hs[(total_hs + 0 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister b = hs[(total_hs + 1 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister c = hs[(total_hs + 2 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister d = hs[(total_hs + 3 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister e = hs[(total_hs + 4 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister f = hs[(total_hs + 5 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister g = hs[(total_hs + 6 - (h_cnt % total_hs)) % total_hs];
+ const VectorRegister h = hs[(total_hs + 7 - (h_cnt % total_hs)) % total_hs];
+ // temporaries
+ const VectorRegister Ch = VR20;
+ const VectorRegister Maj = VR21;
+ const VectorRegister bsa = VR22;
+ const VectorRegister bse = VR23;
+ const VectorRegister tmp1 = VR24;
+ const VectorRegister tmp2 = VR25;
+
+ vsel (Ch, g, f, e);
+ vxor (Maj, a, b);
+ vshasigmad(bse, e, 1, 0xf);
+ vaddudm (tmp2, Ch, kpw);
+ vaddudm (tmp1, h, bse);
+ vsel (Maj, b, c, Maj);
+ vaddudm (tmp1, tmp1, tmp2);
+ vshasigmad(bsa, a, 1, 0);
+ vaddudm (tmp2, bsa, Maj);
+ vaddudm (d, d, tmp1);
+ vaddudm (h, tmp1, tmp2);
+
+ // advance vector pointer to the next iteration
+ h_cnt++;
+}
+
+void MacroAssembler::sha512_calc_2w(const VectorRegister w0,
+ const VectorRegister w1,
+ const VectorRegister w2,
+ const VectorRegister w3,
+ const VectorRegister w4,
+ const VectorRegister w5,
+ const VectorRegister w6,
+ const VectorRegister w7,
+ const VectorRegister kpw0,
+ const VectorRegister kpw1,
+ const Register j,
+ const VectorRegister vRb,
+ const Register k) {
+ // Temporaries
+ const VectorRegister VR_a = VR20;
+ const VectorRegister VR_b = VR21;
+ const VectorRegister VR_c = VR22;
+ const VectorRegister VR_d = VR23;
+
+ // load to k[j]
+ lvx (VR_a, j, k);
+ // advance j
+ addi (j, j, 16); // 16 bytes were read
+
+#if defined(VM_LITTLE_ENDIAN)
+ // v6 = w[j-15], w[j-14]
+ vperm (VR_b, w1, w0, vRb);
+ // v12 = w[j-7], w[j-6]
+ vperm (VR_c, w5, w4, vRb);
+#else
+ // v6 = w[j-15], w[j-14]
+ vperm (VR_b, w0, w1, vRb);
+ // v12 = w[j-7], w[j-6]
+ vperm (VR_c, w4, w5, vRb);
+#endif
+
+ // v6 = s0(w[j-15]) , s0(w[j-14])
+ vshasigmad (VR_b, VR_b, 0, 0);
+ // v5 = s1(w[j-2]) , s1(w[j-1])
+ vshasigmad (VR_d, w7, 0, 0xf);
+ // v6 = s0(w[j-15]) + w[j-7] , s0(w[j-14]) + w[j-6]
+ vaddudm (VR_b, VR_b, VR_c);
+ // v8 = s1(w[j-2]) + w[j-16] , s1(w[j-1]) + w[j-15]
+ vaddudm (VR_d, VR_d, w0);
+ // v9 = s0(w[j-15]) + w[j-7] + w[j-16] + s1(w[j-2]), // w[j]
+ // s0(w[j-14]) + w[j-6] + w[j-15] + s1(w[j-1]), // w[j+1]
+ vaddudm (VR_c, VR_d, VR_b);
+ // Updating w0 to w7 to hold the new previous 16 values from w.
+ vmr (w0, w1);
+ vmr (w1, w2);
+ vmr (w2, w3);
+ vmr (w3, w4);
+ vmr (w4, w5);
+ vmr (w5, w6);
+ vmr (w6, w7);
+ vmr (w7, VR_c);
+
+#if defined(VM_LITTLE_ENDIAN)
+ // store k + w to kpw0 (2 values at once)
+ vaddudm (kpw0, VR_c, VR_a);
+ // kpw1 holds (k + w)[1]
+ vsldoi (kpw1, kpw0, kpw0, 8);
+#else
+ // store k + w to kpw0 (2 values at once)
+ vaddudm (kpw1, VR_c, VR_a);
+ // kpw1 holds (k + w)[1]
+ vsldoi (kpw0, kpw1, kpw1, 8);
+#endif
+}
+
+void MacroAssembler::sha512_load_h_vec(const Register state,
+ const VectorRegister* hs,
+ const int total_hs) {
+#if defined(VM_LITTLE_ENDIAN)
+ VectorRegister a = hs[0];
+ VectorRegister g = hs[6];
+ int start_idx = 0;
+#else
+ VectorRegister a = hs[1];
+ VectorRegister g = hs[7];
+ int start_idx = 1;
+#endif
+
+ Register addr = R7;
+ VectorRegister vRb = VR8;
+ Register tmp = R8;
+ Label state_aligned, after_state_aligned;
+
+ andi_(tmp, state, 0xf);
+ beq(CCR0, state_aligned);
+
+ // deal with unaligned addresses
+ VectorRegister aux = VR9;
+
+ lvx(hs[start_idx], state);
+ load_perm(vRb, state);
+
+ for (int n = start_idx + 2; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+ VectorRegister h_prev2 = hs[n - 2];
+ addi(addr, state, (n/2) * 16);
+ lvx(h_cur, addr);
+ vec_perm(h_prev2, h_cur, vRb);
+ }
+ addi(addr, state, (total_hs/2) * 16);
+ lvx (aux, addr);
+ vec_perm(hs[total_hs - 2 + start_idx], aux, vRb);
+ b (after_state_aligned);
+
+ bind(state_aligned);
+
+ // deal with aligned addresses
+ lvx(hs[start_idx], state);
+
+ for (int n = start_idx + 2; n < total_hs; n += 2) {
+ VectorRegister h_cur = hs[n];
+ addi(addr, state, (n/2) * 16);
+ lvx(h_cur, addr);
+ }
+
+ bind(after_state_aligned);
+}
+
+static const uint64_t sha512_round_table[80] __attribute((aligned(16))) = {
+ 0x428a2f98d728ae22, 0x7137449123ef65cd,
+ 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+ 0x3956c25bf348b538, 0x59f111f1b605d019,
+ 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+ 0xd807aa98a3030242, 0x12835b0145706fbe,
+ 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1,
+ 0x9bdc06a725c71235, 0xc19bf174cf692694,
+ 0xe49b69c19ef14ad2, 0xefbe4786384f25e3,
+ 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+ 0x2de92c6f592b0275, 0x4a7484aa6ea6e483,
+ 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210,
+ 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+ 0xc6e00bf33da88fc2, 0xd5a79147930aa725,
+ 0x06ca6351e003826f, 0x142929670a0e6e70,
+ 0x27b70a8546d22ffc, 0x2e1b21385c26c926,
+ 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8,
+ 0x81c2c92e47edaee6, 0x92722c851482353b,
+ 0xa2bfe8a14cf10364, 0xa81a664bbc423001,
+ 0xc24b8b70d0f89791, 0xc76c51a30654be30,
+ 0xd192e819d6ef5218, 0xd69906245565a910,
+ 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53,
+ 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+ 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb,
+ 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+ 0x748f82ee5defb2fc, 0x78a5636f43172f60,
+ 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9,
+ 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+ 0xca273eceea26619c, 0xd186b8c721c0c207,
+ 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+ 0x06f067aa72176fba, 0x0a637dc5a2c898a6,
+ 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493,
+ 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+ 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a,
+ 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+};
+static const uint64_t *sha512_round_consts = sha512_round_table;
+
+// R3_ARG1 - byte[] Input string with padding but in Big Endian
+// R4_ARG2 - int[] SHA.state (at first, the root of primes)
+// R5_ARG3 - int offset
+// R6_ARG4 - int limit
+//
+// Internal Register usage:
+// R7 R8 R9 - volatile temporaries
+// VR0-VR7 - a-h
+// VR8 - vRb
+// VR9 - aux (highly volatile, use with care)
+// VR10-VR17 - w0-w7 | ini_a-ini_h
+// VR18 - vsp16 | kplusw0
+// VR19 - vsp32 | kplusw1
+// VR20-VR25 - sha512_calc_2w and sha512_round temporaries
+void MacroAssembler::sha512(bool multi_block) {
+ static const ssize_t buf_size = 128;
+ static const uint8_t w_size = sizeof(sha512_round_table)/sizeof(uint64_t);
+#ifdef AIX
+ // malloc provides 16 byte alignment
+ if (((uintptr_t)sha512_round_consts & 0xF) != 0) {
+ uint64_t *new_round_consts = (uint64_t*)malloc(sizeof(sha512_round_table));
+ guarantee(new_round_consts, "oom");
+ memcpy(new_round_consts, sha512_round_consts, sizeof(sha512_round_table));
+ sha512_round_consts = (const uint64_t*)new_round_consts;
+ }
+#endif
+
+ Register buf_in = R3_ARG1;
+ Register state = R4_ARG2;
+ Register ofs = R5_ARG3;
+ Register limit = R6_ARG4;
+
+ Label sha_loop, core_loop;
+
+ // Save non-volatile vector registers in the red zone
+ static const VectorRegister nv[] = {
+ VR20, VR21, VR22, VR23, VR24, VR25/*, VR26, VR27, VR28, VR29, VR30, VR31*/
+ };
+ static const uint8_t nv_size = sizeof(nv) / sizeof (VectorRegister);
+
+ for (int c = 0; c < nv_size; c++) {
+ Register idx = R7;
+ li (idx, (c - (nv_size)) * 16);
+ stvx(nv[c], idx, R1);
+ }
+
+ // Load hash state to registers
+ VectorRegister a = VR0;
+ VectorRegister b = VR1;
+ VectorRegister c = VR2;
+ VectorRegister d = VR3;
+ VectorRegister e = VR4;
+ VectorRegister f = VR5;
+ VectorRegister g = VR6;
+ VectorRegister h = VR7;
+ static const VectorRegister hs[] = {a, b, c, d, e, f, g, h};
+ static const int total_hs = sizeof(hs)/sizeof(VectorRegister);
+ // counter for cycling through hs vector to avoid register moves between iterations
+ int h_cnt = 0;
+
+ // Load a-h registers from the memory pointed by state
+ sha512_load_h_vec(state, hs, total_hs);
+
+ Register k = R9;
+ assert(((uintptr_t)sha512_round_consts & 0xF) == 0, "k alignment");
+ load_const_optimized(k, (address)sha512_round_consts, R0);
+
+ if (multi_block) {
+ align(OptoLoopAlignment);
+ }
+ bind(sha_loop);
+
+ for (int n = 0; n < total_hs; n += 2) {
+#if defined(VM_LITTLE_ENDIAN)
+ VectorRegister h_cur = hs[n];
+ VectorRegister h_next = hs[n + 1];
+#else
+ VectorRegister h_cur = hs[n + 1];
+ VectorRegister h_next = hs[n];
+#endif
+ vsldoi (h_next, h_cur, h_cur, 8);
+ }
+
+ // Load 16 elements from w out of the loop.
+ // Order of the long values is Endianess specific.
+ VectorRegister w0 = VR10;
+ VectorRegister w1 = VR11;
+ VectorRegister w2 = VR12;
+ VectorRegister w3 = VR13;
+ VectorRegister w4 = VR14;
+ VectorRegister w5 = VR15;
+ VectorRegister w6 = VR16;
+ VectorRegister w7 = VR17;
+ static const VectorRegister ws[] = {w0, w1, w2, w3, w4, w5, w6, w7};
+ static const int total_ws = sizeof(ws)/sizeof(VectorRegister);
+
+ // Load 16 w into vectors and setup vsl for vperm
+ sha512_load_w_vec(buf_in, ws, total_ws);
+
+#if defined(VM_LITTLE_ENDIAN)
+ VectorRegister vsp16 = VR18;
+ VectorRegister vsp32 = VR19;
+ VectorRegister shiftarg = VR9;
+
+ vspltisw(vsp16, 8);
+ vspltisw(shiftarg, 1);
+ vsl (vsp16, vsp16, shiftarg);
+ vsl (vsp32, vsp16, shiftarg);
+
+ VectorRegister vsp8 = VR9;
+ vspltish(vsp8, 8);
+
+ // Convert input from Big Endian to Little Endian
+ for (int c = 0; c < total_ws; c++) {
+ VectorRegister w = ws[c];
+ vrlh (w, w, vsp8);
+ }
+ for (int c = 0; c < total_ws; c++) {
+ VectorRegister w = ws[c];
+ vrlw (w, w, vsp16);
+ }
+ for (int c = 0; c < total_ws; c++) {
+ VectorRegister w = ws[c];
+ vrld (w, w, vsp32);
+ }
+#endif
+
+ Register Rb = R10;
+ VectorRegister vRb = VR8;
+ li (Rb, 8);
+ load_perm(vRb, Rb);
+
+ VectorRegister kplusw0 = VR18;
+ VectorRegister kplusw1 = VR19;
+
+ Register addr = R7;
+
+ for (int n = 0; n < total_ws; n++) {
+ VectorRegister w = ws[n];
+
+ if (n == 0) {
+ lvx (kplusw0, k);
+ } else {
+ addi (addr, k, n * 16);
+ lvx (kplusw0, addr);
+ }
+#if defined(VM_LITTLE_ENDIAN)
+ vaddudm(kplusw0, kplusw0, w);
+ vsldoi (kplusw1, kplusw0, kplusw0, 8);
+#else
+ vaddudm(kplusw1, kplusw0, w);
+ vsldoi (kplusw0, kplusw1, kplusw1, 8);
+#endif
+
+ sha512_round(hs, total_hs, h_cnt, kplusw0);
+ sha512_round(hs, total_hs, h_cnt, kplusw1);
+ }
+
+ Register tmp = R8;
+ li (tmp, (w_size-16)/total_hs);
+ mtctr (tmp);
+ // j will be aligned to 4 for loading words.
+ // Whenever read, advance the pointer (e.g: when j is used in a function)
+ Register j = tmp;
+ li (j, 8*16);
+
+ align(OptoLoopAlignment);
+ bind(core_loop);
+
+ // due to VectorRegister rotate, always iterate in multiples of total_hs
+ for (int n = 0; n < total_hs/2; n++) {
+ sha512_calc_2w(w0, w1, w2, w3, w4, w5, w6, w7, kplusw0, kplusw1, j, vRb, k);
+ sha512_round(hs, total_hs, h_cnt, kplusw0);
+ sha512_round(hs, total_hs, h_cnt, kplusw1);
+ }
+
+ bdnz (core_loop);
+
+ sha512_update_sha_state(state, hs, total_hs);
+
+ if (multi_block) {
+ addi(buf_in, buf_in, buf_size);
+ addi(ofs, ofs, buf_size);
+ cmplw(CCR0, ofs, limit);
+ ble(CCR0, sha_loop);
+
+ // return ofs
+ mr(R3_RET, ofs);
+ }
+
+ // Restore non-volatile registers
+ for (int c = 0; c < nv_size; c++) {
+ Register idx = R7;
+ li (idx, (c - (nv_size)) * 16);
+ lvx(nv[c], idx, R1);
+ }
+}
diff --git a/src/cpu/ppc/vm/register_ppc.cpp b/src/cpu/ppc/vm/register_ppc.cpp
index edff7485a..e24176b7e 100644
--- a/src/cpu/ppc/vm/register_ppc.cpp
+++ b/src/cpu/ppc/vm/register_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2013 SAP AG. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2018 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
@@ -75,3 +75,23 @@ const char* VectorRegisterImpl::name() const {
};
return is_valid() ? names[encoding()] : "vnoreg";
}
+
+const char* VectorSRegisterImpl::name() const {
+ const char* names[number_of_registers] = {
+ "VSR0", "VSR1", "VSR2", "VSR3", "VSR4", "VSR5", "VSR6", "VSR7",
+ "VSR8", "VSR9", "VSR10", "VSR11", "VSR12", "VSR13", "VSR14", "VSR15",
+ "VSR16", "VSR17", "VSR18", "VSR19", "VSR20", "VSR21", "VSR22", "VSR23",
+ "VSR24", "VSR25", "VSR26", "VSR27", "VSR28", "VSR29", "VSR30", "VSR31",
+ "VSR32", "VSR33", "VSR34", "VSR35", "VSR36", "VSR37", "VSR38", "VSR39",
+ "VSR40", "VSR41", "VSR42", "VSR43", "VSR44", "VSR45", "VSR46", "VSR47",
+ "VSR48", "VSR49", "VSR50", "VSR51", "VSR52", "VSR53", "VSR54", "VSR55",
+ "VSR56", "VSR57", "VSR58", "VSR59", "VSR60", "VSR61", "VSR62", "VSR63"
+ };
+ return is_valid() ? names[encoding()] : "vsnoreg";
+}
+
+// Method to convert a VectorRegister to a Vector-Scalar Register (VectorSRegister)
+VectorSRegister VectorRegisterImpl::to_vsr() const {
+ if (this == vnoreg) { return vsnoregi; }
+ return as_VectorSRegister(encoding() + 32);
+}
diff --git a/src/cpu/ppc/vm/register_ppc.hpp b/src/cpu/ppc/vm/register_ppc.hpp
index 107c5bab8..ed46fb2b7 100644
--- a/src/cpu/ppc/vm/register_ppc.hpp
+++ b/src/cpu/ppc/vm/register_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2018 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
@@ -399,6 +399,11 @@ inline VectorRegister as_VectorRegister(int encoding) {
return (VectorRegister)(intptr_t)encoding;
}
+// Forward declaration
+// Use VectorSRegister as a shortcut.
+class VectorSRegisterImpl;
+typedef VectorSRegisterImpl* VectorSRegister;
+
// The implementation of vector registers for the Power architecture
class VectorRegisterImpl: public AbstractRegisterImpl {
public:
@@ -416,6 +421,9 @@ class VectorRegisterImpl: public AbstractRegisterImpl {
bool is_valid() const { return 0 <= value() && value() < number_of_registers; }
const char* name() const;
+
+ // convert to VSR
+ VectorSRegister to_vsr() const;
};
// The Vector registers of the Power architecture
@@ -492,6 +500,166 @@ CONSTANT_REGISTER_DECLARATION(VectorRegister, VR31, (31));
#endif // DONT_USE_REGISTER_DEFINES
+inline VectorSRegister as_VectorSRegister(int encoding) {
+ return (VectorSRegister)(intptr_t)encoding;
+}
+
+// The implementation of Vector-Scalar (VSX) registers on POWER architecture.
+class VectorSRegisterImpl: public AbstractRegisterImpl {
+ public:
+ enum {
+ number_of_registers = 64
+ };
+
+ // construction
+ inline friend VectorSRegister as_VectorSRegister(int encoding);
+
+ // accessors
+ int encoding() const { assert(is_valid(), "invalid register"); return value(); }
+
+ // testers
+ bool is_valid() const { return 0 <= value() && value() < number_of_registers; }
+
+ const char* name() const;
+};
+
+// The Vector-Scalar (VSX) registers of the POWER architecture.
+
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, vsnoreg, (-1));
+
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR0, ( 0));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR1, ( 1));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR2, ( 2));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR3, ( 3));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR4, ( 4));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR5, ( 5));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR6, ( 6));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR7, ( 7));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR8, ( 8));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR9, ( 9));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR10, (10));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR11, (11));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR12, (12));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR13, (13));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR14, (14));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR15, (15));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR16, (16));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR17, (17));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR18, (18));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR19, (19));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR20, (20));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR21, (21));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR22, (22));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR23, (23));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR24, (24));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR25, (25));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR26, (26));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR27, (27));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR28, (28));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR29, (29));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR30, (30));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR31, (31));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR32, (32));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR33, (33));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR34, (34));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR35, (35));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR36, (36));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR37, (37));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR38, (38));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR39, (39));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR40, (40));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR41, (41));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR42, (42));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR43, (43));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR44, (44));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR45, (45));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR46, (46));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR47, (47));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR48, (48));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR49, (49));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR50, (50));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR51, (51));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR52, (52));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR53, (53));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR54, (54));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR55, (55));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR56, (56));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR57, (57));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR58, (58));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR59, (59));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR60, (60));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR61, (61));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR62, (62));
+CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR63, (63));
+
+#ifndef DONT_USE_REGISTER_DEFINES
+#define vsnoregi ((VectorSRegister)(vsnoreg_VectorSRegisterEnumValue))
+#define VSR0 ((VectorSRegister)( VSR0_VectorSRegisterEnumValue))
+#define VSR1 ((VectorSRegister)( VSR1_VectorSRegisterEnumValue))
+#define VSR2 ((VectorSRegister)( VSR2_VectorSRegisterEnumValue))
+#define VSR3 ((VectorSRegister)( VSR3_VectorSRegisterEnumValue))
+#define VSR4 ((VectorSRegister)( VSR4_VectorSRegisterEnumValue))
+#define VSR5 ((VectorSRegister)( VSR5_VectorSRegisterEnumValue))
+#define VSR6 ((VectorSRegister)( VSR6_VectorSRegisterEnumValue))
+#define VSR7 ((VectorSRegister)( VSR7_VectorSRegisterEnumValue))
+#define VSR8 ((VectorSRegister)( VSR8_VectorSRegisterEnumValue))
+#define VSR9 ((VectorSRegister)( VSR9_VectorSRegisterEnumValue))
+#define VSR10 ((VectorSRegister)( VSR10_VectorSRegisterEnumValue))
+#define VSR11 ((VectorSRegister)( VSR11_VectorSRegisterEnumValue))
+#define VSR12 ((VectorSRegister)( VSR12_VectorSRegisterEnumValue))
+#define VSR13 ((VectorSRegister)( VSR13_VectorSRegisterEnumValue))
+#define VSR14 ((VectorSRegister)( VSR14_VectorSRegisterEnumValue))
+#define VSR15 ((VectorSRegister)( VSR15_VectorSRegisterEnumValue))
+#define VSR16 ((VectorSRegister)( VSR16_VectorSRegisterEnumValue))
+#define VSR17 ((VectorSRegister)( VSR17_VectorSRegisterEnumValue))
+#define VSR18 ((VectorSRegister)( VSR18_VectorSRegisterEnumValue))
+#define VSR19 ((VectorSRegister)( VSR19_VectorSRegisterEnumValue))
+#define VSR20 ((VectorSRegister)( VSR20_VectorSRegisterEnumValue))
+#define VSR21 ((VectorSRegister)( VSR21_VectorSRegisterEnumValue))
+#define VSR22 ((VectorSRegister)( VSR22_VectorSRegisterEnumValue))
+#define VSR23 ((VectorSRegister)( VSR23_VectorSRegisterEnumValue))
+#define VSR24 ((VectorSRegister)( VSR24_VectorSRegisterEnumValue))
+#define VSR25 ((VectorSRegister)( VSR25_VectorSRegisterEnumValue))
+#define VSR26 ((VectorSRegister)( VSR26_VectorSRegisterEnumValue))
+#define VSR27 ((VectorSRegister)( VSR27_VectorSRegisterEnumValue))
+#define VSR28 ((VectorSRegister)( VSR28_VectorSRegisterEnumValue))
+#define VSR29 ((VectorSRegister)( VSR29_VectorSRegisterEnumValue))
+#define VSR30 ((VectorSRegister)( VSR30_VectorSRegisterEnumValue))
+#define VSR31 ((VectorSRegister)( VSR31_VectorSRegisterEnumValue))
+#define VSR32 ((VectorSRegister)( VSR32_VectorSRegisterEnumValue))
+#define VSR33 ((VectorSRegister)( VSR33_VectorSRegisterEnumValue))
+#define VSR34 ((VectorSRegister)( VSR34_VectorSRegisterEnumValue))
+#define VSR35 ((VectorSRegister)( VSR35_VectorSRegisterEnumValue))
+#define VSR36 ((VectorSRegister)( VSR36_VectorSRegisterEnumValue))
+#define VSR37 ((VectorSRegister)( VSR37_VectorSRegisterEnumValue))
+#define VSR38 ((VectorSRegister)( VSR38_VectorSRegisterEnumValue))
+#define VSR39 ((VectorSRegister)( VSR39_VectorSRegisterEnumValue))
+#define VSR40 ((VectorSRegister)( VSR40_VectorSRegisterEnumValue))
+#define VSR41 ((VectorSRegister)( VSR41_VectorSRegisterEnumValue))
+#define VSR42 ((VectorSRegister)( VSR42_VectorSRegisterEnumValue))
+#define VSR43 ((VectorSRegister)( VSR43_VectorSRegisterEnumValue))
+#define VSR44 ((VectorSRegister)( VSR44_VectorSRegisterEnumValue))
+#define VSR45 ((VectorSRegister)( VSR45_VectorSRegisterEnumValue))
+#define VSR46 ((VectorSRegister)( VSR46_VectorSRegisterEnumValue))
+#define VSR47 ((VectorSRegister)( VSR47_VectorSRegisterEnumValue))
+#define VSR48 ((VectorSRegister)( VSR48_VectorSRegisterEnumValue))
+#define VSR49 ((VectorSRegister)( VSR49_VectorSRegisterEnumValue))
+#define VSR50 ((VectorSRegister)( VSR50_VectorSRegisterEnumValue))
+#define VSR51 ((VectorSRegister)( VSR51_VectorSRegisterEnumValue))
+#define VSR52 ((VectorSRegister)( VSR52_VectorSRegisterEnumValue))
+#define VSR53 ((VectorSRegister)( VSR53_VectorSRegisterEnumValue))
+#define VSR54 ((VectorSRegister)( VSR54_VectorSRegisterEnumValue))
+#define VSR55 ((VectorSRegister)( VSR55_VectorSRegisterEnumValue))
+#define VSR56 ((VectorSRegister)( VSR56_VectorSRegisterEnumValue))
+#define VSR57 ((VectorSRegister)( VSR57_VectorSRegisterEnumValue))
+#define VSR58 ((VectorSRegister)( VSR58_VectorSRegisterEnumValue))
+#define VSR59 ((VectorSRegister)( VSR59_VectorSRegisterEnumValue))
+#define VSR60 ((VectorSRegister)( VSR60_VectorSRegisterEnumValue))
+#define VSR61 ((VectorSRegister)( VSR61_VectorSRegisterEnumValue))
+#define VSR62 ((VectorSRegister)( VSR62_VectorSRegisterEnumValue))
+#define VSR63 ((VectorSRegister)( VSR63_VectorSRegisterEnumValue))
+#endif // DONT_USE_REGISTER_DEFINES
+
// Maximum number of incoming arguments that can be passed in i registers.
const int PPC_ARGS_IN_REGS_NUM = 8;
@@ -510,7 +678,7 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
* 2 // register halves
+ ConditionRegisterImpl::number_of_registers // condition code registers
+ SpecialRegisterImpl::number_of_registers // special registers
- + VectorRegisterImpl::number_of_registers // vector registers
+ + VectorRegisterImpl::number_of_registers // VSX registers
};
static const int max_gpr;
diff --git a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
index 047779e38..404670547 100644
--- a/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
+++ b/src/cpu/ppc/vm/sharedRuntime_ppc.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 2012, 2017 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
@@ -2513,16 +2513,11 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ reset_last_Java_frame();
- // Unpack oop result.
+ // Unbox oop result, e.g. JNIHandles::resolve value.
// --------------------------------------------------------------------------
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label skip_unboxing;
- __ cmpdi(CCR0, R3_RET, 0);
- __ beq(CCR0, skip_unboxing);
- __ ld(R3_RET, 0, R3_RET);
- __ bind(skip_unboxing);
- __ verify_oop(R3_RET);
+ __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false); // kills R31
}
diff --git a/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/src/cpu/ppc/vm/stubGenerator_ppc.cpp
index 1b7fb419a..7f2c4427f 100644
--- a/src/cpu/ppc/vm/stubGenerator_ppc.cpp
+++ b/src/cpu/ppc/vm/stubGenerator_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018, SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, SAP SE. 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
@@ -1131,8 +1131,11 @@ class StubGenerator: public StubCodeGenerator {
Register tmp3 = R8_ARG6;
Register tmp4 = R9_ARG7;
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
+
+ Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9, l_10;
- Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9;
// Don't try anything fancy if arrays don't have many elements.
__ li(tmp3, 0);
__ cmpwi(CCR0, R5_ARG3, 17);
@@ -1186,6 +1189,8 @@ class StubGenerator: public StubCodeGenerator {
__ andi_(R5_ARG3, R5_ARG3, 31);
__ mtctr(tmp1);
+ if (!VM_Version::has_vsx()) {
+
__ bind(l_8);
// Use unrolled version for mass copying (copy 32 elements a time)
// Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1201,7 +1206,44 @@ class StubGenerator: public StubCodeGenerator {
__ addi(R3_ARG1, R3_ARG1, 32);
__ addi(R4_ARG2, R4_ARG2, 32);
__ bdnz(l_8);
- }
+
+ } else { // Processor supports VSX, so use it to mass copy.
+
+ // Prefetch the data into the L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. Not 16-byte align as
+ // loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_10);
+ // Use loop with VSX load/store instructions to
+ // copy 32 elements a time.
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load src
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst
+ __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1); // Load src + 16
+ __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+ __ addi(R3_ARG1, R3_ARG1, 32); // Update src+=32
+ __ addi(R4_ARG2, R4_ARG2, 32); // Update dsc+=32
+ __ bdnz(l_10); // Dec CTR and loop if not zero.
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+
+ } // VSX
+ } // FasterArrayCopy
__ bind(l_6);
@@ -1352,9 +1394,13 @@ class StubGenerator: public StubCodeGenerator {
Register tmp3 = R8_ARG6;
Register tmp4 = R9_ARG7;
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
+
address start = __ function_entry();
- Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8;
+ Label l_1, l_2, l_3, l_4, l_5, l_6, l_7, l_8, l_9;
+
// don't try anything fancy if arrays don't have many elements
__ li(tmp3, 0);
__ cmpwi(CCR0, R5_ARG3, 9);
@@ -1412,22 +1458,60 @@ class StubGenerator: public StubCodeGenerator {
__ andi_(R5_ARG3, R5_ARG3, 15);
__ mtctr(tmp1);
- __ bind(l_8);
- // Use unrolled version for mass copying (copy 16 elements a time).
- // Load feeding store gets zero latency on Power6, however not on Power5.
- // Therefore, the following sequence is made for the good of both.
- __ ld(tmp1, 0, R3_ARG1);
- __ ld(tmp2, 8, R3_ARG1);
- __ ld(tmp3, 16, R3_ARG1);
- __ ld(tmp4, 24, R3_ARG1);
- __ std(tmp1, 0, R4_ARG2);
- __ std(tmp2, 8, R4_ARG2);
- __ std(tmp3, 16, R4_ARG2);
- __ std(tmp4, 24, R4_ARG2);
- __ addi(R3_ARG1, R3_ARG1, 32);
- __ addi(R4_ARG2, R4_ARG2, 32);
- __ bdnz(l_8);
- }
+ if (!VM_Version::has_vsx()) {
+
+ __ bind(l_8);
+ // Use unrolled version for mass copying (copy 16 elements a time).
+ // Load feeding store gets zero latency on Power6, however not on Power5.
+ // Therefore, the following sequence is made for the good of both.
+ __ ld(tmp1, 0, R3_ARG1);
+ __ ld(tmp2, 8, R3_ARG1);
+ __ ld(tmp3, 16, R3_ARG1);
+ __ ld(tmp4, 24, R3_ARG1);
+ __ std(tmp1, 0, R4_ARG2);
+ __ std(tmp2, 8, R4_ARG2);
+ __ std(tmp3, 16, R4_ARG2);
+ __ std(tmp4, 24, R4_ARG2);
+ __ addi(R3_ARG1, R3_ARG1, 32);
+ __ addi(R4_ARG2, R4_ARG2, 32);
+ __ bdnz(l_8);
+
+ } else { // Processor supports VSX, so use it to mass copy.
+
+ // Prefetch src data into L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. It's not aligned 16-byte
+ // as loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_9);
+ // Use loop with VSX load/store instructions to
+ // copy 16 elements a time.
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load from src.
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst.
+ __ lxvd2x(tmp_vsr2, R3_ARG1, tmp1); // Load from src + 16.
+ __ stxvd2x(tmp_vsr2, R4_ARG2, tmp1); // Store to dst + 16.
+ __ addi(R3_ARG1, R3_ARG1, 32); // Update src+=32.
+ __ addi(R4_ARG2, R4_ARG2, 32); // Update dsc+=32.
+ __ bdnz(l_9); // Dec CTR and loop if not zero.
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+
+ }
+ } // FasterArrayCopy
__ bind(l_6);
// copy 2 elements at a time
@@ -1528,7 +1612,11 @@ class StubGenerator: public StubCodeGenerator {
Register tmp3 = R8_ARG6;
Register tmp4 = R0;
- Label l_1, l_2, l_3, l_4, l_5, l_6;
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
+
+ Label l_1, l_2, l_3, l_4, l_5, l_6, l_7;
+
// for short arrays, just do single element copy
__ li(tmp3, 0);
__ cmpwi(CCR0, R5_ARG3, 5);
@@ -1563,6 +1651,8 @@ class StubGenerator: public StubCodeGenerator {
__ andi_(R5_ARG3, R5_ARG3, 7);
__ mtctr(tmp1);
+ if (!VM_Version::has_vsx()) {
+
__ bind(l_6);
// Use unrolled version for mass copying (copy 8 elements a time).
// Load feeding store gets zero latency on power6, however not on power 5.
@@ -1578,7 +1668,44 @@ class StubGenerator: public StubCodeGenerator {
__ addi(R3_ARG1, R3_ARG1, 32);
__ addi(R4_ARG2, R4_ARG2, 32);
__ bdnz(l_6);
- }
+
+ } else { // Processor supports VSX, so use it to mass copy.
+
+ // Prefetch the data into the L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. Not 16-byte align as
+ // loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_7);
+ // Use loop with VSX load/store instructions to
+ // copy 8 elements a time.
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load src
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst
+ __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1); // Load src + 16
+ __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+ __ addi(R3_ARG1, R3_ARG1, 32); // Update src+=32
+ __ addi(R4_ARG2, R4_ARG2, 32); // Update dsc+=32
+ __ bdnz(l_7); // Dec CTR and loop if not zero.
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+
+ } // VSX
+ } // FasterArrayCopy
// copy 1 element at a time
__ bind(l_2);
@@ -1629,13 +1756,16 @@ class StubGenerator: public StubCodeGenerator {
// Do reverse copy. We assume the case of actual overlap is rare enough
// that we don't have to optimize it.
- Label l_1, l_2, l_3, l_4, l_5, l_6;
+ Label l_1, l_2, l_3, l_4, l_5, l_6, l_7;
Register tmp1 = R6_ARG4;
Register tmp2 = R7_ARG5;
Register tmp3 = R8_ARG6;
Register tmp4 = R0;
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
+
{ // FasterArrayCopy
__ cmpwi(CCR0, R5_ARG3, 0);
__ beq(CCR0, l_6);
@@ -1645,6 +1775,25 @@ class StubGenerator: public StubCodeGenerator {
__ add(R4_ARG2, R4_ARG2, R5_ARG3);
__ srdi(R5_ARG3, R5_ARG3, 2);
+ if (!aligned) {
+ // check if arrays have same alignment mod 8.
+ __ xorr(tmp1, R3_ARG1, R4_ARG2);
+ __ andi_(R0, tmp1, 7);
+ // Not the same alignment, but ld and std just need to be 4 byte aligned.
+ __ bne(CCR0, l_7); // to OR from is 8 byte aligned -> copy 2 at a time
+
+ // copy 1 element to align to and from on an 8 byte boundary
+ __ andi_(R0, R3_ARG1, 7);
+ __ beq(CCR0, l_7);
+
+ __ addi(R3_ARG1, R3_ARG1, -4);
+ __ addi(R4_ARG2, R4_ARG2, -4);
+ __ addi(R5_ARG3, R5_ARG3, -1);
+ __ lwzx(tmp2, R3_ARG1);
+ __ stwx(tmp2, R4_ARG2);
+ __ bind(l_7);
+ }
+
__ cmpwi(CCR0, R5_ARG3, 7);
__ ble(CCR0, l_5); // copy 1 at a time if less than 8 elements remain
@@ -1652,6 +1801,7 @@ class StubGenerator: public StubCodeGenerator {
__ andi(R5_ARG3, R5_ARG3, 7);
__ mtctr(tmp1);
+ if (!VM_Version::has_vsx()) {
__ bind(l_4);
// Use unrolled version for mass copying (copy 4 elements a time).
// Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1667,6 +1817,40 @@ class StubGenerator: public StubCodeGenerator {
__ std(tmp2, 8, R4_ARG2);
__ std(tmp1, 0, R4_ARG2);
__ bdnz(l_4);
+ } else { // Processor supports VSX, so use it to mass copy.
+ // Prefetch the data into the L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. Not 16-byte align as
+ // loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_4);
+ // Use loop with VSX load/store instructions to
+ // copy 8 elements a time.
+ __ addi(R3_ARG1, R3_ARG1, -32); // Update src-=32
+ __ addi(R4_ARG2, R4_ARG2, -32); // Update dsc-=32
+ __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1); // Load src+16
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load src
+ __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst+16
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst
+ __ bdnz(l_4);
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+ }
__ cmpwi(CCR0, R5_ARG3, 0);
__ beq(CCR0, l_6);
@@ -1730,7 +1914,10 @@ class StubGenerator: public StubCodeGenerator {
Register tmp3 = R8_ARG6;
Register tmp4 = R0;
- Label l_1, l_2, l_3, l_4;
+ Label l_1, l_2, l_3, l_4, l_5;
+
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
{ // FasterArrayCopy
__ cmpwi(CCR0, R5_ARG3, 3);
@@ -1740,6 +1927,7 @@ class StubGenerator: public StubCodeGenerator {
__ andi_(R5_ARG3, R5_ARG3, 3);
__ mtctr(tmp1);
+ if (!VM_Version::has_vsx()) {
__ bind(l_4);
// Use unrolled version for mass copying (copy 4 elements a time).
// Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1755,7 +1943,44 @@ class StubGenerator: public StubCodeGenerator {
__ addi(R3_ARG1, R3_ARG1, 32);
__ addi(R4_ARG2, R4_ARG2, 32);
__ bdnz(l_4);
- }
+
+ } else { // Processor supports VSX, so use it to mass copy.
+
+ // Prefetch the data into the L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. Not 16-byte align as
+ // loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_5);
+ // Use loop with VSX load/store instructions to
+ // copy 4 elements a time.
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load src
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst
+ __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1); // Load src + 16
+ __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst + 16
+ __ addi(R3_ARG1, R3_ARG1, 32); // Update src+=32
+ __ addi(R4_ARG2, R4_ARG2, 32); // Update dsc+=32
+ __ bdnz(l_5); // Dec CTR and loop if not zero.
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+
+ } // VSX
+ } // FasterArrayCopy
// copy 1 element at a time
__ bind(l_3);
@@ -1808,6 +2033,9 @@ class StubGenerator: public StubCodeGenerator {
Register tmp3 = R8_ARG6;
Register tmp4 = R0;
+ VectorSRegister tmp_vsr1 = VSR1;
+ VectorSRegister tmp_vsr2 = VSR2;
+
Label l_1, l_2, l_3, l_4, l_5;
__ cmpwi(CCR0, R5_ARG3, 0);
@@ -1826,6 +2054,7 @@ class StubGenerator: public StubCodeGenerator {
__ andi(R5_ARG3, R5_ARG3, 3);
__ mtctr(tmp1);
+ if (!VM_Version::has_vsx()) {
__ bind(l_4);
// Use unrolled version for mass copying (copy 4 elements a time).
// Load feeding store gets zero latency on Power6, however not on Power5.
@@ -1841,6 +2070,40 @@ class StubGenerator: public StubCodeGenerator {
__ std(tmp2, 8, R4_ARG2);
__ std(tmp1, 0, R4_ARG2);
__ bdnz(l_4);
+ } else { // Processor supports VSX, so use it to mass copy.
+ // Prefetch the data into the L2 cache.
+ __ dcbt(R3_ARG1, 0);
+
+ // If supported set DSCR pre-fetch to deepest.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7);
+ __ mtdscr(tmp2);
+ }
+
+ __ li(tmp1, 16);
+
+ // Backbranch target aligned to 32-byte. Not 16-byte align as
+ // loop contains < 8 instructions that fit inside a single
+ // i-cache sector.
+ __ align(32);
+
+ __ bind(l_4);
+ // Use loop with VSX load/store instructions to
+ // copy 4 elements a time.
+ __ addi(R3_ARG1, R3_ARG1, -32); // Update src-=32
+ __ addi(R4_ARG2, R4_ARG2, -32); // Update dsc-=32
+ __ lxvd2x(tmp_vsr2, tmp1, R3_ARG1); // Load src+16
+ __ lxvd2x(tmp_vsr1, R3_ARG1); // Load src
+ __ stxvd2x(tmp_vsr2, tmp1, R4_ARG2); // Store to dst+16
+ __ stxvd2x(tmp_vsr1, R4_ARG2); // Store to dst
+ __ bdnz(l_4);
+
+ // Restore DSCR pre-fetch value.
+ if (VM_Version::has_mfdscr()) {
+ __ load_const_optimized(tmp2, VM_Version::_dscr_val);
+ __ mtdscr(tmp2);
+ }
+ }
__ cmpwi(CCR0, R5_ARG3, 0);
__ beq(CCR0, l_1);
@@ -1961,7 +2224,7 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
- // Arguments for generated stub (little endian only):
+ // Arguments for generated stub:
// R3_ARG1 - source byte array address
// R4_ARG2 - destination byte array address
// R5_ARG3 - round key array
@@ -1980,7 +2243,6 @@ class StubGenerator: public StubCodeGenerator {
Register keylen = R8;
Register temp = R9;
Register keypos = R10;
- Register hex = R11;
Register fifteen = R12;
VectorRegister vRet = VR0;
@@ -2000,164 +2262,170 @@ class StubGenerator: public StubCodeGenerator {
VectorRegister vTmp3 = VR11;
VectorRegister vTmp4 = VR12;
- VectorRegister vLow = VR13;
- VectorRegister vHigh = VR14;
-
- __ li (hex, 16);
__ li (fifteen, 15);
- __ vspltisb (fSplt, 0x0f);
// load unaligned from[0-15] to vsRet
__ lvx (vRet, from);
__ lvx (vTmp1, fifteen, from);
__ lvsl (fromPerm, from);
+#ifdef VM_LITTLE_ENDIAN
+ __ vspltisb (fSplt, 0x0f);
__ vxor (fromPerm, fromPerm, fSplt);
+#endif
__ vperm (vRet, vRet, vTmp1, fromPerm);
// load keylen (44 or 52 or 60)
__ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT), key);
// to load keys
- __ lvsr (keyPerm, key);
- __ vxor (vTmp2, vTmp2, vTmp2);
+ __ load_perm (keyPerm, key);
+#ifdef VM_LITTLE_ENDIAN
__ vspltisb (vTmp2, -16);
__ vrld (keyPerm, keyPerm, vTmp2);
__ vrld (keyPerm, keyPerm, vTmp2);
__ vsldoi (keyPerm, keyPerm, keyPerm, 8);
+#endif
- // load the 1st round key to vKey1
- __ li (keypos, 0);
+ // load the 1st round key to vTmp1
+ __ lvx (vTmp1, key);
+ __ li (keypos, 16);
__ lvx (vKey1, keypos, key);
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey1, vTmp1, vKey1, keyPerm);
+ __ vec_perm (vTmp1, vKey1, keyPerm);
// 1st round
- __ vxor (vRet, vRet, vKey1);
+ __ vxor (vRet, vRet, vTmp1);
// load the 2nd round key to vKey1
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 32);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vKey2, keyPerm);
// load the 3rd round key to vKey2
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ __ li (keypos, 48);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, keyPerm);
// load the 4th round key to vKey3
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey3, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 64);
+ __ lvx (vKey4, keypos, key);
+ __ vec_perm (vKey3, vKey4, keyPerm);
// load the 5th round key to vKey4
- __ addi (keypos, keypos, 16);
+ __ li (keypos, 80);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey4, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey4, vTmp1, keyPerm);
// 2nd - 5th rounds
- __ vcipher (vRet, vRet, vKey1);
- __ vcipher (vRet, vRet, vKey2);
- __ vcipher (vRet, vRet, vKey3);
- __ vcipher (vRet, vRet, vKey4);
+ __ vcipher (vRet, vRet, vKey1);
+ __ vcipher (vRet, vRet, vKey2);
+ __ vcipher (vRet, vRet, vKey3);
+ __ vcipher (vRet, vRet, vKey4);
// load the 6th round key to vKey1
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 96);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vTmp1, vKey2, keyPerm);
// load the 7th round key to vKey2
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ __ li (keypos, 112);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, keyPerm);
// load the 8th round key to vKey3
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey3, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 128);
+ __ lvx (vKey4, keypos, key);
+ __ vec_perm (vKey3, vKey4, keyPerm);
// load the 9th round key to vKey4
- __ addi (keypos, keypos, 16);
+ __ li (keypos, 144);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey4, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey4, vTmp1, keyPerm);
// 6th - 9th rounds
- __ vcipher (vRet, vRet, vKey1);
- __ vcipher (vRet, vRet, vKey2);
- __ vcipher (vRet, vRet, vKey3);
- __ vcipher (vRet, vRet, vKey4);
+ __ vcipher (vRet, vRet, vKey1);
+ __ vcipher (vRet, vRet, vKey2);
+ __ vcipher (vRet, vRet, vKey3);
+ __ vcipher (vRet, vRet, vKey4);
// load the 10th round key to vKey1
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 160);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vTmp1, vKey2, keyPerm);
// load the 11th round key to vKey2
- __ addi (keypos, keypos, 16);
+ __ li (keypos, 176);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey2, vTmp1, keyPerm);
// if all round keys are loaded, skip next 4 rounds
__ cmpwi (CCR0, keylen, 44);
__ beq (CCR0, L_doLast);
// 10th - 11th rounds
- __ vcipher (vRet, vRet, vKey1);
- __ vcipher (vRet, vRet, vKey2);
+ __ vcipher (vRet, vRet, vKey1);
+ __ vcipher (vRet, vRet, vKey2);
// load the 12th round key to vKey1
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 192);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vTmp1, vKey2, keyPerm);
// load the 13th round key to vKey2
- __ addi (keypos, keypos, 16);
+ __ li (keypos, 208);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey2, vTmp1, keyPerm);
// if all round keys are loaded, skip next 2 rounds
__ cmpwi (CCR0, keylen, 52);
__ beq (CCR0, L_doLast);
// 12th - 13th rounds
- __ vcipher (vRet, vRet, vKey1);
- __ vcipher (vRet, vRet, vKey2);
+ __ vcipher (vRet, vRet, vKey1);
+ __ vcipher (vRet, vRet, vKey2);
// load the 14th round key to vKey1
- __ addi (keypos, keypos, 16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ __ li (keypos, 224);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vTmp1, vKey2, keyPerm);
// load the 15th round key to vKey2
- __ addi (keypos, keypos, 16);
+ __ li (keypos, 240);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey2, vTmp1, keyPerm);
__ bind(L_doLast);
// last two rounds
- __ vcipher (vRet, vRet, vKey1);
- __ vcipherlast (vRet, vRet, vKey2);
-
- __ neg (temp, to);
- __ lvsr (toPerm, temp);
- __ vspltisb (vTmp2, -1);
- __ vxor (vTmp1, vTmp1, vTmp1);
- __ vperm (vTmp2, vTmp2, vTmp1, toPerm);
- __ vxor (toPerm, toPerm, fSplt);
+ __ vcipher (vRet, vRet, vKey1);
+ __ vcipherlast (vRet, vRet, vKey2);
+
+ // store result (unaligned)
+#ifdef VM_LITTLE_ENDIAN
+ __ lvsl (toPerm, to);
+#else
+ __ lvsr (toPerm, to);
+#endif
+ __ vspltisb (vTmp3, -1);
+ __ vspltisb (vTmp4, 0);
__ lvx (vTmp1, to);
- __ vperm (vRet, vRet, vRet, toPerm);
- __ vsel (vTmp1, vTmp1, vRet, vTmp2);
- __ lvx (vTmp4, fifteen, to);
+ __ lvx (vTmp2, fifteen, to);
+#ifdef VM_LITTLE_ENDIAN
+ __ vperm (vTmp3, vTmp3, vTmp4, toPerm); // generate select mask
+ __ vxor (toPerm, toPerm, fSplt); // swap bytes
+#else
+ __ vperm (vTmp3, vTmp4, vTmp3, toPerm); // generate select mask
+#endif
+ __ vperm (vTmp4, vRet, vRet, toPerm); // rotate data
+ __ vsel (vTmp2, vTmp4, vTmp2, vTmp3);
+ __ vsel (vTmp1, vTmp1, vTmp4, vTmp3);
+ __ stvx (vTmp2, fifteen, to); // store this one first (may alias)
__ stvx (vTmp1, to);
- __ vsel (vRet, vRet, vTmp4, vTmp2);
- __ stvx (vRet, fifteen, to);
__ blr();
return start;
}
- // Arguments for generated stub (little endian only):
+ // Arguments for generated stub:
// R3_ARG1 - source byte array address
// R4_ARG2 - destination byte array address
// R5_ARG3 - K (key) in little endian int array
@@ -2179,7 +2447,6 @@ class StubGenerator: public StubCodeGenerator {
Register keylen = R8;
Register temp = R9;
Register keypos = R10;
- Register hex = R11;
Register fifteen = R12;
VectorRegister vRet = VR0;
@@ -2200,30 +2467,30 @@ class StubGenerator: public StubCodeGenerator {
VectorRegister vTmp3 = VR12;
VectorRegister vTmp4 = VR13;
- VectorRegister vLow = VR14;
- VectorRegister vHigh = VR15;
-
- __ li (hex, 16);
__ li (fifteen, 15);
- __ vspltisb (fSplt, 0x0f);
// load unaligned from[0-15] to vsRet
__ lvx (vRet, from);
__ lvx (vTmp1, fifteen, from);
__ lvsl (fromPerm, from);
+#ifdef VM_LITTLE_ENDIAN
+ __ vspltisb (fSplt, 0x0f);
__ vxor (fromPerm, fromPerm, fSplt);
+#endif
__ vperm (vRet, vRet, vTmp1, fromPerm); // align [and byte swap in LE]
// load keylen (44 or 52 or 60)
__ lwz (keylen, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT), key);
// to load keys
- __ lvsr (keyPerm, key);
+ __ load_perm (keyPerm, key);
+#ifdef VM_LITTLE_ENDIAN
__ vxor (vTmp2, vTmp2, vTmp2);
__ vspltisb (vTmp2, -16);
__ vrld (keyPerm, keyPerm, vTmp2);
__ vrld (keyPerm, keyPerm, vTmp2);
__ vsldoi (keyPerm, keyPerm, keyPerm, 8);
+#endif
__ cmpwi (CCR0, keylen, 44);
__ beq (CCR0, L_do44);
@@ -2231,32 +2498,32 @@ class StubGenerator: public StubCodeGenerator {
__ cmpwi (CCR0, keylen, 52);
__ beq (CCR0, L_do52);
- // load the 15th round key to vKey11
+ // load the 15th round key to vKey1
__ li (keypos, 240);
- __ lvx (vTmp1, keypos, key);
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp1, vTmp2, keyPerm);
+ __ lvx (vKey1, keypos, key);
+ __ li (keypos, 224);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vKey2, vKey1, keyPerm);
- // load the 14th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp2, vTmp1, keyPerm);
+ // load the 14th round key to vKey2
+ __ li (keypos, 208);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, vKey2, keyPerm);
- // load the 13th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey3, vTmp1, vTmp2, keyPerm);
+ // load the 13th round key to vKey3
+ __ li (keypos, 192);
+ __ lvx (vKey4, keypos, key);
+ __ vec_perm (vKey3, vKey4, vKey3, keyPerm);
- // load the 12th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey4, vTmp2, vTmp1, keyPerm);
+ // load the 12th round key to vKey4
+ __ li (keypos, 176);
+ __ lvx (vKey5, keypos, key);
+ __ vec_perm (vKey4, vKey5, vKey4, keyPerm);
- // load the 11th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey5, vTmp1, vTmp2, keyPerm);
+ // load the 11th round key to vKey5
+ __ li (keypos, 160);
+ __ lvx (vTmp1, keypos, key);
+ __ vec_perm (vKey5, vTmp1, vKey5, keyPerm);
// 1st - 5th rounds
__ vxor (vRet, vRet, vKey1);
@@ -2269,22 +2536,22 @@ class StubGenerator: public StubCodeGenerator {
__ bind (L_do52);
- // load the 13th round key to vKey11
+ // load the 13th round key to vKey1
__ li (keypos, 208);
- __ lvx (vTmp1, keypos, key);
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp1, vTmp2, keyPerm);
+ __ lvx (vKey1, keypos, key);
+ __ li (keypos, 192);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vKey2, vKey1, keyPerm);
- // load the 12th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp2, vTmp1, keyPerm);
+ // load the 12th round key to vKey2
+ __ li (keypos, 176);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, vKey2, keyPerm);
- // load the 11th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey3, vTmp1, vTmp2, keyPerm);
+ // load the 11th round key to vKey3
+ __ li (keypos, 160);
+ __ lvx (vTmp1, keypos, key);
+ __ vec_perm (vKey3, vTmp1, vKey3, keyPerm);
// 1st - 3rd rounds
__ vxor (vRet, vRet, vKey1);
@@ -2295,42 +2562,42 @@ class StubGenerator: public StubCodeGenerator {
__ bind (L_do44);
- // load the 11th round key to vKey11
+ // load the 11th round key to vKey1
__ li (keypos, 176);
+ __ lvx (vKey1, keypos, key);
+ __ li (keypos, 160);
__ lvx (vTmp1, keypos, key);
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp1, vTmp2, keyPerm);
+ __ vec_perm (vKey1, vTmp1, vKey1, keyPerm);
// 1st round
__ vxor (vRet, vRet, vKey1);
__ bind (L_doLast);
- // load the 10th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey1, vTmp2, vTmp1, keyPerm);
+ // load the 10th round key to vKey1
+ __ li (keypos, 144);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vKey2, vTmp1, keyPerm);
- // load the 9th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey2, vTmp1, vTmp2, keyPerm);
+ // load the 9th round key to vKey2
+ __ li (keypos, 128);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, vKey2, keyPerm);
- // load the 8th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey3, vTmp2, vTmp1, keyPerm);
+ // load the 8th round key to vKey3
+ __ li (keypos, 112);
+ __ lvx (vKey4, keypos, key);
+ __ vec_perm (vKey3, vKey4, vKey3, keyPerm);
- // load the 7th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey4, vTmp1, vTmp2, keyPerm);
+ // load the 7th round key to vKey4
+ __ li (keypos, 96);
+ __ lvx (vKey5, keypos, key);
+ __ vec_perm (vKey4, vKey5, vKey4, keyPerm);
- // load the 6th round key to vKey10
- __ addi (keypos, keypos, -16);
+ // load the 6th round key to vKey5
+ __ li (keypos, 80);
__ lvx (vTmp1, keypos, key);
- __ vperm (vKey5, vTmp2, vTmp1, keyPerm);
+ __ vec_perm (vKey5, vTmp1, vKey5, keyPerm);
// last 10th - 6th rounds
__ vncipher (vRet, vRet, vKey1);
@@ -2339,30 +2606,29 @@ class StubGenerator: public StubCodeGenerator {
__ vncipher (vRet, vRet, vKey4);
__ vncipher (vRet, vRet, vKey5);
- // load the 5th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey1, vTmp1, vTmp2, keyPerm);
+ // load the 5th round key to vKey1
+ __ li (keypos, 64);
+ __ lvx (vKey2, keypos, key);
+ __ vec_perm (vKey1, vKey2, vTmp1, keyPerm);
- // load the 4th round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey2, vTmp2, vTmp1, keyPerm);
+ // load the 4th round key to vKey2
+ __ li (keypos, 48);
+ __ lvx (vKey3, keypos, key);
+ __ vec_perm (vKey2, vKey3, vKey2, keyPerm);
- // load the 3rd round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey3, vTmp1, vTmp2, keyPerm);
+ // load the 3rd round key to vKey3
+ __ li (keypos, 32);
+ __ lvx (vKey4, keypos, key);
+ __ vec_perm (vKey3, vKey4, vKey3, keyPerm);
- // load the 2nd round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp1, keypos, key);
- __ vperm (vKey4, vTmp2, vTmp1, keyPerm);
+ // load the 2nd round key to vKey4
+ __ li (keypos, 16);
+ __ lvx (vKey5, keypos, key);
+ __ vec_perm (vKey4, vKey5, vKey4, keyPerm);
- // load the 1st round key to vKey10
- __ addi (keypos, keypos, -16);
- __ lvx (vTmp2, keypos, key);
- __ vperm (vKey5, vTmp1, vTmp2, keyPerm);
+ // load the 1st round key to vKey5
+ __ lvx (vTmp1, key);
+ __ vec_perm (vKey5, vTmp1, vKey5, keyPerm);
// last 5th - 1th rounds
__ vncipher (vRet, vRet, vKey1);
@@ -2371,24 +2637,54 @@ class StubGenerator: public StubCodeGenerator {
__ vncipher (vRet, vRet, vKey4);
__ vncipherlast (vRet, vRet, vKey5);
- __ neg (temp, to);
- __ lvsr (toPerm, temp);
- __ vspltisb (vTmp2, -1);
- __ vxor (vTmp1, vTmp1, vTmp1);
- __ vperm (vTmp2, vTmp2, vTmp1, toPerm);
- __ vxor (toPerm, toPerm, fSplt);
+ // store result (unaligned)
+#ifdef VM_LITTLE_ENDIAN
+ __ lvsl (toPerm, to);
+#else
+ __ lvsr (toPerm, to);
+#endif
+ __ vspltisb (vTmp3, -1);
+ __ vspltisb (vTmp4, 0);
__ lvx (vTmp1, to);
- __ vperm (vRet, vRet, vRet, toPerm);
- __ vsel (vTmp1, vTmp1, vRet, vTmp2);
- __ lvx (vTmp4, fifteen, to);
+ __ lvx (vTmp2, fifteen, to);
+#ifdef VM_LITTLE_ENDIAN
+ __ vperm (vTmp3, vTmp3, vTmp4, toPerm); // generate select mask
+ __ vxor (toPerm, toPerm, fSplt); // swap bytes
+#else
+ __ vperm (vTmp3, vTmp4, vTmp3, toPerm); // generate select mask
+#endif
+ __ vperm (vTmp4, vRet, vRet, toPerm); // rotate data
+ __ vsel (vTmp2, vTmp4, vTmp2, vTmp3);
+ __ vsel (vTmp1, vTmp1, vTmp4, vTmp3);
+ __ stvx (vTmp2, fifteen, to); // store this one first (may alias)
__ stvx (vTmp1, to);
- __ vsel (vRet, vRet, vTmp4, vTmp2);
- __ stvx (vRet, fifteen, to);
__ blr();
return start;
}
+ address generate_sha256_implCompress(bool multi_block, const char *name) {
+ assert(UseSHA, "need SHA instructions");
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ function_entry();
+
+ __ sha256 (multi_block);
+
+ __ blr();
+ return start;
+ }
+
+ address generate_sha512_implCompress(bool multi_block, const char *name) {
+ assert(UseSHA, "need SHA instructions");
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ function_entry();
+
+ __ sha512 (multi_block);
+
+ __ blr();
+ return start;
+ }
+
void generate_arraycopy_stubs() {
// Note: the disjoint stubs must be generated first, some of
// the conjoint stubs use them.
@@ -2618,6 +2914,15 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_montgomerySquare
= CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square);
}
+
+ if (UseSHA256Intrinsics) {
+ StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
+ StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
+ }
+ if (UseSHA512Intrinsics) {
+ StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress");
+ StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB");
+ }
}
public:
diff --git a/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp b/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
index 3655c1f78..e6e90ae76 100644
--- a/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
+++ b/src/cpu/ppc/vm/stubRoutines_ppc_64.hpp
@@ -34,7 +34,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _call_
enum platform_dependent_constants {
code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 20000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
};
// CRC32 Intrinsics.
diff --git a/src/cpu/ppc/vm/vm_version_ppc.cpp b/src/cpu/ppc/vm/vm_version_ppc.cpp
index eb47bb2a6..bbc52691b 100644
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2018 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
@@ -45,7 +45,7 @@ int VM_Version::_features = VM_Version::unknown_m;
int VM_Version::_measured_cache_line_size = 128; // default value
const char* VM_Version::_features_str = "";
bool VM_Version::_is_determine_features_test_running = false;
-
+uint64_t VM_Version::_dscr_val = 0;
#define MSG(flag) \
if (flag && !FLAG_IS_DEFAULT(flag)) \
@@ -60,7 +60,9 @@ void VM_Version::initialize() {
// If PowerArchitecturePPC64 hasn't been specified explicitly determine from features.
if (FLAG_IS_DEFAULT(PowerArchitecturePPC64)) {
- if (VM_Version::has_popcntw()) {
+ if (VM_Version::has_lqarx()) {
+ FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 8);
+ } else if (VM_Version::has_popcntw()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 7);
} else if (VM_Version::has_cmpb()) {
FLAG_SET_ERGO(uintx, PowerArchitecturePPC64, 6);
@@ -71,8 +73,14 @@ void VM_Version::initialize() {
}
}
guarantee(PowerArchitecturePPC64 == 0 || PowerArchitecturePPC64 == 5 ||
- PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7,
- "PowerArchitecturePPC64 should be 0, 5, 6 or 7");
+ PowerArchitecturePPC64 == 6 || PowerArchitecturePPC64 == 7 ||
+ PowerArchitecturePPC64 == 8,
+ "PowerArchitecturePPC64 should be 0, 5, 6, 7, or 8");
+
+ // Power 8: Configure Data Stream Control Register.
+ if (PowerArchitecturePPC64 >= 8) {
+ config_dscr();
+ }
if (!UseSIGTRAP) {
MSG(TrapBasedICMissChecks);
@@ -102,7 +110,7 @@ void VM_Version::initialize() {
// Create and print feature-string.
char buf[(num_features+1) * 16]; // Max 16 chars per feature.
jio_snprintf(buf, sizeof(buf),
- "ppc64%s%s%s%s%s%s%s%s%s%s",
+ "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
(has_fsqrt() ? " fsqrt" : ""),
(has_isel() ? " isel" : ""),
(has_lxarxeh() ? " lxarxeh" : ""),
@@ -112,12 +120,18 @@ void VM_Version::initialize() {
(has_popcntw() ? " popcntw" : ""),
(has_fcfids() ? " fcfids" : ""),
(has_vand() ? " vand" : ""),
+ (has_lqarx() ? " lqarx" : ""),
(has_vcipher() ? " aes" : ""),
- (has_vpmsumb() ? " vpmsumb" : "")
+ (has_vpmsumb() ? " vpmsumb" : ""),
+ (has_mfdscr() ? " mfdscr" : ""),
+ (has_vsx() ? " vsx" : ""),
+ (has_vshasig() ? " sha" : "")
// Make sure number of %s matches num_features!
);
_features_str = strdup(buf);
- NOT_PRODUCT(if (Verbose) print_features(););
+ if (Verbose) {
+ print_features();
+ }
// PPC64 supports 8-byte compare-exchange operations (see
// Atomic::cmpxchg and StubGenerator::generate_atomic_cmpxchg_ptr)
@@ -160,7 +174,6 @@ void VM_Version::initialize() {
}
// The AES intrinsic stubs require AES instruction support.
-#if defined(VM_LITTLE_ENDIAN)
if (has_vcipher()) {
if (FLAG_IS_DEFAULT(UseAES)) {
UseAES = true;
@@ -181,29 +194,43 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
}
-#else
- if (UseAES) {
- warning("AES instructions are not available on this CPU");
- FLAG_SET_DEFAULT(UseAES, false);
- }
- if (UseAESIntrinsics) {
- if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
- warning("AES intrinsics are not available on this CPU");
- FLAG_SET_DEFAULT(UseAESIntrinsics, false);
- }
-#endif
-
- if (UseSHA) {
- warning("SHA instructions are not available on this CPU");
+ if (has_vshasig()) {
+ if (FLAG_IS_DEFAULT(UseSHA)) {
+ UseSHA = true;
+ }
+ } else if (UseSHA) {
+ if (!FLAG_IS_DEFAULT(UseSHA))
+ warning("SHA instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseSHA, false);
}
- if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
- warning("SHA intrinsics are not available on this CPU");
+
+ if (UseSHA1Intrinsics) {
+ warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+ }
+
+ if (UseSHA && has_vshasig()) {
+ if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
+ }
+ } else if (UseSHA256Intrinsics) {
+ warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+ }
+
+ if (UseSHA && has_vshasig()) {
+ if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
+ }
+ } else if (UseSHA512Intrinsics) {
+ warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
+ if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA, false);
+ }
+
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
UseMontgomeryMultiplyIntrinsic = true;
}
@@ -485,8 +512,12 @@ void VM_Version::determine_features() {
a->popcntw(R7, R5); // code[7] -> popcntw
a->fcfids(F3, F4); // code[8] -> fcfids
a->vand(VR0, VR0, VR0); // code[9] -> vand
- a->vcipher(VR0, VR1, VR2); // code[10] -> vcipher
- a->vpmsumb(VR0, VR1, VR2); // code[11] -> vpmsumb
+ a->lqarx_unchecked(R7, R3_ARG1, R4_ARG2, 1); // code[10] -> lqarx_m
+ a->vcipher(VR0, VR1, VR2); // code[11] -> vcipher
+ a->vpmsumb(VR0, VR1, VR2); // code[12] -> vpmsumb
+ a->mfdscr(R0); // code[13] -> mfdscr
+ a->lxvd2x(VSR0, R3_ARG1); // code[14] -> vsx
+ a->vshasigmaw(VR0, VR1, 1, 0xF); // code[15] -> vshasig
a->blr();
// Emit function to set one cache line to zero. Emit function descriptor and get pointer to it.
@@ -530,8 +561,12 @@ void VM_Version::determine_features() {
if (code[feature_cntr++]) features |= popcntw_m;
if (code[feature_cntr++]) features |= fcfids_m;
if (code[feature_cntr++]) features |= vand_m;
+ if (code[feature_cntr++]) features |= lqarx_m;
if (code[feature_cntr++]) features |= vcipher_m;
if (code[feature_cntr++]) features |= vpmsumb_m;
+ if (code[feature_cntr++]) features |= mfdscr_m;
+ if (code[feature_cntr++]) features |= vsx_m;
+ if (code[feature_cntr++]) features |= vshasig_m;
// Print the detection code.
if (PrintAssembly) {
@@ -543,6 +578,69 @@ void VM_Version::determine_features() {
_features = features;
}
+// Power 8: Configure Data Stream Control Register.
+void VM_Version::config_dscr() {
+ assert(has_lqarx(), "Only execute on Power 8 or later!");
+
+ // 7 InstWords for each call (function descriptor + blr instruction).
+ const int code_size = (2+2*7)*BytesPerInstWord;
+
+ // Allocate space for the code.
+ ResourceMark rm;
+ CodeBuffer cb("config_dscr", code_size, 0);
+ MacroAssembler* a = new MacroAssembler(&cb);
+
+ // Emit code.
+ uint64_t (*get_dscr)() = (uint64_t(*)())(void *)a->function_entry();
+ uint32_t *code = (uint32_t *)a->pc();
+ a->mfdscr(R3);
+ a->blr();
+
+ void (*set_dscr)(long) = (void(*)(long))(void *)a->function_entry();
+ a->mtdscr(R3);
+ a->blr();
+
+ uint32_t *code_end = (uint32_t *)a->pc();
+ a->flush();
+
+ // Print the detection code.
+ if (PrintAssembly) {
+ ttyLocker ttyl;
+ tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", p2i(code));
+ Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
+ }
+
+ // Apply the configuration if needed.
+ _dscr_val = (*get_dscr)();
+ if (Verbose) {
+ tty->print_cr("dscr value was 0x%lx" , _dscr_val);
+ }
+ bool change_requested = false;
+ if (DSCR_PPC64 != (uintx)-1) {
+ _dscr_val = DSCR_PPC64;
+ change_requested = true;
+ }
+ if (DSCR_DPFD_PPC64 <= 7) {
+ uint64_t mask = 0x7;
+ if ((_dscr_val & mask) != DSCR_DPFD_PPC64) {
+ _dscr_val = (_dscr_val & ~mask) | (DSCR_DPFD_PPC64);
+ change_requested = true;
+ }
+ }
+ if (DSCR_URG_PPC64 <= 7) {
+ uint64_t mask = 0x7 << 6;
+ if ((_dscr_val & mask) != DSCR_DPFD_PPC64 << 6) {
+ _dscr_val = (_dscr_val & ~mask) | (DSCR_URG_PPC64 << 6);
+ change_requested = true;
+ }
+ }
+ if (change_requested) {
+ (*set_dscr)(_dscr_val);
+ if (Verbose) {
+ tty->print_cr("dscr was set to 0x%lx" , (*get_dscr)());
+ }
+ }
+}
static int saved_features = 0;
diff --git a/src/cpu/ppc/vm/vm_version_ppc.hpp b/src/cpu/ppc/vm/vm_version_ppc.hpp
index 55442f720..86243a1a8 100644
--- a/src/cpu/ppc/vm/vm_version_ppc.hpp
+++ b/src/cpu/ppc/vm/vm_version_ppc.hpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012, 2014 SAP AG. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2012, 2018 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
@@ -42,8 +42,12 @@ protected:
fcfids,
vand,
dcba,
+ lqarx,
vcipher,
vpmsumb,
+ mfdscr,
+ vsx,
+ vshasig,
num_features // last entry to count features
};
enum Feature_Flag_Set {
@@ -58,8 +62,12 @@ protected:
fcfids_m = (1 << fcfids ),
vand_m = (1 << vand ),
dcba_m = (1 << dcba ),
+ lqarx_m = (1 << lqarx ),
vcipher_m = (1 << vcipher),
+ vshasig_m = (1 << vshasig),
vpmsumb_m = (1 << vpmsumb),
+ mfdscr_m = (1 << mfdscr ),
+ vsx_m = (1 << vsx ),
all_features_m = -1
};
static int _features;
@@ -69,6 +77,7 @@ protected:
static void print_features();
static void determine_features(); // also measures cache line size
+ static void config_dscr(); // Power 8: Configure Data Stream Control Register.
static void determine_section_size();
static void power6_micro_bench();
public:
@@ -87,8 +96,12 @@ public:
static bool has_fcfids() { return (_features & fcfids_m) != 0; }
static bool has_vand() { return (_features & vand_m) != 0; }
static bool has_dcba() { return (_features & dcba_m) != 0; }
+ static bool has_lqarx() { return (_features & lqarx_m) != 0; }
static bool has_vcipher() { return (_features & vcipher_m) != 0; }
static bool has_vpmsumb() { return (_features & vpmsumb_m) != 0; }
+ static bool has_mfdscr() { return (_features & mfdscr_m) != 0; }
+ static bool has_vsx() { return (_features & vsx_m) != 0; }
+ static bool has_vshasig() { return (_features & vshasig_m) != 0; }
static const char* cpu_features() { return _features_str; }
@@ -97,6 +110,9 @@ public:
// Assembler testing
static void allow_all();
static void revert();
+
+ // POWER 8: DSCR current value.
+ static uint64_t _dscr_val;
};
#endif // CPU_PPC_VM_VM_VERSION_PPC_HPP
diff --git a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
index b3b3dcb55..b519b34da 100644
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp
@@ -579,7 +579,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
__ and3(Rscratch, divisor - 1, Rscratch);
}
__ add(Rdividend, Rscratch, Rscratch);
- __ sra(Rscratch, log2_intptr(divisor), Rresult);
+ __ sra(Rscratch, log2_int(divisor), Rresult);
return;
} else {
if (divisor == 2) {
diff --git a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
index d2c04c9ab..f1160792a 100644
--- a/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
@@ -294,11 +294,11 @@ void LIRGenerator::cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Opr bas
bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result, LIR_Opr tmp) {
assert(left != result, "should be different registers");
if (is_power_of_2(c + 1)) {
- __ shift_left(left, log2_intptr(c + 1), result);
+ __ shift_left(left, log2_int(c + 1), result);
__ sub(result, left, result);
return true;
} else if (is_power_of_2(c - 1)) {
- __ shift_left(left, log2_intptr(c - 1), result);
+ __ shift_left(left, log2_int(c - 1), result);
__ add(result, left, result);
return true;
}
diff --git a/src/cpu/sparc/vm/jniFastGetField_sparc.cpp b/src/cpu/sparc/vm/jniFastGetField_sparc.cpp
index 6d3f05a2a..ff9fcd694 100644
--- a/src/cpu/sparc/vm/jniFastGetField_sparc.cpp
+++ b/src/cpu/sparc/vm/jniFastGetField_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -68,6 +68,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
@@ -147,6 +148,7 @@ address JNI_FastGetField::generate_fast_get_long_field() {
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
__ add (O5, O4, O5);
@@ -219,6 +221,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
__ andcc (G4, 1, G0);
__ br (Assembler::notZero, false, Assembler::pn, label1);
__ delayed()->srl (O2, 2, O4);
+ __ andn (O1, JNIHandles::weak_tag_mask, O1);
__ ld_ptr (O1, 0, O5);
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
index 7e72da895..1cea35f57 100644
--- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
@@ -2706,15 +2706,30 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ verify_thread(); // G2_thread must be correct
__ reset_last_Java_frame();
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value in I0.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ addcc(G0, I0, G0);
- __ brx(Assembler::notZero, true, Assembler::pt, L);
- __ delayed()->ld_ptr(I0, 0, I0);
- __ mov(G0, I0);
- __ bind(L);
- __ verify_oop(I0);
+ Label done, not_weak;
+ __ br_null(I0, false, Assembler::pn, done); // Use NULL as-is.
+ __ delayed()->andcc(I0, JNIHandles::weak_tag_mask, G0); // Test for jweak
+ __ brx(Assembler::zero, true, Assembler::pt, not_weak);
+ __ delayed()->ld_ptr(I0, 0, I0); // Maybe resolve (untagged) jobject.
+ // Resolve jweak.
+ __ ld_ptr(I0, -JNIHandles::weak_tag_value, I0);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ // Copy to O0 because macro doesn't allow pre_val in input reg.
+ __ mov(I0, O0);
+ __ g1_write_barrier_pre(noreg /* obj */,
+ noreg /* index */,
+ 0 /* offset */,
+ O0 /* pre_val */,
+ G3_scratch /* tmp */,
+ true /* preserve_o_regs */);
+ }
+#endif // INCLUDE_ALL_GCS
+ __ bind(not_weak);
+ __ verify_oop(I0);
+ __ bind(done);
}
if (!is_critical_native) {
diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
index e4cc113c2..6ad0b1a41 100644
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
@@ -4483,7 +4483,7 @@ class StubGenerator: public StubCodeGenerator {
// save F48:F54 in temp registers
__ movdtox(F54,G2);
__ movdtox(F52,G3);
- __ movdtox(F50,G6);
+ __ movdtox(F50,L6);
__ movdtox(F48,G1);
for ( int i = 46; i >= 14; i -= 8 ) {
__ aes_dround23(as_FloatRegister(i), F0, F2, F4);
@@ -4511,7 +4511,7 @@ class StubGenerator: public StubCodeGenerator {
// re-init F48:F54 with their original values
__ movxtod(G2,F54);
__ movxtod(G3,F52);
- __ movxtod(G6,F50);
+ __ movxtod(L6,F50);
__ movxtod(G1,F48);
__ movxtod(L0,F6);
diff --git a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
index 5ffaf2faf..83d40496c 100644
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -1160,11 +1160,23 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
__ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch);
__ cmp_and_brx_short(G3_scratch, Lscratch, Assembler::notEqual, Assembler::pt, no_oop);
- __ addcc(G0, O0, O0);
- __ brx(Assembler::notZero, true, Assembler::pt, store_result); // if result is not NULL:
- __ delayed()->ld_ptr(O0, 0, O0); // unbox it
- __ mov(G0, O0);
-
+ // Unbox oop result, e.g. JNIHandles::resolve value in O0.
+ __ br_null(O0, false, Assembler::pn, store_result); // Use NULL as-is.
+ __ delayed()->andcc(O0, JNIHandles::weak_tag_mask, G0); // Test for jweak
+ __ brx(Assembler::zero, true, Assembler::pt, store_result);
+ __ delayed()->ld_ptr(O0, 0, O0); // Maybe resolve (untagged) jobject.
+ // Resolve jweak.
+ __ ld_ptr(O0, -JNIHandles::weak_tag_value, O0);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ __ g1_write_barrier_pre(noreg /* obj */,
+ noreg /* index */,
+ 0 /* offset */,
+ O0 /* pre_val */,
+ G3_scratch /* tmp */,
+ true /* preserve_o_regs */);
+ }
+#endif // INCLUDE_ALL_GCS
__ bind(store_result);
// Store it where gc will look for it and result handler expects it.
__ st_ptr(O0, FP, (frame::interpreter_frame_oop_temp_offset*wordSize) + STACK_BIAS);
diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
index 1db53a9dd..9fcb53316 100644
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp
@@ -2650,7 +2650,7 @@ void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right,
Register dreg = result->as_register();
if (right->is_constant()) {
- int divisor = right->as_constant_ptr()->as_jint();
+ jint divisor = right->as_constant_ptr()->as_jint();
assert(divisor > 0 && is_power_of_2(divisor), "must be");
if (code == lir_idiv) {
assert(lreg == rax, "must be rax,");
@@ -2662,7 +2662,7 @@ void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right,
__ andl(rdx, divisor - 1);
__ addl(lreg, rdx);
}
- __ sarl(lreg, log2_intptr(divisor));
+ __ sarl(lreg, log2_jint(divisor));
move_regs(lreg, dreg);
} else if (code == lir_irem) {
Label done;
diff --git a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index 48cab82b0..7f6b1d60e 100644
--- a/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -237,12 +237,12 @@ bool LIRGenerator::strength_reduce_multiply(LIR_Opr left, int c, LIR_Opr result,
if (tmp->is_valid()) {
if (is_power_of_2(c + 1)) {
__ move(left, tmp);
- __ shift_left(left, log2_intptr(c + 1), left);
+ __ shift_left(left, log2_jint(c + 1), left);
__ sub(left, tmp, result);
return true;
} else if (is_power_of_2(c - 1)) {
__ move(left, tmp);
- __ shift_left(left, log2_intptr(c - 1), left);
+ __ shift_left(left, log2_jint(c - 1), left);
__ add(left, tmp, result);
return true;
}
diff --git a/src/cpu/x86/vm/jniFastGetField_x86_32.cpp b/src/cpu/x86/vm/jniFastGetField_x86_32.cpp
index a45e0eb9a..48c4400e2 100644
--- a/src/cpu/x86/vm/jniFastGetField_x86_32.cpp
+++ b/src/cpu/x86/vm/jniFastGetField_x86_32.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -79,14 +79,17 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
__ mov(rax, rcx);
__ andptr(rax, 1); // rax, must end up 0
__ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
- // obj, notice rax, is 0.
- // rdx is data dependent on rcx.
+ // obj, notice rax, is 0.
+ // rdx is data dependent on rcx.
} else {
- __ movptr (rdx, Address(rsp, 2*wordSize)); // obj
+ __ movptr (rdx, Address(rsp, 2*wordSize)); // obj
}
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
- __ shrptr (rax, 2); // offset
+ __ shrptr (rax, 2); // offset
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
@@ -194,14 +197,17 @@ address JNI_FastGetField::generate_fast_get_long_field() {
__ jcc (Assembler::notZero, slow);
if (os::is_MP()) {
__ mov(rax, rcx);
- __ andptr(rax, 1); // rax, must end up 0
+ __ andptr(rax, 1); // rax, must end up 0
__ movptr(rdx, Address(rsp, rax, Address::times_1, 3*wordSize));
// obj, notice rax, is 0.
// rdx is data dependent on rcx.
} else {
- __ movptr(rdx, Address(rsp, 3*wordSize)); // obj
+ __ movptr(rdx, Address(rsp, 3*wordSize)); // obj
}
__ movptr(rsi, Address(rsp, 4*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rsi, 2); // offset
@@ -283,7 +289,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
__ jcc (Assembler::notZero, slow);
if (os::is_MP()) {
__ mov(rax, rcx);
- __ andptr(rax, 1); // rax, must end up 0
+ __ andptr(rax, 1); // rax, must end up 0
__ movptr(rdx, Address(rsp, rax, Address::times_1, 2*wordSize));
// obj, notice rax, is 0.
// rdx is data dependent on rcx.
@@ -291,6 +297,9 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
__ movptr(rdx, Address(rsp, 2*wordSize)); // obj
}
__ movptr(rax, Address(rsp, 3*wordSize)); // jfieldID
+
+ __ clear_jweak_tag(rdx);
+
__ movptr(rdx, Address(rdx, 0)); // *obj
__ shrptr(rax, 2); // offset
diff --git a/src/cpu/x86/vm/jniFastGetField_x86_64.cpp b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp
index 7286fd124..9b538002f 100644
--- a/src/cpu/x86/vm/jniFastGetField_x86_64.cpp
+++ b/src/cpu/x86/vm/jniFastGetField_x86_64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, 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
@@ -76,13 +76,16 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
__ jcc (Assembler::notZero, slow);
if (os::is_MP()) {
__ xorptr(robj, rcounter);
- __ xorptr(robj, rcounter); // obj, since
+ __ xorptr(robj, rcounter); // obj, since
// robj ^ rcounter ^ rcounter == robj
// robj is data dependent on rcounter.
}
- __ movptr(robj, Address(robj, 0)); // *obj
+
+ __ clear_jweak_tag(robj);
+
+ __ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
- __ shrptr(roffset, 2); // offset
+ __ shrptr(roffset, 2); // offset
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
@@ -174,13 +177,16 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
__ jcc (Assembler::notZero, slow);
if (os::is_MP()) {
__ xorptr(robj, rcounter);
- __ xorptr(robj, rcounter); // obj, since
+ __ xorptr(robj, rcounter); // obj, since
// robj ^ rcounter ^ rcounter == robj
// robj is data dependent on rcounter.
}
- __ movptr(robj, Address(robj, 0)); // *obj
+
+ __ clear_jweak_tag(robj);
+
+ __ movptr(robj, Address(robj, 0)); // *obj
__ mov (roffset, c_rarg2);
- __ shrptr(roffset, 2); // offset
+ __ shrptr(roffset, 2); // offset
assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
speculative_load_pclist[count] = __ pc();
diff --git a/src/cpu/x86/vm/macroAssembler_x86.cpp b/src/cpu/x86/vm/macroAssembler_x86.cpp
index 0e757f29c..1b09514c9 100644
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -4119,6 +4119,42 @@ void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src
}
}
+void MacroAssembler::resolve_jobject(Register value,
+ Register thread,
+ Register tmp) {
+ assert_different_registers(value, thread, tmp);
+ Label done, not_weak;
+ testptr(value, value);
+ jcc(Assembler::zero, done); // Use NULL as-is.
+ testptr(value, JNIHandles::weak_tag_mask); // Test for jweak tag.
+ jcc(Assembler::zero, not_weak);
+ // Resolve jweak.
+ movptr(value, Address(value, -JNIHandles::weak_tag_value));
+ verify_oop(value);
+#if INCLUDE_ALL_GCS
+ if (UseG1GC) {
+ g1_write_barrier_pre(noreg /* obj */,
+ value /* pre_val */,
+ thread /* thread */,
+ tmp /* tmp */,
+ true /* tosca_live */,
+ true /* expand_call */);
+ }
+#endif // INCLUDE_ALL_GCS
+ jmp(done);
+ bind(not_weak);
+ // Resolve (untagged) jobject.
+ movptr(value, Address(value, 0));
+ verify_oop(value);
+ bind(done);
+}
+
+void MacroAssembler::clear_jweak_tag(Register possibly_jweak) {
+ const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask);
+ STATIC_ASSERT(inverted_jweak_mask == -2); // otherwise check this code
+ // The inverted mask is sign-extended
+ andptr(possibly_jweak, inverted_jweak_mask);
+}
//////////////////////////////////////////////////////////////////////////////////
#if INCLUDE_ALL_GCS
diff --git a/src/cpu/x86/vm/macroAssembler_x86.hpp b/src/cpu/x86/vm/macroAssembler_x86.hpp
index c3c0a7911..e94fdd7d7 100644
--- a/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -298,6 +298,9 @@ class MacroAssembler: public Assembler {
void store_check(Register obj); // store check for obj - register is destroyed afterwards
void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed)
+ void resolve_jobject(Register value, Register thread, Register tmp);
+ void clear_jweak_tag(Register possibly_jweak);
+
#if INCLUDE_ALL_GCS
void g1_write_barrier_pre(Register obj,
diff --git a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
index 9debbc118..d701d4495 100644
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
+++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
@@ -2253,14 +2253,11 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ reset_last_Java_frame(thread, false);
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ cmpptr(rax, (int32_t)NULL_WORD);
- __ jcc(Assembler::equal, L);
- __ movptr(rax, Address(rax, 0));
- __ bind(L);
- __ verify_oop(rax);
+ __ resolve_jobject(rax /* value */,
+ thread /* thread */,
+ rcx /* tmp */);
}
if (!is_critical_native) {
diff --git a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index e50c72218..c2f69f7c3 100644
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -2499,14 +2499,11 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ reset_last_Java_frame(false);
- // Unpack oop result
+ // Unbox oop result, e.g. JNIHandles::resolve value.
if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
- Label L;
- __ testptr(rax, rax);
- __ jcc(Assembler::zero, L);
- __ movptr(rax, Address(rax, 0));
- __ bind(L);
- __ verify_oop(rax);
+ __ resolve_jobject(rax /* value */,
+ r15_thread /* thread */,
+ rcx /* tmp */);
}
if (!is_critical_native) {
diff --git a/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/src/cpu/x86/vm/stubRoutines_x86_64.hpp
index 15922b8ae..b048fd74e 100644
--- a/src/cpu/x86/vm/stubRoutines_x86_64.hpp
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.hpp
@@ -33,7 +33,7 @@ static bool returns_to_call_stub(address return_pc) { return return_pc == _
enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 23000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 24000 // simply increase if too small (assembler will crash if too small)
};
class x86 {
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
index 4d94902ee..b7c515031 100644
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -1296,19 +1296,18 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
__ movl(Address(t, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD);
// If result was an oop then unbox and save it in the frame
- { Label L;
- Label no_oop, store_result;
+ {
+ Label no_oop;
ExternalAddress handler(AbstractInterpreter::result_handler(T_OBJECT));
__ cmpptr(Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize),
handler.addr());
__ jcc(Assembler::notEqual, no_oop);
__ cmpptr(Address(rsp, 0), (int32_t)NULL_WORD);
__ pop(ltos);
- __ testptr(rax, rax);
- __ jcc(Assembler::zero, store_result);
- // unbox
- __ movptr(rax, Address(rax, 0));
- __ bind(store_result);
+ // Unbox oop result, e.g. JNIHandles::resolve value.
+ __ resolve_jobject(rax /* value */,
+ thread /* thread */,
+ t /* tmp */);
__ movptr(Address(rbp, (frame::interpreter_frame_oop_temp_offset)*wordSize), rax);
// keep stack depth as expected by pushing oop which will eventually be discarded
__ push(ltos);
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
index 121738292..209a3f676 100644
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, 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
@@ -1272,16 +1272,16 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// and result handler will pick it up
{
- Label no_oop, store_result;
+ Label no_oop;
__ lea(t, ExternalAddress(AbstractInterpreter::result_handler(T_OBJECT)));
__ cmpptr(t, Address(rbp, frame::interpreter_frame_result_handler_offset*wordSize));
__ jcc(Assembler::notEqual, no_oop);
// retrieve result
__ pop(ltos);
- __ testptr(rax, rax);
- __ jcc(Assembler::zero, store_result);
- __ movptr(rax, Address(rax, 0));
- __ bind(store_result);
+ // Unbox oop result, e.g. JNIHandles::resolve value.
+ __ resolve_jobject(rax /* value */,
+ r15_thread /* thread */,
+ t /* tmp */);
__ movptr(Address(rbp, frame::interpreter_frame_oop_temp_offset*wordSize), rax);
// keep stack depth as expected by pushing oop which will eventually be discarde
__ push(ltos);
diff --git a/src/cpu/x86/vm/x86_64.ad b/src/cpu/x86/vm/x86_64.ad
index e20b02d2b..e36604faf 100644
--- a/src/cpu/x86/vm/x86_64.ad
+++ b/src/cpu/x86/vm/x86_64.ad
@@ -3740,6 +3740,23 @@ operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale)
%}
%}
+// Indirect Memory Plus Positive Index Register Plus Offset Operand
+operand indPosIndexOffset(any_RegP reg, immL32 off, rRegI idx)
+%{
+ constraint(ALLOC_IN_RC(ptr_reg));
+ predicate(n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
+ match(AddP (AddP reg (ConvI2L idx)) off);
+
+ op_cost(10);
+ format %{"[$reg + $off + $idx]" %}
+ interface(MEMORY_INTER) %{
+ base($reg);
+ index($idx);
+ scale(0x0);
+ disp($off);
+ %}
+%}
+
// Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
operand indPosIndexScaleOffset(any_RegP reg, immL32 off, rRegI idx, immI2 scale)
%{
@@ -3891,6 +3908,23 @@ operand indIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegL lreg, immI2 scale
%}
%}
+// Indirect Memory Times Plus Positive Index Register Plus Offset Operand
+operand indPosIndexOffsetNarrow(rRegN reg, immL32 off, rRegI idx)
+%{
+ constraint(ALLOC_IN_RC(ptr_reg));
+ predicate(Universe::narrow_oop_shift() == 0 && n->in(2)->in(3)->as_Type()->type()->is_long()->_lo >= 0);
+ match(AddP (AddP (DecodeN reg) (ConvI2L idx)) off);
+
+ op_cost(10);
+ format %{"[$reg + $off + $idx]" %}
+ interface(MEMORY_INTER) %{
+ base($reg);
+ index($idx);
+ scale(0x0);
+ disp($off);
+ %}
+%}
+
// Indirect Memory Times Scale Plus Positive Index Register Plus Offset Operand
operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 scale)
%{
@@ -4082,11 +4116,11 @@ operand cmpOpUCF2() %{
// case of this is memory operands.
opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
- indIndexScale, indIndexScaleOffset, indPosIndexScaleOffset,
+ indIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset,
indCompressedOopOffset,
indirectNarrow, indOffset8Narrow, indOffset32Narrow,
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
- indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow);
+ indIndexScaleOffsetNarrow, indPosIndexOffsetNarrow, indPosIndexScaleOffsetNarrow);
//----------PIPELINE-----------------------------------------------------------
// Rules which define the behavior of the target architectures pipeline.
@@ -5120,6 +5154,17 @@ instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem)
ins_pipe(ialu_reg_reg_fat);
%}
+instruct leaPPosIdxOff(rRegP dst, indPosIndexOffset mem)
+%{
+ match(Set dst mem);
+
+ ins_cost(110);
+ format %{ "leaq $dst, $mem\t# ptr posidxoff" %}
+ opcode(0x8D);
+ ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
+ ins_pipe(ialu_reg_reg_fat);
+%}
+
instruct leaPPosIdxScaleOff(rRegP dst, indPosIndexScaleOffset mem)
%{
match(Set dst mem);
@@ -5204,6 +5249,18 @@ instruct leaPIdxScaleOffNarrow(rRegP dst, indIndexScaleOffsetNarrow mem)
ins_pipe(ialu_reg_reg_fat);
%}
+instruct leaPPosIdxOffNarrow(rRegP dst, indPosIndexOffsetNarrow mem)
+%{
+ predicate(Universe::narrow_oop_shift() == 0);
+ match(Set dst mem);
+
+ ins_cost(110);
+ format %{ "leaq $dst, $mem\t# ptr posidxoffnarrow" %}
+ opcode(0x8D);
+ ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
+ ins_pipe(ialu_reg_reg_fat);
+%}
+
instruct leaPPosIdxScaleOffNarrow(rRegP dst, indPosIndexScaleOffsetNarrow mem)
%{
predicate(Universe::narrow_oop_shift() == 0);
diff --git a/src/cpu/zero/vm/cppInterpreter_zero.cpp b/src/cpu/zero/vm/cppInterpreter_zero.cpp
index 242ce1cfd..525031eb9 100644
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp
+++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -405,10 +405,12 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) {
// oop_temp where the garbage collector can see it before
// we release the handle it might be protected by.
if (handler->result_type() == &ffi_type_pointer) {
- if (result[0])
- istate->set_oop_temp(*(oop *) result[0]);
- else
+ if (result[0] == 0) {
istate->set_oop_temp(NULL);
+ } else {
+ jobject handle = reinterpret_cast<jobject>(result[0]);
+ istate->set_oop_temp(JNIHandles::resolve(handle));
+ }
}
// Reset handle block
diff --git a/src/os/aix/vm/os_aix.cpp b/src/os/aix/vm/os_aix.cpp
index 8cd1f4e8f..717f692c2 100644
--- a/src/os/aix/vm/os_aix.cpp
+++ b/src/os/aix/vm/os_aix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -4184,8 +4184,7 @@ bool os::dir_is_empty(const char* path) {
/* Scan the directory */
bool result = true;
- char buf[sizeof(struct dirent) + MAX_PATH];
- while (result && (ptr = ::readdir(dir)) != NULL) {
+ while (result && (ptr = readdir(dir)) != NULL) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
result = false;
}
@@ -5142,7 +5141,7 @@ extern char** environ;
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
-int os::fork_and_exec(char* cmd) {
+int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
char * argv[4] = {"sh", "-c", cmd, NULL};
pid_t pid = fork();
diff --git a/src/os/aix/vm/os_aix.inline.hpp b/src/os/aix/vm/os_aix.inline.hpp
index a97c94c07..421ea342e 100644
--- a/src/os/aix/vm/os_aix.inline.hpp
+++ b/src/os/aix/vm/os_aix.inline.hpp
@@ -92,19 +92,6 @@ inline void os::dll_unload(void *lib) {
inline const int os::default_file_open_flags() { return 0;}
-inline DIR* os::opendir(const char* dirname)
-{
- assert(dirname != NULL, "just checking");
- return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
- // according to aix sys/limits, NAME_MAX must be retrieved at runtime. */
- const long my_NAME_MAX = pathconf(path, _PC_NAME_MAX);
- return my_NAME_MAX + sizeof(dirent) + 1;
-}
-
inline jlong os::lseek(int fd, jlong offset, int whence) {
return (jlong) ::lseek64(fd, offset, whence);
}
@@ -121,28 +108,6 @@ inline int os::ftruncate(int fd, jlong length) {
return ::ftruncate64(fd, length);
}
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
- dirent* p;
- int status;
- assert(dirp != NULL, "just checking");
-
- // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
- // version. Here is the doc for this function:
- // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
- if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
- errno = status;
- return NULL;
- } else
- return p;
-}
-
-inline int os::closedir(DIR *dirp) {
- assert(dirp != NULL, "argument is NULL");
- return ::closedir(dirp);
-}
-
// macros for restartable system calls
#define RESTARTABLE(_cmd, _result) do { \
diff --git a/src/os/aix/vm/perfMemory_aix.cpp b/src/os/aix/vm/perfMemory_aix.cpp
index 96f8451d2..80ae9e7a8 100644
--- a/src/os/aix/vm/perfMemory_aix.cpp
+++ b/src/os/aix/vm/perfMemory_aix.cpp
@@ -612,9 +612,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
- while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+ while ((dentry = os::readdir(tmpdirp)) != NULL) {
// check if the directory entry is a hsperfdata file
if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -648,9 +647,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
- while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+ while ((udentry = os::readdir(subdirp)) != NULL) {
if (filename_to_pid(udentry->d_name) == vmid) {
struct stat statbuf;
@@ -694,11 +692,9 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -774,10 +770,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// loop under these conditions is dependent upon the implementation of
// opendir/readdir.
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
errno = 0;
- while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+ while ((entry = os::readdir(dirp)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
@@ -816,7 +810,6 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// Close the directory and reset the current working directory.
close_directory_secure_cwd(dirp, saved_cwd_fd);
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// Make the user specific temporary directory. Returns true if
diff --git a/src/os/bsd/vm/os_bsd.cpp b/src/os/bsd/vm/os_bsd.cpp
index c377c7d9f..1c0336edd 100644
--- a/src/os/bsd/vm/os_bsd.cpp
+++ b/src/os/bsd/vm/os_bsd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -3957,8 +3957,7 @@ bool os::dir_is_empty(const char* path) {
/* Scan the directory */
bool result = true;
- char buf[sizeof(struct dirent) + MAX_PATH];
- while (result && (ptr = ::readdir(dir)) != NULL) {
+ while (result && (ptr = readdir(dir)) != NULL) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
result = false;
}
@@ -4716,7 +4715,7 @@ extern char** environ;
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
-int os::fork_and_exec(char* cmd) {
+int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
const char * argv[4] = {"sh", "-c", cmd, NULL};
// fork() in BsdThreads/NPTL is not async-safe. It needs to run
diff --git a/src/os/bsd/vm/os_bsd.inline.hpp b/src/os/bsd/vm/os_bsd.inline.hpp
index 10b39941d..c35abf486 100644
--- a/src/os/bsd/vm/os_bsd.inline.hpp
+++ b/src/os/bsd/vm/os_bsd.inline.hpp
@@ -95,17 +95,6 @@ inline void os::dll_unload(void *lib) {
inline const int os::default_file_open_flags() { return 0;}
-inline DIR* os::opendir(const char* dirname)
-{
- assert(dirname != NULL, "just checking");
- return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
- return NAME_MAX + sizeof(dirent) + 1;
-}
-
inline jlong os::lseek(int fd, jlong offset, int whence) {
return (jlong) ::lseek(fd, offset, whence);
}
@@ -122,28 +111,6 @@ inline int os::ftruncate(int fd, jlong length) {
return ::ftruncate(fd, length);
}
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
- dirent* p;
- int status;
- assert(dirp != NULL, "just checking");
-
- // NOTE: Bsd readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
- // version. Here is the doc for this function:
- // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
- if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
- errno = status;
- return NULL;
- } else
- return p;
-}
-
-inline int os::closedir(DIR *dirp) {
- assert(dirp != NULL, "argument is NULL");
- return ::closedir(dirp);
-}
-
// macros for restartable system calls
#define RESTARTABLE(_cmd, _result) do { \
diff --git a/src/os/bsd/vm/perfMemory_bsd.cpp b/src/os/bsd/vm/perfMemory_bsd.cpp
index df4fca613..802d0908f 100644
--- a/src/os/bsd/vm/perfMemory_bsd.cpp
+++ b/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -533,9 +533,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
- while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+ while ((dentry = os::readdir(tmpdirp)) != NULL) {
// check if the directory entry is a hsperfdata file
if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -557,9 +556,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
- while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+ while ((udentry = os::readdir(subdirp)) != NULL) {
if (filename_to_pid(udentry->d_name) == vmid) {
struct stat statbuf;
@@ -603,11 +601,9 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -686,10 +682,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
errno = 0;
- while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+ while ((entry = os::readdir(dirp)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
@@ -729,7 +723,6 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
index 4d4dad060..03cabfefb 100644
--- a/src/os/linux/vm/os_linux.cpp
+++ b/src/os/linux/vm/os_linux.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -136,6 +136,7 @@ uintptr_t os::Linux::_initial_thread_stack_size = 0;
int (*os::Linux::_clock_gettime)(clockid_t, struct timespec *) = NULL;
int (*os::Linux::_pthread_getcpuclockid)(pthread_t, clockid_t *) = NULL;
+int (*os::Linux::_pthread_setname_np)(pthread_t, const char*) = NULL;
Mutex* os::Linux::_createThread_lock = NULL;
pthread_t os::Linux::_main_thread;
int os::Linux::_page_size = -1;
@@ -5054,6 +5055,11 @@ void os::init(void) {
StackRedPages = 1;
StackShadowPages = round_to((StackShadowPages*Linux::vm_default_page_size()), vm_page_size()) / vm_page_size();
}
+
+ // retrieve entry point for pthread_setname_np
+ Linux::_pthread_setname_np =
+ (int(*)(pthread_t, const char*))dlsym(RTLD_DEFAULT, "pthread_setname_np");
+
}
// To install functions for atexit system call
@@ -5308,8 +5314,14 @@ int os::active_processor_count() {
}
void os::set_native_thread_name(const char *name) {
- // Not yet implemented.
- return;
+ if (Linux::_pthread_setname_np) {
+ char buf [16]; // according to glibc manpage, 16 chars incl. '/0'
+ snprintf(buf, sizeof(buf), "%s", name);
+ buf[sizeof(buf) - 1] = '\0';
+ const int rc = Linux::_pthread_setname_np(pthread_self(), buf);
+ // ERANGE should not happen; all other errors should just be ignored.
+ assert(rc != ERANGE, "pthread_setname_np failed");
+ }
}
bool os::distribute_processes(uint length, uint* distribution) {
@@ -5489,8 +5501,7 @@ bool os::dir_is_empty(const char* path) {
/* Scan the directory */
bool result = true;
- char buf[sizeof(struct dirent) + MAX_PATH];
- while (result && (ptr = ::readdir(dir)) != NULL) {
+ while (result && (ptr = readdir(dir)) != NULL) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
result = false;
}
@@ -6337,10 +6348,16 @@ extern char** environ;
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
-int os::fork_and_exec(char* cmd) {
+int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
const char * argv[4] = {"sh", "-c", cmd, NULL};
- pid_t pid = fork();
+ pid_t pid ;
+
+ if (use_vfork_if_available) {
+ pid = vfork();
+ } else {
+ pid = fork();
+ }
if (pid < 0) {
// fork failed
diff --git a/src/os/linux/vm/os_linux.hpp b/src/os/linux/vm/os_linux.hpp
index e207dccd7..79a9f39ab 100644
--- a/src/os/linux/vm/os_linux.hpp
+++ b/src/os/linux/vm/os_linux.hpp
@@ -56,6 +56,7 @@ class Linux {
static int (*_clock_gettime)(clockid_t, struct timespec *);
static int (*_pthread_getcpuclockid)(pthread_t, clockid_t *);
+ static int (*_pthread_setname_np)(pthread_t, const char*);
static address _initial_thread_stack_bottom;
static uintptr_t _initial_thread_stack_size;
diff --git a/src/os/linux/vm/os_linux.inline.hpp b/src/os/linux/vm/os_linux.inline.hpp
index fea10fa64..a23bd5631 100644
--- a/src/os/linux/vm/os_linux.inline.hpp
+++ b/src/os/linux/vm/os_linux.inline.hpp
@@ -87,17 +87,6 @@ inline void os::dll_unload(void *lib) {
inline const int os::default_file_open_flags() { return 0;}
-inline DIR* os::opendir(const char* dirname)
-{
- assert(dirname != NULL, "just checking");
- return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path)
-{
- return NAME_MAX + sizeof(dirent) + 1;
-}
-
inline jlong os::lseek(int fd, jlong offset, int whence) {
return (jlong) ::lseek64(fd, offset, whence);
}
@@ -114,33 +103,6 @@ inline int os::ftruncate(int fd, jlong length) {
return ::ftruncate64(fd, length);
}
-// readdir_r has been deprecated since glibc 2.24.
-// See https://sourceware.org/bugzilla/show_bug.cgi?id=19056 for more details.
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf)
-{
-
- dirent* p;
- int status;
- assert(dirp != NULL, "just checking");
-
- // NOTE: Linux readdir_r (on RH 6.2 and 7.2 at least) is NOT like the POSIX
- // version. Here is the doc for this function:
- // http://www.gnu.org/manual/glibc-2.2.3/html_node/libc_262.html
-
- if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
- errno = status;
- return NULL;
- } else
- return p;
-
-}
-
-inline int os::closedir(DIR *dirp) {
- assert(dirp != NULL, "argument is NULL");
- return ::closedir(dirp);
-}
-
// macros for restartable system calls
#define RESTARTABLE(_cmd, _result) do { \
diff --git a/src/os/linux/vm/perfMemory_linux.cpp b/src/os/linux/vm/perfMemory_linux.cpp
index 4143f655a..8293b7168 100644
--- a/src/os/linux/vm/perfMemory_linux.cpp
+++ b/src/os/linux/vm/perfMemory_linux.cpp
@@ -533,9 +533,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
- while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+ while ((dentry = os::readdir(tmpdirp)) != NULL) {
// check if the directory entry is a hsperfdata file
if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -569,9 +568,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
- while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+ while ((udentry = os::readdir(subdirp)) != NULL) {
if (filename_to_pid(udentry->d_name) == vmid) {
struct stat statbuf;
@@ -615,11 +613,9 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -698,10 +694,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
errno = 0;
- while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+ while ((entry = os::readdir(dirp)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
@@ -738,8 +732,6 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
-
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
diff --git a/src/os/posix/vm/os_posix.cpp b/src/os/posix/vm/os_posix.cpp
index c301898a2..a43a855b2 100644
--- a/src/os/posix/vm/os_posix.cpp
+++ b/src/os/posix/vm/os_posix.cpp
@@ -302,6 +302,21 @@ FILE* os::open(int fd, const char* mode) {
return ::fdopen(fd, mode);
}
+DIR* os::opendir(const char* dirname) {
+ assert(dirname != NULL, "just checking");
+ return ::opendir(dirname);
+}
+
+struct dirent* os::readdir(DIR* dirp) {
+ assert(dirp != NULL, "just checking");
+ return ::readdir(dirp);
+}
+
+int os::closedir(DIR *dirp) {
+ assert(dirp != NULL, "just checking");
+ return ::closedir(dirp);
+}
+
// Builds a platform dependent Agent_OnLoad_<lib_name> function name
// which is used to find statically linked in agents.
// Parameters:
@@ -604,7 +619,11 @@ const char* os::Posix::describe_sa_flags(int flags, char* buffer, size_t size) {
strncpy(buffer, "none", size);
const struct {
- int i;
+ // NB: i is an unsigned int here because SA_RESETHAND is on some
+ // systems 0x80000000, which is implicitly unsigned. Assignining
+ // it to an int field would be an overflow in unsigned-to-signed
+ // conversion.
+ unsigned int i;
const char* s;
} flaginfo [] = {
{ SA_NOCLDSTOP, "SA_NOCLDSTOP" },
diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp
index 4a786cffb..6956f63d9 100644
--- a/src/os/solaris/vm/os_solaris.cpp
+++ b/src/os/solaris/vm/os_solaris.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -160,6 +160,7 @@ address os::Solaris::handler_end; // end pc of thr_sighndlrinfo
address os::Solaris::_main_stack_base = NULL; // 4352906 workaround
+os::Solaris::pthread_setname_np_func_t os::Solaris::_pthread_setname_np = NULL;
// "default" initializers for missing libc APIs
extern "C" {
@@ -519,8 +520,15 @@ static bool assign_distribution(processorid_t* id_array,
}
void os::set_native_thread_name(const char *name) {
- // Not yet implemented.
- return;
+ if (Solaris::_pthread_setname_np != NULL) {
+ // Only the first 31 bytes of 'name' are processed by pthread_setname_np
+ // but we explicitly copy into a size-limited buffer to avoid any
+ // possible overflow.
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%s", name);
+ buf[sizeof(buf) - 1] = '\0';
+ Solaris::_pthread_setname_np(pthread_self(), buf);
+ }
}
bool os::distribute_processes(uint length, uint* distribution) {
@@ -4921,6 +4929,13 @@ void os::init(void) {
// the minimum of what the OS supports (thr_min_stack()), and
// enough to allow the thread to get to user bytecode execution.
Solaris::min_stack_allowed = MAX2(thr_min_stack(), Solaris::min_stack_allowed);
+
+ // retrieve entry point for pthread_setname_np
+ void * handle = dlopen("libc.so.1", RTLD_LAZY);
+ if (handle != NULL) {
+ Solaris::_pthread_setname_np =
+ (Solaris::pthread_setname_np_func_t)dlsym(handle, "pthread_setname_np");
+ }
// If the pagesize of the VM is greater than 8K determine the appropriate
// number of initial guard pages. The user can change this with the
// command line arguments, if needed.
@@ -5148,9 +5163,7 @@ bool os::dir_is_empty(const char* path) {
/* Scan the directory */
bool result = true;
- char buf[sizeof(struct dirent) + MAX_PATH];
- struct dirent *dbuf = (struct dirent *) buf;
- while (result && (ptr = readdir(dir, dbuf)) != NULL) {
+ while (result && (ptr = readdir(dir)) != NULL) {
if (strcmp(ptr->d_name, ".") != 0 && strcmp(ptr->d_name, "..") != 0) {
result = false;
}
@@ -6153,7 +6166,7 @@ extern char** environ;
// or -1 on failure (e.g. can't fork a new process).
// Unlike system(), this function can be called from signal handler. It
// doesn't block SIGINT et al.
-int os::fork_and_exec(char* cmd) {
+int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
char * argv[4];
argv[0] = (char *)"sh";
argv[1] = (char *)"-c";
diff --git a/src/os/solaris/vm/os_solaris.hpp b/src/os/solaris/vm/os_solaris.hpp
index a22f0e9fe..65e837801 100644
--- a/src/os/solaris/vm/os_solaris.hpp
+++ b/src/os/solaris/vm/os_solaris.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -132,6 +132,9 @@ class Solaris {
static void set_SIGinterrupt(int newsig) { _SIGinterrupt = newsig; }
static void set_SIGasync(int newsig) { _SIGasync = newsig; }
+ typedef int (*pthread_setname_np_func_t)(pthread_t, const char*);
+ static pthread_setname_np_func_t _pthread_setname_np;
+
public:
// Large Page Support--ISM.
static bool largepage_range(char* addr, size_t size);
diff --git a/src/os/solaris/vm/os_solaris.inline.hpp b/src/os/solaris/vm/os_solaris.inline.hpp
index 921fcf7c0..8e095ab69 100644
--- a/src/os/solaris/vm/os_solaris.inline.hpp
+++ b/src/os/solaris/vm/os_solaris.inline.hpp
@@ -71,37 +71,6 @@ inline void os::bang_stack_shadow_pages() {
}
inline void os::dll_unload(void *lib) { ::dlclose(lib); }
-inline DIR* os::opendir(const char* dirname) {
- assert(dirname != NULL, "just checking");
- return ::opendir(dirname);
-}
-
-inline int os::readdir_buf_size(const char *path) {
- int size = pathconf(path, _PC_NAME_MAX);
- return (size < 0 ? MAXPATHLEN : size) + sizeof(dirent) + 1;
-}
-
-inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) {
- assert(dirp != NULL, "just checking");
-#if defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
- dirent* p;
- int status;
-
- if((status = ::readdir_r(dirp, dbuf, &p)) != 0) {
- errno = status;
- return NULL;
- } else
- return p;
-#else // defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
- return ::readdir_r(dirp, dbuf);
-#endif // defined(_LP64) || defined(_GNU_SOURCE) || _FILE_OFFSET_BITS==64
-}
-
-inline int os::closedir(DIR *dirp) {
- assert(dirp != NULL, "argument is NULL");
- return ::closedir(dirp);
-}
-
//////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/os/solaris/vm/perfMemory_solaris.cpp b/src/os/solaris/vm/perfMemory_solaris.cpp
index 7c6f61604..8af1b2441 100644
--- a/src/os/solaris/vm/perfMemory_solaris.cpp
+++ b/src/os/solaris/vm/perfMemory_solaris.cpp
@@ -524,9 +524,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
- while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+ while ((dentry = os::readdir(tmpdirp)) != NULL) {
// check if the directory entry is a hsperfdata file
if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -560,9 +559,8 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
- while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+ while ((udentry = os::readdir(subdirp)) != NULL) {
if (filename_to_pid(udentry->d_name) == vmid) {
struct stat statbuf;
@@ -606,11 +604,9 @@ static char* get_user_name_slow(int vmid, TRAPS) {
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -737,10 +733,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
-
errno = 0;
- while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+ while ((entry = os::readdir(dirp)) != NULL) {
pid_t pid = filename_to_pid(entry->d_name);
@@ -780,7 +774,6 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// close the directory and reset the current working directory
close_directory_secure_cwd(dirp, saved_cwd_fd);
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp
index ca798a295..06eebde00 100644
--- a/src/os/windows/vm/os_windows.cpp
+++ b/src/os/windows/vm/os_windows.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -744,8 +744,29 @@ int os::active_processor_count() {
}
void os::set_native_thread_name(const char *name) {
- // Not yet implemented.
- return;
+
+ // See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+ //
+ // Note that unfortunately this only works if the process
+ // is already attached to a debugger; debugger must observe
+ // the exception below to show the correct name.
+
+ const DWORD MS_VC_EXCEPTION = 0x406D1388;
+ struct {
+ DWORD dwType; // must be 0x1000
+ LPCSTR szName; // pointer to name (in user addr space)
+ DWORD dwThreadID; // thread ID (-1=caller thread)
+ DWORD dwFlags; // reserved for future use, must be zero
+ } info;
+
+ info.dwType = 0x1000;
+ info.szName = name;
+ info.dwThreadID = -1;
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info );
+ } __except(EXCEPTION_CONTINUE_EXECUTION) {}
}
bool os::distribute_processes(uint length, uint* distribution) {
@@ -1151,14 +1172,12 @@ os::opendir(const char *dirname)
return dirp;
}
-/* parameter dbuf unused on Windows */
-
struct dirent *
-os::readdir(DIR *dirp, dirent *dbuf)
+os::readdir(DIR *dirp)
{
assert(dirp != NULL, "just checking"); // hotspot change
if (dirp->handle == INVALID_HANDLE_VALUE) {
- return 0;
+ return NULL;
}
strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);
@@ -1166,7 +1185,7 @@ os::readdir(DIR *dirp, dirent *dbuf)
if (!FindNextFile(dirp->handle, &dirp->find_data)) {
if (GetLastError() == ERROR_INVALID_HANDLE) {
errno = EBADF;
- return 0;
+ return NULL;
}
FindClose(dirp->handle);
dirp->handle = INVALID_HANDLE_VALUE;
@@ -5040,7 +5059,7 @@ void Parker::unpark() {
// Run the specified command in a separate process. Return its exit value,
// or -1 on failure (e.g. can't create a new process).
-int os::fork_and_exec(char* cmd) {
+int os::fork_and_exec(char* cmd, bool use_vfork_if_available) {
STARTUPINFO si;
PROCESS_INFORMATION pi;
diff --git a/src/os/windows/vm/os_windows.inline.hpp b/src/os/windows/vm/os_windows.inline.hpp
index 30ce4682e..5dac11c90 100644
--- a/src/os/windows/vm/os_windows.inline.hpp
+++ b/src/os/windows/vm/os_windows.inline.hpp
@@ -65,14 +65,6 @@ inline bool os::allocate_stack_guard_pages() {
return true;
}
-inline int os::readdir_buf_size(const char *path)
-{
- /* As Windows doesn't use the directory entry buffer passed to
- os::readdir() this can be as short as possible */
-
- return 1;
-}
-
// Bang the shadow pages if they need to be touched to be mapped.
inline void os::bang_stack_shadow_pages() {
// Write to each page of our new frame to force OS mapping.
diff --git a/src/os/windows/vm/perfMemory_windows.cpp b/src/os/windows/vm/perfMemory_windows.cpp
index b32fd9a15..c4cf8c1d5 100644
--- a/src/os/windows/vm/perfMemory_windows.cpp
+++ b/src/os/windows/vm/perfMemory_windows.cpp
@@ -316,9 +316,8 @@ static char* get_user_name_slow(int vmid) {
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
- while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
+ while ((dentry = os::readdir(tmpdirp)) != NULL) {
// check if the directory entry is a hsperfdata file
if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) {
@@ -351,9 +350,8 @@ static char* get_user_name_slow(int vmid) {
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
- while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
+ while ((udentry = os::readdir(subdirp)) != NULL) {
if (filename_to_pid(udentry->d_name) == vmid) {
struct stat statbuf;
@@ -405,11 +403,9 @@ static char* get_user_name_slow(int vmid) {
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(latest_user);
}
@@ -639,9 +635,8 @@ static void cleanup_sharedmem_resources(const char* dirname) {
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
- while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
+ while ((entry = os::readdir(dirp)) != NULL) {
int pid = filename_to_pid(entry->d_name);
@@ -682,7 +677,6 @@ static void cleanup_sharedmem_resources(const char* dirname) {
errno = 0;
}
os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// create a file mapping object with the requested name, and size
diff --git a/src/share/vm/adlc/adlparse.cpp b/src/share/vm/adlc/adlparse.cpp
index 54bff63ad..31955ff7d 100644
--- a/src/share/vm/adlc/adlparse.cpp
+++ b/src/share/vm/adlc/adlparse.cpp
@@ -2868,7 +2868,8 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) {
const char* param = NULL;
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
- OperandForm* opForm = (OperandForm*) inst._localNames[param];
+ OpClassForm* opForm = inst._localNames[param]->is_opclass();
+ assert(opForm != NULL, "sanity");
encoding->add_parameter(opForm->_ident, param);
}
@@ -3338,7 +3339,8 @@ void ADLParser::constant_parse(InstructForm& inst) {
const char* param = NULL;
inst._parameters.reset();
while ((param = inst._parameters.iter()) != NULL) {
- OperandForm* opForm = (OperandForm*) inst._localNames[param];
+ OpClassForm* opForm = inst._localNames[param]->is_opclass();
+ assert(opForm != NULL, "sanity");
encoding->add_parameter(opForm->_ident, param);
}
diff --git a/src/share/vm/adlc/dfa.cpp b/src/share/vm/adlc/dfa.cpp
index 80ef1af36..e8d1c5d71 100644
--- a/src/share/vm/adlc/dfa.cpp
+++ b/src/share/vm/adlc/dfa.cpp
@@ -757,19 +757,27 @@ const char *Expr::compute_expr(const Expr *c1, const Expr *c2) {
}
int Expr::compute_min(const Expr *c1, const Expr *c2) {
- int result = c1->_min_value + c2->_min_value;
- assert( result >= 0, "Invalid cost computation");
+ int v1 = c1->_min_value;
+ int v2 = c2->_min_value;
+ assert(0 <= v2 && v2 <= Expr::Max, "sanity");
+ assert(v1 <= Expr::Max - v2, "Invalid cost computation");
- return result;
+ return v1 + v2;
}
+
int Expr::compute_max(const Expr *c1, const Expr *c2) {
- int result = c1->_max_value + c2->_max_value;
- if( result < 0 ) { // check for overflow
- result = Expr::Max;
+ int v1 = c1->_max_value;
+ int v2 = c2->_max_value;
+
+ // Check for overflow without producing UB. If v2 is positive
+ // and not larger than Max, the subtraction cannot underflow.
+ assert(0 <= v2 && v2 <= Expr::Max, "sanity");
+ if (v1 > Expr::Max - v2) {
+ return Expr::Max;
}
- return result;
+ return v1 + v2;
}
void Expr::print() const {
diff --git a/src/share/vm/adlc/formssel.cpp b/src/share/vm/adlc/formssel.cpp
index 36914d363..fd80ba24b 100644
--- a/src/share/vm/adlc/formssel.cpp
+++ b/src/share/vm/adlc/formssel.cpp
@@ -921,7 +921,8 @@ void InstructForm::build_components() {
const char *name;
const char *kill_name = NULL;
for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {
- OperandForm *opForm = (OperandForm*)_localNames[name];
+ OpClassForm *opForm = _localNames[name]->is_opclass();
+ assert(opForm != NULL, "sanity");
Effect* e = NULL;
{
@@ -938,7 +939,8 @@ void InstructForm::build_components() {
// complex so simply enforce the restriction during parse.
if (kill_name != NULL &&
e->isa(Component::TEMP) && !e->isa(Component::DEF)) {
- OperandForm* kill = (OperandForm*)_localNames[kill_name];
+ OpClassForm* kill = _localNames[kill_name]->is_opclass();
+ assert(kill != NULL, "sanity");
globalAD->syntax_err(_linenum, "%s: %s %s must be at the end of the argument list\n",
_ident, kill->_ident, kill_name);
} else if (e->isa(Component::KILL) && !e->isa(Component::USE)) {
@@ -2339,7 +2341,8 @@ void OperandForm::build_components() {
// Add parameters that "do not appear in match rule".
const char *name;
for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {
- OperandForm *opForm = (OperandForm*)_localNames[name];
+ OpClassForm *opForm = _localNames[name]->is_opclass();
+ assert(opForm != NULL, "sanity");
if ( _components.operand_position(name) == -1 ) {
_components.insert(name, opForm->_ident, Component::INVALID, false);
diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp
index 2a4373ba0..21cd08da9 100644
--- a/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -2305,6 +2305,10 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
// We can have generate one runtime check here. Let's start with
// the offset check.
+ // Allocate temp register to src and load it here, otherwise
+ // control flow below may confuse register allocator.
+ LIR_Opr src_reg = new_register(T_OBJECT);
+ __ move(src.result(), src_reg);
if (gen_offset_check) {
// if (offset != referent_offset) -> continue
// If offset is an int then we can do the comparison with the
@@ -2327,14 +2331,14 @@ void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
if (gen_source_check) {
// offset is a const and equals referent offset
// if (source == null) -> continue
- __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL));
+ __ cmp(lir_cond_equal, src_reg, LIR_OprFact::oopConst(NULL));
__ branch(lir_cond_equal, T_OBJECT, Lcont->label());
}
LIR_Opr src_klass = new_register(T_OBJECT);
if (gen_type_check) {
// We have determined that offset == referent_offset && src != null.
// if (src->_klass->_reference_type == REF_NONE) -> continue
- __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
+ __ move(new LIR_Address(src_reg, oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
LIR_Opr reference_type = new_register(T_INT);
__ move(reference_type_addr, reference_type);
diff --git a/src/share/vm/c1/c1_Optimizer.cpp b/src/share/vm/c1/c1_Optimizer.cpp
index f366462f6..a2ba0e376 100644
--- a/src/share/vm/c1/c1_Optimizer.cpp
+++ b/src/share/vm/c1/c1_Optimizer.cpp
@@ -175,6 +175,12 @@ void CE_Eliminator::block_do(BlockBegin* block) {
for_each_phi_fun(t_block, phi, return; );
for_each_phi_fun(f_block, phi, return; );
+ // Only replace safepoint gotos if state_before information is available (if is a safepoint)
+ bool is_safepoint = if_->is_safepoint();
+ if (!is_safepoint && (t_goto->is_safepoint() || f_goto->is_safepoint())) {
+ return;
+ }
+
// 2) substitute conditional expression
// with an IfOp followed by a Goto
// cut if_ away and get node before
@@ -203,7 +209,7 @@ void CE_Eliminator::block_do(BlockBegin* block) {
// append Goto to successor
ValueStack* state_before = if_->state_before();
- Goto* goto_ = new Goto(sux, state_before, if_->is_safepoint() || t_goto->is_safepoint() || f_goto->is_safepoint());
+ Goto* goto_ = new Goto(sux, state_before, is_safepoint);
// prepare state for Goto
ValueStack* goto_state = if_state;
diff --git a/src/share/vm/ci/bcEscapeAnalyzer.cpp b/src/share/vm/ci/bcEscapeAnalyzer.cpp
index 4c4db3e85..2b9e0e514 100644
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp
@@ -1170,45 +1170,43 @@ void BCEscapeAnalyzer::iterate_blocks(Arena *arena) {
}
}
-bool BCEscapeAnalyzer::do_analysis() {
+void BCEscapeAnalyzer::do_analysis() {
Arena* arena = CURRENT_ENV->arena();
// identify basic blocks
_methodBlocks = _method->get_method_blocks();
iterate_blocks(arena);
- // TEMPORARY
- return true;
}
vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
vmIntrinsics::ID iid = method()->intrinsic_id();
-
if (iid == vmIntrinsics::_getClass ||
iid == vmIntrinsics::_fillInStackTrace ||
- iid == vmIntrinsics::_hashCode)
+ iid == vmIntrinsics::_hashCode) {
return iid;
- else
+ } else {
return vmIntrinsics::_none;
+ }
}
-bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
+void BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
ArgumentMap arg;
arg.clear();
switch (iid) {
- case vmIntrinsics::_getClass:
- _return_local = false;
- break;
- case vmIntrinsics::_fillInStackTrace:
- arg.set(0); // 'this'
- set_returned(arg);
- break;
- case vmIntrinsics::_hashCode:
- // initialized state is correct
- break;
+ case vmIntrinsics::_getClass:
+ _return_local = false;
+ _return_allocated = false;
+ break;
+ case vmIntrinsics::_fillInStackTrace:
+ arg.set(0); // 'this'
+ set_returned(arg);
+ break;
+ case vmIntrinsics::_hashCode:
+ // initialized state is correct
+ break;
default:
assert(false, "unexpected intrinsic");
}
- return true;
}
void BCEscapeAnalyzer::initialize() {
@@ -1279,7 +1277,7 @@ void BCEscapeAnalyzer::compute_escape_info() {
vmIntrinsics::ID iid = known_intrinsic();
// check if method can be analyzed
- if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized()
+ if (iid == vmIntrinsics::_none && (method()->is_abstract() || method()->is_native() || !method()->holder()->is_initialized()
|| _level > MaxBCEAEstimateLevel
|| method()->code_size() > MaxBCEAEstimateSize)) {
if (BCEATraceLevel >= 1) {
@@ -1312,8 +1310,6 @@ void BCEscapeAnalyzer::compute_escape_info() {
tty->print_cr(" (%d bytes)", method()->code_size());
}
- bool success;
-
initialize();
// Do not scan method if it has no object parameters and
@@ -1329,9 +1325,9 @@ void BCEscapeAnalyzer::compute_escape_info() {
}
if (iid != vmIntrinsics::_none)
- success = compute_escape_for_intrinsic(iid);
+ compute_escape_for_intrinsic(iid);
else {
- success = do_analysis();
+ do_analysis();
}
// don't store interprocedural escape information if it introduces
diff --git a/src/share/vm/ci/bcEscapeAnalyzer.hpp b/src/share/vm/ci/bcEscapeAnalyzer.hpp
index 74a0d3106..acca5a210 100644
--- a/src/share/vm/ci/bcEscapeAnalyzer.hpp
+++ b/src/share/vm/ci/bcEscapeAnalyzer.hpp
@@ -101,8 +101,8 @@ class BCEscapeAnalyzer : public ResourceObj {
void clear_escape_info();
void compute_escape_info();
vmIntrinsics::ID known_intrinsic();
- bool compute_escape_for_intrinsic(vmIntrinsics::ID iid);
- bool do_analysis();
+ void compute_escape_for_intrinsic(vmIntrinsics::ID iid);
+ void do_analysis();
void read_escape_info();
diff --git a/src/share/vm/ci/ciStreams.cpp b/src/share/vm/ci/ciStreams.cpp
index 76520fdff..a4eaf4739 100644
--- a/src/share/vm/ci/ciStreams.cpp
+++ b/src/share/vm/ci/ciStreams.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -361,14 +361,14 @@ int ciBytecodeStream::get_method_index() {
ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_signature_result) {
VM_ENTRY_MARK;
ciEnv* env = CURRENT_ENV;
- constantPoolHandle cpool(_method->get_Method()->constants());
+ constantPoolHandle cpool(THREAD, _method->get_Method()->constants());
ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
will_link = m->is_loaded();
// Use the MethodType stored in the CP cache to create a signature
// with correct types (in respect to class loaders).
if (has_method_type()) {
- ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index()));
+ ciSymbol* sig_sym = env->get_symbol(cpool->symbol_at(get_method_signature_index(cpool)));
ciKlass* pool_holder = env->get_klass(cpool->pool_holder());
ciMethodType* method_type = get_method_type();
ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type);
@@ -465,9 +465,8 @@ int ciBytecodeStream::get_method_holder_index() {
// Get the constant pool index of the signature of the method
// referenced by the current bytecode. Used for generating
// deoptimization information.
-int ciBytecodeStream::get_method_signature_index() {
+int ciBytecodeStream::get_method_signature_index(const constantPoolHandle& cpool) {
GUARDED_VM_ENTRY(
- ConstantPool* cpool = _holder->get_instanceKlass()->constants();
const int method_index = get_method_index();
const int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
return cpool->signature_ref_index_at(name_and_type_index);
diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
index 091aa1bdf..07e573b59 100644
--- a/src/share/vm/ci/ciStreams.hpp
+++ b/src/share/vm/ci/ciStreams.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -264,7 +264,7 @@ public:
ciMethodType* get_method_type();
ciKlass* get_declared_method_holder();
int get_method_holder_index();
- int get_method_signature_index();
+ int get_method_signature_index(const constantPoolHandle& cpool);
// Get the resolved references arrays from the constant pool
ciObjArray* get_resolved_references();
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
index 1de221359..7f0e82071 100644
--- a/src/share/vm/classfile/vmSymbols.hpp
+++ b/src/share/vm/classfile/vmSymbols.hpp
@@ -832,21 +832,21 @@
do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \
do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
- do_name( encryptBlock_name, "encryptBlock") \
- do_name( decryptBlock_name, "decryptBlock") \
+ do_name( encryptBlock_name, "implEncryptBlock") \
+ do_name( decryptBlock_name, "implDecryptBlock") \
do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \
\
do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \
do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
- do_name( encrypt_name, "encrypt") \
- do_name( decrypt_name, "decrypt") \
+ do_name( encrypt_name, "implEncrypt") \
+ do_name( decrypt_name, "implDecrypt") \
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
\
/* support for sun.security.provider.SHA */ \
do_class(sun_security_provider_sha, "sun/security/provider/SHA") \
do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \
- do_name( implCompress_name, "implCompress") \
+ do_name( implCompress_name, "implCompress0") \
do_signature(implCompress_signature, "([BI)V") \
\
/* support for sun.security.provider.SHA2 */ \
@@ -860,7 +860,7 @@
/* support for sun.security.provider.DigestBase */ \
do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \
do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \
- do_name( implCompressMB_name, "implCompressMultiBlock") \
+ do_name( implCompressMB_name, "implCompressMultiBlock0") \
do_signature(implCompressMB_signature, "([BII)I") \
\
/* support for java.util.zip */ \
diff --git a/src/share/vm/code/codeCache.cpp b/src/share/vm/code/codeCache.cpp
index 9e5b7e98c..5f9792d8f 100644
--- a/src/share/vm/code/codeCache.cpp
+++ b/src/share/vm/code/codeCache.cpp
@@ -336,16 +336,19 @@ void CodeCache::blobs_do(CodeBlobClosure* f) {
}
// Walk the list of methods which might contain non-perm oops.
-void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) {
+void CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure* f) {
assert_locked_or_safepoint(CodeCache_lock);
if (UseG1GC) {
return;
}
+ const bool fix_relocations = f->fix_relocations();
debug_only(mark_scavenge_root_nmethods());
- for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
+ nmethod* prev = NULL;
+ nmethod* cur = scavenge_root_nmethods();
+ while (cur != NULL) {
debug_only(cur->clear_scavenge_root_marked());
assert(cur->scavenge_root_not_marked(), "");
assert(cur->on_scavenge_root_list(), "else shouldn't be on this list");
@@ -360,6 +363,18 @@ void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) {
// Perform cur->oops_do(f), maybe just once per nmethod.
f->do_code_blob(cur);
}
+ nmethod* const next = cur->scavenge_root_link();
+ // The scavengable nmethod list must contain all methods with scavengable
+ // oops. It is safe to include more nmethod on the list, but we do not
+ // expect any live non-scavengable nmethods on the list.
+ if (fix_relocations) {
+ if (!is_live || !cur->detect_scavenge_root_oops()) {
+ unlink_scavenge_root_nmethod(cur, prev);
+ } else {
+ prev = cur;
+ }
+ }
+ cur = next;
}
// Check for stray marks.
@@ -379,6 +394,24 @@ void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
print_trace("add_scavenge_root", nm);
}
+void CodeCache::unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev) {
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ assert((prev == NULL && scavenge_root_nmethods() == nm) ||
+ (prev != NULL && prev->scavenge_root_link() == nm), "precondition");
+
+ assert(!UseG1GC, "G1 does not use the scavenge_root_nmethods list");
+
+ print_trace("unlink_scavenge_root", nm);
+ if (prev == NULL) {
+ set_scavenge_root_nmethods(nm->scavenge_root_link());
+ } else {
+ prev->set_scavenge_root_link(nm->scavenge_root_link());
+ }
+ nm->set_scavenge_root_link(NULL);
+ nm->clear_on_scavenge_root_list();
+}
+
void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
@@ -387,20 +420,13 @@ void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
}
print_trace("drop_scavenge_root", nm);
- nmethod* last = NULL;
- nmethod* cur = scavenge_root_nmethods();
- while (cur != NULL) {
- nmethod* next = cur->scavenge_root_link();
+ nmethod* prev = NULL;
+ for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
if (cur == nm) {
- if (last != NULL)
- last->set_scavenge_root_link(next);
- else set_scavenge_root_nmethods(next);
- nm->set_scavenge_root_link(NULL);
- nm->clear_on_scavenge_root_list();
+ unlink_scavenge_root_nmethod(cur, prev);
return;
}
- last = cur;
- cur = next;
+ prev = cur;
}
assert(false, "should have been on list");
}
@@ -429,11 +455,7 @@ void CodeCache::prune_scavenge_root_nmethods() {
} else {
// Prune it from the list, so we don't have to look at it any more.
print_trace("prune_scavenge_root", cur);
- cur->set_scavenge_root_link(NULL);
- cur->clear_on_scavenge_root_list();
- if (last != NULL)
- last->set_scavenge_root_link(next);
- else set_scavenge_root_nmethods(next);
+ unlink_scavenge_root_nmethod(cur, last);
}
cur = next;
}
diff --git a/src/share/vm/code/codeCache.hpp b/src/share/vm/code/codeCache.hpp
index f098284a3..415f67750 100644
--- a/src/share/vm/code/codeCache.hpp
+++ b/src/share/vm/code/codeCache.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -65,6 +65,10 @@ class CodeCache : AllStatic {
static int _codemem_full_count;
+ static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; }
+ static void prune_scavenge_root_nmethods();
+ static void unlink_scavenge_root_nmethod(nmethod* nm, nmethod* prev);
+
public:
// Initialization
@@ -135,13 +139,17 @@ class CodeCache : AllStatic {
// to "true" iff some code got unloaded.
static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
- static void scavenge_root_nmethods_do(CodeBlobClosure* f);
+
+ // Apply f to every live code blob in scavengable nmethods. Prune nmethods
+ // from the list of scavengable nmethods if f->fix_relocations() and a nmethod
+ // no longer has scavengable oops. If f->fix_relocations(), then f must copy
+ // objects to their new location immediately to avoid fixing nmethods on the
+ // basis of the old object locations.
+ static void scavenge_root_nmethods_do(CodeBlobToOopClosure* f);
static nmethod* scavenge_root_nmethods() { return _scavenge_root_nmethods; }
- static void set_scavenge_root_nmethods(nmethod* nm) { _scavenge_root_nmethods = nm; }
static void add_scavenge_root_nmethod(nmethod* nm);
static void drop_scavenge_root_nmethod(nmethod* nm);
- static void prune_scavenge_root_nmethods();
// Printing/debugging
static void print(); // prints summary
diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp
index 2b8ed3624..9e4edf342 100644
--- a/src/share/vm/code/nmethod.cpp
+++ b/src/share/vm/code/nmethod.cpp
@@ -1392,7 +1392,6 @@ void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
assert(_method == NULL, "Tautology");
set_osr_link(NULL);
- //set_scavenge_root_link(NULL); // done by prune_scavenge_root_nmethods
NMethodSweeper::report_state_change(this);
}
@@ -2176,6 +2175,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
}
} else if (iter.type() == relocInfo::virtual_call_type) {
// Check compiledIC holders associated with this nmethod
+ ResourceMark rm;
CompiledIC *ic = CompiledIC_at(&iter);
if (ic->is_icholder_call()) {
CompiledICHolder* cichk = ic->cached_icholder();
diff --git a/src/share/vm/compiler/compileBroker.cpp b/src/share/vm/compiler/compileBroker.cpp
index 104aaaef7..da380e622 100644
--- a/src/share/vm/compiler/compileBroker.cpp
+++ b/src/share/vm/compiler/compileBroker.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -751,7 +751,9 @@ CompileTask* CompileQueue::get() {
No_Safepoint_Verifier nsv;
task = CompilationPolicy::policy()->select_task(this);
}
- remove(task);
+ if (task != NULL) {
+ remove(task);
+ }
purge_stale_tasks(); // may temporarily release MCQ lock
return task;
}
diff --git a/src/share/vm/compiler/compileBroker.hpp b/src/share/vm/compiler/compileBroker.hpp
index 7a381cd3a..ad37ff173 100644
--- a/src/share/vm/compiler/compileBroker.hpp
+++ b/src/share/vm/compiler/compileBroker.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -339,7 +339,6 @@ class CompileBroker: AllStatic {
static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS);
static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count);
- static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level);
static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level);
static bool is_compile_blocking ();
static void preload_classes (methodHandle method, TRAPS);
@@ -389,6 +388,7 @@ class CompileBroker: AllStatic {
return NULL;
}
+ static bool compilation_is_complete(methodHandle method, int osr_bci, int comp_level);
static bool compilation_is_in_queue(methodHandle method);
static int queue_size(int comp_level) {
CompileQueue *q = compile_queue(comp_level);
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index f42f1c9e7..1872e72e3 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -9541,6 +9541,7 @@ TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorSt
case CMSCollector::InitialMarking:
initialize(true /* fullGC */ ,
cause /* cause of the GC */,
+ true /* allMemoryPoolsAffected */,
true /* recordGCBeginTime */,
true /* recordPreGCUsage */,
false /* recordPeakUsage */,
@@ -9553,6 +9554,7 @@ TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorSt
case CMSCollector::FinalMarking:
initialize(true /* fullGC */ ,
cause /* cause of the GC */,
+ true /* allMemoryPoolsAffected */,
false /* recordGCBeginTime */,
false /* recordPreGCUsage */,
false /* recordPeakUsage */,
@@ -9565,6 +9567,7 @@ TraceCMSMemoryManagerStats::TraceCMSMemoryManagerStats(CMSCollector::CollectorSt
case CMSCollector::Sweeping:
initialize(true /* fullGC */ ,
cause /* cause of the GC */,
+ true /* allMemoryPoolsAffected */,
false /* recordGCBeginTime */,
false /* recordPreGCUsage */,
true /* recordPeakUsage */,
diff --git a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
index f6ef67081..ead98e24a 100644
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
+++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
@@ -447,8 +447,6 @@ G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
}
HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
- assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
- "just checking");
_next_offset_index = _array->index_for_raw(_bottom);
_next_offset_index++;
_next_offset_threshold =
@@ -457,8 +455,6 @@ HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
}
void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
- assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
- "just checking");
size_t bottom_index = _array->index_for_raw(_bottom);
assert(_array->address_for_index_raw(bottom_index) == _bottom,
"Precondition of call");
@@ -466,8 +462,6 @@ void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
}
HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
- assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
- "just checking");
_next_offset_index = _array->index_for(_bottom);
_next_offset_index++;
_next_offset_threshold =
diff --git a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
index e0de6f15d..2b360f0cd 100644
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
+++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
@@ -145,7 +145,7 @@ private:
// Array for keeping offsets for retrieving object start fast given an
// address.
- u_char* _offset_array; // byte array keeping backwards offsets
+ volatile u_char* _offset_array; // byte array keeping backwards offsets
void check_offset(size_t offset, const char* msg) const {
assert(offset <= N_words,
@@ -158,9 +158,7 @@ private:
// For performance these have to devolve to array accesses in product builds.
inline u_char offset_array(size_t index) const;
- void set_offset_array_raw(size_t index, u_char offset) {
- _offset_array[index] = offset;
- }
+ inline void set_offset_array_raw(size_t index, u_char offset);
inline void set_offset_array(size_t index, u_char offset);
diff --git a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
index be5cf309a..70646a417 100644
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
+++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
@@ -63,6 +63,10 @@ u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
return _offset_array[index];
}
+inline void G1BlockOffsetSharedArray::set_offset_array_raw(size_t index, u_char offset) {
+ _offset_array[index] = offset;
+}
+
void G1BlockOffsetSharedArray::set_offset_array(size_t index, u_char offset) {
check_index(index, "index out of range");
set_offset_array_raw(index, offset);
@@ -81,7 +85,7 @@ void G1BlockOffsetSharedArray::set_offset_array(size_t left, size_t right, u_cha
assert(left <= right, "indexes out of order");
size_t num_cards = right - left + 1;
if (UseMemSetInBOT) {
- memset(&_offset_array[left], offset, num_cards);
+ memset(const_cast<u_char*> (&_offset_array[left]), offset, num_cards);
} else {
size_t i = left;
const size_t end = i + num_cards;
diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index d1ca35e42..aa6bbc81a 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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
@@ -2790,6 +2790,7 @@ HeapRegion* G1CollectedHeap::start_cset_region_for_worker(uint worker_i) {
// Previous workers starting region is valid
// so let's iterate from there
start_ind = (cs_size * (worker_i - 1)) / active_workers;
+ OrderAccess::loadload();
result = _worker_cset_start_region[worker_i - 1];
}
@@ -4008,7 +4009,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
log_gc_header();
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
- TraceMemoryManagerStats tms(false /* fullGC */, gc_cause());
+ TraceMemoryManagerStats tms(false /* fullGC */, gc_cause(),
+ yc_type() == Mixed /* allMemoryPoolsAffected */);
// If the secondary_free_list is not empty, append it to the
// free_list. No need to wait for the cleanup operation to finish;
diff --git a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
index 69084775e..be4cebb54 100644
--- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
+++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
@@ -237,12 +237,6 @@ class G1AdjustPointersClosure: public HeapRegionClosure {
}
};
-class G1AlwaysTrueClosure: public BoolObjectClosure {
-public:
- bool do_object_b(oop p) { return true; }
-};
-static G1AlwaysTrueClosure always_true;
-
void G1MarkSweep::mark_sweep_phase3() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
@@ -266,7 +260,7 @@ void G1MarkSweep::mark_sweep_phase3() {
// Now adjust pointers in remaining weak roots. (All of which should
// have been cleared if they pointed to non-surviving objects.)
- JNIHandles::weak_oops_do(&always_true, &GenMarkSweep::adjust_pointer_closure);
+ JNIHandles::weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
if (G1StringDedup::is_enabled()) {
G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
index 114d39dfe..5f4f98c83 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
@@ -594,13 +594,6 @@ void PSMarkSweep::mark_sweep_phase2() {
old_gen->precompact();
}
-// This should be moved to the shared markSweep code!
-class PSAlwaysTrueClosure: public BoolObjectClosure {
-public:
- bool do_object_b(oop p) { return true; }
-};
-static PSAlwaysTrueClosure always_true;
-
void PSMarkSweep::mark_sweep_phase3() {
// Adjust the pointers to reflect the new locations
GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id());
@@ -630,7 +623,7 @@ void PSMarkSweep::mark_sweep_phase3() {
// Now adjust pointers in remaining weak roots. (All of which should
// have been cleared if they pointed to non-surviving objects.)
// Global (weak) JNI handles
- JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
+ JNIHandles::weak_oops_do(adjust_pointer_closure());
CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
CodeCache::blobs_do(&adjust_from_blobs);
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
index b2c3b06cc..bdf254d61 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -2441,13 +2441,6 @@ void PSParallelCompact::follow_class_loader(ParCompactionManager* cm,
cld->oops_do(&mark_and_push_closure, &follow_klass_closure, true);
}
-// This should be moved to the shared markSweep code!
-class PSAlwaysTrueClosure: public BoolObjectClosure {
-public:
- bool do_object_b(oop p) { return true; }
-};
-static PSAlwaysTrueClosure always_true;
-
void PSParallelCompact::adjust_roots() {
// Adjust the pointers to reflect the new locations
GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
@@ -2470,7 +2463,7 @@ void PSParallelCompact::adjust_roots() {
// Now adjust pointers in remaining weak roots. (All of which should
// have been cleared if they pointed to non-surviving objects.)
// Global (weak) JNI handles
- JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
+ JNIHandles::weak_oops_do(adjust_pointer_closure());
CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
CodeCache::blobs_do(&adjust_from_blobs);
diff --git a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
index 6d728ccf5..5d7e99bd2 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -636,12 +636,6 @@ bool PSScavenge::invoke_no_policy() {
NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
- {
- GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer, _gc_tracer.gc_id());
-
- CodeCache::prune_scavenge_root_nmethods();
- }
-
// Re-verify object start arrays
if (VerifyObjectStartArray &&
VerifyAfterGC) {
diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp
index f7c9591d9..ddf0a860c 100644
--- a/src/share/vm/memory/genCollectedHeap.cpp
+++ b/src/share/vm/memory/genCollectedHeap.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -619,7 +619,7 @@ void GenCollectedHeap::process_roots(bool activate_scope,
OopClosure* weak_roots,
CLDClosure* strong_cld_closure,
CLDClosure* weak_cld_closure,
- CodeBlobClosure* code_roots) {
+ CodeBlobToOopClosure* code_roots) {
StrongRootsScope srs(this, activate_scope);
// General roots.
@@ -638,7 +638,7 @@ void GenCollectedHeap::process_roots(bool activate_scope,
// Don't process them if they will be processed during the ClassLoaderDataGraph phase.
CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
// Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway
- CodeBlobClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
+ CodeBlobToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);
@@ -745,14 +745,8 @@ void GenCollectedHeap::gen_process_roots(int level,
}
-class AlwaysTrueClosure: public BoolObjectClosure {
-public:
- bool do_object_b(oop p) { return true; }
-};
-static AlwaysTrueClosure always_true;
-
void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {
- JNIHandles::weak_oops_do(&always_true, root_closure);
+ JNIHandles::weak_oops_do(root_closure);
for (int i = 0; i < _n_gens; i++) {
_gens[i]->ref_processor()->weak_oops_do(root_closure);
}
diff --git a/src/share/vm/memory/genCollectedHeap.hpp b/src/share/vm/memory/genCollectedHeap.hpp
index 58786eded..1a2fcaa06 100644
--- a/src/share/vm/memory/genCollectedHeap.hpp
+++ b/src/share/vm/memory/genCollectedHeap.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -416,7 +416,7 @@ public:
OopClosure* weak_roots,
CLDClosure* strong_cld_closure,
CLDClosure* weak_cld_closure,
- CodeBlobClosure* code_roots);
+ CodeBlobToOopClosure* code_roots);
void gen_process_roots(int level,
bool younger_gens_as_roots,
diff --git a/src/share/vm/memory/iterator.hpp b/src/share/vm/memory/iterator.hpp
index 6622e1310..62204eea7 100644
--- a/src/share/vm/memory/iterator.hpp
+++ b/src/share/vm/memory/iterator.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -219,6 +219,16 @@ class BoolObjectClosure : public Closure {
virtual bool do_object_b(oop obj) = 0;
};
+class AlwaysTrueClosure: public BoolObjectClosure {
+ public:
+ bool do_object_b(oop p) { return true; }
+};
+
+class AlwaysFalseClosure : public BoolObjectClosure {
+ public:
+ bool do_object_b(oop p) { return false; }
+};
+
// Applies an oop closure to all ref fields in objects iterated over in an
// object iteration.
class ObjectToOopClosure: public ObjectClosure {
@@ -291,9 +301,12 @@ class CodeBlobToOopClosure : public CodeBlobClosure {
protected:
void do_nmethod(nmethod* nm);
public:
+ // If fix_relocations(), then cl must copy objects to their new location immediately to avoid
+ // patching nmethods with the old locations.
CodeBlobToOopClosure(OopClosure* cl, bool fix_relocations) : _cl(cl), _fix_relocations(fix_relocations) {}
virtual void do_code_blob(CodeBlob* cb);
+ bool fix_relocations() const { return _fix_relocations; }
const static bool FixRelocations = true;
};
diff --git a/src/share/vm/memory/metaspace.cpp b/src/share/vm/memory/metaspace.cpp
index 64f1abd82..5f944d1ec 100644
--- a/src/share/vm/memory/metaspace.cpp
+++ b/src/share/vm/memory/metaspace.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -1422,7 +1422,15 @@ size_t MetaspaceGC::capacity_until_GC() {
return value;
}
-bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) {
+// Try to increase the _capacity_until_GC limit counter by v bytes.
+// Returns true if it succeeded. It may fail if either another thread
+// concurrently increased the limit or the new limit would be larger
+// than MaxMetaspaceSize.
+// On success, optionally returns new and old metaspace capacity in
+// new_cap_until_GC and old_cap_until_GC respectively.
+// On error, optionally sets can_retry to indicate whether if there is
+// actually enough space remaining to satisfy the request.
+bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC, bool* can_retry) {
assert_is_size_aligned(v, Metaspace::commit_alignment());
size_t capacity_until_GC = (size_t) _capacity_until_GC;
@@ -1433,6 +1441,17 @@ bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size
new_value = align_size_down(max_uintx, Metaspace::commit_alignment());
}
+ if (new_value > MaxMetaspaceSize) {
+ if (can_retry != NULL) {
+ *can_retry = false;
+ }
+ return false;
+ }
+
+ if (can_retry != NULL) {
+ *can_retry = true;
+ }
+
intptr_t expected = (intptr_t) capacity_until_GC;
intptr_t actual = Atomic::cmpxchg_ptr((intptr_t) new_value, &_capacity_until_GC, expected);
@@ -1520,7 +1539,7 @@ void MetaspaceGC::compute_new_size() {
const double min_tmp = used_after_gc / maximum_used_percentage;
size_t minimum_desired_capacity =
- (size_t)MIN2(min_tmp, double(max_uintx));
+ (size_t)MIN2(min_tmp, double(MaxMetaspaceSize));
// Don't shrink less than the initial generation size
minimum_desired_capacity = MAX2(minimum_desired_capacity,
MetaspaceSize);
@@ -1579,7 +1598,7 @@ void MetaspaceGC::compute_new_size() {
const double maximum_free_percentage = MaxMetaspaceFreeRatio / 100.0;
const double minimum_used_percentage = 1.0 - maximum_free_percentage;
const double max_tmp = used_after_gc / minimum_used_percentage;
- size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx));
+ size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(MaxMetaspaceSize));
maximum_desired_capacity = MAX2(maximum_desired_capacity,
MetaspaceSize);
if (PrintGCDetails && Verbose) {
@@ -3408,6 +3427,7 @@ MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype)
size_t before = 0;
size_t after = 0;
+ bool can_retry = true;
MetaWord* res;
bool incremented;
@@ -3415,9 +3435,9 @@ MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype)
// the HWM, an allocation is still attempted. This is because another thread must then
// have incremented the HWM and therefore the allocation might still succeed.
do {
- incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before);
+ incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before, &can_retry);
res = allocate(word_size, mdtype);
- } while (!incremented && res == NULL);
+ } while (!incremented && res == NULL && can_retry);
if (incremented) {
tracer()->report_gc_threshold(before, after,
diff --git a/src/share/vm/memory/metaspace.hpp b/src/share/vm/memory/metaspace.hpp
index e1979ff67..3920004a8 100644
--- a/src/share/vm/memory/metaspace.hpp
+++ b/src/share/vm/memory/metaspace.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -416,7 +416,8 @@ class MetaspaceGC : AllStatic {
static size_t capacity_until_GC();
static bool inc_capacity_until_GC(size_t v,
size_t* new_cap_until_GC = NULL,
- size_t* old_cap_until_GC = NULL);
+ size_t* old_cap_until_GC = NULL,
+ bool* can_retry = NULL);
static size_t dec_capacity_until_GC(size_t v);
static bool should_concurrent_collect() { return _should_concurrent_collect; }
diff --git a/src/share/vm/memory/referenceProcessor.cpp b/src/share/vm/memory/referenceProcessor.cpp
index 3c776f4b8..0f483d89e 100644
--- a/src/share/vm/memory/referenceProcessor.cpp
+++ b/src/share/vm/memory/referenceProcessor.cpp
@@ -275,11 +275,6 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
#ifndef PRODUCT
// Calculate the number of jni handles.
uint ReferenceProcessor::count_jni_refs() {
- class AlwaysAliveClosure: public BoolObjectClosure {
- public:
- virtual bool do_object_b(oop obj) { return true; }
- };
-
class CountHandleClosure: public OopClosure {
private:
int _count;
@@ -290,8 +285,7 @@ uint ReferenceProcessor::count_jni_refs() {
int count() { return _count; }
};
CountHandleClosure global_handle_count;
- AlwaysAliveClosure always_alive;
- JNIHandles::weak_oops_do(&always_alive, &global_handle_count);
+ JNIHandles::weak_oops_do(&global_handle_count);
return global_handle_count.count();
}
#endif
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
index 2cff42cc3..0204188ad 100644
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -147,7 +147,7 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
- data, len, (clss)->class_loader(), thread_type); \
+ data, len, (void *)(clss)->class_loader(), thread_type); \
}
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
@@ -160,7 +160,7 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
- data, len, (clss)->class_loader(), thread_type, wait); \
+ data, len, (void *)(clss)->class_loader(), thread_type, wait); \
}
#endif /* USDT2 */
@@ -2925,6 +2925,13 @@ void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_na
// On-stack replacement stuff
void InstanceKlass::add_osr_nmethod(nmethod* n) {
+#ifndef PRODUCT
+ if (TieredCompilation) {
+ nmethod * prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true);
+ assert(prev == NULL || !prev->is_in_use(),
+ "redundunt OSR recompilation detected. memory leak in CodeCache!");
+ }
+#endif
// only one compilation can be active
NEEDS_CLEANUP
// This is a short non-blocking critical region, so the no safepoint check is ok.
@@ -3046,7 +3053,9 @@ nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_le
osr = osr->osr_link();
}
OsrList_lock->unlock();
- if (best != NULL && best->comp_level() >= comp_level && match_level == false) {
+
+ assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set");
+ if (best != NULL && best->comp_level() >= comp_level) {
return best;
}
return NULL;
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
index a5f2eb346..444eadd38 100644
--- a/src/share/vm/oops/instanceKlass.hpp
+++ b/src/share/vm/oops/instanceKlass.hpp
@@ -225,6 +225,7 @@ class InstanceKlass: public Klass {
// _is_marked_dependent can be set concurrently, thus cannot be part of the
// _misc_flags.
bool _is_marked_dependent; // used for marking during flushing and deoptimization
+ bool _is_being_redefined; // used for locking redefinition
bool _has_unloaded_dependent;
enum {
@@ -667,6 +668,10 @@ class InstanceKlass: public Klass {
_nonstatic_oop_map_size = words;
}
+ // Redefinition locking. Class can only be redefined by one thread at a time.
+ bool is_being_redefined() const { return _is_being_redefined; }
+ void set_is_being_redefined(bool value) { _is_being_redefined = value; }
+
// RedefineClasses() support for previous versions:
void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
diff --git a/src/share/vm/oops/klass.hpp b/src/share/vm/oops/klass.hpp
index 9f612c3e7..df018923c 100644
--- a/src/share/vm/oops/klass.hpp
+++ b/src/share/vm/oops/klass.hpp
@@ -335,10 +335,11 @@ protected:
_lh_header_size_mask = right_n_bits(BitsPerByte), // shifted mask
_lh_array_tag_bits = 2,
_lh_array_tag_shift = BitsPerInt - _lh_array_tag_bits,
- _lh_array_tag_type_value = ~0x00, // 0xC0000000 >> 30
_lh_array_tag_obj_value = ~0x01 // 0x80000000 >> 30
};
+ static const unsigned int _lh_array_tag_type_value = 0Xffffffff; // ~0x00, // 0xC0000000 >> 30
+
static int layout_helper_size_in_bytes(jint lh) {
assert(lh > (jint)_lh_neutral_value, "must be instance");
return (int) lh & ~_lh_instance_slow_path_bit;
diff --git a/src/share/vm/oops/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp
index 315d97f3e..61dd4c21d 100644
--- a/src/share/vm/oops/klassVtable.cpp
+++ b/src/share/vm/oops/klassVtable.cpp
@@ -663,6 +663,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
Method* super_method = NULL;
InstanceKlass *holder = NULL;
Method* recheck_method = NULL;
+ bool found_pkg_prvt_method = false;
while (k != NULL) {
// lookup through the hierarchy for a method with matching name and sign.
super_method = InstanceKlass::cast(k)->lookup_method(name, signature);
@@ -684,12 +685,31 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
return false;
// else keep looking for transitive overrides
}
+ // If we get here then one of the super classes has a package private method
+ // that will not get overridden because it is in a different package. But,
+ // that package private method does "override" any matching methods in super
+ // interfaces, so there will be no miranda vtable entry created. So, set flag
+ // to TRUE for use below, in case there are no methods in super classes that
+ // this target method overrides.
+ assert(super_method->is_package_private(), "super_method must be package private");
+ assert(!superk->is_same_class_package(classloader(), classname),
+ "Must be different packages");
+ found_pkg_prvt_method = true;
}
// Start with lookup result and continue to search up
k = superk->super(); // haven't found an override match yet; continue to look
}
+ // If found_pkg_prvt_method is set, then the ONLY matching method in the
+ // superclasses is package private in another package. That matching method will
+ // prevent a miranda vtable entry from being created. Because the target method can not
+ // override the package private method in another package, then it needs to be the root
+ // for its own vtable entry.
+ if (found_pkg_prvt_method) {
+ return true;
+ }
+
// if the target method is public or protected it may have a matching
// miranda method in the super, whose entry it should re-use.
// Actually, to handle cases that javac would not generate, we need
@@ -697,7 +717,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
InstanceKlass *sk = InstanceKlass::cast(super);
if (sk->has_miranda_methods()) {
if (sk->lookup_method_in_all_interfaces(name, signature, Klass::find_defaults) != NULL) {
- return false; // found a matching miranda; we do not need a new entry
+ return false; // found a matching miranda; we do not need a new entry
}
}
return true; // found no match; we need a new entry
diff --git a/src/share/vm/opto/addnode.cpp b/src/share/vm/opto/addnode.cpp
index 045e4f209..1ec4c7cfc 100644
--- a/src/share/vm/opto/addnode.cpp
+++ b/src/share/vm/opto/addnode.cpp
@@ -344,8 +344,8 @@ Node *AddINode::Identity( PhaseTransform *phase ) {
const Type *AddINode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeInt *r0 = t0->is_int(); // Handy access
const TypeInt *r1 = t1->is_int();
- int lo = r0->_lo + r1->_lo;
- int hi = r0->_hi + r1->_hi;
+ int lo = java_add(r0->_lo, r1->_lo);
+ int hi = java_add(r0->_hi, r1->_hi);
if( !(r0->is_con() && r1->is_con()) ) {
// Not both constants, compute approximate result
if( (r0->_lo & r1->_lo) < 0 && lo >= 0 ) {
@@ -462,8 +462,8 @@ Node *AddLNode::Identity( PhaseTransform *phase ) {
const Type *AddLNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeLong *r0 = t0->is_long(); // Handy access
const TypeLong *r1 = t1->is_long();
- jlong lo = r0->_lo + r1->_lo;
- jlong hi = r0->_hi + r1->_hi;
+ jlong lo = java_add(r0->_lo, r1->_lo);
+ jlong hi = java_add(r0->_hi, r1->_hi);
if( !(r0->is_con() && r1->is_con()) ) {
// Not both constants, compute approximate result
if( (r0->_lo & r1->_lo) < 0 && lo >= 0 ) {
diff --git a/src/share/vm/opto/connode.cpp b/src/share/vm/opto/connode.cpp
index 604e971f9..ff56804df 100644
--- a/src/share/vm/opto/connode.cpp
+++ b/src/share/vm/opto/connode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -1083,7 +1083,11 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
+ Node *hook = new (phase->C) Node(1);
+ hook->init_req(0, cx); // Add a use to cx to prevent him from dying
Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
+ hook->del_req(0); // Just yank bogus edge
+ hook->destruct();
switch (op) {
case Op_AddI: return new (phase->C) AddLNode(cx, cy);
case Op_SubI: return new (phase->C) SubLNode(cx, cy);
diff --git a/src/share/vm/opto/divnode.cpp b/src/share/vm/opto/divnode.cpp
index 24f4fcb7e..e1a8ad558 100644
--- a/src/share/vm/opto/divnode.cpp
+++ b/src/share/vm/opto/divnode.cpp
@@ -131,7 +131,7 @@ static Node *transform_int_divide( PhaseGVN *phase, Node *dividend, jint divisor
}
// Add rounding to the shift to handle the sign bit
- int l = log2_intptr(d-1)+1;
+ int l = log2_jint(d-1)+1;
if (needs_rounding) {
// Divide-by-power-of-2 can be made into a shift, but you have to do
// more math for the rounding. You need to add 0 for positive
diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
index 16313f097..dabc7e758 100644
--- a/src/share/vm/opto/graphKit.cpp
+++ b/src/share/vm/opto/graphKit.cpp
@@ -1787,12 +1787,13 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p
// A better answer would be to separate out card marks from other memory.
// For now, return the input memory state, so that it can be reused
// after the call, if this call has restricted memory effects.
-Node* GraphKit::set_predefined_input_for_runtime_call(SafePointNode* call) {
+Node* GraphKit::set_predefined_input_for_runtime_call(SafePointNode* call, Node* narrow_mem) {
// Set fixed predefined input arguments
Node* memory = reset_memory();
+ Node* m = narrow_mem == NULL ? memory : narrow_mem;
call->init_req( TypeFunc::Control, control() );
call->init_req( TypeFunc::I_O, top() ); // does no i/o
- call->init_req( TypeFunc::Memory, memory ); // may gc ptrs
+ call->init_req( TypeFunc::Memory, m ); // may gc ptrs
call->init_req( TypeFunc::FramePtr, frameptr() );
call->init_req( TypeFunc::ReturnAdr, top() );
return memory;
@@ -2382,9 +2383,7 @@ Node* GraphKit::make_runtime_call(int flags,
} else {
assert(!wide_out, "narrow in => narrow out");
Node* narrow_mem = memory(adr_type);
- prev_mem = reset_memory();
- map()->set_memory(narrow_mem);
- set_predefined_input_for_runtime_call(call);
+ prev_mem = set_predefined_input_for_runtime_call(call, narrow_mem);
}
// Hook each parm in order. Stop looking at the first NULL.
diff --git a/src/share/vm/opto/graphKit.hpp b/src/share/vm/opto/graphKit.hpp
index c584cef75..7a363fd33 100644
--- a/src/share/vm/opto/graphKit.hpp
+++ b/src/share/vm/opto/graphKit.hpp
@@ -700,7 +700,7 @@ class GraphKit : public Phase {
void set_predefined_output_for_runtime_call(Node* call,
Node* keep_mem,
const TypePtr* hook_mem);
- Node* set_predefined_input_for_runtime_call(SafePointNode* call);
+ Node* set_predefined_input_for_runtime_call(SafePointNode* call, Node* narrow_mem = NULL);
// Replace the call with the current state of the kit. Requires
// that the call was generated with separate io_projs so that
diff --git a/src/share/vm/opto/ifnode.cpp b/src/share/vm/opto/ifnode.cpp
index 3101455e2..68f068d06 100644
--- a/src/share/vm/opto/ifnode.cpp
+++ b/src/share/vm/opto/ifnode.cpp
@@ -601,7 +601,7 @@ Node* IfNode::up_one_dom(Node *curr, bool linear_only) {
if( din4->is_Call() && // Handle a slow-path call on either arm
(din4 = din4->in(0)) )
din4 = din4->in(0);
- if( din3 == din4 && din3->is_If() )
+ if (din3 != NULL && din3 == din4 && din3->is_If()) // Regions not degraded to a copy
return din3; // Skip around diamonds
}
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 5f2bb3084..4bb5ca886 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -3803,7 +3803,7 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
}
// Now test the correct condition.
jint nval = (obj_array
- ? ((jint)Klass::_lh_array_tag_type_value
+ ? (jint)(Klass::_lh_array_tag_type_value
<< Klass::_lh_array_tag_shift)
: Klass::_lh_neutral_value);
Node* cmp = _gvn.transform(new(C) CmpINode(layout_val, intcon(nval)));
@@ -6759,10 +6759,18 @@ bool LibraryCallKit::inline_sha_implCompressMB(Node* digestBase_obj, ciInstanceK
if (state == NULL) return false;
// Call the stub.
- Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
- OptoRuntime::digestBase_implCompressMB_Type(),
- stubAddr, stubName, TypePtr::BOTTOM,
- src_start, state, ofs, limit);
+ Node *call;
+ if (CCallingConventionRequiresIntsAsLongs) {
+ call = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::digestBase_implCompressMB_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ src_start, state, ofs XTOP, limit XTOP);
+ } else {
+ call = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::digestBase_implCompressMB_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ src_start, state, ofs, limit);
+ }
// return ofs (int)
Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms));
set_result(result);
diff --git a/src/share/vm/opto/loopPredicate.cpp b/src/share/vm/opto/loopPredicate.cpp
index 5d2b469d4..db7c10846 100644
--- a/src/share/vm/opto/loopPredicate.cpp
+++ b/src/share/vm/opto/loopPredicate.cpp
@@ -611,7 +611,11 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
const TypeInt* idx_type = TypeInt::INT;
if ((stride > 0) == (scale > 0) == upper) {
if (TraceLoopPredicate) {
- predString->print(limit->is_Con() ? "(%d " : "(limit ", con_limit);
+ if (limit->is_Con()) {
+ predString->print("(%d ", con_limit);
+ } else {
+ predString->print("(limit ");
+ }
predString->print("- %d) ", stride);
}
// Check if (limit - stride) may overflow
@@ -639,7 +643,11 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
register_new_node(max_idx_expr, ctrl);
} else {
if (TraceLoopPredicate) {
- predString->print(init->is_Con() ? "%d " : "init ", con_init);
+ if (init->is_Con()) {
+ predString->print("%d ", con_init);
+ } else {
+ predString->print("init ");
+ }
}
idx_type = _igvn.type(init)->isa_int();
max_idx_expr = init;
@@ -675,7 +683,11 @@ BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
if (offset && (!offset->is_Con() || con_offset != 0)){
if (TraceLoopPredicate) {
- predString->print(offset->is_Con() ? "+ %d " : "+ offset", con_offset);
+ if (offset->is_Con()) {
+ predString->print("+ %d ", con_offset);
+ } else {
+ predString->print("+ offset");
+ }
}
// Check if (max_idx_expr + offset) may overflow
const TypeInt* offset_type = _igvn.type(offset)->isa_int();
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index e39ffcb60..7ef67c155 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -1310,8 +1310,8 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
limit = new (C) Opaque2Node( C, limit );
register_new_node( limit, opaq_ctrl );
}
- if (stride_con > 0 && ((limit_type->_lo - stride_con) < limit_type->_lo) ||
- stride_con < 0 && ((limit_type->_hi - stride_con) > limit_type->_hi)) {
+ if (stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo) ||
+ stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi)) {
// No underflow.
new_limit = new (C) SubINode(limit, stride);
} else {
@@ -1537,13 +1537,20 @@ bool IdealLoopTree::dominates_backedge(Node* ctrl) {
//------------------------------adjust_limit-----------------------------------
// Helper function for add_constraint().
-Node* PhaseIdealLoop::adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl) {
+Node* PhaseIdealLoop::adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl, bool round_up) {
// Compute "I :: (limit-offset)/scale"
Node *con = new (C) SubINode(rc_limit, offset);
register_new_node(con, pre_ctrl);
Node *X = new (C) DivINode(0, con, scale);
register_new_node(X, pre_ctrl);
+ // When the absolute value of scale is greater than one, the integer
+ // division may round limit down so add one to the limit.
+ if (round_up) {
+ X = new (C) AddINode(X, _igvn.intcon(1));
+ register_new_node(X, pre_ctrl);
+ }
+
// Adjust loop limit
loop_limit = (stride_con > 0)
? (Node*)(new (C) MinINode(loop_limit, X))
@@ -1584,7 +1591,7 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
// (upper_limit-offset) may overflow or underflow.
// But it is fine since main loop will either have
// less iterations or will be skipped in such case.
- *main_limit = adjust_limit(stride_con, scale, offset, upper_limit, *main_limit, pre_ctrl);
+ *main_limit = adjust_limit(stride_con, scale, offset, upper_limit, *main_limit, pre_ctrl, false);
// The underflow limit: low_limit <= scale*I+offset.
// For pre-loop compute
@@ -1620,7 +1627,8 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
// max(pre_limit, original_limit) is used in do_range_check().
}
// Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
- *pre_limit = adjust_limit((-stride_con), scale, offset, low_limit, *pre_limit, pre_ctrl);
+ *pre_limit = adjust_limit((-stride_con), scale, offset, low_limit, *pre_limit, pre_ctrl,
+ scale_con > 1 && stride_con > 0);
} else { // stride_con*scale_con < 0
// For negative stride*scale pre-loop checks for overflow and
@@ -1646,7 +1654,8 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
Node *plus_one = new (C) AddINode(offset, one);
register_new_node( plus_one, pre_ctrl );
// Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
- *pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl);
+ *pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl,
+ scale_con < -1 && stride_con > 0);
if (low_limit->get_int() == -max_jint) {
if (!RangeLimitCheck) return;
@@ -1681,7 +1690,8 @@ void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset
// I > (low_limit-(offset+1))/scale
// )
- *main_limit = adjust_limit(stride_con, scale, plus_one, low_limit, *main_limit, pre_ctrl);
+ *main_limit = adjust_limit(stride_con, scale, plus_one, low_limit, *main_limit, pre_ctrl,
+ false);
}
}
diff --git a/src/share/vm/opto/loopnode.hpp b/src/share/vm/opto/loopnode.hpp
index d97bf07ca..0ce98a063 100644
--- a/src/share/vm/opto/loopnode.hpp
+++ b/src/share/vm/opto/loopnode.hpp
@@ -959,7 +959,7 @@ public:
// loop. Scale_con, offset and limit are all loop invariant.
void add_constraint( int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit );
// Helper function for add_constraint().
- Node* adjust_limit( int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl );
+ Node* adjust_limit(int stride_con, Node * scale, Node *offset, Node *rc_limit, Node *loop_limit, Node *pre_ctrl, bool round_up);
// Partially peel loop up through last_peel node.
bool partial_peel( IdealLoopTree *loop, Node_List &old_new );
diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp
index b4dda4803..965f1a952 100644
--- a/src/share/vm/opto/matcher.cpp
+++ b/src/share/vm/opto/matcher.cpp
@@ -2043,6 +2043,12 @@ void Matcher::find_shared( Node *n ) {
// Node is shared and has no reason to clone. Flag it as shared.
// This causes it to match into a register for the sharing.
set_shared(n); // Flag as shared and
+ if (n->is_DecodeNarrowPtr()) {
+ // Oop field/array element loads must be shared but since
+ // they are shared through a DecodeN they may appear to have
+ // a single use so force sharing here.
+ set_shared(n->in(1));
+ }
mstack.pop(); // remove node from stack
continue;
}
@@ -2165,13 +2171,6 @@ void Matcher::find_shared( Node *n ) {
continue; // for(int i = ...)
}
- if( mop == Op_AddP && m->in(AddPNode::Base)->is_DecodeNarrowPtr()) {
- // Bases used in addresses must be shared but since
- // they are shared through a DecodeN they may appear
- // to have a single use so force sharing here.
- set_shared(m->in(AddPNode::Base)->in(1));
- }
-
// if 'n' and 'm' are part of a graph for BMI instruction, clone this node.
#ifdef X86
if (UseBMI1Instructions && is_bmi_pattern(n, m)) {
diff --git a/src/share/vm/opto/memnode.cpp b/src/share/vm/opto/memnode.cpp
index 1e76cbc79..590111a39 100644
--- a/src/share/vm/opto/memnode.cpp
+++ b/src/share/vm/opto/memnode.cpp
@@ -1359,6 +1359,14 @@ Node *LoadNode::split_through_phi(PhaseGVN *phase) {
Node* in = mem->in(i);
Node* m = optimize_memory_chain(in, t_oop, this, phase);
if (m == mem) {
+ if (i == 1) {
+ // if the first edge was a loop, check second edge too.
+ // If both are replaceable - we are in an infinite loop
+ Node *n = optimize_memory_chain(mem->in(2), t_oop, this, phase);
+ if (n == mem) {
+ break;
+ }
+ }
set_req(Memory, mem->in(cnt - i));
return this; // made change
}
@@ -1514,10 +1522,14 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* ctrl = in(MemNode::Control);
Node* address = in(MemNode::Address);
+ bool addr_mark = ((phase->type(address)->isa_oopptr() || phase->type(address)->isa_narrowoop()) &&
+ phase->type(address)->is_ptr()->offset() == oopDesc::mark_offset_in_bytes());
+
// Skip up past a SafePoint control. Cannot do this for Stores because
// pointer stores & cardmarks must stay on the same side of a SafePoint.
if( ctrl != NULL && ctrl->Opcode() == Op_SafePoint &&
- phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw ) {
+ phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw &&
+ !addr_mark ) {
ctrl = ctrl->in(0);
set_req(MemNode::Control,ctrl);
}
@@ -3349,9 +3361,6 @@ bool InitializeNode::detect_init_independence(Node* n, int& count) {
// within the initialized memory.
intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) {
const int FAIL = 0;
- if (st->is_unaligned_access()) {
- return FAIL;
- }
if (st->req() != MemNode::ValueIn + 1)
return FAIL; // an inscrutable StoreNode (card mark?)
Node* ctl = st->in(MemNode::Control);
@@ -3367,6 +3376,10 @@ intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase,
return FAIL; // inscrutable address
if (alloc != allocation())
return FAIL; // wrong allocation! (store needs to float up)
+ int size_in_bytes = st->memory_size();
+ if ((size_in_bytes != 0) && (offset % size_in_bytes) != 0) {
+ return FAIL; // mismatched access
+ }
Node* val = st->in(MemNode::ValueIn);
int complexity_count = 0;
if (!detect_init_independence(val, complexity_count))
diff --git a/src/share/vm/opto/mulnode.cpp b/src/share/vm/opto/mulnode.cpp
index 4896e98a7..9f2a134f1 100644
--- a/src/share/vm/opto/mulnode.cpp
+++ b/src/share/vm/opto/mulnode.cpp
@@ -169,7 +169,6 @@ const Type *MulNode::Value( PhaseTransform *phase ) const {
return mul_ring(t1,t2); // Local flavor of type multiplication
}
-
//=============================================================================
//------------------------------Ideal------------------------------------------
// Check for power-of-2 multiply, then try the regular MulNode::Ideal
@@ -184,42 +183,43 @@ Node *MulINode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
// Now we have a constant Node on the right and the constant in con
- if( con == 0 ) return NULL; // By zero is handled by Value call
- if( con == 1 ) return NULL; // By one is handled by Identity call
+ if (con == 0) return NULL; // By zero is handled by Value call
+ if (con == 1) return NULL; // By one is handled by Identity call
// Check for negative constant; if so negate the final result
bool sign_flip = false;
- if( con < 0 ) {
- con = -con;
+
+ unsigned int abs_con = uabs(con);
+ if (abs_con != (unsigned int)con) {
sign_flip = true;
}
// Get low bit; check for being the only bit
Node *res = NULL;
- jint bit1 = con & -con; // Extract low bit
- if( bit1 == con ) { // Found a power of 2?
- res = new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) );
+ unsigned int bit1 = abs_con & (0-abs_con); // Extract low bit
+ if (bit1 == abs_con) { // Found a power of 2?
+ res = new (phase->C) LShiftINode(in(1), phase->intcon(log2_uint(bit1)));
} else {
// Check for constant with 2 bits set
- jint bit2 = con-bit1;
- bit2 = bit2 & -bit2; // Extract 2nd bit
- if( bit2 + bit1 == con ) { // Found all bits in con?
- Node *n1 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit1)) ) );
- Node *n2 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(bit2)) ) );
- res = new (phase->C) AddINode( n2, n1 );
-
- } else if (is_power_of_2(con+1)) {
+ unsigned int bit2 = abs_con-bit1;
+ bit2 = bit2 & (0-bit2); // Extract 2nd bit
+ if (bit2 + bit1 == abs_con) { // Found all bits in con?
+ Node *n1 = phase->transform( new (phase->C) LShiftINode(in(1), phase->intcon(log2_uint(bit1))));
+ Node *n2 = phase->transform( new (phase->C) LShiftINode(in(1), phase->intcon(log2_uint(bit2))));
+ res = new (phase->C) AddINode(n2, n1);
+
+ } else if (is_power_of_2(abs_con+1)) {
// Sleezy: power-of-2 -1. Next time be generic.
- jint temp = (jint) (con + 1);
- Node *n1 = phase->transform( new (phase->C) LShiftINode( in(1), phase->intcon(log2_intptr(temp)) ) );
- res = new (phase->C) SubINode( n1, in(1) );
+ unsigned int temp = abs_con + 1;
+ Node *n1 = phase->transform(new (phase->C) LShiftINode(in(1), phase->intcon(log2_uint(temp))));
+ res = new (phase->C) SubINode(n1, in(1));
} else {
return MulNode::Ideal(phase, can_reshape);
}
}
- if( sign_flip ) { // Need to negate result?
+ if (sign_flip) { // Need to negate result?
res = phase->transform(res);// Transform, before making the zero con
res = new (phase->C) SubINode(phase->intcon(0),res);
}
@@ -244,13 +244,13 @@ const Type *MulINode::mul_ring(const Type *t0, const Type *t1) const {
double d = (double)hi1;
// Compute all endpoints & check for overflow
- int32 A = lo0*lo1;
+ int32 A = java_multiply(lo0, lo1);
if( (double)A != a*c ) return TypeInt::INT; // Overflow?
- int32 B = lo0*hi1;
+ int32 B = java_multiply(lo0, hi1);
if( (double)B != a*d ) return TypeInt::INT; // Overflow?
- int32 C = hi0*lo1;
+ int32 C = java_multiply(hi0, lo1);
if( (double)C != b*c ) return TypeInt::INT; // Overflow?
- int32 D = hi0*hi1;
+ int32 D = java_multiply(hi0, hi1);
if( (double)D != b*d ) return TypeInt::INT; // Overflow?
if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
@@ -280,42 +280,42 @@ Node *MulLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
// Now we have a constant Node on the right and the constant in con
- if( con == CONST64(0) ) return NULL; // By zero is handled by Value call
- if( con == CONST64(1) ) return NULL; // By one is handled by Identity call
+ if (con == CONST64(0)) return NULL; // By zero is handled by Value call
+ if (con == CONST64(1)) return NULL; // By one is handled by Identity call
// Check for negative constant; if so negate the final result
bool sign_flip = false;
- if( con < 0 ) {
- con = -con;
+ julong abs_con = uabs(con);
+ if (abs_con != (julong)con) {
sign_flip = true;
}
// Get low bit; check for being the only bit
Node *res = NULL;
- jlong bit1 = con & -con; // Extract low bit
- if( bit1 == con ) { // Found a power of 2?
- res = new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) );
+ julong bit1 = abs_con & (0-abs_con); // Extract low bit
+ if (bit1 == abs_con) { // Found a power of 2?
+ res = new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit1)));
} else {
// Check for constant with 2 bits set
- jlong bit2 = con-bit1;
- bit2 = bit2 & -bit2; // Extract 2nd bit
- if( bit2 + bit1 == con ) { // Found all bits in con?
- Node *n1 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit1)) ) );
- Node *n2 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(bit2)) ) );
- res = new (phase->C) AddLNode( n2, n1 );
-
- } else if (is_power_of_2_long(con+1)) {
+ julong bit2 = abs_con-bit1;
+ bit2 = bit2 & (0-bit2); // Extract 2nd bit
+ if (bit2 + bit1 == abs_con) { // Found all bits in con?
+ Node *n1 = phase->transform(new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit1))));
+ Node *n2 = phase->transform(new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(bit2))));
+ res = new (phase->C) AddLNode(n2, n1);
+
+ } else if (is_power_of_2_long(abs_con+1)) {
// Sleezy: power-of-2 -1. Next time be generic.
- jlong temp = (jlong) (con + 1);
- Node *n1 = phase->transform( new (phase->C) LShiftLNode( in(1), phase->intcon(log2_long(temp)) ) );
- res = new (phase->C) SubLNode( n1, in(1) );
+ julong temp = abs_con + 1;
+ Node *n1 = phase->transform( new (phase->C) LShiftLNode(in(1), phase->intcon(log2_long(temp))));
+ res = new (phase->C) SubLNode(n1, in(1));
} else {
return MulNode::Ideal(phase, can_reshape);
}
}
- if( sign_flip ) { // Need to negate result?
+ if (sign_flip) { // Need to negate result?
res = phase->transform(res);// Transform, before making the zero con
res = new (phase->C) SubLNode(phase->longcon(0),res);
}
@@ -340,13 +340,13 @@ const Type *MulLNode::mul_ring(const Type *t0, const Type *t1) const {
double d = (double)hi1;
// Compute all endpoints & check for overflow
- jlong A = lo0*lo1;
+ jlong A = java_multiply(lo0, lo1);
if( (double)A != a*c ) return TypeLong::LONG; // Overflow?
- jlong B = lo0*hi1;
+ jlong B = java_multiply(lo0, hi1);
if( (double)B != a*d ) return TypeLong::LONG; // Overflow?
- jlong C = hi0*lo1;
+ jlong C = java_multiply(hi0, lo1);
if( (double)C != b*c ) return TypeLong::LONG; // Overflow?
- jlong D = hi0*hi1;
+ jlong D = java_multiply(hi0, hi1);
if( (double)D != b*d ) return TypeLong::LONG; // Overflow?
if( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
@@ -444,7 +444,7 @@ Node *AndINode::Identity( PhaseTransform *phase ) {
// Masking off high bits which are always zero is useless.
const TypeInt* t1 = phase->type( in(1) )->isa_int();
if (t1 != NULL && t1->_lo >= 0) {
- jint t1_support = right_n_bits(1 + log2_intptr(t1->_hi));
+ jint t1_support = right_n_bits(1 + log2_jint(t1->_hi));
if ((t1_support & con) == t1_support)
return in1;
}
@@ -573,7 +573,8 @@ Node *AndLNode::Identity( PhaseTransform *phase ) {
// Masking off high bits which are always zero is useless.
const TypeLong* t1 = phase->type( in(1) )->isa_long();
if (t1 != NULL && t1->_lo >= 0) {
- jlong t1_support = ((jlong)1 << (1 + log2_long(t1->_hi))) - 1;
+ int bit_count = log2_long(t1->_hi) + 1;
+ jlong t1_support = jlong(max_julong >> (BitsPerJavaLong - bit_count));
if ((t1_support & con) == t1_support)
return usr;
}
@@ -801,7 +802,7 @@ Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits
// before shifting them away.
- const jlong bits_mask = ((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) - CONST64(1);
+ const jlong bits_mask = jlong(max_julong >> con);
if( add1_op == Op_AndL &&
phase->type(add1->in(2)) == TypeLong::make( bits_mask ) )
return new (phase->C) LShiftLNode( add1->in(1), in(2) );
@@ -1253,7 +1254,7 @@ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count
// note: mask computation below does not work for 0 shift count
// We'll be wanting the right-shift amount as a mask of that many bits
- const jlong mask = (((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - con)) -1);
+ const jlong mask = jlong(max_julong >> con);
// Check for ((x << z) + Y) >>> z. Replace with x + con>>>z
// The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z".
diff --git a/src/share/vm/opto/reg_split.cpp b/src/share/vm/opto/reg_split.cpp
index af798914a..a132f1f9f 100644
--- a/src/share/vm/opto/reg_split.cpp
+++ b/src/share/vm/opto/reg_split.cpp
@@ -1171,9 +1171,8 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
(deflrg._direct_conflict || deflrg._must_spill)) ||
// Check for LRG being up in a register and we are inside a high
// pressure area. Spill it down immediately.
- (defup && is_high_pressure(b,&deflrg,insidx))) ) {
+ (defup && is_high_pressure(b,&deflrg,insidx) && !n->is_SpillCopy())) ) {
assert( !n->rematerialize(), "" );
- assert( !n->is_SpillCopy(), "" );
// Do a split at the def site.
maxlrg = split_DEF( n, b, insidx, maxlrg, Reachblock, debug_defs, splits, slidx );
// If it wasn't split bail
diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp
index 364152c56..57d2f5764 100644
--- a/src/share/vm/opto/runtime.cpp
+++ b/src/share/vm/opto/runtime.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -930,12 +930,24 @@ const TypeFunc* OptoRuntime::digestBase_implCompressMB_Type() {
// create input type (domain)
int num_args = 4;
int argcnt = num_args;
+ if(CCallingConventionRequiresIntsAsLongs) {
+ argcnt += 2;
+ }
const Type** fields = TypeTuple::fields(argcnt);
int argp = TypeFunc::Parms;
- fields[argp++] = TypePtr::NOTNULL; // buf
- fields[argp++] = TypePtr::NOTNULL; // state
- fields[argp++] = TypeInt::INT; // ofs
- fields[argp++] = TypeInt::INT; // limit
+ if(CCallingConventionRequiresIntsAsLongs) {
+ fields[argp++] = TypePtr::NOTNULL; // buf
+ fields[argp++] = TypePtr::NOTNULL; // state
+ fields[argp++] = TypeLong::LONG; // ofs
+ fields[argp++] = Type::HALF;
+ fields[argp++] = TypeLong::LONG; // limit
+ fields[argp++] = Type::HALF;
+ } else {
+ fields[argp++] = TypePtr::NOTNULL; // buf
+ fields[argp++] = TypePtr::NOTNULL; // state
+ fields[argp++] = TypeInt::INT; // ofs
+ fields[argp++] = TypeInt::INT; // limit
+ }
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
diff --git a/src/share/vm/opto/subnode.cpp b/src/share/vm/opto/subnode.cpp
index 441bd3421..858dda6ef 100644
--- a/src/share/vm/opto/subnode.cpp
+++ b/src/share/vm/opto/subnode.cpp
@@ -252,8 +252,8 @@ Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
const Type *SubINode::sub( const Type *t1, const Type *t2 ) const {
const TypeInt *r0 = t1->is_int(); // Handy access
const TypeInt *r1 = t2->is_int();
- int32 lo = r0->_lo - r1->_hi;
- int32 hi = r0->_hi - r1->_lo;
+ int32 lo = java_subtract(r0->_lo, r1->_hi);
+ int32 hi = java_subtract(r0->_hi, r1->_lo);
// We next check for 32-bit overflow.
// If that happens, we just assume all integers are possible.
@@ -361,8 +361,8 @@ Node *SubLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
const Type *SubLNode::sub( const Type *t1, const Type *t2 ) const {
const TypeLong *r0 = t1->is_long(); // Handy access
const TypeLong *r1 = t2->is_long();
- jlong lo = r0->_lo - r1->_hi;
- jlong hi = r0->_hi - r1->_lo;
+ jlong lo = java_subtract(r0->_lo, r1->_hi);
+ jlong hi = java_subtract(r0->_hi, r1->_lo);
// We next check for 32-bit overflow.
// If that happens, we just assume all integers are possible.
diff --git a/src/share/vm/opto/superword.cpp b/src/share/vm/opto/superword.cpp
index f005ef411..718f077d0 100644
--- a/src/share/vm/opto/superword.cpp
+++ b/src/share/vm/opto/superword.cpp
@@ -482,7 +482,9 @@ bool SuperWord::ref_is_alignable(SWPointer& p) {
if (init_nd->is_Con() && p.invar() == NULL) {
int init = init_nd->bottom_type()->is_int()->get_con();
int init_offset = init * p.scale_in_bytes() + offset;
- assert(init_offset >= 0, "positive offset from object start");
+ if (init_offset < 0) { // negative offset from object start?
+ return false; // may happen in dead loop
+ }
if (vw % span == 0) {
// If vm is a multiple of span, we use formula (1).
if (span > 0) {
diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp
index 47431396d..1a231df98 100644
--- a/src/share/vm/opto/type.cpp
+++ b/src/share/vm/opto/type.cpp
@@ -1329,8 +1329,8 @@ const Type *TypeInt::narrow( const Type *old ) const {
// The new type narrows the old type, so look for a "death march".
// See comments on PhaseTransform::saturate.
- juint nrange = _hi - _lo;
- juint orange = ohi - olo;
+ juint nrange = (juint)_hi - _lo;
+ juint orange = (juint)ohi - olo;
if (nrange < max_juint - 1 && nrange > (orange >> 1) + (SMALLINT*2)) {
// Use the new type only if the range shrinks a lot.
// We do not want the optimizer computing 2^31 point by point.
@@ -1363,7 +1363,7 @@ bool TypeInt::eq( const Type *t ) const {
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeInt::hash(void) const {
- return _lo+_hi+_widen+(int)Type::Int;
+ return java_add(java_add(_lo, _hi), java_add(_widen, (int)Type::Int));
}
//------------------------------is_finite--------------------------------------
@@ -1544,7 +1544,7 @@ const Type *TypeLong::widen( const Type *old, const Type* limit ) const {
// If neither endpoint is extremal yet, push out the endpoint
// which is closer to its respective limit.
if (_lo >= 0 || // easy common case
- (julong)(_lo - min) >= (julong)(max - _hi)) {
+ ((julong)_lo - min) >= ((julong)max - _hi)) {
// Try to widen to an unsigned range type of 32/63 bits:
if (max >= max_juint && _hi < max_juint)
return make(_lo, max_juint, WidenMax);
@@ -2314,7 +2314,7 @@ bool TypePtr::eq( const Type *t ) const {
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypePtr::hash(void) const {
- return _ptr + _offset;
+ return java_add(_ptr, _offset);
}
//------------------------------dump2------------------------------------------
@@ -2904,12 +2904,8 @@ bool TypeOopPtr::eq( const Type *t ) const {
// Type-specific hashing function.
int TypeOopPtr::hash(void) const {
return
- (const_oop() ? const_oop()->hash() : 0) +
- _klass_is_exact +
- _instance_id +
- hash_speculative() +
- _inline_depth +
- TypePtr::hash();
+ java_add(java_add(java_add(const_oop() ? const_oop()->hash() : 0, _klass_is_exact),
+ java_add(_instance_id , hash_speculative())), java_add(_inline_depth , TypePtr::hash()));
}
//------------------------------dump2------------------------------------------
@@ -3635,7 +3631,7 @@ bool TypeInstPtr::eq( const Type *t ) const {
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeInstPtr::hash(void) const {
- int hash = klass()->hash() + TypeOopPtr::hash();
+ int hash = java_add(klass()->hash(), TypeOopPtr::hash());
return hash;
}
@@ -4530,7 +4526,7 @@ bool TypeKlassPtr::eq( const Type *t ) const {
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
int TypeKlassPtr::hash(void) const {
- return klass()->hash() + TypePtr::hash();
+ return java_add(klass()->hash(), TypePtr::hash());
}
//------------------------------singleton--------------------------------------
diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp
index 51b453ee5..0a908270d 100644
--- a/src/share/vm/prims/jni.cpp
+++ b/src/share/vm/prims/jni.cpp
@@ -709,6 +709,7 @@ JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
ShouldNotReachHere();
+ return 0; // Mute compiler.
JNI_END
#ifndef USDT2
@@ -735,6 +736,7 @@ JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))
Handle protection_domain (THREAD, k->protection_domain());
THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);
ShouldNotReachHere();
+ return 0; // Mute compiler.
JNI_END
@@ -1140,8 +1142,7 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }
inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }
- inline void get_object() { jobject l = va_arg(_ap, jobject);
- _arguments->push_oop(Handle((oop *)l, false)); }
+ inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); }
inline void set_ap(va_list rap) {
#ifdef va_copy
@@ -1235,7 +1236,7 @@ class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
inline void get_long() { _arguments->push_long((_ap++)->j); }
inline void get_float() { _arguments->push_float((_ap++)->f); }
inline void get_double() { _arguments->push_double((_ap++)->d);}
- inline void get_object() { _arguments->push_oop(Handle((oop *)(_ap++)->l, false)); }
+ inline void get_object() { _arguments->push_jobject((_ap++)->l); }
inline void set_ap(const jvalue *rap) { _ap = rap; }
@@ -5121,6 +5122,7 @@ void execute_internal_vm_tests() {
run_unit_test(TestMetachunk_test());
run_unit_test(TestVirtualSpaceNode_test());
run_unit_test(GlobalDefinitions::test_globals());
+ run_unit_test(GlobalDefinitions::test_proper_unit());
run_unit_test(GCTimerAllTest::all());
run_unit_test(arrayOopDesc::test_max_array_length());
run_unit_test(CollectedHeap::test_is_in());
diff --git a/src/share/vm/prims/jvmtiEnv.cpp b/src/share/vm/prims/jvmtiEnv.cpp
index d88e39698..344f3d0a4 100644
--- a/src/share/vm/prims/jvmtiEnv.cpp
+++ b/src/share/vm/prims/jvmtiEnv.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -1621,6 +1621,13 @@ JvmtiEnv::FollowReferences(jint heap_filter, jclass klass, jobject initial_objec
}
}
+ if (initial_object != NULL) {
+ oop init_obj = JNIHandles::resolve_external_guard(initial_object);
+ if (init_obj == NULL) {
+ return JVMTI_ERROR_INVALID_OBJECT;
+ }
+ }
+
Thread *thread = Thread::current();
HandleMark hm(thread);
KlassHandle kh (thread, k_oop);
diff --git a/src/share/vm/prims/jvmtiEnvBase.hpp b/src/share/vm/prims/jvmtiEnvBase.hpp
index e8c23b10f..c6a7db187 100644
--- a/src/share/vm/prims/jvmtiEnvBase.hpp
+++ b/src/share/vm/prims/jvmtiEnvBase.hpp
@@ -32,6 +32,7 @@
#include "runtime/fieldDescriptor.hpp"
#include "runtime/frame.hpp"
#include "runtime/handles.inline.hpp"
+#include "runtime/orderAccess.hpp"
#include "runtime/thread.hpp"
#include "runtime/vm_operations.hpp"
#include "utilities/growableArray.hpp"
@@ -97,7 +98,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
const void *_env_local_storage; // per env agent allocated data.
jvmtiEventCallbacks _event_callbacks;
jvmtiExtEventCallbacks _ext_event_callbacks;
- JvmtiTagMap* _tag_map;
+ JvmtiTagMap* volatile _tag_map;
JvmtiEnvEventEnable _env_event_enable;
jvmtiCapabilities _current_capabilities;
jvmtiCapabilities _prohibited_capabilities;
@@ -251,6 +252,13 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
return _tag_map;
}
+ JvmtiTagMap* tag_map_acquire() {
+ return (JvmtiTagMap*)OrderAccess::load_ptr_acquire(&_tag_map);
+ }
+
+ void release_set_tag_map(JvmtiTagMap* tag_map) {
+ OrderAccess::release_store_ptr(&_tag_map, tag_map);
+ }
// return true if event is enabled globally or for any thread
// True only if there is a callback for it.
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.cpp b/src/share/vm/prims/jvmtiRedefineClasses.cpp
index 0e194b6f4..8b99b217d 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -67,6 +67,43 @@ VM_RedefineClasses::VM_RedefineClasses(jint class_count,
_res = JVMTI_ERROR_NONE;
}
+static inline InstanceKlass* get_ik(jclass def) {
+ oop mirror = JNIHandles::resolve_non_null(def);
+ return InstanceKlass::cast(java_lang_Class::as_Klass(mirror));
+}
+
+// If any of the classes are being redefined, wait
+// Parallel constant pool merging leads to indeterminate constant pools.
+void VM_RedefineClasses::lock_classes() {
+ MutexLocker ml(RedefineClasses_lock);
+ bool has_redefined;
+ do {
+ has_redefined = false;
+ // Go through classes each time until none are being redefined.
+ for (int i = 0; i < _class_count; i++) {
+ if (get_ik(_class_defs[i].klass)->is_being_redefined()) {
+ RedefineClasses_lock->wait();
+ has_redefined = true;
+ break; // for loop
+ }
+ }
+ } while (has_redefined);
+ for (int i = 0; i < _class_count; i++) {
+ get_ik(_class_defs[i].klass)->set_is_being_redefined(true);
+ }
+ RedefineClasses_lock->notify_all();
+}
+
+void VM_RedefineClasses::unlock_classes() {
+ MutexLocker ml(RedefineClasses_lock);
+ for (int i = 0; i < _class_count; i++) {
+ assert(get_ik(_class_defs[i].klass)->is_being_redefined(),
+ "should be being redefined to get here");
+ get_ik(_class_defs[i].klass)->set_is_being_redefined(false);
+ }
+ RedefineClasses_lock->notify_all();
+}
+
bool VM_RedefineClasses::doit_prologue() {
if (_class_count == 0) {
_res = JVMTI_ERROR_NONE;
@@ -89,12 +126,21 @@ bool VM_RedefineClasses::doit_prologue() {
_res = JVMTI_ERROR_NULL_POINTER;
return false;
}
+
+ oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
+ // classes for primitives and arrays cannot be redefined
+ // check here so following code can assume these classes are InstanceKlass
+ if (!is_modifiable_class(mirror)) {
+ _res = JVMTI_ERROR_UNMODIFIABLE_CLASS;
+ return false;
+ }
}
// Start timer after all the sanity checks; not quite accurate, but
// better than adding a bunch of stop() calls.
RC_TIMER_START(_timer_vm_op_prologue);
+ lock_classes();
// We first load new class versions in the prologue, because somewhere down the
// call chain it is required that the current thread is a Java thread.
_res = load_new_class_versions(Thread::current());
@@ -105,12 +151,18 @@ bool VM_RedefineClasses::doit_prologue() {
ClassLoaderData* cld = _scratch_classes[i]->class_loader_data();
// Free the memory for this class at class unloading time. Not before
// because CMS might think this is still live.
+ InstanceKlass* ik = get_ik(_class_defs[i].klass);
+ if (ik->get_cached_class_file() == ((InstanceKlass*)_scratch_classes[i])->get_cached_class_file()) {
+ // Don't double-free cached_class_file copied from the original class if error.
+ ((InstanceKlass*)_scratch_classes[i])->set_cached_class_file(NULL);
+ }
cld->add_to_deallocate_list((InstanceKlass*)_scratch_classes[i]);
}
}
// Free os::malloc allocated memory in load_new_class_version.
os::free(_scratch_classes);
RC_TIMER_STOP(_timer_vm_op_prologue);
+ unlock_classes();
return false;
}
@@ -170,6 +222,8 @@ void VM_RedefineClasses::doit() {
}
void VM_RedefineClasses::doit_epilogue() {
+ unlock_classes();
+
// Free os::malloc allocated memory.
os::free(_scratch_classes);
@@ -961,14 +1015,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
// versions are deleted. Constant pools are deallocated while merging
// constant pools
HandleMark hm(THREAD);
-
- oop mirror = JNIHandles::resolve_non_null(_class_defs[i].klass);
- // classes for primitives cannot be redefined
- if (!is_modifiable_class(mirror)) {
- return JVMTI_ERROR_UNMODIFIABLE_CLASS;
- }
- Klass* the_class_oop = java_lang_Class::as_Klass(mirror);
- instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
+ instanceKlassHandle the_class(THREAD, get_ik(_class_defs[i].klass));
Symbol* the_class_sym = the_class->name();
// RC_TRACE_WITH_THREAD macro has an embedded ResourceMark
@@ -3855,22 +3902,19 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
HandleMark hm(THREAD); // make sure handles from this call are freed
RC_TIMER_START(_timer_rsc_phase1);
- instanceKlassHandle scratch_class(scratch_class_oop);
-
- oop the_class_mirror = JNIHandles::resolve_non_null(the_jclass);
- Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror);
- instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop);
+ instanceKlassHandle scratch_class(THREAD, scratch_class_oop);
+ instanceKlassHandle the_class(THREAD, get_ik(the_jclass));
// Remove all breakpoints in methods of this class
JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints();
- jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop);
+ jvmti_breakpoints.clearall_in_class_at_safepoint(the_class());
// Deoptimize all compiled code that depends on this class
flush_dependent_code(the_class, THREAD);
_old_methods = the_class->methods();
_new_methods = scratch_class->methods();
- _the_class_oop = the_class_oop;
+ _the_class_oop = the_class();
compute_added_deleted_matching_methods();
update_jmethod_ids();
@@ -3980,12 +4024,12 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
// with them was cached on the scratch class, move to the_class.
// Note: we still want to do this if nothing needed caching since it
// should get cleared in the_class too.
- if (the_class->get_cached_class_file_bytes() == 0) {
+ if (the_class->get_cached_class_file() == 0) {
// the_class doesn't have a cache yet so copy it
the_class->set_cached_class_file(scratch_class->get_cached_class_file());
}
- else if (scratch_class->get_cached_class_file_bytes() !=
- the_class->get_cached_class_file_bytes()) {
+ else if (scratch_class->get_cached_class_file() !=
+ the_class->get_cached_class_file()) {
// The same class can be present twice in the scratch classes list or there
// are multiple concurrent RetransformClasses calls on different threads.
// In such cases we have to deallocate scratch_class cached_class_file.
@@ -4094,14 +4138,14 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
RC_TRACE_WITH_THREAD(0x00000001, THREAD,
("redefined name=%s, count=%d (avail_mem=" UINT64_FORMAT "K)",
the_class->external_name(),
- java_lang_Class::classRedefinedCount(the_class_mirror),
+ java_lang_Class::classRedefinedCount(the_class->java_mirror()),
os::available_memory() >> 10));
{
ResourceMark rm(THREAD);
Events::log_redefinition(THREAD, "redefined class name=%s, count=%d",
the_class->external_name(),
- java_lang_Class::classRedefinedCount(the_class_mirror));
+ java_lang_Class::classRedefinedCount(the_class->java_mirror()));
}
RC_TIMER_STOP(_timer_rsc_phase2);
diff --git a/src/share/vm/prims/jvmtiRedefineClasses.hpp b/src/share/vm/prims/jvmtiRedefineClasses.hpp
index aab9d4549..167c01c31 100644
--- a/src/share/vm/prims/jvmtiRedefineClasses.hpp
+++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp
@@ -490,6 +490,10 @@ class VM_RedefineClasses: public VM_Operation {
void flush_dependent_code(instanceKlassHandle k_h, TRAPS);
+ // lock classes to redefine since constant pool merging isn't thread safe.
+ void lock_classes();
+ void unlock_classes();
+
static void dump_methods();
// Check that there are no old or obsolete methods
diff --git a/src/share/vm/prims/jvmtiTagMap.cpp b/src/share/vm/prims/jvmtiTagMap.cpp
index c45181dc7..ba48fc3ef 100644
--- a/src/share/vm/prims/jvmtiTagMap.cpp
+++ b/src/share/vm/prims/jvmtiTagMap.cpp
@@ -430,7 +430,7 @@ JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
_hashmap = new JvmtiTagHashmap();
// finally add us to the environment
- ((JvmtiEnvBase *)env)->set_tag_map(this);
+ ((JvmtiEnvBase *)env)->release_set_tag_map(this);
}
@@ -499,7 +499,7 @@ void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
// returns the tag map for the given environments. If the tag map
// doesn't exist then it is created.
JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
- JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
+ JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map_acquire();
if (tag_map == NULL) {
MutexLocker mu(JvmtiThreadState_lock);
tag_map = ((JvmtiEnvBase*)env)->tag_map();
@@ -3282,7 +3282,7 @@ void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
if (JvmtiEnv::environments_might_exist()) {
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
- JvmtiTagMap* tag_map = env->tag_map();
+ JvmtiTagMap* tag_map = env->tag_map_acquire();
if (tag_map != NULL && !tag_map->is_empty()) {
tag_map->do_weak_oops(is_alive, f);
}
diff --git a/src/share/vm/prims/whitebox.cpp b/src/share/vm/prims/whitebox.cpp
index a778dafc1..116d0f37c 100644
--- a/src/share/vm/prims/whitebox.cpp
+++ b/src/share/vm/prims/whitebox.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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,6 +26,7 @@
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
+#include "memory/iterator.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
@@ -171,7 +172,7 @@ WB_END
WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
CollectorPolicy * p = Universe::heap()->collector_policy();
gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
- SIZE_FORMAT" Maximum heap " SIZE_FORMAT " Min alignment " SIZE_FORMAT " Max alignment " SIZE_FORMAT,
+ SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
p->space_alignment(), p->heap_alignment());
}
@@ -371,6 +372,13 @@ WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size,
return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
WB_END
+// Alloc memory with pseudo call stack and specific memory type.
+WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
+ address pc = (address)(size_t)pseudo_stack;
+ NativeCallStack stack(&pc, 1);
+ return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
+WB_END
+
// Free the memory allocated by NMTAllocTest
WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
os::free((void*)(uintptr_t)mem, mtTest);
@@ -576,11 +584,6 @@ class VM_WhiteBoxOperation : public VM_Operation {
bool allow_nested_vm_operations() const { return true; }
};
-class AlwaysFalseClosure : public BoolObjectClosure {
- public:
- bool do_object_b(oop p) { return false; }
-};
-
static AlwaysFalseClosure always_false;
class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation {
@@ -630,6 +633,25 @@ WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
}
WB_END
+WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
+ jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+ CHECK_JNI_EXCEPTION(env);
+ methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+
+ MethodData* mdo = mh->method_data();
+ if (mdo == NULL) {
+ Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
+ mdo = mh->method_data();
+ }
+ mdo->init();
+ InvocationCounter* icnt = mdo->invocation_counter();
+ InvocationCounter* bcnt = mdo->backedge_counter();
+ // set i-counter according to AdvancedThresholdPolicy::is_method_profiled
+ // because SimpleThresholdPolicy::call_predicate_helper uses > in jdk8u, that's why we need to plus one.
+ icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold + 1);
+ bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold + 1);
+WB_END
+
template <typename T>
static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) {
if (name == NULL) {
@@ -845,19 +867,23 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo
ThreadToNativeFromVM ttn(thread);
jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
CHECK_JNI_EXCEPTION_(env, NULL);
- result = env->NewObjectArray(2, clazz, NULL);
+ result = env->NewObjectArray(3, clazz, NULL);
if (result == NULL) {
return result;
}
- jobject obj = integerBox(thread, env, code->comp_level());
+ jobject level = integerBox(thread, env, code->comp_level());
+ CHECK_JNI_EXCEPTION_(env, NULL);
+ env->SetObjectArrayElement(result, 0, level);
+
+ jobject id = integerBox(thread, env, code->compile_id());
CHECK_JNI_EXCEPTION_(env, NULL);
- env->SetObjectArrayElement(result, 0, obj);
+ env->SetObjectArrayElement(result, 1, id);
jbyteArray insts = env->NewByteArray(insts_size);
CHECK_JNI_EXCEPTION_(env, NULL);
env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
- env->SetObjectArrayElement(result, 1, insts);
+ env->SetObjectArrayElement(result, 2, insts);
return result;
WB_END
@@ -1081,6 +1107,7 @@ static JNINativeMethod methods[] = {
#if INCLUDE_NMT
{CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
{CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
+ {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType},
{CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
{CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
{CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
@@ -1115,6 +1142,8 @@ static JNINativeMethod methods[] = {
CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
{CC"clearMethodState",
CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
+ {CC"markMethodProfiled",
+ CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled},
{CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
{CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
{CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
diff --git a/src/share/vm/runtime/advancedThresholdPolicy.cpp b/src/share/vm/runtime/advancedThresholdPolicy.cpp
index a57c12ae2..c43528322 100644
--- a/src/share/vm/runtime/advancedThresholdPolicy.cpp
+++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2019, 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
@@ -47,8 +47,8 @@ void AdvancedThresholdPolicy::initialize() {
int count = CICompilerCount;
if (CICompilerCountPerCPU) {
// Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n
- int log_cpu = log2_intptr(os::active_processor_count());
- int loglog_cpu = log2_intptr(MAX2(log_cpu, 1));
+ int log_cpu = log2_int(os::active_processor_count());
+ int loglog_cpu = log2_int(MAX2(log_cpu, 1));
count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2;
}
@@ -131,7 +131,8 @@ bool AdvancedThresholdPolicy::is_old(Method* method) {
}
double AdvancedThresholdPolicy::weight(Method* method) {
- return (method->rate() + 1) * ((method->invocation_count() + 1) * (method->backedge_count() + 1));
+ return (double)(method->rate() + 1) *
+ (method->invocation_count() + 1) * (method->backedge_count() + 1);
}
// Apply heuristics and return true if x should be compiled before y
@@ -195,6 +196,16 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) {
if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile
&& is_method_profiled(max_method)) {
+
+ if (CompileBroker::compilation_is_complete(max_method, max_task->osr_bci(), CompLevel_limited_profile)) {
+ if (PrintTieredEvents) {
+ print_event(REMOVE_FROM_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
+ }
+ compile_queue->remove_and_mark_stale(max_task);
+ max_method->clear_queued_for_compilation();
+ return NULL;
+ }
+
max_task->set_comp_level(CompLevel_limited_profile);
if (PrintTieredEvents) {
print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
index 43e31d224..2665b6b8c 100644
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
@@ -556,8 +556,7 @@ char* SysClassPath::add_jars_to_path(char* path, const char* directory) {
/* Scan the directory for jars/zips, appending them to path. */
struct dirent *entry;
- char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
- while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+ while ((entry = os::readdir(dir)) != NULL) {
const char* name = entry->d_name;
const char* ext = name + strlen(name) - 4;
bool isJarOrZip = ext > name &&
@@ -571,7 +570,6 @@ char* SysClassPath::add_jars_to_path(char* path, const char* directory) {
FREE_C_HEAP_ARRAY(char, jarpath, mtInternal);
}
}
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
os::closedir(dir);
return path;
}
@@ -3485,14 +3483,12 @@ static bool has_jar_files(const char* directory) {
if (dir == NULL) return false;
struct dirent *entry;
- char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
bool hasJarFile = false;
- while (!hasJarFile && (entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+ while (!hasJarFile && (entry = os::readdir(dir)) != NULL) {
const char* name = entry->d_name;
const char* ext = name + strlen(name) - 4;
hasJarFile = ext > name && (os::file_name_strcmp(ext, ".jar") == 0);
}
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
os::closedir(dir);
return hasJarFile ;
}
@@ -3574,8 +3570,7 @@ static bool check_endorsed_and_ext_dirs() {
if (dir != NULL) {
int num_ext_jars = 0;
struct dirent *entry;
- char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(extDir), mtInternal);
- while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
+ while ((entry = os::readdir(dir)) != NULL) {
const char* name = entry->d_name;
const char* ext = name + strlen(name) - 4;
if (ext > name && (os::file_name_strcmp(ext, ".jar") == 0)) {
@@ -3594,7 +3589,6 @@ static bool check_endorsed_and_ext_dirs() {
}
}
}
- FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
os::closedir(dir);
if (num_ext_jars > 0) {
nonEmptyDirs += 1;
diff --git a/src/share/vm/runtime/compilationPolicy.cpp b/src/share/vm/runtime/compilationPolicy.cpp
index a0af68671..f9c421d36 100644
--- a/src/share/vm/runtime/compilationPolicy.cpp
+++ b/src/share/vm/runtime/compilationPolicy.cpp
@@ -181,7 +181,7 @@ void NonTieredCompPolicy::initialize() {
// Example: if CICompilerCountPerCPU is true, then we get
// max(log2(8)-1,1) = 2 compiler threads on an 8-way machine.
// May help big-app startup time.
- _compiler_count = MAX2(log2_intptr(os::active_processor_count())-1,1);
+ _compiler_count = MAX2(log2_int(os::active_processor_count())-1,1);
FLAG_SET_ERGO(intx, CICompilerCount, _compiler_count);
} else {
_compiler_count = CICompilerCount;
diff --git a/src/share/vm/runtime/java.cpp b/src/share/vm/runtime/java.cpp
index faec9bae9..721f74321 100644
--- a/src/share/vm/runtime/java.cpp
+++ b/src/share/vm/runtime/java.cpp
@@ -45,6 +45,7 @@
#include "runtime/arguments.hpp"
#include "runtime/biasedLocking.hpp"
#include "runtime/compilationPolicy.hpp"
+#include "runtime/deoptimization.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
diff --git a/src/share/vm/runtime/javaCalls.cpp b/src/share/vm/runtime/javaCalls.cpp
index 52fe2fb2c..12925a9aa 100644
--- a/src/share/vm/runtime/javaCalls.cpp
+++ b/src/share/vm/runtime/javaCalls.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -325,9 +325,9 @@ void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArgument
// Verify the arguments
if (CheckJNICalls) {
- args->verify(method, result->get_type(), thread);
+ args->verify(method, result->get_type());
}
- else debug_only(args->verify(method, result->get_type(), thread));
+ else debug_only(args->verify(method, result->get_type()));
// Ignore call if method is empty
if (method->is_empty_method()) {
@@ -429,12 +429,42 @@ void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArgument
//--------------------------------------------------------------------------------------
// Implementation of JavaCallArguments
+inline bool is_value_state_indirect_oop(uint state) {
+ assert(state != JavaCallArguments::value_state_oop,
+ "Checking for handles after removal");
+ assert(state < JavaCallArguments::value_state_limit, "Invalid value state");
+ return state != JavaCallArguments::value_state_primitive;
+}
+
+inline oop resolve_indirect_oop(intptr_t value, uint state) {
+ switch (state) {
+ case JavaCallArguments::value_state_handle:
+ {
+ oop* ptr = reinterpret_cast<oop*>(value);
+ return Handle::raw_resolve(ptr);
+ }
+
+ case JavaCallArguments::value_state_jobject:
+ {
+ jobject obj = reinterpret_cast<jobject>(value);
+ return JNIHandles::resolve(obj);
+ }
+
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+}
+
intptr_t* JavaCallArguments::parameters() {
// First convert all handles to oops
for(int i = 0; i < _size; i++) {
- if (_is_oop[i]) {
- // Handle conversion
- _value[i] = cast_from_oop<intptr_t>(Handle::raw_resolve((oop *)_value[i]));
+ uint state = _value_state[i];
+ assert(state != value_state_oop, "Multiple handle conversions");
+ if (is_value_state_indirect_oop(state)) {
+ oop obj = resolve_indirect_oop(_value[i], state);
+ _value[i] = cast_from_oop<intptr_t>(obj);
+ _value_state[i] = value_state_oop;
}
}
// Return argument vector
@@ -444,30 +474,40 @@ intptr_t* JavaCallArguments::parameters() {
class SignatureChekker : public SignatureIterator {
private:
- bool *_is_oop;
- int _pos;
- BasicType _return_type;
- intptr_t* _value;
- Thread* _thread;
+ int _pos;
+ BasicType _return_type;
+ u_char* _value_state;
+ intptr_t* _value;
public:
bool _is_return;
- SignatureChekker(Symbol* signature, BasicType return_type, bool is_static, bool* is_oop, intptr_t* value, Thread* thread) : SignatureIterator(signature) {
- _is_oop = is_oop;
- _is_return = false;
- _return_type = return_type;
- _pos = 0;
- _value = value;
- _thread = thread;
-
+ SignatureChekker(Symbol* signature,
+ BasicType return_type,
+ bool is_static,
+ u_char* value_state,
+ intptr_t* value) :
+ SignatureIterator(signature),
+ _pos(0),
+ _return_type(return_type),
+ _value_state(value_state),
+ _value(value),
+ _is_return(false)
+ {
if (!is_static) {
check_value(true); // Receiver must be an oop
}
}
void check_value(bool type) {
- guarantee(_is_oop[_pos++] == type, "signature does not match pushed arguments");
+ uint state = _value_state[_pos++];
+ if (type) {
+ guarantee(is_value_state_indirect_oop(state),
+ "signature does not match pushed arguments");
+ } else {
+ guarantee(state == JavaCallArguments::value_state_primitive,
+ "signature does not match pushed arguments");
+ }
}
void check_doing_return(bool state) { _is_return = state; }
@@ -502,24 +542,19 @@ class SignatureChekker : public SignatureIterator {
return;
}
- // verify handle and the oop pointed to by handle
- int p = _pos;
- bool bad = false;
- // If argument is oop
- if (_is_oop[p]) {
- intptr_t v = _value[p];
- if (v != 0 ) {
- size_t t = (size_t)v;
- bad = (t < (size_t)os::vm_page_size() ) || !Handle::raw_resolve((oop *)v)->is_oop_or_null(true);
- if (CheckJNICalls && bad) {
- ReportJNIFatalError((JavaThread*)_thread, "Bad JNI oop argument");
- }
- }
- // for the regular debug case.
- assert(!bad, "Bad JNI oop argument");
+ intptr_t v = _value[_pos];
+ if (v != 0) {
+ // v is a "handle" referring to an oop, cast to integral type.
+ // There shouldn't be any handles in very low memory.
+ guarantee((size_t)v >= (size_t)os::vm_page_size(),
+ "Bad JNI oop argument");
+ // Verify the pointee.
+ oop vv = resolve_indirect_oop(v, _value_state[_pos]);
+ guarantee(vv->is_oop_or_null(true),
+ "Bad JNI oop argument");
}
- check_value(true);
+ check_value(true); // Verify value state.
}
void do_bool() { check_int(T_BOOLEAN); }
@@ -536,8 +571,7 @@ class SignatureChekker : public SignatureIterator {
};
-void JavaCallArguments::verify(methodHandle method, BasicType return_type,
- Thread *thread) {
+void JavaCallArguments::verify(methodHandle method, BasicType return_type) {
guarantee(method->size_of_parameters() == size_of_parameters(), "wrong no. of arguments pushed");
// Treat T_OBJECT and T_ARRAY as the same
@@ -546,7 +580,11 @@ void JavaCallArguments::verify(methodHandle method, BasicType return_type,
// Check that oop information is correct
Symbol* signature = method->signature();
- SignatureChekker sc(signature, return_type, method->is_static(),_is_oop, _value, thread);
+ SignatureChekker sc(signature,
+ return_type,
+ method->is_static(),
+ _value_state,
+ _value);
sc.iterate_parameters();
sc.check_doing_return(true);
sc.iterate_returntype();
diff --git a/src/share/vm/runtime/javaCalls.hpp b/src/share/vm/runtime/javaCalls.hpp
index bdf4d34c9..4af6a8c4b 100644
--- a/src/share/vm/runtime/javaCalls.hpp
+++ b/src/share/vm/runtime/javaCalls.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -92,25 +92,42 @@ class JavaCallArguments : public StackObj {
_default_size = 8 // Must be at least # of arguments in JavaCalls methods
};
- intptr_t _value_buffer [_default_size + 1];
- bool _is_oop_buffer[_default_size + 1];
+ intptr_t _value_buffer [_default_size + 1];
+ u_char _value_state_buffer[_default_size + 1];
intptr_t* _value;
- bool* _is_oop;
+ u_char* _value_state;
int _size;
int _max_size;
bool _start_at_zero; // Support late setting of receiver
void initialize() {
// Starts at first element to support set_receiver.
- _value = &_value_buffer[1];
- _is_oop = &_is_oop_buffer[1];
+ _value = &_value_buffer[1];
+ _value_state = &_value_state_buffer[1];
_max_size = _default_size;
_size = 0;
_start_at_zero = false;
}
+ // Helper for push_oop and the like. The value argument is a
+ // "handle" that refers to an oop. We record the address of the
+ // handle rather than the designated oop. The handle is later
+ // resolved to the oop by parameters(). This delays the exposure of
+ // naked oops until it is GC-safe.
+ template<typename T>
+ inline int push_oop_impl(T handle, int size) {
+ // JNITypes::put_obj expects an oop value, so we play fast and
+ // loose with the type system. The cast from handle type to oop
+ // *must* use a C-style cast. In a product build it performs a
+ // reinterpret_cast. In a debug build (more accurately, in a
+ // CHECK_UNHANDLED_OOPS build) it performs a static_cast, invoking
+ // the debug-only oop class's conversion from void* constructor.
+ JNITypes::put_obj((oop)handle, _value, size); // Updates size.
+ return size; // Return the updated size.
+ }
+
public:
JavaCallArguments() { initialize(); }
@@ -121,11 +138,12 @@ class JavaCallArguments : public StackObj {
JavaCallArguments(int max_size) {
if (max_size > _default_size) {
- _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1);
- _is_oop = NEW_RESOURCE_ARRAY(bool, max_size + 1);
+ _value = NEW_RESOURCE_ARRAY(intptr_t, max_size + 1);
+ _value_state = NEW_RESOURCE_ARRAY(u_char, max_size + 1);
- // Reserve room for potential receiver in value and is_oop
- _value++; _is_oop++;
+ // Reserve room for potential receiver in value and state
+ _value++;
+ _value_state++;
_max_size = max_size;
_size = 0;
@@ -135,25 +153,52 @@ class JavaCallArguments : public StackObj {
}
}
- inline void push_oop(Handle h) { _is_oop[_size] = true;
- JNITypes::put_obj((oop)h.raw_value(), _value, _size); }
+ // The possible values for _value_state elements.
+ enum {
+ value_state_primitive,
+ value_state_oop,
+ value_state_handle,
+ value_state_jobject,
+ value_state_limit
+ };
- inline void push_int(int i) { _is_oop[_size] = false;
- JNITypes::put_int(i, _value, _size); }
+ inline void push_oop(Handle h) {
+ _value_state[_size] = value_state_handle;
+ _size = push_oop_impl(h.raw_value(), _size);
+ }
- inline void push_double(double d) { _is_oop[_size] = false; _is_oop[_size + 1] = false;
- JNITypes::put_double(d, _value, _size); }
+ inline void push_jobject(jobject h) {
+ _value_state[_size] = value_state_jobject;
+ _size = push_oop_impl(h, _size);
+ }
- inline void push_long(jlong l) { _is_oop[_size] = false; _is_oop[_size + 1] = false;
- JNITypes::put_long(l, _value, _size); }
+ inline void push_int(int i) {
+ _value_state[_size] = value_state_primitive;
+ JNITypes::put_int(i, _value, _size);
+ }
- inline void push_float(float f) { _is_oop[_size] = false;
- JNITypes::put_float(f, _value, _size); }
+ inline void push_double(double d) {
+ _value_state[_size] = value_state_primitive;
+ _value_state[_size + 1] = value_state_primitive;
+ JNITypes::put_double(d, _value, _size);
+ }
+
+ inline void push_long(jlong l) {
+ _value_state[_size] = value_state_primitive;
+ _value_state[_size + 1] = value_state_primitive;
+ JNITypes::put_long(l, _value, _size);
+ }
+
+ inline void push_float(float f) {
+ _value_state[_size] = value_state_primitive;
+ JNITypes::put_float(f, _value, _size);
+ }
// receiver
Handle receiver() {
assert(_size > 0, "must at least be one argument");
- assert(_is_oop[0], "first argument must be an oop");
+ assert(_value_state[0] == value_state_handle,
+ "first argument must be an oop");
assert(_value[0] != 0, "receiver must be not-null");
return Handle((oop*)_value[0], false);
}
@@ -161,11 +206,11 @@ class JavaCallArguments : public StackObj {
void set_receiver(Handle h) {
assert(_start_at_zero == false, "can only be called once");
_start_at_zero = true;
- _is_oop--;
+ _value_state--;
_value--;
_size++;
- _is_oop[0] = true;
- _value[0] = (intptr_t)h.raw_value();
+ _value_state[0] = value_state_handle;
+ push_oop_impl(h.raw_value(), 0);
}
// Converts all Handles to oops, and returns a reference to parameter vector
@@ -173,7 +218,7 @@ class JavaCallArguments : public StackObj {
int size_of_parameters() const { return _size; }
// Verify that pushed arguments fits a given method
- void verify(methodHandle method, BasicType return_type, Thread *thread);
+ void verify(methodHandle method, BasicType return_type);
};
// All calls to Java have to go via JavaCalls. Sets up the stack frame
diff --git a/src/share/vm/runtime/jniHandles.cpp b/src/share/vm/runtime/jniHandles.cpp
index 393730d5a..be8438f29 100644
--- a/src/share/vm/runtime/jniHandles.cpp
+++ b/src/share/vm/runtime/jniHandles.cpp
@@ -24,11 +24,15 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
+#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.inline.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@@ -86,34 +90,52 @@ jobject JNIHandles::make_global(Handle obj) {
return res;
}
-
jobject JNIHandles::make_weak_global(Handle obj) {
assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC");
jobject res = NULL;
if (!obj.is_null()) {
// ignore null handles
- MutexLocker ml(JNIGlobalHandle_lock);
- assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
- res = _weak_global_handles->allocate_handle(obj());
+ {
+ MutexLocker ml(JNIGlobalHandle_lock);
+ assert(Universe::heap()->is_in_reserved(obj()), "sanity check");
+ res = _weak_global_handles->allocate_handle(obj());
+ }
+ // Add weak tag.
+ assert(is_ptr_aligned(res, weak_tag_alignment), "invariant");
+ char* tptr = reinterpret_cast<char*>(res) + weak_tag_value;
+ res = reinterpret_cast<jobject>(tptr);
} else {
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
}
return res;
}
+template<bool external_guard>
+oop JNIHandles::resolve_jweak(jweak handle) {
+ assert(is_jweak(handle), "precondition");
+ oop result = jweak_ref(handle);
+ result = guard_value<external_guard>(result);
+#if INCLUDE_ALL_GCS
+ if (result != NULL && UseG1GC) {
+ G1SATBCardTableModRefBS::enqueue(result);
+ }
+#endif // INCLUDE_ALL_GCS
+ return result;
+}
+
+template oop JNIHandles::resolve_jweak<true>(jweak);
+template oop JNIHandles::resolve_jweak<false>(jweak);
void JNIHandles::destroy_global(jobject handle) {
if (handle != NULL) {
assert(is_global_handle(handle), "Invalid delete of global JNI handle");
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jobject_ref(handle) = deleted_handle();
}
}
-
void JNIHandles::destroy_weak_global(jobject handle) {
if (handle != NULL) {
- assert(!CheckJNICalls || is_weak_global_handle(handle), "Invalid delete of weak global JNI handle");
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jweak_ref(handle) = deleted_handle();
}
}
@@ -129,6 +151,12 @@ void JNIHandles::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
}
+void JNIHandles::weak_oops_do(OopClosure* f) {
+ AlwaysTrueClosure always_true;
+ weak_oops_do(&always_true, f);
+}
+
+
void JNIHandles::initialize() {
_global_handles = JNIHandleBlock::allocate_block();
_weak_global_handles = JNIHandleBlock::allocate_block();
@@ -186,11 +214,6 @@ long JNIHandles::weak_global_handle_memory_usage() {
}
-class AlwaysAliveClosure: public BoolObjectClosure {
-public:
- bool do_object_b(oop obj) { return true; }
-};
-
class CountHandleClosure: public OopClosure {
private:
int _count;
@@ -212,9 +235,8 @@ void JNIHandles::print_on(outputStream* st) {
"JNIHandles not initialized");
CountHandleClosure global_handle_count;
- AlwaysAliveClosure always_alive;
oops_do(&global_handle_count);
- weak_oops_do(&always_alive, &global_handle_count);
+ weak_oops_do(&global_handle_count);
st->print_cr("JNI global references: %d", global_handle_count.count());
st->cr();
@@ -231,10 +253,9 @@ public:
void JNIHandles::verify() {
VerifyHandleClosure verify_handle;
- AlwaysAliveClosure always_alive;
oops_do(&verify_handle);
- weak_oops_do(&always_alive, &verify_handle);
+ weak_oops_do(&verify_handle);
}
diff --git a/src/share/vm/runtime/jniHandles.hpp b/src/share/vm/runtime/jniHandles.hpp
index 1f749536f..645e45bf9 100644
--- a/src/share/vm/runtime/jniHandles.hpp
+++ b/src/share/vm/runtime/jniHandles.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, 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
@@ -40,7 +40,28 @@ class JNIHandles : AllStatic {
static JNIHandleBlock* _weak_global_handles; // First weak global handle block
static oop _deleted_handle; // Sentinel marking deleted handles
+ inline static bool is_jweak(jobject handle);
+ inline static oop& jobject_ref(jobject handle); // NOT jweak!
+ inline static oop& jweak_ref(jobject handle);
+
+ template<bool external_guard> inline static oop guard_value(oop value);
+ template<bool external_guard> inline static oop resolve_impl(jobject handle);
+ template<bool external_guard> static oop resolve_jweak(jweak handle);
+
public:
+ // Low tag bit in jobject used to distinguish a jweak. jweak is
+ // type equivalent to jobject, but there are places where we need to
+ // be able to distinguish jweak values from other jobjects, and
+ // is_weak_global_handle is unsuitable for performance reasons. To
+ // provide such a test we add weak_tag_value to the (aligned) byte
+ // address designated by the jobject to produce the corresponding
+ // jweak. Accessing the value of a jobject must account for it
+ // being a possibly offset jweak.
+ static const uintptr_t weak_tag_size = 1;
+ static const uintptr_t weak_tag_alignment = (1u << weak_tag_size);
+ static const uintptr_t weak_tag_mask = weak_tag_alignment - 1;
+ static const int weak_tag_value = 1;
+
// Resolve handle into oop
inline static oop resolve(jobject handle);
// Resolve externally provided handle into oop with some guards
@@ -86,6 +107,8 @@ class JNIHandles : AllStatic {
static void oops_do(OopClosure* f);
// Traversal of weak global handles. Unreachable oops are cleared.
static void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f);
+ // Traversal of weak global handles.
+ static void weak_oops_do(OopClosure* f);
};
@@ -171,36 +194,85 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
#endif
};
+inline bool JNIHandles::is_jweak(jobject handle) {
+ STATIC_ASSERT(weak_tag_size == 1);
+ STATIC_ASSERT(weak_tag_value == 1);
+ return (reinterpret_cast<uintptr_t>(handle) & weak_tag_mask) != 0;
+}
-inline oop JNIHandles::resolve(jobject handle) {
- oop result = (handle == NULL ? (oop)NULL : *(oop*)handle);
- assert(result != NULL || (handle == NULL || !CheckJNICalls || is_weak_global_handle(handle)), "Invalid value read from jni handle");
- assert(result != badJNIHandle, "Pointing to zapped jni handle area");
+inline oop& JNIHandles::jobject_ref(jobject handle) {
+ assert(!is_jweak(handle), "precondition");
+ return *reinterpret_cast<oop*>(handle);
+}
+
+inline oop& JNIHandles::jweak_ref(jobject handle) {
+ assert(is_jweak(handle), "precondition");
+ char* ptr = reinterpret_cast<char*>(handle) - weak_tag_value;
+ return *reinterpret_cast<oop*>(ptr);
+}
+
+// external_guard is true if called from resolve_external_guard.
+// Treat deleted (and possibly zapped) as NULL for external_guard,
+// else as (asserted) error.
+template<bool external_guard>
+inline oop JNIHandles::guard_value(oop value) {
+ if (!external_guard) {
+ assert(value != badJNIHandle, "Pointing to zapped jni handle area");
+ assert(value != deleted_handle(), "Used a deleted global handle");
+ } else if ((value == badJNIHandle) || (value == deleted_handle())) {
+ value = NULL;
+ }
+ return value;
+}
+
+// external_guard is true if called from resolve_external_guard.
+template<bool external_guard>
+inline oop JNIHandles::resolve_impl(jobject handle) {
+ assert(handle != NULL, "precondition");
+ oop result;
+ if (is_jweak(handle)) { // Unlikely
+ result = resolve_jweak<external_guard>(handle);
+ } else {
+ result = jobject_ref(handle);
+ // Construction of jobjects canonicalize a null value into a null
+ // jobject, so for non-jweak the pointee should never be null.
+ assert(external_guard || result != NULL,
+ "Invalid value read from jni handle");
+ result = guard_value<external_guard>(result);
+ }
return result;
-};
+}
+inline oop JNIHandles::resolve(jobject handle) {
+ oop result = NULL;
+ if (handle != NULL) {
+ result = resolve_impl<false /* external_guard */ >(handle);
+ }
+ return result;
+}
+// Resolve some erroneous cases to NULL, rather than treating them as
+// possibly unchecked errors. In particular, deleted handles are
+// treated as NULL (though a deleted and later reallocated handle
+// isn't detected).
inline oop JNIHandles::resolve_external_guard(jobject handle) {
- if (handle == NULL) return NULL;
- oop result = *(oop*)handle;
- if (result == NULL || result == badJNIHandle) return NULL;
+ oop result = NULL;
+ if (handle != NULL) {
+ result = resolve_impl<true /* external_guard */ >(handle);
+ }
return result;
-};
-
+}
inline oop JNIHandles::resolve_non_null(jobject handle) {
assert(handle != NULL, "JNI handle should not be null");
- oop result = *(oop*)handle;
- assert(result != NULL, "Invalid value read from jni handle");
- assert(result != badJNIHandle, "Pointing to zapped jni handle area");
- // Don't let that private _deleted_handle object escape into the wild.
- assert(result != deleted_handle(), "Used a deleted global handle.");
+ oop result = resolve_impl<false /* external_guard */ >(handle);
+ assert(result != NULL, "NULL read from jni handle");
return result;
-};
+}
inline void JNIHandles::destroy_local(jobject handle) {
if (handle != NULL) {
- *((oop*)handle) = deleted_handle(); // Mark the handle as deleted, allocate will reuse it
+ jobject_ref(handle) = deleted_handle();
}
}
diff --git a/src/share/vm/runtime/mutexLocker.cpp b/src/share/vm/runtime/mutexLocker.cpp
index f358c75ea..1f61967aa 100644
--- a/src/share/vm/runtime/mutexLocker.cpp
+++ b/src/share/vm/runtime/mutexLocker.cpp
@@ -125,6 +125,7 @@ Monitor* GCTaskManager_lock = NULL;
Mutex* Management_lock = NULL;
Monitor* Service_lock = NULL;
Monitor* PeriodicTask_lock = NULL;
+Monitor* RedefineClasses_lock = NULL;
#ifdef INCLUDE_TRACE
Mutex* JfrStacktrace_lock = NULL;
@@ -279,6 +280,7 @@ void mutex_init() {
def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread
def(CompileThread_lock , Monitor, nonleaf+5, false );
def(PeriodicTask_lock , Monitor, nonleaf+5, true);
+ def(RedefineClasses_lock , Monitor, nonleaf+5, true);
#ifdef INCLUDE_TRACE
def(JfrMsg_lock , Monitor, leaf, true);
diff --git a/src/share/vm/runtime/mutexLocker.hpp b/src/share/vm/runtime/mutexLocker.hpp
index be86bac71..138e30e83 100644
--- a/src/share/vm/runtime/mutexLocker.hpp
+++ b/src/share/vm/runtime/mutexLocker.hpp
@@ -141,6 +141,7 @@ extern Mutex* MMUTracker_lock; // protects the MMU
extern Mutex* Management_lock; // a lock used to serialize JVM management
extern Monitor* Service_lock; // a lock used for service thread operation
extern Monitor* PeriodicTask_lock; // protects the periodic task structure
+extern Monitor* RedefineClasses_lock; // locks classes from parallel redefinition
#ifdef INCLUDE_TRACE
extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table
diff --git a/src/share/vm/runtime/os.cpp b/src/share/vm/runtime/os.cpp
index 8cf2ed994..f4b593be9 100644
--- a/src/share/vm/runtime/os.cpp
+++ b/src/share/vm/runtime/os.cpp
@@ -1284,7 +1284,7 @@ char** os::split_path(const char* path, int* n) {
}
void os::set_memory_serialize_page(address page) {
- int count = log2_intptr(sizeof(class JavaThread)) - log2_intptr(64);
+ int count = log2_intptr(sizeof(class JavaThread)) - log2_int(64);
_mem_serialize_page = (volatile int32_t *)page;
// We initialize the serialization page shift count here
// We assume a cache line size of 64 bytes
diff --git a/src/share/vm/runtime/os.hpp b/src/share/vm/runtime/os.hpp
index 92553ab47..14cd94237 100644
--- a/src/share/vm/runtime/os.hpp
+++ b/src/share/vm/runtime/os.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -527,7 +527,7 @@ class os: AllStatic {
static char* do_you_want_to_debug(const char* message);
// run cmd in a separate process and return its exit code; or -1 on failures
- static int fork_and_exec(char *cmd);
+ static int fork_and_exec(char *cmd, bool use_vfork_if_available = false);
// os::exit() is merged with vm_exit()
// static void exit(int num);
@@ -561,8 +561,7 @@ class os: AllStatic {
// Reading directories.
static DIR* opendir(const char* dirname);
- static int readdir_buf_size(const char *path);
- static struct dirent* readdir(DIR* dirp, dirent* dbuf);
+ static struct dirent* readdir(DIR* dirp);
static int closedir(DIR* dirp);
// Dynamic library extension
diff --git a/src/share/vm/runtime/simpleThresholdPolicy.cpp b/src/share/vm/runtime/simpleThresholdPolicy.cpp
index 11803f1f6..5eb6f97c5 100644
--- a/src/share/vm/runtime/simpleThresholdPolicy.cpp
+++ b/src/share/vm/runtime/simpleThresholdPolicy.cpp
@@ -139,7 +139,7 @@ void SimpleThresholdPolicy::initialize() {
}
int count = CICompilerCount;
if (CICompilerCountPerCPU) {
- count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2;
+ count = MAX2(log2_int(os::active_processor_count()), 1) * 3 / 2;
}
set_c1_count(MAX2(count / 3, 1));
set_c2_count(MAX2(count - c1_count(), 1));
diff --git a/src/share/vm/runtime/stubRoutines.cpp b/src/share/vm/runtime/stubRoutines.cpp
index eb3064034..6b8f7e754 100644
--- a/src/share/vm/runtime/stubRoutines.cpp
+++ b/src/share/vm/runtime/stubRoutines.cpp
@@ -174,6 +174,9 @@ void StubRoutines::initialize1() {
}
CodeBuffer buffer(_code1);
StubGenerator_generate(&buffer, false);
+ // When new stubs added we need to make sure there is some space left
+ // to catch situation when we should increase size again.
+ assert(buffer.insts_remaining() > 200, "increase code_size1");
}
}
@@ -226,6 +229,9 @@ void StubRoutines::initialize2() {
}
CodeBuffer buffer(_code2);
StubGenerator_generate(&buffer, true);
+ // When new stubs added we need to make sure there is some space left
+ // to catch situation when we should increase size again.
+ assert(buffer.insts_remaining() > 200, "increase code_size2");
}
#ifdef ASSERT
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
index 48bba789f..5d56cfea3 100644
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
@@ -1310,6 +1310,7 @@ void WatcherThread::run() {
this->record_stack_base_and_size();
this->initialize_thread_local_storage();
+ this->set_native_thread_name(this->name());
this->set_active_handles(JNIHandleBlock::allocate_block());
while(!_should_terminate) {
assert(watcher_thread() == Thread::current(), "thread consistency check");
diff --git a/src/share/vm/runtime/vmThread.cpp b/src/share/vm/runtime/vmThread.cpp
index 0ee5982a9..d08c5db81 100644
--- a/src/share/vm/runtime/vmThread.cpp
+++ b/src/share/vm/runtime/vmThread.cpp
@@ -252,6 +252,7 @@ void VMThread::run() {
assert(this == vm_thread(), "check");
this->initialize_thread_local_storage();
+ this->set_native_thread_name(this->name());
this->record_stack_base_and_size();
// Notify_lock wait checks on active_handles() to rewait in
// case of spurious wakeup, it should wait on the last
diff --git a/src/share/vm/services/classLoadingService.cpp b/src/share/vm/services/classLoadingService.cpp
index 92a548ba5..fce2b27f8 100644
--- a/src/share/vm/services/classLoadingService.cpp
+++ b/src/share/vm/services/classLoadingService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -69,7 +69,7 @@ HS_DTRACE_PROBE_DECL4(hotspot, class__unloaded, char*, int, oop, bool);
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_##type( /* type = unloaded, loaded */ \
- data, len, (clss)->class_loader(), (shared)); \
+ data, len, (void *)(clss)->class_loader(), (shared)); \
}
#endif /* USDT2 */
diff --git a/src/share/vm/services/heapDumper.cpp b/src/share/vm/services/heapDumper.cpp
index a62ce9114..e5de80eae 100644
--- a/src/share/vm/services/heapDumper.cpp
+++ b/src/share/vm/services/heapDumper.cpp
@@ -941,8 +941,14 @@ void DumperSupport::dump_instance(DumpWriter* writer, oop o) {
// its array classes
void DumperSupport::dump_class_and_array_classes(DumpWriter* writer, Klass* k) {
Klass* klass = k;
- assert(klass->oop_is_instance(), "not an InstanceKlass");
- InstanceKlass* ik = (InstanceKlass*)klass;
+ InstanceKlass* ik = InstanceKlass::cast(k);
+
+ // We can safepoint and do a heap dump at a point where we have a Klass,
+ // but no java mirror class has been setup for it. So we need to check
+ // that the class is at least loaded, to avoid crash from a null mirror.
+ if (!ik->is_loaded()) {
+ return;
+ }
writer->write_u1(HPROF_GC_CLASS_DUMP);
diff --git a/src/share/vm/services/memReporter.cpp b/src/share/vm/services/memReporter.cpp
index 8199ee0aa..67e3eea09 100644
--- a/src/share/vm/services/memReporter.cpp
+++ b/src/share/vm/services/memReporter.cpp
@@ -572,9 +572,15 @@ void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const
void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early,
const MallocSite* current) const {
- assert(early->flags() == current->flags(), "Must be the same memory type");
- diff_malloc_site(current->call_stack(), current->size(), current->count(),
- early->size(), early->count(), early->flags());
+ if (early->flags() != current->flags()) {
+ // If malloc site type changed, treat it as deallocation of old type and
+ // allocation of new type.
+ old_malloc_site(early);
+ new_malloc_site(current);
+ } else {
+ diff_malloc_site(current->call_stack(), current->size(), current->count(),
+ early->size(), early->count(), early->flags());
+ }
}
void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_t current_size,
diff --git a/src/share/vm/services/memoryManager.cpp b/src/share/vm/services/memoryManager.cpp
index d3c41fed9..26d6ed004 100644
--- a/src/share/vm/services/memoryManager.cpp
+++ b/src/share/vm/services/memoryManager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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,13 +49,15 @@ MemoryManager::MemoryManager() {
(void)const_cast<instanceOop&>(_memory_mgr_obj = instanceOop(NULL));
}
-void MemoryManager::add_pool(MemoryPool* pool) {
- assert(_num_pools < MemoryManager::max_num_pools, "_num_pools exceeds the max");
- if (_num_pools < MemoryManager::max_num_pools) {
- _pools[_num_pools] = pool;
+int MemoryManager::add_pool(MemoryPool* pool) {
+ int index = _num_pools;
+ assert(index < MemoryManager::max_num_pools, "_num_pools exceeds the max");
+ if (index < MemoryManager::max_num_pools) {
+ _pools[index] = pool;
_num_pools++;
}
pool->add_manager(this);
+ return index;
}
MemoryManager* MemoryManager::get_code_cache_memory_manager() {
@@ -217,6 +219,15 @@ GCMemoryManager::~GCMemoryManager() {
delete _current_gc_stat;
}
+void GCMemoryManager::add_pool(MemoryPool* pool) {
+ add_pool(pool, true);
+}
+
+void GCMemoryManager::add_pool(MemoryPool* pool, bool always_affected_by_gc) {
+ int index = MemoryManager::add_pool(pool);
+ _pool_always_affected_by_gc[index] = always_affected_by_gc;
+}
+
void GCMemoryManager::initialize_gc_stat_info() {
assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
_last_gc_stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(MemoryService::num_memory_pools());
@@ -266,7 +277,8 @@ void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
void GCMemoryManager::gc_end(bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection,
- GCCause::Cause cause) {
+ GCCause::Cause cause,
+ bool allMemoryPoolsAffected) {
if (recordAccumulatedGCTime) {
_accumulated_timer.stop();
}
@@ -304,8 +316,11 @@ void GCMemoryManager::gc_end(bool recordPostGCUsage,
MemoryUsage usage = pool->get_memory_usage();
// Compare with GC usage threshold
- pool->set_last_collection_usage(usage);
- LowMemoryDetector::detect_after_gc_memory(pool);
+ if (allMemoryPoolsAffected || pool_always_affected_by_gc(i)) {
+ // Compare with GC usage threshold
+ pool->set_last_collection_usage(usage);
+ LowMemoryDetector::detect_after_gc_memory(pool);
+ }
}
}
diff --git a/src/share/vm/services/memoryManager.hpp b/src/share/vm/services/memoryManager.hpp
index 8e61f521b..dde6638c7 100644
--- a/src/share/vm/services/memoryManager.hpp
+++ b/src/share/vm/services/memoryManager.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -41,11 +41,12 @@ class GCMemoryManager;
class OopClosure;
class MemoryManager : public CHeapObj<mtInternal> {
-private:
+protected:
enum {
max_num_pools = 10
};
+private:
MemoryPool* _pools[max_num_pools];
int _num_pools;
@@ -75,7 +76,7 @@ public:
return _pools[index];
}
- void add_pool(MemoryPool* pool);
+ int add_pool(MemoryPool* pool);
bool is_manager(instanceHandle mh) { return mh() == _memory_mgr_obj; }
@@ -177,10 +178,20 @@ private:
GCStatInfo* _current_gc_stat;
int _num_gc_threads;
volatile bool _notification_enabled;
+ bool _pool_always_affected_by_gc[MemoryManager::max_num_pools];
+
public:
GCMemoryManager();
~GCMemoryManager();
+ void add_pool(MemoryPool* pool);
+ void add_pool(MemoryPool* pool, bool always_affected_by_gc);
+
+ bool pool_always_affected_by_gc(int index) {
+ assert(index >= 0 && index < num_memory_pools(), "Invalid index");
+ return _pool_always_affected_by_gc[index];
+ }
+
void initialize_gc_stat_info();
bool is_gc_memory_manager() { return true; }
@@ -192,7 +203,8 @@ public:
void gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,
bool recordAccumulatedGCTime);
void gc_end(bool recordPostGCUsage, bool recordAccumulatedGCTime,
- bool recordGCEndTime, bool countCollection, GCCause::Cause cause);
+ bool recordGCEndTime, bool countCollection, GCCause::Cause cause,
+ bool allMemoryPoolsAffected);
void reset_gc_stat() { _num_collections = 0; _accumulated_timer.reset(); }
diff --git a/src/share/vm/services/memoryService.cpp b/src/share/vm/services/memoryService.cpp
index 8115a3e24..31cf2badc 100644
--- a/src/share/vm/services/memoryService.cpp
+++ b/src/share/vm/services/memoryService.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -187,7 +187,7 @@ void MemoryService::add_g1_heap_info(G1CollectedHeap* g1h) {
_managers_list->append(_major_gc_manager);
add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
- add_g1OldGen_memory_pool(g1h, _major_gc_manager);
+ add_g1OldGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
}
#endif // INCLUDE_ALL_GCS
@@ -241,8 +241,8 @@ MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space,
// Add memory pool(s) for one generation
void MemoryService::add_generation_memory_pool(Generation* gen,
- MemoryManager* major_mgr,
- MemoryManager* minor_mgr) {
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr) {
guarantee(gen != NULL, "No generation for memory pool");
Generation::Name kind = gen->kind();
int index = _pools_list->length();
@@ -332,7 +332,9 @@ void MemoryService::add_generation_memory_pool(Generation* gen,
#if INCLUDE_ALL_GCS
-void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) {
+void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen,
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr) {
assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers");
// Add a memory pool for each space and young gen doesn't
@@ -356,7 +358,7 @@ void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* majo
_pools_list->append(survivor);
}
-void MemoryService::add_psOld_memory_pool(PSOldGen* gen, MemoryManager* mgr) {
+void MemoryService::add_psOld_memory_pool(PSOldGen* gen, GCMemoryManager* mgr) {
PSGenerationPool* old_gen = new PSGenerationPool(gen,
"PS Old Gen",
MemoryPool::Heap,
@@ -366,8 +368,8 @@ void MemoryService::add_psOld_memory_pool(PSOldGen* gen, MemoryManager* mgr) {
}
void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
- MemoryManager* major_mgr,
- MemoryManager* minor_mgr) {
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr) {
assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
G1EdenPool* eden = new G1EdenPool(g1h);
@@ -382,11 +384,13 @@ void MemoryService::add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
}
void MemoryService::add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
- MemoryManager* mgr) {
- assert(mgr != NULL, "should have one manager");
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr) {
+ assert(major_mgr != NULL && minor_mgr != NULL, "should have two managers");
G1OldGenPool* old_gen = new G1OldGenPool(g1h);
- mgr->add_pool(old_gen);
+ major_mgr->add_pool(old_gen);
+ minor_mgr->add_pool(old_gen, false /* always_affected_by_gc */);
_pools_list->append(old_gen);
}
#endif // INCLUDE_ALL_GCS
@@ -484,7 +488,8 @@ void MemoryService::gc_begin(bool fullGC, bool recordGCBeginTime,
void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection,
- GCCause::Cause cause) {
+ GCCause::Cause cause,
+ bool allMemoryPoolsAffected) {
GCMemoryManager* mgr;
if (fullGC) {
@@ -496,7 +501,7 @@ void MemoryService::gc_end(bool fullGC, bool recordPostGCUsage,
// register the GC end statistics and memory usage
mgr->gc_end(recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
- countCollection, cause);
+ countCollection, cause, allMemoryPoolsAffected);
}
void MemoryService::oops_do(OopClosure* f) {
@@ -573,10 +578,11 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause:
}
// this has to be called in a stop the world pause and represent
// an entire gc pause, start to finish:
- initialize(_fullGC, cause,true, true, true, true, true, true, true);
+ initialize(_fullGC, cause, true, true, true, true, true, true, true, true);
}
TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
GCCause::Cause cause,
+ bool allMemoryPoolsAffected,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
@@ -584,7 +590,8 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
bool recordAccumulatedGCTime,
bool recordGCEndTime,
bool countCollection) {
- initialize(fullGC, cause, recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
+ initialize(fullGC, cause, allMemoryPoolsAffected,
+ recordGCBeginTime, recordPreGCUsage, recordPeakUsage,
recordPostGCUsage, recordAccumulatedGCTime, recordGCEndTime,
countCollection);
}
@@ -593,6 +600,7 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(bool fullGC,
// the MemoryService
void TraceMemoryManagerStats::initialize(bool fullGC,
GCCause::Cause cause,
+ bool allMemoryPoolsAffected,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
@@ -601,6 +609,7 @@ void TraceMemoryManagerStats::initialize(bool fullGC,
bool recordGCEndTime,
bool countCollection) {
_fullGC = fullGC;
+ _allMemoryPoolsAffected = allMemoryPoolsAffected;
_recordGCBeginTime = recordGCBeginTime;
_recordPreGCUsage = recordPreGCUsage;
_recordPeakUsage = recordPeakUsage;
@@ -616,5 +625,5 @@ void TraceMemoryManagerStats::initialize(bool fullGC,
TraceMemoryManagerStats::~TraceMemoryManagerStats() {
MemoryService::gc_end(_fullGC, _recordPostGCUsage, _recordAccumulatedGCTime,
- _recordGCEndTime, _countCollection, _cause);
+ _recordGCEndTime, _countCollection, _cause, _allMemoryPoolsAffected);
}
diff --git a/src/share/vm/services/memoryService.hpp b/src/share/vm/services/memoryService.hpp
index 23979ed67..ce1685961 100644
--- a/src/share/vm/services/memoryService.hpp
+++ b/src/share/vm/services/memoryService.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -77,25 +77,26 @@ private:
static MemoryPool* _compressed_class_pool;
static void add_generation_memory_pool(Generation* gen,
- MemoryManager* major_mgr,
- MemoryManager* minor_mgr);
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr);
static void add_generation_memory_pool(Generation* gen,
- MemoryManager* major_mgr) {
+ GCMemoryManager* major_mgr) {
add_generation_memory_pool(gen, major_mgr, NULL);
}
static void add_psYoung_memory_pool(PSYoungGen* gen,
- MemoryManager* major_mgr,
- MemoryManager* minor_mgr);
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr);
static void add_psOld_memory_pool(PSOldGen* gen,
- MemoryManager* mgr);
+ GCMemoryManager* mgr);
static void add_g1YoungGen_memory_pool(G1CollectedHeap* g1h,
- MemoryManager* major_mgr,
- MemoryManager* minor_mgr);
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr);
static void add_g1OldGen_memory_pool(G1CollectedHeap* g1h,
- MemoryManager* mgr);
+ GCMemoryManager* major_mgr,
+ GCMemoryManager* minor_mgr);
static MemoryPool* add_space(ContiguousSpace* space,
const char* name,
@@ -162,7 +163,8 @@ public:
static void gc_end(bool fullGC, bool recordPostGCUsage,
bool recordAccumulatedGCTime,
bool recordGCEndTime, bool countCollection,
- GCCause::Cause cause);
+ GCCause::Cause cause,
+ bool allMemoryPoolsAffected);
static void oops_do(OopClosure* f);
@@ -185,6 +187,7 @@ public:
class TraceMemoryManagerStats : public StackObj {
private:
bool _fullGC;
+ bool _allMemoryPoolsAffected;
bool _recordGCBeginTime;
bool _recordPreGCUsage;
bool _recordPeakUsage;
@@ -197,6 +200,7 @@ public:
TraceMemoryManagerStats() {}
TraceMemoryManagerStats(bool fullGC,
GCCause::Cause cause,
+ bool allMemoryPoolsAffected = true,
bool recordGCBeginTime = true,
bool recordPreGCUsage = true,
bool recordPeakUsage = true,
@@ -207,6 +211,7 @@ public:
void initialize(bool fullGC,
GCCause::Cause cause,
+ bool allMemoryPoolsAffected,
bool recordGCBeginTime,
bool recordPreGCUsage,
bool recordPeakUsage,
diff --git a/src/share/vm/shark/sharkNativeWrapper.cpp b/src/share/vm/shark/sharkNativeWrapper.cpp
index 53fea3154..27cb29aa2 100644
--- a/src/share/vm/shark/sharkNativeWrapper.cpp
+++ b/src/share/vm/shark/sharkNativeWrapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -50,6 +50,7 @@ void SharkNativeWrapper::initialize(const char *name) {
// Create and push our stack frame
builder()->SetInsertPoint(CreateBlock());
+#error Needs to be updated for tagged jweak; see JNIHandles.
_stack = SharkStack::CreateBuildAndPushFrame(this, method);
NOT_PRODUCT(method = NULL);
diff --git a/src/share/vm/utilities/bitMap.cpp b/src/share/vm/utilities/bitMap.cpp
index 4627a5321..e64add155 100644
--- a/src/share/vm/utilities/bitMap.cpp
+++ b/src/share/vm/utilities/bitMap.cpp
@@ -154,14 +154,24 @@ void BitMap::clear_range(idx_t beg, idx_t end) {
}
}
+bool BitMap::is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word) {
+ // There is little point to call large version on small ranges.
+ // Need to check carefully, keeping potential idx_t underflow in mind.
+ // The threshold should be at least one word.
+ STATIC_ASSERT(small_range_words >= 1);
+ return (beg_full_word + small_range_words >= end_full_word);
+}
+
void BitMap::set_large_range(idx_t beg, idx_t end) {
verify_range(beg, end);
idx_t beg_full_word = word_index_round_up(beg);
idx_t end_full_word = word_index(end);
- assert(end_full_word - beg_full_word >= 32,
- "the range must include at least 32 bytes");
+ if (is_small_range_of_words(beg_full_word, end_full_word)) {
+ set_range(beg, end);
+ return;
+ }
// The range includes at least one full word.
set_range_within_word(beg, bit_index(beg_full_word));
@@ -175,8 +185,10 @@ void BitMap::clear_large_range(idx_t beg, idx_t end) {
idx_t beg_full_word = word_index_round_up(beg);
idx_t end_full_word = word_index(end);
- assert(end_full_word - beg_full_word >= 32,
- "the range must include at least 32 bytes");
+ if (is_small_range_of_words(beg_full_word, end_full_word)) {
+ clear_range(beg, end);
+ return;
+ }
// The range includes at least one full word.
clear_range_within_word(beg, bit_index(beg_full_word));
@@ -264,8 +276,10 @@ void BitMap::par_at_put_large_range(idx_t beg, idx_t end, bool value) {
idx_t beg_full_word = word_index_round_up(beg);
idx_t end_full_word = word_index(end);
- assert(end_full_word - beg_full_word >= 32,
- "the range must include at least 32 bytes");
+ if (is_small_range_of_words(beg_full_word, end_full_word)) {
+ par_at_put_range(beg, end, value);
+ return;
+ }
// The range includes at least one full word.
par_put_range_within_word(beg, bit_index(beg_full_word), value);
diff --git a/src/share/vm/utilities/bitMap.hpp b/src/share/vm/utilities/bitMap.hpp
index e04f71843..51c58da8e 100644
--- a/src/share/vm/utilities/bitMap.hpp
+++ b/src/share/vm/utilities/bitMap.hpp
@@ -56,6 +56,10 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
// the bitmap appropriately if needed using factor-of-two expansion.
void at_put_grow(idx_t index, bool value);
+ // Threshold for performing small range operation, even when large range
+ // operation was requested. Measured in words.
+ static const size_t small_range_words = 32;
+
protected:
// Return the position of bit within the word that contains it (e.g., if
// bitmap words are 32 bits, return a number 0 <= n <= 31).
@@ -97,6 +101,8 @@ class BitMap VALUE_OBJ_CLASS_SPEC {
void set_large_range_of_words (idx_t beg, idx_t end);
void clear_large_range_of_words (idx_t beg, idx_t end);
+ static bool is_small_range_of_words(idx_t beg_full_word, idx_t end_full_word);
+
// The index of the first full word in a range.
idx_t word_index_round_up(idx_t bit) const;
diff --git a/src/share/vm/utilities/bitMap.inline.hpp b/src/share/vm/utilities/bitMap.inline.hpp
index 318b178f1..ef4c30930 100644
--- a/src/share/vm/utilities/bitMap.inline.hpp
+++ b/src/share/vm/utilities/bitMap.inline.hpp
@@ -321,10 +321,12 @@ BitMap::inverted_bit_mask_for_range(idx_t beg, idx_t end) const {
}
inline void BitMap::set_large_range_of_words(idx_t beg, idx_t end) {
+ assert(beg <= end, "underflow");
memset(_map + beg, ~(unsigned char)0, (end - beg) * sizeof(uintptr_t));
}
inline void BitMap::clear_large_range_of_words(idx_t beg, idx_t end) {
+ assert(beg <= end, "underflow");
memset(_map + beg, 0, (end - beg) * sizeof(uintptr_t));
}
diff --git a/src/share/vm/utilities/globalDefinitions.cpp b/src/share/vm/utilities/globalDefinitions.cpp
index 20c11862e..888e8d453 100644
--- a/src/share/vm/utilities/globalDefinitions.cpp
+++ b/src/share/vm/utilities/globalDefinitions.cpp
@@ -384,4 +384,67 @@ void GlobalDefinitions::test_globals() {
}
}
+#define EXPECT_EQ(expected, actual) \
+ assert(expected == actual, "Test failed");
+#define EXPECT_STREQ(expected, actual) \
+ assert(strcmp(expected, actual) == 0, "Test failed");
+
+void GlobalDefinitions::test_proper_unit() {
+ EXPECT_EQ(0u, byte_size_in_proper_unit(0u));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(0u));
+
+ EXPECT_EQ(1u, byte_size_in_proper_unit(1u));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(1u));
+
+ EXPECT_EQ(1023u, byte_size_in_proper_unit(K - 1));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(K - 1));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(K));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(K));
+
+ EXPECT_EQ(1025u, byte_size_in_proper_unit(K + 1));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(K + 1));
+
+ EXPECT_EQ(51200u, byte_size_in_proper_unit(50*K));
+ EXPECT_STREQ("B", proper_unit_for_byte_size(50*K));
+
+ EXPECT_EQ(1023u, byte_size_in_proper_unit(M - 1));
+ EXPECT_STREQ("K", proper_unit_for_byte_size(M - 1));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(M));
+ EXPECT_STREQ("K", proper_unit_for_byte_size(M));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(M + 1));
+ EXPECT_STREQ("K", proper_unit_for_byte_size(M + 1));
+
+ EXPECT_EQ(1025u, byte_size_in_proper_unit(M + K));
+ EXPECT_STREQ("K", proper_unit_for_byte_size(M + K));
+
+ EXPECT_EQ(51200u, byte_size_in_proper_unit(50*M));
+ EXPECT_STREQ("K", proper_unit_for_byte_size(50*M));
+
+#ifdef _LP64
+ EXPECT_EQ(1023u, byte_size_in_proper_unit(G - 1));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(G - 1));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(G));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(G));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(G + 1));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(G + 1));
+
+ EXPECT_EQ(1024u, byte_size_in_proper_unit(G + K));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(G + K));
+
+ EXPECT_EQ(1025u, byte_size_in_proper_unit(G + M));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(G + M));
+
+ EXPECT_EQ(51200u, byte_size_in_proper_unit(50*G));
+ EXPECT_STREQ("M", proper_unit_for_byte_size(50*G));
+#endif
+}
+
+#undef EXPECT_EQ
+#undef EXPECT_STREQ
+
#endif // PRODUCT
diff --git a/src/share/vm/utilities/globalDefinitions.hpp b/src/share/vm/utilities/globalDefinitions.hpp
index 2fb6a3cad..2659418be 100644
--- a/src/share/vm/utilities/globalDefinitions.hpp
+++ b/src/share/vm/utilities/globalDefinitions.hpp
@@ -211,15 +211,20 @@ const int NANOUNITS = 1000000000; // nano units per base unit
const jlong NANOSECS_PER_SEC = CONST64(1000000000);
const jint NANOSECS_PER_MILLISEC = 1000000;
+// Proper units routines try to maintain at least three significant digits.
+// In worst case, it would print five significant digits with lower prefix.
+// G is close to MAX_SIZE on 32-bit platforms, so its product can easily overflow,
+// and therefore we need to be careful.
+
inline const char* proper_unit_for_byte_size(size_t s) {
#ifdef _LP64
- if (s >= 10*G) {
+ if (s >= 100*G) {
return "G";
}
#endif
- if (s >= 10*M) {
+ if (s >= 100*M) {
return "M";
- } else if (s >= 10*K) {
+ } else if (s >= 100*K) {
return "K";
} else {
return "B";
@@ -229,13 +234,13 @@ inline const char* proper_unit_for_byte_size(size_t s) {
template <class T>
inline T byte_size_in_proper_unit(T s) {
#ifdef _LP64
- if (s >= 10*G) {
+ if (s >= 100*G) {
return (T)(s/G);
}
#endif
- if (s >= 10*M) {
+ if (s >= 100*M) {
return (T)(s/M);
- } else if (s >= 10*K) {
+ } else if (s >= 100*K) {
return (T)(s/K);
} else {
return s;
@@ -327,7 +332,7 @@ inline size_t pointer_delta(const MetaWord* left, const MetaWord* right) {
// so far from the middle of the road that it is likely to be problematic in
// many C++ compilers.
//
-#define CAST_TO_FN_PTR(func_type, value) ((func_type)(castable_address(value)))
+#define CAST_TO_FN_PTR(func_type, value) (reinterpret_cast<func_type>(value))
#define CAST_FROM_FN_PTR(new_type, func_ptr) ((new_type)((address_word)(func_ptr)))
// Unsigned byte types for os and stream.hpp
@@ -1136,10 +1141,10 @@ inline bool is_power_of_2_long(jlong x) {
//* largest i such that 2^i <= x
// A negative value of 'x' will return '31'
-inline int log2_intptr(intptr_t x) {
+inline int log2_intptr(uintptr_t x) {
int i = -1;
uintptr_t p = 1;
- while (p != 0 && p <= (uintptr_t)x) {
+ while (p != 0 && p <= x) {
// p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
i++; p *= 2;
}
@@ -1149,11 +1154,10 @@ inline int log2_intptr(intptr_t x) {
}
//* largest i such that 2^i <= x
-// A negative value of 'x' will return '63'
-inline int log2_long(jlong x) {
+inline int log2_long(julong x) {
int i = -1;
julong p = 1;
- while (p != 0 && p <= (julong)x) {
+ while (p != 0 && p <= x) {
// p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
i++; p *= 2;
}
@@ -1162,6 +1166,27 @@ inline int log2_long(jlong x) {
return i;
}
+inline int log2_intptr(intptr_t x) {
+ return log2_intptr((uintptr_t)x);
+}
+
+inline int log2_int(int x) {
+ return log2_intptr((uintptr_t)x);
+}
+
+inline int log2_jint(jint x) {
+ return log2_intptr((uintptr_t)x);
+}
+
+inline int log2_uint(uint x) {
+ return log2_intptr((uintptr_t)x);
+}
+
+// A negative value of 'x' will return '63'
+inline int log2_jlong(jlong x) {
+ return log2_long((julong)x);
+}
+
//* the argument must be exactly a power of 2
inline int exact_log2(intptr_t x) {
#ifdef ASSERT
@@ -1201,6 +1226,29 @@ inline intptr_t round_down(intptr_t x, uintx s) {
inline bool is_odd (intx x) { return x & 1; }
inline bool is_even(intx x) { return !is_odd(x); }
+// abs methods which cannot overflow and so are well-defined across
+// the entire domain of integer types.
+static inline unsigned int uabs(unsigned int n) {
+ union {
+ unsigned int result;
+ int value;
+ };
+ result = n;
+ if (value < 0) result = 0-result;
+ return result;
+}
+static inline julong uabs(julong n) {
+ union {
+ julong result;
+ jlong value;
+ };
+ result = n;
+ if (value < 0) result = 0-result;
+ return result;
+}
+static inline julong uabs(jlong n) { return uabs((julong)n); }
+static inline unsigned int uabs(int n) { return uabs((unsigned int)n); }
+
// "to" should be greater than "from."
inline intx byte_size(void* from, void* to) {
return (address)to - (address)from;
@@ -1403,6 +1451,32 @@ inline intptr_t p2i(const void * p) {
#define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
+//----------------------------------------------------------------------------------------------------
+// Sum and product which can never overflow: they wrap, just like the
+// Java operations. Note that we don't intend these to be used for
+// general-purpose arithmetic: their purpose is to emulate Java
+// operations.
+
+// The goal of this code to avoid undefined or implementation-defined
+// behaviour. The use of an lvalue to reference cast is explicitly
+// permitted by Lvalues and rvalues [basic.lval]. [Section 3.10 Para
+// 15 in C++03]
+#define JAVA_INTEGER_OP(OP, NAME, TYPE, UNSIGNED_TYPE) \
+inline TYPE NAME (TYPE in1, TYPE in2) { \
+ UNSIGNED_TYPE ures = static_cast<UNSIGNED_TYPE>(in1); \
+ ures OP ## = static_cast<UNSIGNED_TYPE>(in2); \
+ return reinterpret_cast<TYPE&>(ures); \
+}
+
+JAVA_INTEGER_OP(+, java_add, jint, juint)
+JAVA_INTEGER_OP(-, java_subtract, jint, juint)
+JAVA_INTEGER_OP(*, java_multiply, jint, juint)
+JAVA_INTEGER_OP(+, java_add, jlong, julong)
+JAVA_INTEGER_OP(-, java_subtract, jlong, julong)
+JAVA_INTEGER_OP(*, java_multiply, jlong, julong)
+
+#undef JAVA_INTEGER_OP
+
// Dereference vptr
// All C++ compilers that we know of have the vtbl pointer in the first
// word. If there are exceptions, this function needs to be made compiler
@@ -1417,6 +1491,7 @@ static inline void* dereference_vptr(const void* addr) {
class GlobalDefinitions {
public:
static void test_globals();
+ static void test_proper_unit();
};
#endif // PRODUCT
diff --git a/src/share/vm/utilities/hashtable.cpp b/src/share/vm/utilities/hashtable.cpp
index ec260e964..61c8f24f3 100644
--- a/src/share/vm/utilities/hashtable.cpp
+++ b/src/share/vm/utilities/hashtable.cpp
@@ -55,7 +55,7 @@ template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsig
if (_first_free_entry + _entry_size >= _end_block) {
int block_size = MIN2(512, MAX2((int)_table_size / 2, (int)_number_of_entries));
int len = _entry_size * block_size;
- len = 1 << log2_intptr(len); // round down to power of 2
+ len = 1 << log2_int(len); // round down to power of 2
assert(len >= _entry_size, "");
_first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
_end_block = _first_free_entry + len;
diff --git a/src/share/vm/utilities/taskqueue.hpp b/src/share/vm/utilities/taskqueue.hpp
index 8bdb38d31..d2b39c943 100644
--- a/src/share/vm/utilities/taskqueue.hpp
+++ b/src/share/vm/utilities/taskqueue.hpp
@@ -29,6 +29,7 @@
#include "memory/allocation.inline.hpp"
#include "runtime/mutex.hpp"
#include "runtime/orderAccess.inline.hpp"
+#include "utilities/globalDefinitions.hpp"
#include "utilities/stack.hpp"
// Simple TaskQueue stats that are collected by default in debug builds.
@@ -607,7 +608,9 @@ class ParallelTaskTerminator: public StackObj {
private:
int _n_threads;
TaskQueueSetSuper* _queue_set;
+ char _pad_before[DEFAULT_CACHE_LINE_SIZE];
int _offered_termination;
+ char _pad_after[DEFAULT_CACHE_LINE_SIZE];
#ifdef TRACESPINNING
static uint _total_yields;
diff --git a/src/share/vm/utilities/vmError.cpp b/src/share/vm/utilities/vmError.cpp
index 5b4225b60..2f6223d17 100644
--- a/src/share/vm/utilities/vmError.cpp
+++ b/src/share/vm/utilities/vmError.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -1060,7 +1060,7 @@ void VMError::report_and_die() {
out.print_raw (cmd);
out.print_raw_cr("\" ...");
- if (os::fork_and_exec(cmd) < 0) {
+ if (os::fork_and_exec(cmd, true) < 0) {
out.print_cr("os::fork_and_exec failed: %s (%d)", strerror(errno), errno);
}
}
diff --git a/test/Makefile b/test/Makefile
index e91844ece..447619b47 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -119,11 +119,11 @@ TEST_ROOT := $(shell pwd)
# Root of all test results
ifdef ALT_OUTPUTDIR
- ABS_BUILD_ROOT = $(ALT_OUTPUTDIR)/$(PLATFORM)-$(ARCH)
+ ABS_BUILD_ROOT = $(ALT_OUTPUTDIR)
else
ABS_BUILD_ROOT = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
endif
-ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput
+ABS_TEST_OUTPUT_DIR = $(ABS_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
ifndef PRODUCT_HOME
@@ -267,7 +267,7 @@ JTREG_BASIC_OPTIONS += -agentvm
# Only run automatic tests
JTREG_BASIC_OPTIONS += -a
# Report details on all failed or error tests, times too
-JTREG_BASIC_OPTIONS += -v:fail,error,time
+JTREG_BASIC_OPTIONS += -v:fail,error,summary
# Retain all files for failing tests
JTREG_BASIC_OPTIONS += -retain:fail,error
# Ignore tests are not run and completely silent about it
diff --git a/test/TEST.groups b/test/TEST.groups
index 40750364b..216e307cf 100644
--- a/test/TEST.groups
+++ b/test/TEST.groups
@@ -124,7 +124,6 @@ compact3 = \
-:needs_jre \
-:needs_jdk
-
# When called from top level the test suites use the hotspot_ prefix
hotspot_wbapitest = \
sanity/
@@ -147,6 +146,11 @@ hotspot_all = \
:hotspot_gc \
:hotspot_runtime \
:hotspot_serviceability
+
+# Right now tier1 runs all hotspot tests
+hotspot_tier1 = \
+ :jdk
+
# Tests that require compact3 API's
#
needs_compact3 = \
diff --git a/test/compiler/8209951/TestCipherBlockChainingEncrypt.java b/test/compiler/8209951/TestCipherBlockChainingEncrypt.java
new file mode 100644
index 000000000..649135eea
--- /dev/null
+++ b/test/compiler/8209951/TestCipherBlockChainingEncrypt.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2019, 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 8209951
+ * @summary SIGBUS in com.sun.crypto.provider.CipherBlockChaining
+ * @run main/othervm/timeout=300 -Xbatch
+ * compiler.codegen.aes.TestCipherBlockChainingEncrypt
+ */
+
+package compiler.codegen.aes;
+
+import java.io.PrintStream;
+import java.security.*;
+import java.util.Random;
+import java.lang.reflect.Method;
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+public class TestCipherBlockChainingEncrypt {
+ private static String algorithm = "PBEWithHmacSHA1AndAES_256";
+ private static final String PBEPASS = "Hush, it's supposed to be a secret!";
+
+ private static final int INPUT_LENGTH = 800;
+ private static final int[] OFFSETS = {0};
+ private static final int NUM_PAD_BYTES = 8;
+ private static final int PBKDF2_ADD_PAD_BYTES = 8;
+
+ private static SecretKey key;
+ private static Cipher ci;
+
+ public static void main(String[] args) throws Exception {
+ for(int i=0; i<5_000; i++) {
+ if (!(new TestCipherBlockChainingEncrypt().test(args))) {
+ throw new RuntimeException("TestCipherBlockChainingEncrypt test failed");
+ }
+ }
+ }
+
+ public boolean test(String[] args) throws Exception {
+ boolean result = true;
+
+ Provider p = Security.getProvider("SunJCE");
+ ci = Cipher.getInstance(algorithm, p);
+ key = SecretKeyFactory.getInstance(algorithm, p).generateSecret(
+ new PBEKeySpec(PBEPASS.toCharArray()));
+
+ // generate input data
+ byte[] inputText = new byte[INPUT_LENGTH + NUM_PAD_BYTES
+ + PBKDF2_ADD_PAD_BYTES];
+ new Random().nextBytes(inputText);
+
+ try {
+ // Encrypt
+ execute(Cipher.ENCRYPT_MODE,
+ inputText,
+ 0,
+ INPUT_LENGTH);
+
+ // PBKDF2 required 16 byte padding
+ int padLength = NUM_PAD_BYTES + PBKDF2_ADD_PAD_BYTES;
+
+ // Decrypt
+ // Note: inputText is implicitly padded by the above encrypt
+ // operation so decrypt operation can safely proceed
+ execute(Cipher.DECRYPT_MODE,
+ inputText,
+ 0,
+ INPUT_LENGTH + padLength);
+
+ } catch (Exception ex) {
+ ex.printStackTrace(System.out);
+ result = false;
+ }
+ return result;
+ }
+
+ private void execute(int edMode, byte[] inputText, int offset, int len) {
+ try {
+ // init Cipher
+ if (Cipher.ENCRYPT_MODE == edMode) {
+ ci.init(Cipher.ENCRYPT_MODE, this.key);
+ } else {
+ ci.init(Cipher.DECRYPT_MODE, this.key, ci.getParameters());
+ }
+
+ // First, generate the cipherText at an allocated buffer
+ byte[] outputText = ci.doFinal(inputText, offset, len);
+
+ // Second, generate cipherText again at the same buffer of plainText
+ int myoff = offset / 2;
+ int off = ci.update(inputText, offset, len, inputText, myoff);
+ ci.doFinal(inputText, myoff + off);
+
+ // Compare to see whether the two results are the same or not
+ boolean e = equalsBlock(inputText, myoff, outputText, 0,
+ outputText.length);
+ } catch (Exception ex) {
+ System.out.println("Got unexpected exception for " + algorithm);
+ ex.printStackTrace(System.out);
+ }
+ }
+
+ private boolean equalsBlock(byte[] b1, int off1,
+ byte[] b2, int off2, int len) {
+ for (int i = off1, j = off2, k = 0; k < len; i++, j++, k++) {
+ if (b1[i] != b2[j]) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/test/compiler/c1/TestGotoIf.jasm b/test/compiler/c1/TestGotoIf.jasm
new file mode 100644
index 000000000..b5dc03af2
--- /dev/null
+++ b/test/compiler/c1/TestGotoIf.jasm
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2019, 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.
+ *
+ */
+
+public class compiler/c1/TestGotoIf version 52:0 {
+ public Field f1:"I";
+ public Field f2:"I";
+ public static Field i:"I";
+
+ Method "<init>":"()V" stack 1 locals 1 {
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+ }
+
+ public Method test1:"()I" stack 3 locals 1 {
+ aload_0;
+ getfield Field f1:"I";
+ aload_0;
+ getfield Field f2:"I";
+ iconst_1;
+ isub;
+ // Without the fix, if got eliminated by CEE
+ if_icmpgt Null;
+ iconst_1;
+ Return: stack_frame_type stack1;
+ stack_map int;
+ ireturn;
+ Null: stack_frame_type same;
+ iconst_0;
+ goto Return; // Backbranch (t_goto) with safepoint
+ }
+
+ public Method test2:"()I" stack 3 locals 1 {
+ aload_0;
+ getfield Field f1:"I";
+ aload_0;
+ getfield Field f2:"I";
+ iconst_1;
+ isub;
+ goto Skip;
+ Return: stack_frame_type full;
+ stack_map int;
+ ireturn;
+ Skip: stack_frame_type full;
+ stack_map int, int;
+ // Without the fix, if got eliminated by CEE
+ if_icmpgt Null;
+ iconst_1;
+ goto Return; // Backbranch (f_goto) with safepoint
+ Null: stack_frame_type full;
+ stack_map;
+ iconst_0;
+ goto Return; // Backbranch (t_goto) with safepoint
+ }
+
+ public Method test3:"()I" stack 3 locals 1 {
+ aload_0;
+ getfield Field f1:"I";
+ aload_0;
+ getfield Field f2:"I";
+ iconst_1;
+ isub;
+ goto Skip;
+ Return: stack_frame_type full;
+ stack_map int;
+ ireturn;
+ Null: stack_frame_type full;
+ stack_map;
+ iconst_0;
+ goto Return; // Backbranch (t_goto) with safepoint
+ Skip: stack_frame_type full;
+ stack_map int, int;
+ // If will be eliminated by CEE
+ if_icmpgt Null; // Backbranch (if) with safepoint
+ iconst_1;
+ goto Return; // Backbranch (f_goto) with safepoint
+ }
+
+ public Method test4:"()I" stack 3 locals 1 {
+ aload_0;
+ getfield Field f1:"I";
+ aload_0;
+ getfield Field f2:"I";
+ iconst_1;
+ isub;
+ goto Skip;
+ Null: stack_frame_type full;
+ stack_map;
+ iconst_0;
+ Return: stack_frame_type full;
+ stack_map int;
+ ireturn;
+ Skip: stack_frame_type full;
+ stack_map int, int;
+ // If will be eliminated by CEE
+ if_icmpgt Null; // Backbranch (if) with safepoint
+ iconst_1;
+ goto Return; // Backbranch (f_goto) with safepoint
+ }
+
+ public Method test5:"()I" stack 3 locals 2 {
+ aload_0;
+ getfield Field f1:"I";
+ aload_0;
+ getfield Field f2:"I";
+ iconst_1;
+ isub;
+ goto Skip;
+ Null: stack_frame_type full;
+ stack_map;
+ iconst_0;
+ goto Return;
+ Skip: stack_frame_type full;
+ stack_map int, int;
+ // If will be eliminated by CEE
+ if_icmpgt Null; // Backbranch (if) with safepoint
+ iconst_1;
+ Return: stack_frame_type full;
+ stack_map int;
+ ireturn;
+ }
+
+ public Method test6:"()I" stack 4 locals 1 {
+ getstatic Field i:"I";
+ Loop: stack_frame_type full;
+ stack_map int;
+ // Decrement i and exit loop if < 0
+ iconst_0;
+ getstatic Field i:"I";
+ iconst_1;
+ isub;
+ dup;
+ putstatic Field i:"I";
+ if_icmpgt Exit;
+
+ iconst_1;
+ // Without the fix, if got eliminated by CEE
+ if_icmpgt Null;
+ iconst_1;
+ goto Loop; // Backbranch (f_goto) with safepoint
+ Null: stack_frame_type same;
+ iconst_0;
+ goto Loop; // Backbranch (t_goto) with safepoint
+
+ Exit: stack_frame_type full;
+ stack_map int;
+ iconst_0;
+ ireturn;
+ }
+}
diff --git a/test/compiler/c1/TestGotoIfMain.java b/test/compiler/c1/TestGotoIfMain.java
new file mode 100644
index 000000000..ac8b1b8be
--- /dev/null
+++ b/test/compiler/c1/TestGotoIfMain.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2019, 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 8218721
+ * @compile TestGotoIf.jasm
+ * @run main/othervm -XX:TieredStopAtLevel=1 -Xcomp
+ * -XX:CompileCommand=compileonly,compiler.c1.TestGotoIf::test*
+ * compiler.c1.TestGotoIfMain
+ */
+
+package compiler.c1;
+
+public class TestGotoIfMain {
+ public static void main(String[] args) {
+ TestGotoIf test = new TestGotoIf();
+ test.i = 5;
+ test.test1();
+ test.test2();
+ test.test3();
+ test.test4();
+ test.test5();
+ test.test6();
+ }
+}
diff --git a/test/compiler/c2/Test8202414.java b/test/compiler/c2/Test8202414.java
new file mode 100644
index 000000000..1d8ef8d93
--- /dev/null
+++ b/test/compiler/c2/Test8202414.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2019, Huawei Technologies Co. Ltd. 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 8202414
+ * @summary Unsafe write after primitive array creation may result in array length change
+ * @requires (os.arch != "sparc") & (os.arch != "sparcv9")
+ * @run main/othervm compiler.c2.Test8202414
+ */
+
+package compiler.c2;
+
+import sun.misc.Unsafe;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+public class Test8202414 {
+
+ public static void main(String[] args) {
+ System.err.close();
+ int count = 0;
+ while (count++ < 120000) {
+ test();
+ }
+ }
+
+ public static void test() {
+ byte[] newBufb = serByte(397);
+ short[] newBufs = serShort(397);
+ int[] newBufi = serInt(397);
+ long[] newBufl = serLong(397);
+ if (newBufb.length != 397 || newBufs.length != 397
+ || newBufi.length != 397 || newBufl.length != 397) {
+ System.out.println("array length internal error");
+ throw new RuntimeException("Test failed");
+ }
+
+ }
+
+ public static byte[] serByte(int bufLen) {
+ byte[] buf = new byte[bufLen];
+ THE_UNSAFE.putByte(buf, BYTE_ARRAY_BASE_OFFSET + 1, (byte) buf.length);
+ System.err.println("ref " + buf);
+ return buf;
+ }
+
+ public static short[] serShort(int bufLen) {
+ short[] buf = new short[bufLen];
+ THE_UNSAFE.putShort(buf, SHORT_ARRAY_BASE_OFFSET + 1, (short) buf.length);
+ System.err.println("ref " + buf);
+ return buf;
+ }
+
+ public static int[] serInt(int bufLen) {
+ int[] buf = new int[bufLen];
+ THE_UNSAFE.putInt(buf, INT_ARRAY_BASE_OFFSET + 1, buf.length);
+ System.err.println("ref " + buf);
+ return buf;
+ }
+
+ public static long[] serLong(int bufLen) {
+ long[] buf = new long[bufLen];
+ THE_UNSAFE.putLong(buf, LONG_ARRAY_BASE_OFFSET + 1, buf.length);
+ System.err.println("ref " + buf);
+ return buf;
+ }
+
+ /* Unsafe fields and initialization
+ */
+ static final Unsafe THE_UNSAFE;
+ static final long BYTE_ARRAY_BASE_OFFSET;
+ static final long SHORT_ARRAY_BASE_OFFSET;
+ static final long INT_ARRAY_BASE_OFFSET;
+ static final long LONG_ARRAY_BASE_OFFSET;
+ static {
+ THE_UNSAFE = (Unsafe) AccessController.doPrivileged (
+ new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ return f.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new Error();
+ }
+ }
+ }
+ );
+ BYTE_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(byte[].class);
+ SHORT_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(short[].class);
+ INT_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(int[].class);
+ LONG_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(long[].class);
+ }
+}
diff --git a/test/compiler/c2/Test8217359.java b/test/compiler/c2/Test8217359.java
new file mode 100644
index 000000000..ca0d2cc75
--- /dev/null
+++ b/test/compiler/c2/Test8217359.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019, Huawei Technologies Co. Ltd. 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 8217359
+ * @summary C2 compiler triggers SIGSEGV after transformation in ConvI2LNode::Ideal
+ *
+ * @run main/othervm -XX:-TieredCompilation
+ * -XX:CompileCommand=compileonly,compiler.c2.Test8217359::test
+ * compiler.c2.Test8217359
+ */
+
+package compiler.c2;
+
+public class Test8217359 {
+
+ public static int ival = 0;
+ public static long lsum = 0;
+ public static long lval = 0;
+
+ public static void test() {
+ short s = -25632;
+ float f = 0.512F, f1 = 2.556F;
+ int i6 = 32547, i7 = 9, i8 = -9, i9 = 36, i10 = -223;
+
+ for (i6 = 4; i6 < 182; i6++) {
+ i8 = 1;
+ while (++i8 < 17) {
+ f1 = 1;
+ do {
+ i7 += (182 + (f1 * f1));
+ } while (++f1 < 1);
+
+ Test8217359.ival += (i8 | Test8217359.ival);
+ }
+ }
+
+ for (i9 = 9; i9 < 100; ++i9) {
+ i10 -= i6;
+ i10 >>= s;
+ i7 += (((i9 * i10) + i6) - Test8217359.lval);
+ }
+
+ lsum += i6 + i7 + i8;
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 16000; i++) {
+ test();
+ }
+ }
+
+}
diff --git a/test/compiler/c2/TestIfWithDeadRegion.java b/test/compiler/c2/TestIfWithDeadRegion.java
new file mode 100644
index 000000000..1117908e1
--- /dev/null
+++ b/test/compiler/c2/TestIfWithDeadRegion.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019, 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 8219807
+ * @summary Test IfNode::up_one_dom() with dead regions.
+ * @compile -XDstringConcat=inline TestIfWithDeadRegion.java
+ * @run main/othervm -XX:CompileCommand=compileonly,compiler.c2.TestIfWithDeadRegion::test
+ * compiler.c2.TestIfWithDeadRegion
+ */
+
+package compiler.c2;
+
+import java.util.function.Supplier;
+
+public class TestIfWithDeadRegion {
+
+ static String msg;
+
+ static String getString(String s, int i) {
+ String current = s + String.valueOf(i);
+ System.nanoTime();
+ return current;
+ }
+
+ static void test(Supplier<String> supplier) {
+ msg = supplier.get();
+ }
+
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; ++i) {
+ test(() -> getString("Test1", 42));
+ test(() -> getString("Test2", 42));
+ }
+ }
+}
diff --git a/test/compiler/escapeAnalysis/TestGetClass.java b/test/compiler/escapeAnalysis/TestGetClass.java
new file mode 100644
index 000000000..7b2b587b2
--- /dev/null
+++ b/test/compiler/escapeAnalysis/TestGetClass.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, 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 8218201
+ * @summary BCEscapeAnalyzer assigns wrong escape state to getClass return value.
+ * @run main/othervm -XX:-TieredCompilation -Xcomp -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_getClass
+ * -XX:CompileCommand=quiet -XX:CompileCommand=compileonly,compiler.escapeAnalysis.TestGetClass::test
+ * -XX:+PrintCompilation compiler.escapeAnalysis.TestGetClass
+ */
+
+package compiler.escapeAnalysis;
+
+public class TestGetClass {
+ static Object obj = new Object();
+
+ public static boolean test() {
+ if (obj.getClass() == Object.class) {
+ synchronized (obj) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void main(String[] args) {
+ if (!test()) {
+ throw new RuntimeException("Test failed");
+ }
+ }
+}
diff --git a/test/compiler/integerArithmetic/MultiplyByConstantLongMax.java b/test/compiler/integerArithmetic/MultiplyByConstantLongMax.java
new file mode 100644
index 000000000..f586f90c1
--- /dev/null
+++ b/test/compiler/integerArithmetic/MultiplyByConstantLongMax.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. 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 8214189
+ * @summary test/hotspot/jtreg/compiler/intrinsics/mathexact/MulExactLConstantTest.java fails on Windows x64 when run with -XX:-TieredCompilation
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement MultiplyByConstantLongMax
+ *
+ */
+
+public class MultiplyByConstantLongMax {
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; i++) {
+ if (test(1) != Long.MAX_VALUE) {
+ throw new RuntimeException("incorrect result");
+ }
+ }
+ }
+
+ private static long test(long v) {
+ return v * Long.MAX_VALUE;
+ }
+}
diff --git a/test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java b/test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java
new file mode 100644
index 000000000..3ebb1982b
--- /dev/null
+++ b/test/compiler/integerArithmetic/MultiplyByIntegerMinHang.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. 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 8213419
+ * @summary C2 may hang in MulLNode::Ideal()/MulINode::Ideal() with gcc 8.2.1
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement MultiplyByIntegerMinHang
+ *
+ */
+
+public class MultiplyByIntegerMinHang {
+ public static void main(String[] args) {
+ for (int i = 0; i < 20_000; i++) {
+ if (test1(0) != 0) {
+ throw new RuntimeException("incorrect result");
+ }
+ if (test1(1) != Integer.MIN_VALUE) {
+ throw new RuntimeException("incorrect result");
+ }
+ if (test1(2) != 0) {
+ throw new RuntimeException("incorrect result");
+ }
+ if (test2(0) != 0) {
+ throw new RuntimeException("incorrect result");
+ }
+ if (test2(1) != Long.MIN_VALUE) {
+ throw new RuntimeException("incorrect result");
+ }
+ if (test2(2) != 0) {
+ throw new RuntimeException("incorrect result");
+ }
+ }
+ }
+
+ private static int test1(int v) {
+ return v * Integer.MIN_VALUE;
+ }
+
+ private static long test2(long v) {
+ return v * Long.MIN_VALUE;
+ }
+}
diff --git a/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java b/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
index c5d21ed4b..32850711a 100644
--- a/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
+++ b/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java
@@ -36,7 +36,8 @@ public class GenericTestCaseForOtherCPU extends
public GenericTestCaseForOtherCPU(String optionName) {
// Execute the test case on any CPU except SPARC and X86
super(optionName, new NotPredicate(new OrPredicate(Platform::isSparc,
- new OrPredicate(Platform::isX64, Platform::isX86))));
+ new OrPredicate(Platform::isPPC,
+ new OrPredicate(Platform::isX64, Platform::isX86)))));
}
@Override
diff --git a/test/compiler/loopopts/superword/TestNegBaseOffset.java b/test/compiler/loopopts/superword/TestNegBaseOffset.java
new file mode 100644
index 000000000..4fe83eed5
--- /dev/null
+++ b/test/compiler/loopopts/superword/TestNegBaseOffset.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018, 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 8202948
+ * @summary Test skipping vector packs with negative base offset.
+ * @comment Test fails only with -Xcomp when profiling data is not present.
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions
+ * -Xcomp -XX:-TieredCompilation -XX:CICompilerCount=1
+ * -XX:CompileOnly=compiler/loopopts/superword/TestNegBaseOffset
+ * compiler.loopopts.superword.TestNegBaseOffset
+ */
+
+package compiler.loopopts.superword;
+
+public class TestNegBaseOffset {
+ public static final int N = 400;
+ public static int iFld=10;
+ public static int iArr[]=new int[N];
+
+ public static void mainTest() {
+ int i0=1, i2;
+ while (++i0 < 339) {
+ if ((i0 % 2) == 0) {
+ for (i2 = 2; i2 > i0; i2 -= 3) {
+ iArr[i2 - 1] &= iFld;
+ }
+ }
+ }
+ }
+
+ public static void main(String[] strArr) {
+ for (int i = 0; i < 10; i++) {
+ mainTest();
+ }
+ }
+}
+
diff --git a/test/compiler/rangechecks/RangeCheckEliminationScaleNotOne.java b/test/compiler/rangechecks/RangeCheckEliminationScaleNotOne.java
new file mode 100644
index 000000000..50b268a25
--- /dev/null
+++ b/test/compiler/rangechecks/RangeCheckEliminationScaleNotOne.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. 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 8215265
+ * @summary C2: range check elimination may allow illegal out of bound access
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:-UseLoopPredicate RangeCheckEliminationScaleNotOne
+ *
+ */
+
+import java.util.Arrays;
+
+public class RangeCheckEliminationScaleNotOne {
+ public static void main(String[] args) {
+ {
+ int[] array = new int[199];
+ boolean[] flags = new boolean[100];
+ Arrays.fill(flags, true);
+ flags[0] = false;
+ flags[1] = false;
+ for (int i = 0; i < 20_000; i++) {
+ test1(100, array, 0, flags);
+ }
+ boolean ex = false;
+ try {
+ test1(100, array, -5, flags);
+ } catch (ArrayIndexOutOfBoundsException aie) {
+ ex = true;
+ }
+ if (!ex) {
+ throw new RuntimeException("no AIOOB exception");
+ }
+ }
+
+ {
+ int[] array = new int[199];
+ boolean[] flags = new boolean[100];
+ Arrays.fill(flags, true);
+ flags[0] = false;
+ flags[1] = false;
+ for (int i = 0; i < 20_000; i++) {
+ test2(100, array, 198, flags);
+ }
+ boolean ex = false;
+ try {
+ test2(100, array, 203, flags);
+ } catch (ArrayIndexOutOfBoundsException aie) {
+ ex = true;
+ }
+ if (!ex) {
+ throw new RuntimeException("no AIOOB exception");
+ }
+ }
+ }
+
+ private static int test1(int stop, int[] array, int offset, boolean[] flags) {
+ if (array == null) {}
+ int res = 0;
+ for (int i = 0; i < stop; i++) {
+ if (flags[i]) {
+ res += array[2 * i + offset];
+ }
+ }
+ return res;
+ }
+
+
+ private static int test2(int stop, int[] array, int offset, boolean[] flags) {
+ if (array == null) {}
+ int res = 0;
+ for (int i = 0; i < stop; i++) {
+ if (flags[i]) {
+ res += array[-2 * i + offset];
+ }
+ }
+ return res;
+ }
+}
diff --git a/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
index 5f1c64cad..8e5a30b7d 100644
--- a/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
+++ b/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -34,6 +34,7 @@
* -XX:+WhiteBoxAPI TestRTMTotalCountIncrRate
*/
+import sun.misc.Unsafe;
import java.util.List;
import com.oracle.java.testlibrary.*;
@@ -96,14 +97,12 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
Asserts.assertEQ(lock.getTotalLocks(), Test.TOTAL_ITERATIONS,
"Total locks should be exactly the same as amount of "
+ "iterations.");
- } else {
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM statistics "
- + "should contain information for at least on lock.");
}
}
public static class Test implements CompilableTest {
private static final long TOTAL_ITERATIONS = 10000L;
+ private static final Unsafe UNSAFE = Utils.getUnsafe();
private final Object monitor = new Object();
// Following field have to be static in order to avoid escape analysis.
@SuppressWarnings("UnsuedDeclaration")
@@ -119,8 +118,17 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
return new String[] { getMethodWithLockName() };
}
- public void lock() {
+ public void lock(boolean forceAbort) {
synchronized(monitor) {
+ if (forceAbort) {
+ // We're calling native method in order to force
+ // abort. It's done by explicit xabort call emitted
+ // in SharedRuntime::generate_native_wrapper.
+ // If an actual JNI call will be replaced by
+ // intrinsic - we'll be in trouble, since xabort
+ // will be no longer called and test may fail.
+ UNSAFE.addressSize();
+ }
Test.field++;
}
}
@@ -139,7 +147,11 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
for (long i = 0L; i < Test.TOTAL_ITERATIONS; i++) {
AbortProvoker.verifyMonitorState(test.monitor,
shouldBeInflated);
- test.lock();
+ // Force abort on first iteration to avoid rare case when
+ // there were no aborts and locks count was not incremented
+ // with RTMTotalCountIncrRate > 1 (in such case JVM won't
+ // print JVM locking statistics).
+ test.lock(i == 0);
}
}
}
diff --git a/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java
index eebaac23b..230d88152 100644
--- a/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java
+++ b/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java
@@ -124,9 +124,6 @@ public class TestPrintPreciseRTMLockingStatistics
RTMLockingStatistics lock = statistics.get(0);
- Asserts.assertGT(lock.getTotalLocks(), 0L, "RTM locking statistics "
- + "should contain non zero total locks count");
-
Asserts.assertGT(lock.getTotalAborts(), 0L,
"RTM locking statistics should contain non zero total aborts "
+ "count");
diff --git a/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
index 51ab609dc..bac466575 100644
--- a/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
+++ b/test/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java
@@ -63,12 +63,20 @@ public class IntrinsicPredicates {
null);
public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE
- = new CPUSpecificPredicate("sparc.*", new String[] { "sha256" },
- null);
+ = new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha256" },
+ null),
+ new OrPredicate(new CPUSpecificPredicate("ppc64.*", new String[] { "sha" },
+ null),
+ new CPUSpecificPredicate("ppc64le.*", new String[] { "sha" },
+ null)));
public static final BooleanSupplier SHA512_INSTRUCTION_AVAILABLE
- = new CPUSpecificPredicate("sparc.*", new String[] { "sha512" },
- null);
+ = new OrPredicate(new CPUSpecificPredicate("sparc.*", new String[] { "sha512" },
+ null),
+ new OrPredicate(new CPUSpecificPredicate("ppc64.*", new String[] { "sha" },
+ null),
+ new CPUSpecificPredicate("ppc64le.*", new String[] { "sha" },
+ null)));
public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE
= new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE,
diff --git a/test/compiler/tiered/ConstantGettersTransitionsTest.java b/test/compiler/tiered/ConstantGettersTransitionsTest.java
new file mode 100644
index 000000000..2de9dc578
--- /dev/null
+++ b/test/compiler/tiered/ConstantGettersTransitionsTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Executable;
+import java.util.concurrent.Callable;
+
+/**
+ * @test ConstantGettersTransitionsTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build TransitionsTestExecutor ConstantGettersTransitionsTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+TieredCompilation
+ * -XX:CompileCommand=compileonly,ConstantGettersTestCase$TrivialMethods::*
+ * TransitionsTestExecutor ConstantGettersTransitionsTest
+ * @summary Test the correctness of compilation level transitions for constant getters methods
+ */
+public class ConstantGettersTransitionsTest extends LevelTransitionTest {
+ public static void main(String[] args) {
+ assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false));
+
+ // run test cases
+ for (TestCase testCase : ConstantGettersTestCase.values()) {
+ new ConstantGettersTransitionsTest(testCase).runTest();
+ }
+ }
+
+ @Override
+ protected boolean isTrivial() {
+ return true;
+ }
+
+ private ConstantGettersTransitionsTest(TestCase testCase) {
+ super(testCase);
+ }
+}
+
+enum ConstantGettersTestCase implements CompilerWhiteBoxTest.TestCase {
+ ICONST_M1,
+ ICONST_0,
+ ICONST_1,
+ ICONST_2,
+ ICONST_3,
+ ICONST_4,
+ ICONST_5,
+ LCONST_0,
+ LCONST_1,
+ FCONST_0,
+ FCONST_1,
+ FCONST_2,
+ DCONST_0,
+ DCONST_1,
+ DCONST_W,
+ BYTE,
+ SHORT,
+ CHAR;
+
+ private final Executable executable;
+ private final Callable<Integer> callable;
+
+ @Override
+ public Executable getExecutable() {
+ return executable;
+ }
+
+ @Override
+ public Callable<Integer> getCallable() {
+ return callable;
+ }
+
+ @Override
+ public boolean isOsr() {
+ return false;
+ }
+
+ private ConstantGettersTestCase() {
+ String name = "make" + this.name();
+ this.executable = LevelTransitionTest.Helper.getMethod(TrivialMethods.class, name);
+ this.callable = LevelTransitionTest.Helper.getCallable(new TrivialMethods(), name);
+ }
+
+ /**
+ * Contains methods that load constants with certain types of bytecodes
+ * See JVMS 2.11.2. Load and Store Instructions
+ * Note that it doesn't have a method for ldc_w instruction
+ */
+ private static class TrivialMethods {
+ public static int makeICONST_M1() {
+ return -1;
+ }
+
+ public static int makeICONST_0() {
+ return 0;
+ }
+
+ public static int makeICONST_1() {
+ return 1;
+ }
+
+ public static int makeICONST_2() {
+ return 2;
+ }
+
+ public static int makeICONST_3() {
+ return 3;
+ }
+
+ public static int makeICONST_4() {
+ return 4;
+ }
+
+ public static int makeICONST_5() {
+ return 5;
+ }
+
+ public static long makeLCONST_0() {
+ return 0L;
+ }
+
+ public static long makeLCONST_1() {
+ return 1L;
+ }
+
+ public static float makeFCONST_0() {
+ return 0F;
+ }
+
+ public static float makeFCONST_1() {
+ return 1F;
+ }
+
+ public static float makeFCONST_2() {
+ return 2F;
+ }
+
+ public static double makeDCONST_0() {
+ return 0D;
+ }
+
+ public static double makeDCONST_1() {
+ return 1D;
+ }
+
+ public static double makeDCONST_W() {
+ // ldc2_w
+ return Double.MAX_VALUE;
+ }
+
+ public static Object makeOBJECT() {
+ // aconst_null
+ return null;
+ }
+
+ public static byte makeBYTE() {
+ // bipush
+ return (byte) 0x7F;
+ }
+
+ public static short makeSHORT() {
+ // sipush
+ return (short) 0x7FFF;
+ }
+
+ public static char makeCHAR() {
+ // ldc
+ return (char) 0xFFFF;
+ }
+
+ public static boolean makeBOOLEAN() {
+ return true;
+ }
+ }
+}
diff --git a/test/compiler/tiered/Level2RecompilationTest.java b/test/compiler/tiered/Level2RecompilationTest.java
new file mode 100644
index 000000000..eb3b6b2f4
--- /dev/null
+++ b/test/compiler/tiered/Level2RecompilationTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2019, 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 Level2RecompilationTest
+ * @summary Test downgrading mechanism from level 3 to level 2 for those profiled methods.
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build Level2RecompilationTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+TieredCompilation
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCounterDecay
+ * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::*
+ * -XX:CompileCommand=print,SimpleTestCase$Helper::*
+ * Level2RecompilationTest
+ */
+public class Level2RecompilationTest extends CompLevelsTest {
+ public static void main(String[] args) throws Throwable {
+ if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) {
+ throw new RuntimeException("Test isn't applicable for non-tiered mode");
+ }
+ String[] testcases = {"METHOD_TEST", "OSR_STATIC_TEST"};
+ CompilerWhiteBoxTest.main(Level2RecompilationTest::new, testcases);
+ }
+
+ protected Level2RecompilationTest(TestCase testCase) {
+ super(testCase);
+ // to prevent inlining of #method
+ WHITE_BOX.testSetDontInlineMethod(method, true);
+ }
+
+ @Override
+ protected void test() throws Exception {
+ if (skipXcompOSR()) {
+ return;
+ }
+
+ checkNotCompiled();
+ int bci = WHITE_BOX.getMethodEntryBci(method);
+ WHITE_BOX.markMethodProfiled(method);
+ if (testCase.isOsr()) {
+ // for OSR compilation, it must be the begin of a BB.
+ // c1_GraphBulider.cpp:153 assert(method()->bci_block_start().at(cur_bci), ...
+ bci = 0;
+ }
+
+ WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_PROFILE, bci);
+ checkCompiled();
+ checkLevel(COMP_LEVEL_LIMITED_PROFILE, getCompLevel());
+
+ for (int i=0; i<100; ++i) {
+ WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_PROFILE, bci);
+ waitBackgroundCompilation();
+ checkLevel(COMP_LEVEL_LIMITED_PROFILE, getCompLevel());
+ }
+ }
+
+ @Override
+ protected void checkLevel(int expected, int actual) {
+ if (expected == COMP_LEVEL_FULL_PROFILE
+ && actual == COMP_LEVEL_LIMITED_PROFILE) {
+ // for simple method full_profile may be replaced by limited_profile
+ if (IS_VERBOSE) {
+ System.out.printf("Level check: full profiling was replaced "
+ + "by limited profiling. Expected: %d, actual:%d\n",
+ expected, actual);
+ }
+ return;
+ }
+ super.checkLevel(expected, actual);
+ }
+}
+
diff --git a/test/compiler/tiered/LevelTransitionTest.java b/test/compiler/tiered/LevelTransitionTest.java
new file mode 100644
index 000000000..84ead05d1
--- /dev/null
+++ b/test/compiler/tiered/LevelTransitionTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.reflect.Executable;
+import java.lang.reflect.Method;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+
+/**
+ * @test LevelTransitionTest
+ * @library /testlibrary /testlibrary/whitebox /compiler/whitebox
+ * @build TransitionsTestExecutor LevelTransitionTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -XX:+TieredCompilation
+ * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::*
+ * -XX:CompileCommand=compileonly,ExtendedTestCase$CompileMethodHolder::*
+ * TransitionsTestExecutor LevelTransitionTest
+ * @summary Test the correctness of compilation level transitions for different methods
+ */
+public class LevelTransitionTest extends TieredLevelsTest {
+ /** Shows if method was profiled by being executed on levels 2 or 3 */
+ protected boolean isMethodProfiled;
+ private int transitionCount;
+
+ public static void main(String[] args) throws Throwable {
+ assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false));
+
+ CompilerWhiteBoxTest.main(LevelTransitionTest::new, args);
+ // run extended test cases
+ for (TestCase testCase : ExtendedTestCase.values()) {
+ new LevelTransitionTest(testCase).runTest();
+ }
+ }
+
+ protected LevelTransitionTest(TestCase testCase) {
+ super(testCase);
+ isMethodProfiled = testCase.isOsr(); // OSR methods were already profiled by warmup
+ transitionCount = 0;
+ }
+
+ @Override
+ protected void test() throws Exception {
+ checkTransitions();
+ deoptimize();
+ printInfo();
+ if (testCase.isOsr()) {
+ // deoptimization makes the following transitions be unstable
+ // methods go to level 3 before 4 because of uncommon_trap and reprofile
+ return;
+ }
+ checkTransitions();
+ }
+
+ /**
+ * Makes and verifies transitions between compilation levels
+ */
+ protected void checkTransitions() {
+ checkNotCompiled();
+ boolean finish = false;
+ while (!finish) {
+ System.out.printf("Level transition #%d%n", ++transitionCount);
+ int newLevel;
+ int current = getCompLevel();
+ int expected = getNextLevel(current);
+ if (current == expected) {
+ // if we are on expected level, just execute it more
+ // to ensure that the level won't change
+ System.out.printf("Method %s is already on expected level %d%n", method, expected);
+ compile();
+ newLevel = getCompLevel();
+ finish = true;
+ } else {
+ newLevel = changeCompLevel();
+ finish = false;
+ }
+ System.out.printf("Method %s is compiled on level %d. Expected level is %d%n", method, newLevel, expected);
+ checkLevel(expected, newLevel);
+ printInfo();
+ };
+ }
+
+ /**
+ * Gets next expected level for the test case on each transition.
+ *
+ * @param currentLevel a level the test case is compiled on
+ * @return expected compilation level
+ */
+ protected int getNextLevel(int currentLevel) {
+ int nextLevel = currentLevel;
+ switch (currentLevel) {
+ case CompilerWhiteBoxTest.COMP_LEVEL_NONE:
+ nextLevel = isMethodProfiled ? CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION
+ : CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE;
+ break;
+ case CompilerWhiteBoxTest.COMP_LEVEL_LIMITED_PROFILE:
+ case CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE:
+ nextLevel = CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION;
+ isMethodProfiled = true;
+ break;
+ }
+ nextLevel = isTrivial() ? CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE : nextLevel;
+ return Math.min(nextLevel, CompilerWhiteBoxTest.TIERED_STOP_AT_LEVEL);
+ }
+
+ /**
+ * Determines if tested method should be handled as trivial
+ *
+ * @return {@code true} for trivial methods, {@code false} otherwise
+ */
+ protected boolean isTrivial() {
+ return testCase == ExtendedTestCase.ACCESSOR_TEST
+ || testCase == SimpleTestCase.METHOD_TEST
+ || testCase == SimpleTestCase.STATIC_TEST
+ || (testCase == ExtendedTestCase.TRIVIAL_CODE_TEST && isMethodProfiled);
+ }
+
+ /**
+ * Invokes {@linkplain #method} until its compilation level is changed.
+ * Note that if the level won't change, it will be an endless loop
+ *
+ * @return compilation level the {@linkplain #method} was compiled on
+ */
+ protected int changeCompLevel() {
+ int currentLevel = getCompLevel();
+ int newLevel = currentLevel;
+ int result = 0;
+ while (currentLevel == newLevel) {
+ result = compile(1);
+ if (WHITE_BOX.isMethodCompiled(method, testCase.isOsr())) {
+ newLevel = getCompLevel();
+ }
+ }
+ return newLevel;
+ }
+
+ protected static class Helper {
+ /**
+ * Gets method from a specified class using its name
+ *
+ * @param aClass type method belongs to
+ * @param name the name of the method
+ * @return {@link Method} that represents corresponding class method
+ */
+ public static Method getMethod(Class<?> aClass, String name) {
+ Method method;
+ try {
+ method = aClass.getDeclaredMethod(name);
+ } catch (NoSuchMethodException e) {
+ throw new Error("TESTBUG: Unable to get method " + name, e);
+ }
+ return method;
+ }
+
+ /**
+ * Gets {@link Callable} that invokes given method from the given object
+ *
+ * @param object the object the specified method is invoked from
+ * @param name the name of the method
+ */
+ public static Callable<Integer> getCallable(Object object, String name) {
+ Method method = getMethod(object.getClass(), name);
+ return () -> {
+ try {
+ return Objects.hashCode(method.invoke(object));
+ } catch (ReflectiveOperationException e) {
+ throw new Error("TESTBUG: Invocation failure", e);
+ }
+ };
+ }
+ }
+}
+
+enum ExtendedTestCase implements CompilerWhiteBoxTest.TestCase {
+ ACCESSOR_TEST("accessor"),
+ NONTRIVIAL_METHOD_TEST("nonTrivialMethod"),
+ TRIVIAL_CODE_TEST("trivialCode");
+
+ private final Executable executable;
+ private final Callable<Integer> callable;
+
+ @Override
+ public Executable getExecutable() {
+ return executable;
+ }
+
+ @Override
+ public Callable<Integer> getCallable() {
+ return callable;
+ }
+
+ @Override
+ public boolean isOsr() {
+ return false;
+ }
+
+ private ExtendedTestCase(String methodName) {
+ this.executable = LevelTransitionTest.Helper.getMethod(CompileMethodHolder.class, methodName);
+ this.callable = LevelTransitionTest.Helper.getCallable(new CompileMethodHolder(), methodName);
+ }
+
+ private static class CompileMethodHolder {
+ private final int iter = 10;
+ private int field = 42;
+
+ /** Non-trivial method for threshold policy: contains loops */
+ public int nonTrivialMethod() {
+ int acc = 0;
+ for (int i = 0; i < iter; i++) {
+ acc += i;
+ }
+ return acc;
+ }
+
+ /** Field accessor method */
+ public int accessor() {
+ return field;
+ }
+
+ /** Method considered as trivial by amount of code */
+ public int trivialCode() {
+ int var = 0xBAAD_C0DE;
+ var *= field;
+ return var;
+ }
+ }
+}
diff --git a/test/compiler/tiered/NonTieredLevelsTest.java b/test/compiler/tiered/NonTieredLevelsTest.java
index 13411a0dd..c089792e9 100644
--- a/test/compiler/tiered/NonTieredLevelsTest.java
+++ b/test/compiler/tiered/NonTieredLevelsTest.java
@@ -54,9 +54,7 @@ public class NonTieredLevelsTest extends CompLevelsTest {
}
public static void main(String[] args) throws Exception {
- if (TIERED_COMPILATION) {
- System.err.println("Test isn't applicable w/ enabled "
- + "TieredCompilation. Skip test.");
+ if (CompilerWhiteBoxTest.skipOnTieredCompilation(true)) {
return;
}
CompilerWhiteBoxTest.main(NonTieredLevelsTest::new, args);
diff --git a/test/compiler/tiered/TieredLevelsTest.java b/test/compiler/tiered/TieredLevelsTest.java
index 9fb2254d0..28d2f76ac 100644
--- a/test/compiler/tiered/TieredLevelsTest.java
+++ b/test/compiler/tiered/TieredLevelsTest.java
@@ -34,16 +34,14 @@
* @author igor.ignatyev@oracle.com
*/
public class TieredLevelsTest extends CompLevelsTest {
- public static void main(String[] args) throws Exception {
- if (!TIERED_COMPILATION) {
- System.err.println("Test isn't applicable w/ disabled "
- + "TieredCompilation. Skip test.");
+ public static void main(String[] args) throws Exception, Throwable {
+ if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) {
return;
}
CompilerWhiteBoxTest.main(TieredLevelsTest::new, args);
}
- private TieredLevelsTest(TestCase testCase) {
+ protected TieredLevelsTest(TestCase testCase) {
super(testCase);
// to prevent inlining of #method
WHITE_BOX.testSetDontInlineMethod(method, true);
@@ -76,14 +74,18 @@ public class TieredLevelsTest extends CompLevelsTest {
}
}
-
@Override
protected void checkLevel(int expected, int actual) {
if (expected == COMP_LEVEL_FULL_PROFILE
&& actual == COMP_LEVEL_LIMITED_PROFILE) {
// for simple method full_profile may be replaced by limited_profile
+ if (IS_VERBOSE) {
+ System.out.printf("Level check: full profiling was replaced "
+ + "by limited profiling. Expected: %d, actual:%d",
+ expected, actual);
+ }
return;
}
super.checkLevel(expected, actual);
- }
+ }
}
diff --git a/test/compiler/tiered/TransitionsTestExecutor.java b/test/compiler/tiered/TransitionsTestExecutor.java
new file mode 100644
index 000000000..15f731b50
--- /dev/null
+++ b/test/compiler/tiered/TransitionsTestExecutor.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Executes given test in a separate VM with enabled Tiered Compilation for
+ * CompilationPolicyChoice 2 and 3
+ */
+public class TransitionsTestExecutor {
+ public static void main(String[] args) throws Throwable {
+ if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) {
+ return;
+ }
+ if (args.length != 1) {
+ throw new Error("TESTBUG: Test name should be specified");
+ }
+ executeTestFor(2, args[0]);
+ executeTestFor(3, args[0]);
+ }
+
+ private static void executeTestFor(int compilationPolicy, String testName) throws Throwable {
+ String policy = "-XX:CompilationPolicyChoice=" + compilationPolicy;
+
+ // Get runtime arguments including VM options given to this executor
+ RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
+ List<String> vmArgs = runtime.getInputArguments();
+
+ // Construct execution command with compilation policy choice and test name
+ List<String> args = new ArrayList<>(vmArgs);
+ Collections.addAll(args, policy, testName);
+
+ OutputAnalyzer out = ProcessTools.executeTestJvm(args.toArray(new String[args.size()]));
+ int exitCode = out.getExitValue();
+ if (exitCode != 0) {
+ throw new Error("Test execution failed with exit code " + exitCode);
+ }
+ }
+}
diff --git a/test/compiler/whitebox/CompilerWhiteBoxTest.java b/test/compiler/whitebox/CompilerWhiteBoxTest.java
index a391ba20e..1bea0033a 100644
--- a/test/compiler/whitebox/CompilerWhiteBoxTest.java
+++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -41,19 +41,19 @@ import java.util.function.Function;
*/
public abstract class CompilerWhiteBoxTest {
/** {@code CompLevel::CompLevel_none} -- Interpreter */
- protected static int COMP_LEVEL_NONE = 0;
+ protected static final int COMP_LEVEL_NONE = 0;
/** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */
- protected static int COMP_LEVEL_ANY = -1;
+ protected static final int COMP_LEVEL_ANY = -1;
/** {@code CompLevel::CompLevel_simple} -- C1 */
- protected static int COMP_LEVEL_SIMPLE = 1;
+ protected static final int COMP_LEVEL_SIMPLE = 1;
/** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation &amp; backedge counters */
- protected static int COMP_LEVEL_LIMITED_PROFILE = 2;
+ protected static final int COMP_LEVEL_LIMITED_PROFILE = 2;
/** {@code CompLevel::CompLevel_full_profile} -- C1, invocation &amp; backedge counters + mdo */
- protected static int COMP_LEVEL_FULL_PROFILE = 3;
+ protected static final int COMP_LEVEL_FULL_PROFILE = 3;
/** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */
- protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+ protected static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
/** Maximal value for CompLevel */
- protected static int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
+ protected static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION;
/** Instance of WhiteBox */
protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
@@ -328,11 +328,11 @@ public abstract class CompilerWhiteBoxTest {
return;
}
final Object obj = new Object();
- for (int i = 0; i < 10
+ for (int i = 0; i < 100
&& WHITE_BOX.isMethodQueuedForCompilation(executable); ++i) {
synchronized (obj) {
try {
- obj.wait(1000);
+ obj.wait(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
@@ -347,14 +347,22 @@ public abstract class CompilerWhiteBoxTest {
System.out.printf("%n%s:%n", method);
System.out.printf("\tcompilable:\t%b%n",
WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false));
- System.out.printf("\tcompiled:\t%b%n",
- WHITE_BOX.isMethodCompiled(method, false));
+ boolean isCompiled = WHITE_BOX.isMethodCompiled(method, false);
+ System.out.printf("\tcompiled:\t%b%n", isCompiled);
+ if (isCompiled) {
+ System.out.printf("\tcompile_id:\t%d%n",
+ NMethod.get(method, false).compile_id);
+ }
System.out.printf("\tcomp_level:\t%d%n",
WHITE_BOX.getMethodCompilationLevel(method, false));
System.out.printf("\tosr_compilable:\t%b%n",
WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true));
- System.out.printf("\tosr_compiled:\t%b%n",
- WHITE_BOX.isMethodCompiled(method, true));
+ isCompiled = WHITE_BOX.isMethodCompiled(method, true);
+ System.out.printf("\tosr_compiled:\t%b%n", isCompiled);
+ if (isCompiled) {
+ System.out.printf("\tosr_compile_id:\t%d%n",
+ NMethod.get(method, true).compile_id);
+ }
System.out.printf("\tosr_comp_level:\t%d%n",
WHITE_BOX.getMethodCompilationLevel(method, true));
System.out.printf("\tin_queue:\t%b%n",
@@ -437,6 +445,22 @@ public abstract class CompilerWhiteBoxTest {
}
return result;
}
+
+ /**
+ * Skip the test for the specified value of Tiered Compilation
+ * @param value of TieredCompilation the test should not run with
+ * @return {@code true} if the test should be skipped,
+ * {@code false} otherwise
+ */
+ protected static boolean skipOnTieredCompilation(boolean value) {
+ if (value == CompilerWhiteBoxTest.TIERED_COMPILATION) {
+ System.err.println("Test isn't applicable w/ "
+ + (value ? "enabled" : "disabled")
+ + "TieredCompilation. Skip test.");
+ return true;
+ }
+ return false;
+ }
}
enum SimpleTestCase implements CompilerWhiteBoxTest.TestCase {
diff --git a/test/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/gc/TestMemoryMXBeansAndPoolsPresence.java
new file mode 100644
index 000000000..85ce5cd1d
--- /dev/null
+++ b/test/gc/TestMemoryMXBeansAndPoolsPresence.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017, 2019, 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 TestMemoryMXBeansAndPoolsPresence
+ * @key gc
+ * @bug 8191564
+ * @summary Tests that GarbageCollectorMXBeans and GC MemoryPools are created.
+ * @library /testlibrary
+ * @requires vm.gc == null
+ * @run main/othervm -XX:+UseParallelGC TestMemoryMXBeansAndPoolsPresence Parallel
+ * @run main/othervm -XX:+UseSerialGC TestMemoryMXBeansAndPoolsPresence Serial
+ * @run main/othervm -XX:+UseConcMarkSweepGC TestMemoryMXBeansAndPoolsPresence CMS
+ * @run main/othervm -XX:+UseG1GC TestMemoryMXBeansAndPoolsPresence G1
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.management.*;
+import java.util.stream.*;
+
+import com.oracle.java.testlibrary.Asserts;
+
+class GCBeanDescription {
+ public String name;
+ public String[] poolNames;
+
+ public GCBeanDescription(String name, String[] poolNames) {
+ this.name = name;
+ this.poolNames = poolNames;
+ }
+}
+
+public class TestMemoryMXBeansAndPoolsPresence {
+ public static void test(GCBeanDescription... expectedBeans) {
+ List<MemoryPoolMXBean> memoryPools = ManagementFactory.getMemoryPoolMXBeans();
+
+ List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
+ Asserts.assertEQ(expectedBeans.length, gcBeans.size());
+
+ for (GCBeanDescription desc : expectedBeans) {
+ List<GarbageCollectorMXBean> beans = gcBeans.stream()
+ .filter(b -> b.getName().equals(desc.name))
+ .collect(Collectors.toList());
+ Asserts.assertEQ(beans.size(), 1);
+
+ GarbageCollectorMXBean bean = beans.get(0);
+ Asserts.assertEQ(desc.name, bean.getName());
+
+ String[] pools = bean.getMemoryPoolNames();
+ Asserts.assertEQ(desc.poolNames.length, pools.length);
+ for (int i = 0; i < desc.poolNames.length; i++) {
+ Asserts.assertEQ(desc.poolNames[i], pools[i]);
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ switch (args[0]) {
+ case "G1":
+ test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}),
+ new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}));
+ break;
+ case "CMS":
+ test(new GCBeanDescription("ParNew", new String[] {"Par Eden Space", "Par Survivor Space"}),
+ new GCBeanDescription("ConcurrentMarkSweep", new String[] {"Par Eden Space", "Par Survivor Space", "CMS Old Gen"}));
+ break;
+ case "Parallel":
+ test(new GCBeanDescription("PS Scavenge", new String[] {"PS Eden Space", "PS Survivor Space"}),
+ new GCBeanDescription("PS MarkSweep", new String[] {"PS Eden Space", "PS Survivor Space", "PS Old Gen"}));
+ break;
+ case "Serial":
+ test(new GCBeanDescription("Copy", new String[] {"Eden Space", "Survivor Space"}),
+ new GCBeanDescription("MarkSweepCompact", new String[] {"Eden Space", "Survivor Space", "Tenured Gen"}));
+ break;
+ default:
+ Asserts.assertTrue(false);
+ break;
+
+ }
+ }
+}
diff --git a/test/gc/arguments/TestMaxHeapSizeTools.java b/test/gc/arguments/TestMaxHeapSizeTools.java
index 0e07f7941..b5859b5cf 100644
--- a/test/gc/arguments/TestMaxHeapSizeTools.java
+++ b/test/gc/arguments/TestMaxHeapSizeTools.java
@@ -41,8 +41,8 @@ final class MinInitialMaxValues {
public long initialHeapSize;
public long maxHeapSize;
- public long minAlignment;
- public long maxAlignment;
+ public long spaceAlignment;
+ public long heapAlignment;
}
class TestMaxHeapSizeTools {
@@ -192,7 +192,7 @@ class TestMaxHeapSizeTools {
// Unfortunately there is no other way to retrieve the minimum heap size and
// the alignments.
- Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Min alignment \\d+ Max alignment \\d+").
+ Matcher m = Pattern.compile("Minimum heap \\d+ Initial heap \\d+ Maximum heap \\d+ Space alignment \\d+ Heap alignment \\d+").
matcher(output.getStdout());
if (!m.find()) {
throw new RuntimeException("Could not find heap size string.");
@@ -204,8 +204,8 @@ class TestMaxHeapSizeTools {
val.minHeapSize = valueAfter(match, "Minimum heap ");
val.initialHeapSize = valueAfter(match, "Initial heap ");
val.maxHeapSize = valueAfter(match, "Maximum heap ");
- val.minAlignment = valueAfter(match, "Min alignment ");
- val.maxAlignment = valueAfter(match, "Max alignment ");
+ val.spaceAlignment = valueAfter(match, "Space alignment ");
+ val.heapAlignment = valueAfter(match, "Heap alignment ");
}
/**
@@ -218,12 +218,12 @@ class TestMaxHeapSizeTools {
MinInitialMaxValues v = new MinInitialMaxValues();
getMinInitialMaxHeap(args, v);
- if ((expectedMin != -1) && (align_up(expectedMin, v.minAlignment) != v.minHeapSize)) {
+ if ((expectedMin != -1) && (align_up(expectedMin, v.heapAlignment) != v.minHeapSize)) {
throw new RuntimeException("Actual minimum heap size of " + v.minHeapSize +
" differs from expected minimum heap size of " + expectedMin);
}
- if ((expectedInitial != -1) && (align_up(expectedInitial, v.minAlignment) != v.initialHeapSize)) {
+ if ((expectedInitial != -1) && (align_up(expectedInitial, v.heapAlignment) != v.initialHeapSize)) {
throw new RuntimeException("Actual initial heap size of " + v.initialHeapSize +
" differs from expected initial heap size of " + expectedInitial);
}
@@ -247,7 +247,7 @@ class TestMaxHeapSizeTools {
MinInitialMaxValues v = new MinInitialMaxValues();
getMinInitialMaxHeap(new String[] { gcflag, "-XX:MaxHeapSize=" + maxHeapsize + "M" }, v);
- long expectedHeapSize = align_up(maxHeapsize * K * K, v.maxAlignment);
+ long expectedHeapSize = align_up(maxHeapsize * K * K, v.heapAlignment);
long actualHeapSize = v.maxHeapSize;
if (actualHeapSize > expectedHeapSize) {
diff --git a/test/gc/g1/mixedgc/TestOldGenCollectionUsage.java b/test/gc/g1/mixedgc/TestOldGenCollectionUsage.java
new file mode 100644
index 000000000..3237b1868
--- /dev/null
+++ b/test/gc/g1/mixedgc/TestOldGenCollectionUsage.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2018, 2019, 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 TestOldGenCollectionUsage.java
+ * @bug 8195115
+ * @summary G1 Old Gen's CollectionUsage.used is zero after mixed GC which is incorrect
+ * @key gc
+ * @requires vm.gc=="G1" | vm.gc=="null"
+ * @library /testlibrary /testlibrary/whitebox
+ * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.WhiteBox TestOldGenCollectionUsage
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions
+ * -XX:+WhiteBoxAPI -verbose:gc -XX:SurvivorRatio=1 -Xmx14m -Xms14m -XX:MaxTenuringThreshold=1
+ * -XX:InitiatingHeapOccupancyPercent=100 -XX:G1MixedGCCountTarget=4 -XX:MaxGCPauseMillis=30000
+ * -XX:G1HeapRegionSize=1m -XX:G1HeapWastePercent=0 -XX:G1MixedGCLiveThresholdPercent=100
+ * TestOldGenCollectionUsage
+ */
+
+import com.oracle.java.testlibrary.Asserts;
+import sun.hotspot.WhiteBox;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+
+import java.lang.management.*;
+
+// 8195115 says that for the "G1 Old Gen" MemoryPool, CollectionUsage.used
+// is zero for G1 after a mixed collection, which is incorrect.
+
+public class TestOldGenCollectionUsage {
+
+ private String poolName = "G1 Old Gen";
+ private String collectorName = "G1 Young Generation";
+
+ public static void main(String [] args) throws Exception {
+ TestOldGenCollectionUsage t = new TestOldGenCollectionUsage();
+ t.run();
+ }
+
+ public TestOldGenCollectionUsage() {
+ System.out.println("Monitor G1 Old Gen pool with G1 Young Generation collector.");
+ }
+
+ public void run() {
+ // Find memory pool and collector
+ List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
+ MemoryPoolMXBean pool = null;
+ boolean foundPool = false;
+ for (int i = 0; i < pools.size(); i++) {
+ pool = pools.get(i);
+ String name = pool.getName();
+ if (name.contains(poolName)) {
+ System.out.println("Found pool: " + name);
+ foundPool = true;
+ break;
+ }
+ }
+ if (!foundPool) {
+ throw new RuntimeException(poolName + " not found, test with -XX:+UseG1GC");
+ }
+
+ List<GarbageCollectorMXBean> collectors = ManagementFactory.getGarbageCollectorMXBeans();
+ GarbageCollectorMXBean collector = null;
+ boolean foundCollector = false;
+ for (int i = 0; i < collectors.size(); i++) {
+ collector = collectors.get(i);
+ String name = collector.getName();
+ if (name.contains(collectorName)) {
+ System.out.println("Found collector: " + name);
+ foundCollector = true;
+ break;
+ }
+ }
+ if (!foundCollector) {
+ throw new RuntimeException(collectorName + " not found, test with -XX:+UseG1GC");
+ }
+
+ MixedGCProvoker gcProvoker = new MixedGCProvoker();
+ gcProvoker.allocateOldObjects();
+
+ // Verify no non-zero result was stored
+ long usage = pool.getCollectionUsage().getUsed();
+ System.out.println(poolName + ": usage after GC = " + usage);
+ if (usage > 0) {
+ throw new RuntimeException("Premature mixed collections(s)");
+ }
+
+ // Verify that collections were done
+ long collectionCount = collector.getCollectionCount();
+ System.out.println(collectorName + ": collection count = "
+ + collectionCount);
+ long collectionTime = collector.getCollectionTime();
+ System.out.println(collectorName + ": collection time = "
+ + collectionTime);
+ if (collectionCount <= 0) {
+ throw new RuntimeException("Collection count <= 0");
+ }
+ if (collectionTime <= 0) {
+ throw new RuntimeException("Collector has not run");
+ }
+
+ gcProvoker.provokeMixedGC();
+
+ usage = pool.getCollectionUsage().getUsed();
+ System.out.println(poolName + ": usage after GC = " + usage);
+ if (usage <= 0) {
+ throw new RuntimeException(poolName + " found with zero usage");
+ }
+
+ long newCollectionCount = collector.getCollectionCount();
+ System.out.println(collectorName + ": collection count = "
+ + newCollectionCount);
+ long newCollectionTime = collector.getCollectionTime();
+ System.out.println(collectorName + ": collection time = "
+ + newCollectionTime);
+ if (newCollectionCount <= collectionCount) {
+ throw new RuntimeException("No new collection");
+ }
+ if (newCollectionTime <= collectionTime) {
+ throw new RuntimeException("Collector has not run some more");
+ }
+
+ System.out.println("Test passed.");
+ }
+
+ /**
+ * Utility class to guarantee a mixed GC. The class allocates several arrays and
+ * promotes them to the oldgen. After that it tries to provoke mixed GC by
+ * allocating new objects.
+ *
+ * The necessary condition for guaranteed mixed GC is running MixedGCProvoker is
+ * running in VM with the following flags: -XX:MaxTenuringThreshold=1 -Xms12M
+ * -Xmx12M -XX:G1MixedGCLiveThresholdPercent=100 -XX:G1HeapWastePercent=0
+ * -XX:G1HeapRegionSize=1m
+ */
+ public class MixedGCProvoker {
+ private final WhiteBox WB = WhiteBox.getWhiteBox();
+ private final List<byte[]> liveOldObjects = new ArrayList<>();
+ private final List<byte[]> newObjects = new ArrayList<>();
+
+ public static final int ALLOCATION_SIZE = 20000;
+ public static final int ALLOCATION_COUNT = 15;
+
+ public void allocateOldObjects() {
+ List<byte[]> deadOldObjects = new ArrayList<>();
+ // Allocates buffer and promotes it to the old gen. Mix live and dead old
+ // objects
+ for (int i = 0; i < ALLOCATION_COUNT; ++i) {
+ liveOldObjects.add(new byte[ALLOCATION_SIZE * 5]);
+ deadOldObjects.add(new byte[ALLOCATION_SIZE * 5]);
+ }
+
+ // Do two young collections, MaxTenuringThreshold=1 will force promotion.
+ // G1HeapRegionSize=1m guarantees that old gen regions will be filled.
+ WB.youngGC();
+ WB.youngGC();
+ // Check it is promoted & keep alive
+ Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
+ "List of the objects is suppose to be in OldGen");
+ Asserts.assertTrue(WB.isObjectInOldGen(deadOldObjects),
+ "List of the objects is suppose to be in OldGen");
+ }
+
+ /**
+ * Waits until Concurent Mark Cycle finishes
+ * @param wb Whitebox instance
+ * @param sleepTime sleep time
+ */
+ private void waitTillCMCFinished(int sleepTime) {
+ while (WB.g1InConcurrentMark()) {
+ if (sleepTime > -1) {
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ System.out.println("Got InterruptedException while waiting for ConcMarkCycle to finish");
+ }
+ }
+ }
+ }
+
+ public void provokeMixedGC() {
+ waitTillCMCFinished(0);
+ WB.g1StartConcMarkCycle();
+ waitTillCMCFinished(0);
+ WB.youngGC();
+
+ System.out.println("Allocating new objects to provoke mixed GC");
+ // Provoke a mixed collection. G1MixedGCLiveThresholdPercent=100
+ // guarantees that full old gen regions will be included.
+ for (int i = 0; i < (ALLOCATION_COUNT * 20); i++) {
+ try {
+ newObjects.add(new byte[ALLOCATION_SIZE]);
+ } catch (OutOfMemoryError e) {
+ newObjects.clear();
+ WB.youngGC();
+ WB.youngGC();
+ System.out.println("OutOfMemoryError is reported, stop allocating new objects");
+ break;
+ }
+ }
+ // check that liveOldObjects still alive
+ Asserts.assertTrue(WB.isObjectInOldGen(liveOldObjects),
+ "List of the objects is suppose to be in OldGen");
+ }
+
+ }
+
+}
diff --git a/test/jbProblemsList.txt b/test/jbProblemsList.txt
index 0d148c6b2..c48917f20 100644
--- a/test/jbProblemsList.txt
+++ b/test/jbProblemsList.txt
@@ -3,8 +3,9 @@ compiler/6857159/Test6857159.java
compiler/gcbarriers/TestMembarDependencies.java 8180904 generic-all
compiler/rtm/locking/TestUseRTMXendForLockBusy.java 8180723 generic-all
runtime/6981737/Test6981737.java generic-all
-runtime/NMT/NMTWithCDS.java 8180936 linux-all,macosx-all,windows-all
+runtime/NMT/NMTWithCDS.java 8180936 generic-all
gc/arguments/TestMinInitialErgonomics.java 8033667 linux-all,macosx-all
+gc/metaspace/TestCapacityUntilGCWrapAround.java 8226236 windows-all
gc/TestVerifySilently.java 8180904 generic-all
gc/TestVerifySubSet.java 8180904 generic-all
serviceability/jvmti/TestRedefineWithUnresolvedClass.java 8180904 generic-all
diff --git a/test/runtime/6981737/Test6981737.java b/test/runtime/6981737/Test6981737.java
index 0171f8373..d31353955 100644
--- a/test/runtime/6981737/Test6981737.java
+++ b/test/runtime/6981737/Test6981737.java
@@ -48,8 +48,6 @@ public class Test6981737 {
vendor_re = "Sun Microsystems Inc\\.";
vm_spec_version_re = "1\\.0";
}
- verifyProperty("java.vendor", vendor_re);
- verifyProperty("java.vm.vendor", vendor_re);
verifyProperty("java.vm.specification.vendor", vendor_re);
verifyProperty("java.specification.vendor", vendor_re);
verifyProperty("java.vm.specification.version", vm_spec_version_re);
diff --git a/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java b/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
index 7e5983457..2224dbdae 100644
--- a/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
+++ b/test/runtime/ErrorHandling/TestCrashOnOutOfMemoryError.java
@@ -25,7 +25,7 @@
* @test TestCrashOnOutOfMemoryError
* @summary Test using -XX:+CrashOnOutOfMemoryError
* @library /testlibrary
- * @build jdk.test.lib.*
+ * @build com.oracle.java.testlibrary.*
* @run driver TestCrashOnOutOfMemoryError
* @bug 8138745
*/
diff --git a/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java b/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java
index a3c1ce701..d8db19c46 100644
--- a/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java
+++ b/test/runtime/ErrorHandling/TestExitOnOutOfMemoryError.java
@@ -25,7 +25,7 @@
* @test TestExitOnOutOfMemoryError
* @summary Test using -XX:ExitOnOutOfMemoryError
* @library /testlibrary
- * @build jdk.test.lib.*
+ * @build com.oracle.java.testlibrary.*
* @run driver TestExitOnOutOfMemoryError
* @bug 8138745
*/
diff --git a/test/runtime/NMT/JcmdDetailDiff.java b/test/runtime/NMT/JcmdDetailDiff.java
index 8f151c29b..d3a5d3e31 100644
--- a/test/runtime/NMT/JcmdDetailDiff.java
+++ b/test/runtime/NMT/JcmdDetailDiff.java
@@ -26,7 +26,6 @@
* @summary run NMT baseline, allocate memory and verify output from detail.diff
* @key nmt jcmd
* @library /testlibrary /testlibrary/whitebox
- * @ignore
* @build JcmdDetailDiff
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail JcmdDetailDiff
diff --git a/test/runtime/NMT/MallocSiteTypeChange.java b/test/runtime/NMT/MallocSiteTypeChange.java
new file mode 100644
index 000000000..a589df902
--- /dev/null
+++ b/test/runtime/NMT/MallocSiteTypeChange.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. 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 MallocSiteTypeChange
+ * @summary Test a malloc site type change results NMT to report deallocation of old type and allocation of new type
+ * @bug 8200109
+ * @key nmt jcmd
+ * @modules java.base/jdk.internal.misc
+ * @library /testlibrary /testlibrary/whitebox
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteTypeChange
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class MallocSiteTypeChange {
+ public static void main(String args[]) throws Exception {
+ OutputAnalyzer output;
+ WhiteBox wb = WhiteBox.getWhiteBox();
+
+ // Grab my own PID
+ String pid = Long.toString(ProcessTools.getProcessId());
+ ProcessBuilder pb = new ProcessBuilder();
+
+ int pc = 1;
+ long addr = wb.NMTMallocWithPseudoStack(4 * 1024, pc);
+
+ // Verify that current tracking level is "detail"
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Test (reserved=4KB, committed=4KB)");
+
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline"});
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Baseline succeeded");
+
+ wb.NMTFree(addr);
+ addr = wb.NMTMallocWithPseudoStackAndType(2 * 1024, pc, 7 /* mtInternal */ );
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail.diff"});
+ output = new OutputAnalyzer(pb.start());
+ output.shouldContain("(malloc=0KB type=Test -4KB)");
+ output.shouldContain("(malloc=2KB type=Internal +2KB #1 +1)");
+ output.shouldHaveExitValue(0);
+ }
+}
diff --git a/test/runtime/NMT/NMTWithCDS.java b/test/runtime/NMT/NMTWithCDS.java
index 4672d3d5f..1d865618f 100644
--- a/test/runtime/NMT/NMTWithCDS.java
+++ b/test/runtime/NMT/NMTWithCDS.java
@@ -34,14 +34,15 @@ public class NMTWithCDS {
public static void main(String[] args) throws Exception {
ProcessBuilder pb;
- pb = ProcessTools.createJavaProcessBuilder("-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump");
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump");
OutputAnalyzer output = new OutputAnalyzer(pb.start());
try {
output.shouldContain("Loading classes to share");
output.shouldHaveExitValue(0);
pb = ProcessTools.createJavaProcessBuilder(
- "-XX:NativeMemoryTracking=detail", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version");
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:NativeMemoryTracking=detail", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("sharing");
output.shouldHaveExitValue(0);
diff --git a/test/runtime/RedefineTests/RedefineDoubleDelete.java b/test/runtime/RedefineTests/RedefineDoubleDelete.java
new file mode 100644
index 000000000..1f4533f8e
--- /dev/null
+++ b/test/runtime/RedefineTests/RedefineDoubleDelete.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 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 8178870
+ * @library /testlibrary
+ * @summary Redefine class with CFLH twice to test deleting the cached_class_file
+ * @build RedefineClassHelper
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineDoubleDelete
+ */
+
+public class RedefineDoubleDelete {
+
+ // Class gets a redefinition error because it adds a data member
+ public static String newB =
+ "class RedefineDoubleDelete$B {" +
+ " int count1 = 0;" +
+ "}";
+
+ public static String newerB =
+ "class RedefineDoubleDelete$B { " +
+ " int faa() { System.out.println(\"baa\"); return 2; }" +
+ "}";
+
+ // The ClassFileLoadHook for this class turns foo into faa and prints out faa.
+ static class B {
+ int faa() { System.out.println("foo"); return 1; }
+ }
+
+ public static void main(String args[]) throws Exception {
+
+ B b = new B();
+ int val = b.faa();
+ if (val != 1) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Redefine B twice to get cached_class_file in both B scratch classes
+ try {
+ RedefineClassHelper.redefineClass(B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+ try {
+ RedefineClassHelper.redefineClass(B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+
+ // Do a full GC.
+ System.gc();
+
+ // Redefine with a compatible class
+ RedefineClassHelper.redefineClass(B.class, newerB);
+ val = b.faa();
+ if (val != 2) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Do another full GC to clean things up.
+ System.gc();
+ }
+}
diff --git a/test/runtime/RedefineTests/libRedefineDoubleDelete.c b/test/runtime/RedefineTests/libRedefineDoubleDelete.c
new file mode 100644
index 000000000..d855e873a
--- /dev/null
+++ b/test/runtime/RedefineTests/libRedefineDoubleDelete.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+static jvmtiEnv *jvmti = NULL;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_1_8;
+}
+
+
+static jint newClassDataLen = 0;
+static unsigned char* newClassData = NULL;
+
+static jint
+getBytecodes(jvmtiEnv *jvmti_env,
+ jint class_data_len, const unsigned char* class_data) {
+ int i;
+ jint res;
+
+ newClassDataLen = class_data_len;
+ res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
+ if (res != JNI_OK) {
+ printf(" Unable to allocate bytes\n");
+ return JNI_ERR;
+ }
+ for (i = 0; i < newClassDataLen; i++) {
+ newClassData[i] = class_data[i];
+ // Rewrite oo in class to aa
+ if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
+ newClassData[i] = newClassData[i-1] = 'a';
+ }
+ }
+ printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
+ return JNI_OK;
+}
+
+
+static void JNICALL
+Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
+ jclass class_being_redefined,
+ jobject loader, const char* name, jobject protection_domain,
+ jint class_data_len, const unsigned char* class_data,
+ jint *new_class_data_len, unsigned char** new_class_data) {
+ if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
+ if (newClassData == NULL) {
+ jint res = getBytecodes(jvmti_env, class_data_len, class_data);
+ if (res == JNI_ERR) {
+ printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
+ return;
+ }
+ // Only change for first CFLH event.
+ *new_class_data_len = newClassDataLen;
+ *new_class_data = newClassData;
+ }
+ printf(">>> ClassFileLoadHook event: class name %s\n", name);
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_1_2);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ printf("Enabling following capabilities: can_generate_all_class_hook_events, "
+ "can_retransform_classes, can_redefine_classes");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_all_class_hook_events = 1;
+ caps.can_retransform_classes = 1;
+ caps.can_redefine_classes = 1;
+ printf("\n");
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/test/runtime/VtableTests/VTableTest.java b/test/runtime/VtableTests/VTableTest.java
new file mode 100644
index 000000000..2ca32e43f
--- /dev/null
+++ b/test/runtime/VtableTests/VTableTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019, 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 8226798
+ * @summary Check that the vTable for class C gets set up without causing
+ * an assertion failure.
+ * @compile pkg/A.java
+ * @run main VTableTest
+ */
+
+public class VTableTest {
+
+ interface Intf {
+ public default void m() { }
+ public default void unusedButNeededToReproduceIssue() { }
+ }
+
+ static class B extends pkg.A implements Intf {
+ }
+
+ static class C extends B {
+ public void m() { System.out.println("In C.m()"); }
+ }
+
+ public static void main(String[] args) {
+ new C().m();
+ }
+}
diff --git a/test/runtime/VtableTests/pkg/A.java b/test/runtime/VtableTests/pkg/A.java
new file mode 100644
index 000000000..a4b7f49e7
--- /dev/null
+++ b/test/runtime/VtableTests/pkg/A.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+package pkg;
+
+public class A {
+ void m() { }
+}
diff --git a/test/runtime/containers/docker/TestCPUAwareness.java b/test/runtime/containers/docker/TestCPUAwareness.java
index fe7d4499b..886aefcaf 100644
--- a/test/runtime/containers/docker/TestCPUAwareness.java
+++ b/test/runtime/containers/docker/TestCPUAwareness.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -125,7 +125,8 @@ private static final String imageName = Common.imageName("cpu");
private static void testCpus(int valueToSet, int expectedTraceValue) throws Exception {
Common.logNewTestCase("test cpus: " + valueToSet);
DockerRunOptions opts = Common.newOpts(imageName)
- .addDockerOpts("--cpus", "" + valueToSet);
+ .addDockerOpts("--cpu-period=" + 10000)
+ .addDockerOpts("--cpu-quota=" + valueToSet * 10000);
Common.run(opts)
.shouldMatch("active_processor_count.*" + expectedTraceValue);
}
diff --git a/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.c b/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.c
new file mode 100644
index 000000000..70a661859
--- /dev/null
+++ b/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include <jni.h>
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: testJNIFieldAccessors
+ * Signature: (LCallWithJNIWeak;)V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_testJNIFieldAccessors(JNIEnv *env, jclass clazz, jobject this) {
+ // Make sure that we have a weak reference to the receiver
+
+ jweak self = (*env)->NewWeakGlobalRef(env, this);
+
+ jclass this_class = (*env)->GetObjectClass(env, self);
+
+ jclass exception = (*env)->FindClass(env, "java/lang/RuntimeException");
+
+ jfieldID id_i = (*env)->GetFieldID(env, this_class, "i", "I");
+ jfieldID id_j = (*env)->GetFieldID(env, this_class, "j", "J");
+ jfieldID id_z = (*env)->GetFieldID(env, this_class, "z", "Z");
+ jfieldID id_c = (*env)->GetFieldID(env, this_class, "c", "C");
+ jfieldID id_s = (*env)->GetFieldID(env, this_class, "s", "S");
+ jfieldID id_f = (*env)->GetFieldID(env, this_class, "f", "F");
+ jfieldID id_d = (*env)->GetFieldID(env, this_class, "d", "D");
+ jfieldID id_l = (*env)->GetFieldID(env, this_class, "l", "Ljava/lang/Object;");
+ jvalue v;
+
+#define CHECK(variable, expected) \
+ do { \
+ if ((variable) != (expected)) { \
+ (*env)->ThrowNew(env, exception, #variable" != " #expected); \
+ return; \
+ } \
+ } while(0)
+
+ // The values checked below must be kept in sync with the Java source file.
+
+ v.i = (*env)->GetIntField(env, self, id_i);
+ CHECK(v.i, 1);
+
+ v.j = (*env)->GetLongField(env, self, id_j);
+ CHECK(v.j, 2);
+
+ v.z = (*env)->GetBooleanField(env, self, id_z);
+ CHECK(v.z, JNI_TRUE);
+
+ v.c = (*env)->GetCharField(env, self, id_c);
+ CHECK(v.c, 'a');
+
+ v.s = (*env)->GetShortField(env, self, id_s);
+ CHECK(v.s, 3);
+
+ v.f = (*env)->GetFloatField(env, self, id_f);
+ CHECK(v.f, 1.0f);
+
+ v.d = (*env)->GetDoubleField(env, self, id_d);
+ CHECK(v.d, 2.0);
+
+#undef CHECK
+
+ v.l = (*env)->GetObjectField(env, self, id_l);
+ if (v.l == NULL) {
+ (*env)->ThrowNew(env, exception, "Object field was null");
+ return;
+ }
+ {
+ jclass clz = (*env)->GetObjectClass(env, v.l);
+ if (!(*env)->IsSameObject(env, clazz, clz)) {
+ (*env)->ThrowNew(env, exception, "Bad object class");
+ }
+ }
+
+ (*env)->DeleteWeakGlobalRef(env, self);
+}
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: runTests
+ * Signature: (LCallWithJNIWeak;)V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_runTests(JNIEnv *env, jclass clazz, jobject this) {
+ jweak that = (*env)->NewWeakGlobalRef(env, this);
+ {
+ jmethodID method = (*env)->GetStaticMethodID(env,
+ clazz, "testJNIFieldAccessors", "(LCallWithJNIWeak;)V");
+ (*env)->CallStaticVoidMethod(env, clazz, method, that);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+
+ {
+ jmethodID method = (*env)->GetMethodID(env, clazz, "weakReceiverTest", "()V");
+ (*env)->CallVoidMethod(env, that, method);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+
+ {
+ jmethodID method = (*env)->GetMethodID(env, clazz, "synchonizedWeakReceiverTest", "()V");
+ (*env)->CallVoidMethod(env, that, method);
+ if ((*env)->ExceptionCheck(env)) {
+ return;
+ }
+ }
+ (*env)->DeleteWeakGlobalRef(env, that);
+}
+
+/*
+ * Class: CallWithJNIWeak
+ * Method: weakReceiverTest0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_CallWithJNIWeak_weakReceiverTest0(JNIEnv *env, jobject obj) {
+ (*env)->GetObjectClass(env, obj);
+}
diff --git a/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java b/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java
new file mode 100644
index 000000000..240f54680
--- /dev/null
+++ b/test/runtime/jni/CallWithJNIWeak/CallWithJNIWeak.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+public class CallWithJNIWeak {
+ static {
+ System.loadLibrary("CallWithJNIWeak");
+ }
+
+ private static native void testJNIFieldAccessors(CallWithJNIWeak o);
+
+ // The field initializations must be kept in sync with the JNI code
+ // which reads verifies the values of these fields.
+ private int i = 1;
+ private long j = 2;
+ private boolean z = true;
+ private char c = 'a';
+ private short s = 3;
+ private float f = 1.0f;
+ private double d = 2.0;
+ private Object l;
+
+ private CallWithJNIWeak() {
+ this.l = this;
+ }
+
+ private native void weakReceiverTest0();
+ private void weakReceiverTest() {
+ weakReceiverTest0();
+ }
+
+ private synchronized void synchonizedWeakReceiverTest() {
+ this.notifyAll();
+ }
+
+ private static native void runTests(CallWithJNIWeak o);
+
+ public static void main(String[] args) {
+ CallWithJNIWeak w = new CallWithJNIWeak();
+ for (int i = 0; i < 20000; i++) {
+ runTests(w);
+ }
+ }
+}
diff --git a/test/runtime/jni/CallWithJNIWeak/test.sh b/test/runtime/jni/CallWithJNIWeak/test.sh
new file mode 100644
index 000000000..d92a2d462
--- /dev/null
+++ b/test/runtime/jni/CallWithJNIWeak/test.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+#
+# Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011 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.
+#
+
+## @test test.sh
+## @bug 8166188
+## @requires vm.opt.ExplicitGCInvokesConcurrent != true
+## @summary Test call of native function with JNI weak global ref.
+## @run shell test.sh
+
+if [ "${TESTSRC}" = "" ]
+then
+ TESTSRC=${PWD}
+ echo "TESTSRC not set. Using "${TESTSRC}" as default"
+fi
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../../test_env.sh
+
+# set platform-dependent variables
+OS=`uname -s`
+echo "Testing on " $OS
+case "$OS" in
+ Linux)
+ cc_cmd=`which gcc`
+ if [ "x$cc_cmd" == "x" ]; then
+ echo "WARNING: gcc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
+ ;;
+ Solaris)
+ cc_cmd=`which cc`
+ if [ "x$cc_cmd" == "x" ]; then
+ echo "WARNING: cc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
+ ;;
+ *)
+ echo "Test passed; only valid for Linux and Solaris"
+ exit 0;
+ ;;
+esac
+
+THIS_DIR=.
+
+cp ${TESTSRC}${FS}*.java ${THIS_DIR}
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+$cc_cmd -fPIC -shared -o libCallWithJNIWeak.so \
+ -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux \
+ ${TESTSRC}${FS}CallWithJNIWeak.c
+
+LD_LIBRARY_PATH=${THIS_DIR}
+echo LD_LIBRARY_PATH = ${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+echo
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xint CallWithJNIWeak
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xint CallWithJNIWeak
+JAVA_RETVAL=$?
+
+if [ "$JAVA_RETVAL" == "0" ]
+then
+ echo
+ echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xcomp CallWithJNIWeak
+ ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xcomp CallWithJNIWeak
+
+ JAVA_RETVAL=$?
+fi
+
+exit $JAVA_RETVAL
diff --git a/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.c b/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.c
new file mode 100644
index 000000000..12d7ae92e
--- /dev/null
+++ b/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * Native support for ReturnJNIWeak test.
+ */
+
+#include "jni.h"
+
+static jweak registered = NULL;
+
+JNIEXPORT void JNICALL
+Java_ReturnJNIWeak_registerObject(JNIEnv* env,
+ jclass jclazz,
+ jobject value) {
+ // assert registered == NULL
+ registered = (*env)->NewWeakGlobalRef(env, value);
+}
+
+JNIEXPORT void JNICALL
+Java_ReturnJNIWeak_unregisterObject(JNIEnv* env, jclass jclazz) {
+ if (registered != NULL) {
+ (*env)->DeleteWeakGlobalRef(env, registered);
+ registered = NULL;
+ }
+}
+
+JNIEXPORT jobject JNICALL
+Java_ReturnJNIWeak_getObject(JNIEnv* env, jclass jclazz) {
+ // assert registered != NULL
+ return registered;
+}
diff --git a/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java b/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java
new file mode 100644
index 000000000..4d57b1d24
--- /dev/null
+++ b/test/runtime/jni/ReturnJNIWeak/ReturnJNIWeak.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+public final class ReturnJNIWeak {
+ static {
+ System.loadLibrary("ReturnJNIWeak");
+ }
+
+ private static final class TestObject {
+ public final int value;
+
+ public TestObject(int value) {
+ this.value = value;
+ }
+ }
+
+ private static volatile TestObject testObject = null;
+
+ private static native void registerObject(Object o);
+ private static native void unregisterObject();
+ private static native Object getObject();
+
+ // Create the test object and record it both strongly and weakly.
+ private static void remember(int value) {
+ TestObject o = new TestObject(value);
+ registerObject(o);
+ testObject = o;
+ }
+
+ // Remove both strong and weak references to the current test object.
+ private static void forget() {
+ unregisterObject();
+ testObject = null;
+ }
+
+ // Verify the weakly recorded object
+ private static void checkValue(int value) throws Exception {
+ Object o = getObject();
+ if (o == null) {
+ throw new RuntimeException("Weak reference unexpectedly null");
+ }
+ TestObject t = (TestObject)o;
+ if (t.value != value) {
+ throw new RuntimeException("Incorrect value");
+ }
+ }
+
+ // Verify we can create a weak reference and get it back.
+ private static void testSanity() throws Exception {
+ System.out.println("running testSanity");
+ int value = 5;
+ try {
+ remember(value);
+ checkValue(value);
+ } finally {
+ forget();
+ }
+ }
+
+ // Verify weak ref value survives across collection if strong ref exists.
+ private static void testSurvival() throws Exception {
+ System.out.println("running testSurvival");
+ int value = 10;
+ try {
+ remember(value);
+ checkValue(value);
+ System.gc();
+ // Verify weak ref still has expected value.
+ checkValue(value);
+ } finally {
+ forget();
+ }
+ }
+
+ // Verify weak ref cleared if no strong ref exists.
+ private static void testClear() throws Exception {
+ System.out.println("running testClear");
+ int value = 15;
+ try {
+ remember(value);
+ checkValue(value);
+ // Verify still good.
+ checkValue(value);
+ // Drop reference.
+ testObject = null;
+ System.gc();
+ // Verify weak ref cleared as expected.
+ Object recorded = getObject();
+ if (recorded != null) {
+ throw new RuntimeException("expected clear");
+ }
+ } finally {
+ forget();
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testSanity();
+ testSurvival();
+ testClear();
+ }
+}
diff --git a/test/runtime/jni/ReturnJNIWeak/test.sh b/test/runtime/jni/ReturnJNIWeak/test.sh
new file mode 100644
index 000000000..c7035bc26
--- /dev/null
+++ b/test/runtime/jni/ReturnJNIWeak/test.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+
+#
+# Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011 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.
+#
+
+## @test test.sh
+## @bug 8166188
+## @requires vm.opt.ExplicitGCInvokesConcurrent != true
+## @summary Test return of JNI weak global refs from native calls.
+## @run shell test.sh
+
+if [ "${TESTSRC}" = "" ]
+then
+ TESTSRC=${PWD}
+ echo "TESTSRC not set. Using "${TESTSRC}" as default"
+fi
+echo "TESTSRC=${TESTSRC}"
+## Adding common setup Variables for running shell tests.
+. ${TESTSRC}/../../../test_env.sh
+
+# set platform-dependent variables
+OS=`uname -s`
+echo "Testing on " $OS
+case "$OS" in
+ Linux)
+ cc_cmd=`which gcc`
+ if [ "x$cc_cmd" == "x" ]; then
+ echo "WARNING: gcc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
+ ;;
+ Solaris)
+ cc_cmd=`which cc`
+ if [ "x$cc_cmd" == "x" ]; then
+ echo "WARNING: cc not found. Cannot execute test." 2>&1
+ exit 0;
+ fi
+ ;;
+ *)
+ echo "Test passed; only valid for Linux and Solaris"
+ exit 0;
+ ;;
+esac
+
+THIS_DIR=.
+
+cp ${TESTSRC}${FS}*.java ${THIS_DIR}
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+$cc_cmd -fPIC -shared -o libReturnJNIWeak.so \
+ -I${TESTJAVA}${FS}include -I${TESTJAVA}${FS}include${FS}linux \
+ ${TESTSRC}${FS}ReturnJNIWeak.c
+
+LD_LIBRARY_PATH=${THIS_DIR}
+echo LD_LIBRARY_PATH = ${LD_LIBRARY_PATH}
+export LD_LIBRARY_PATH
+
+echo
+echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xint ReturnJNIWeak
+${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xint ReturnJNIWeak
+JAVA_RETVAL=$?
+
+if [ "$JAVA_RETVAL" == "0" ]
+then
+ echo
+ echo ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xcomp ReturnJNIWeak
+ ${TESTJAVA}${FS}bin${FS}java -cp ${THIS_DIR} -Xcomp ReturnJNIWeak
+
+ JAVA_RETVAL=$?
+fi
+
+exit $JAVA_RETVAL
diff --git a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
index d2f49da47..1327bd30d 100644
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
+++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -117,6 +117,7 @@ public class WhiteBox {
public native void NMTUncommitMemory(long addr, long size);
public native void NMTReleaseMemory(long addr, long size);
public native long NMTMallocWithPseudoStack(long size, int index);
+ public native long NMTMallocWithPseudoStackAndType(long size, int index, int type);
public native boolean NMTIsDetailSupported();
public native boolean NMTChangeTrackingLevel();
public native int NMTGetHashSize();
@@ -161,6 +162,7 @@ public class WhiteBox {
}
public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
public native void clearMethodState(Executable method);
+ public native void markMethodProfiled(Executable method);
public native int getMethodEntryBci(Executable method);
public native Object[] getNMethod(Executable method, boolean isOsr);
diff --git a/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java b/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java
index 4bdb49d0b..7cd36c25a 100644
--- a/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java
+++ b/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java
@@ -34,18 +34,21 @@ public class NMethod {
return obj == null ? null : new NMethod(obj);
}
private NMethod(Object[] obj) {
- assert obj.length == 2;
+ assert obj.length == 3;
comp_level = (Integer) obj[0];
- insts = (byte[]) obj[1];
+ compile_id = (Integer) obj[1];
+ insts = (byte[]) obj[2];
}
- public byte[] insts;
- public int comp_level;
+ public final byte[] insts;
+ public final int comp_level;
+ public final int compile_id;
@Override
public String toString() {
return "NMethod{" +
"insts=" + insts +
", comp_level=" + comp_level +
+ ", compile_id=" + compile_id +
'}';
}
}