aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Dahlstrom <dahlstrom@google.com>2020-02-12 11:00:00 -0800
committerDana Dahlstrom <dahlstrom@google.com>2020-02-12 11:00:00 -0800
commitb858c62626dee0a44ff853b52c07d6fe63f83a8e (patch)
tree6e9d079fa431ee651644a46eea9a3ae7c64d68ae
parent0c613a25e5e544c2743bbfe485295417b845284a (diff)
parent63388d7cef8a6b2d2fd1c64ee4e612e514e21409 (diff)
downloadjdk8u_hotspot-master.tar.gz
Merge tag jb8u242-b1644.3HEADmastermain
Change-Id: I63388d7cef8a6b2d2fd1c64ee4e612e514e21409
-rw-r--r--.hgtags9
-rw-r--r--THIRD_PARTY_README4
-rw-r--r--src/cpu/ppc/vm/vm_version_ppc.cpp5
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.hpp8
-rw-r--r--src/cpu/sparc/vm/stubGenerator_sparc.cpp128
-rw-r--r--src/cpu/sparc/vm/vm_version_sparc.cpp55
-rw-r--r--src/cpu/x86/vm/assembler_x86.cpp9
-rw-r--r--src/cpu/x86/vm/assembler_x86.hpp2
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_32.cpp170
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_64.cpp176
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86.cpp4
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86.hpp7
-rw-r--r--src/cpu/x86/vm/vm_version_x86.cpp49
-rw-r--r--src/share/vm/c1/c1_LIR.cpp10
-rw-r--r--src/share/vm/classfile/vmSymbols.hpp6
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp17
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp14
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp16
-rw-r--r--src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp1
-rw-r--r--src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp6
-rw-r--r--src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp2
-rw-r--r--src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp4
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp4
-rw-r--r--src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp10
-rw-r--r--src/share/vm/gc_implementation/shared/gSpaceCounters.hpp4
-rw-r--r--src/share/vm/gc_implementation/shared/vmGCOperations.cpp13
-rw-r--r--src/share/vm/gc_implementation/shared/vmGCOperations.hpp4
-rw-r--r--src/share/vm/memory/gcLocker.cpp14
-rw-r--r--src/share/vm/memory/gcLocker.hpp8
-rw-r--r--src/share/vm/memory/genCollectedHeap.cpp24
-rw-r--r--src/share/vm/memory/generation.cpp6
-rw-r--r--src/share/vm/memory/generation.hpp1
-rw-r--r--src/share/vm/oops/instanceKlass.cpp4
-rw-r--r--src/share/vm/oops/instanceKlass.hpp2
-rw-r--r--src/share/vm/oops/klassVtable.cpp13
-rw-r--r--src/share/vm/opto/escape.cpp4
-rw-r--r--src/share/vm/opto/library_call.cpp37
-rw-r--r--src/share/vm/opto/loopTransform.cpp9
-rw-r--r--src/share/vm/opto/loopnode.hpp1
-rw-r--r--src/share/vm/opto/loopopts.cpp2
-rw-r--r--src/share/vm/opto/runtime.cpp20
-rw-r--r--src/share/vm/opto/runtime.hpp2
-rw-r--r--src/share/vm/opto/superword.cpp26
-rw-r--r--src/share/vm/runtime/globals.hpp3
-rw-r--r--src/share/vm/runtime/safepoint.cpp1
-rw-r--r--src/share/vm/runtime/stubRoutines.cpp5
-rw-r--r--src/share/vm/runtime/stubRoutines.hpp2
-rw-r--r--src/share/vm/runtime/vmStructs.cpp1
-rw-r--r--src/share/vm/services/allocationSite.hpp5
-rw-r--r--src/share/vm/services/mallocSiteTable.cpp16
-rw-r--r--src/share/vm/services/mallocSiteTable.hpp8
-rw-r--r--src/share/vm/services/memBaseline.cpp6
-rw-r--r--src/share/vm/services/memReporter.cpp29
-rw-r--r--src/share/vm/services/memReporter.hpp2
-rw-r--r--src/share/vm/services/memoryPool.hpp2
-rw-r--r--src/share/vm/services/virtualMemoryTracker.hpp4
-rw-r--r--src/share/vm/utilities/macros.hpp8
-rw-r--r--src/share/vm/utilities/taskqueue.hpp5
-rw-r--r--src/share/vm/utilities/workgroup.cpp1
-rw-r--r--test/compiler/7184394/TestAESBase.java45
-rw-r--r--test/compiler/7184394/TestAESDecode.java6
-rw-r--r--test/compiler/7184394/TestAESEncode.java8
-rw-r--r--test/compiler/7184394/TestAESMain.java7
-rw-r--r--test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java11
-rw-r--r--test/compiler/loopopts/StrangeControl.jasm48
-rw-r--r--test/compiler/loopopts/TestRemoveEmptyLoop.java53
-rw-r--r--test/compiler/loopopts/TestStrangeControl.java49
-rw-r--r--test/compiler/loopopts/superword/TestFuzzPreLoop.java65
-rw-r--r--test/compiler/print/TestProfileReturnTypePrinting.java68
-rw-r--r--test/gc/stress/gclocker/TestExcessGCLockerCollections.java285
-rw-r--r--test/runtime/8003720/VictimClassLoader.java8
71 files changed, 1536 insertions, 125 deletions
diff --git a/.hgtags b/.hgtags
index a933d7c01..31c3b58f0 100644
--- a/.hgtags
+++ b/.hgtags
@@ -1317,3 +1317,12 @@ c751303497d539aa85c6373aa0fa85580d3f3044 jdk8u232-b07
4170228e11e6313e948e6ddcae9af3eed06b1fbe jdk8u232-b08
12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-b09
12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-ga
+ce42ae95d4d671f74246091f89bd101d5bcbfd91 jdk8u242-b01
+775e2bf92114e41365cc6baf1480c818454256a4 jdk8u242-b02
+ee19c358e3b8deeda2f64d660a0870df7b1abd49 jdk8u242-b03
+20258ba5a788da55485c0648bcc073f8ad2c26ef jdk8u242-b04
+2c1e9fab6964647f4eeffe55fe5592da6399a3ce jdk8u242-b05
+81ddc1072b923330f84c0ace3124226f63877582 jdk8u242-b06
+8b80409d5840142a27e274d33948f483a6406a50 jdk8u242-b07
+7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d jdk8u242-b08
+7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d jdk8u242-ga
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index 7dc54a057..643ea79ce 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -1334,11 +1334,13 @@ SUCH DAMAGE.
--------------------------------------------------------------------------------
-%% This notice is provided with respect to Joni v1.1.9, which may be
+%% This notice is provided with respect to Joni v2.1.16, which may be
included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
+Copyright (c) 2017 JRuby Team
+
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
diff --git a/src/cpu/ppc/vm/vm_version_ppc.cpp b/src/cpu/ppc/vm/vm_version_ppc.cpp
index bbc52691b..3c59c96ca 100644
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp
+++ b/src/cpu/ppc/vm/vm_version_ppc.cpp
@@ -194,6 +194,11 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
}
+ if (UseGHASHIntrinsics) {
+ warning("GHASH intrinsics are not available on this CPU");
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
+ }
+
if (has_vshasig()) {
if (FLAG_IS_DEFAULT(UseSHA)) {
UseSHA = true;
diff --git a/src/cpu/sparc/vm/assembler_sparc.hpp b/src/cpu/sparc/vm/assembler_sparc.hpp
index dd83b092f..55f338754 100644
--- a/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -129,6 +129,7 @@ class Assembler : public AbstractAssembler {
flog3_op3 = 0x36,
edge_op3 = 0x36,
fsrc_op3 = 0x36,
+ xmulx_op3 = 0x36,
impdep2_op3 = 0x37,
stpartialf_op3 = 0x37,
jmpl_op3 = 0x38,
@@ -220,6 +221,8 @@ class Assembler : public AbstractAssembler {
mdtox_opf = 0x110,
mstouw_opf = 0x111,
mstosw_opf = 0x113,
+ xmulx_opf = 0x115,
+ xmulxhi_opf = 0x116,
mxtod_opf = 0x118,
mwtos_opf = 0x119,
@@ -1212,6 +1215,9 @@ public:
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
+ void xmulx(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulx_opf) | rs2(s2)); }
+ void xmulxhi(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulxhi_opf) | rs2(s2)); }
+
// Crypto SHA instructions
void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
index 6ad0b1a41..51064927e 100644
--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
@@ -4788,6 +4788,130 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ /* Single and multi-block ghash operations */
+ address generate_ghash_processBlocks() {
+ __ align(CodeEntryAlignment);
+ Label L_ghash_loop, L_aligned, L_main;
+ StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ address start = __ pc();
+
+ Register state = I0;
+ Register subkeyH = I1;
+ Register data = I2;
+ Register len = I3;
+
+ __ save_frame(0);
+
+ __ ldx(state, 0, O0);
+ __ ldx(state, 8, O1);
+
+ // Loop label for multiblock operations
+ __ BIND(L_ghash_loop);
+
+ // Check if 'data' is unaligned
+ __ andcc(data, 7, G1);
+ __ br(Assembler::zero, false, Assembler::pt, L_aligned);
+ __ delayed()->nop();
+
+ Register left_shift = L1;
+ Register right_shift = L2;
+ Register data_ptr = L3;
+
+ // Get left and right shift values in bits
+ __ sll(G1, LogBitsPerByte, left_shift);
+ __ mov(64, right_shift);
+ __ sub(right_shift, left_shift, right_shift);
+
+ // Align to read 'data'
+ __ sub(data, G1, data_ptr);
+
+ // Load first 8 bytes of 'data'
+ __ ldx(data_ptr, 0, O4);
+ __ sllx(O4, left_shift, O4);
+ __ ldx(data_ptr, 8, O5);
+ __ srlx(O5, right_shift, G4);
+ __ bset(G4, O4);
+
+ // Load second 8 bytes of 'data'
+ __ sllx(O5, left_shift, O5);
+ __ ldx(data_ptr, 16, G4);
+ __ srlx(G4, right_shift, G4);
+ __ ba(L_main);
+ __ delayed()->bset(G4, O5);
+
+ // If 'data' is aligned, load normally
+ __ BIND(L_aligned);
+ __ ldx(data, 0, O4);
+ __ ldx(data, 8, O5);
+
+ __ BIND(L_main);
+ __ ldx(subkeyH, 0, O2);
+ __ ldx(subkeyH, 8, O3);
+
+ __ xor3(O0, O4, O0);
+ __ xor3(O1, O5, O1);
+
+ __ xmulxhi(O0, O3, G3);
+ __ xmulx(O0, O2, O5);
+ __ xmulxhi(O1, O2, G4);
+ __ xmulxhi(O1, O3, G5);
+ __ xmulx(O0, O3, G1);
+ __ xmulx(O1, O3, G2);
+ __ xmulx(O1, O2, O3);
+ __ xmulxhi(O0, O2, O4);
+
+ __ mov(0xE1, O0);
+ __ sllx(O0, 56, O0);
+
+ __ xor3(O5, G3, O5);
+ __ xor3(O5, G4, O5);
+ __ xor3(G5, G1, G1);
+ __ xor3(G1, O3, G1);
+ __ srlx(G2, 63, O1);
+ __ srlx(G1, 63, G3);
+ __ sllx(G2, 63, O3);
+ __ sllx(G2, 58, O2);
+ __ xor3(O3, O2, O2);
+
+ __ sllx(G1, 1, G1);
+ __ or3(G1, O1, G1);
+
+ __ xor3(G1, O2, G1);
+
+ __ sllx(G2, 1, G2);
+
+ __ xmulxhi(G1, O0, O1);
+ __ xmulx(G1, O0, O2);
+ __ xmulxhi(G2, O0, O3);
+ __ xmulx(G2, O0, G1);
+
+ __ xor3(O4, O1, O4);
+ __ xor3(O5, O2, O5);
+ __ xor3(O5, O3, O5);
+
+ __ sllx(O4, 1, O2);
+ __ srlx(O5, 63, O3);
+
+ __ or3(O2, O3, O0);
+
+ __ sllx(O5, 1, O1);
+ __ srlx(G1, 63, O2);
+ __ or3(O1, O2, O1);
+ __ xor3(O1, G3, O1);
+
+ __ deccc(len);
+ __ br(Assembler::notZero, true, Assembler::pt, L_ghash_loop);
+ __ delayed()->add(data, 16, data);
+
+ __ stx(O0, I0, 0);
+ __ stx(O1, I0, 8);
+
+ __ ret();
+ __ delayed()->restore();
+
+ return start;
+ }
+
void generate_initial() {
// Generates all stubs and initializes the entry points
@@ -4860,6 +4984,10 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
}
+ // generate GHASH intrinsics code
+ if (UseGHASHIntrinsics) {
+ StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+ }
// generate SHA1/SHA256/SHA512 intrinsics code
if (UseSHA1Intrinsics) {
diff --git a/src/cpu/sparc/vm/vm_version_sparc.cpp b/src/cpu/sparc/vm/vm_version_sparc.cpp
index c0cd16a18..d7240e876 100644
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp
+++ b/src/cpu/sparc/vm/vm_version_sparc.cpp
@@ -286,39 +286,50 @@ void VM_Version::initialize() {
// SPARC T4 and above should have support for AES instructions
if (has_aes()) {
- if (UseVIS > 2) { // AES intrinsics use MOVxTOd/MOVdTOx which are VIS3
- if (FLAG_IS_DEFAULT(UseAES)) {
- FLAG_SET_DEFAULT(UseAES, true);
- }
- if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
- FLAG_SET_DEFAULT(UseAESIntrinsics, true);
- }
- // we disable both the AES flags if either of them is disabled on the command line
- if (!UseAES || !UseAESIntrinsics) {
- FLAG_SET_DEFAULT(UseAES, false);
- FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ if (FLAG_IS_DEFAULT(UseAES)) {
+ FLAG_SET_DEFAULT(UseAES, true);
+ }
+ if (!UseAES) {
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
}
+ FLAG_SET_DEFAULT(UseAESIntrinsics, false);
} else {
- if (UseAES || UseAESIntrinsics) {
- warning("SPARC AES intrinsics require VIS3 instruction support. Intrinsics will be disabled.");
- if (UseAES) {
- FLAG_SET_DEFAULT(UseAES, false);
- }
- if (UseAESIntrinsics) {
- FLAG_SET_DEFAULT(UseAESIntrinsics, false);
- }
+ // The AES intrinsic stubs require AES instruction support (of course)
+ // but also require VIS3 mode or higher for instructions it use.
+ if (UseVIS > 2) {
+ if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ FLAG_SET_DEFAULT(UseAESIntrinsics, true);
}
+ } else {
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("SPARC AES intrinsics require VIS3 instructions. Intrinsics will be disabled.");
+ }
+ FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ }
}
} else if (UseAES || UseAESIntrinsics) {
- warning("AES instructions are not available on this CPU");
- if (UseAES) {
+ if (UseAES && !FLAG_IS_DEFAULT(UseAES)) {
+ warning("AES instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseAES, false);
}
- if (UseAESIntrinsics) {
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("AES intrinsics are not available on this CPU");
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
}
}
+ // GHASH/GCM intrinsics
+ if (has_vis3() && (UseVIS > 2)) {
+ if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
+ UseGHASHIntrinsics = true;
+ }
+ } else if (UseGHASHIntrinsics) {
+ if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
+ warning("GHASH intrinsics require VIS3 insructions support. Intriniscs will be disabled");
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
+ }
+
// SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
if (has_sha1() || has_sha256() || has_sha512()) {
if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp
index 7cbc47d60..1759ecdfd 100644
--- a/src/cpu/x86/vm/assembler_x86.cpp
+++ b/src/cpu/x86/vm/assembler_x86.cpp
@@ -2575,6 +2575,15 @@ void Assembler::psrldq(XMMRegister dst, int shift) {
emit_int8(shift);
}
+void Assembler::pslldq(XMMRegister dst, int shift) {
+ // Shift left 128 bit value in xmm register by number of bytes.
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66);
+ emit_int8(0x73);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(shift);
+}
+
void Assembler::ptest(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), "");
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp
index 341d9e39b..5ea01311e 100644
--- a/src/cpu/x86/vm/assembler_x86.hpp
+++ b/src/cpu/x86/vm/assembler_x86.hpp
@@ -1527,6 +1527,8 @@ private:
// Shift Right by bytes Logical DoubleQuadword Immediate
void psrldq(XMMRegister dst, int shift);
+ // Shift Left by bytes Logical DoubleQuadword Immediate
+ void pslldq(XMMRegister dst, int shift);
// Logical Compare 128bit
void ptest(XMMRegister dst, XMMRegister src);
diff --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index 50a06d7a5..2e5599807 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -2719,6 +2719,169 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ // byte swap x86 long
+ address generate_ghash_long_swap_mask() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
+ address start = __ pc();
+ __ emit_data(0x0b0a0908, relocInfo::none, 0);
+ __ emit_data(0x0f0e0d0c, relocInfo::none, 0);
+ __ emit_data(0x03020100, relocInfo::none, 0);
+ __ emit_data(0x07060504, relocInfo::none, 0);
+
+ return start;
+ }
+
+ // byte swap x86 byte array
+ address generate_ghash_byte_swap_mask() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
+ address start = __ pc();
+ __ emit_data(0x0c0d0e0f, relocInfo::none, 0);
+ __ emit_data(0x08090a0b, relocInfo::none, 0);
+ __ emit_data(0x04050607, relocInfo::none, 0);
+ __ emit_data(0x00010203, relocInfo::none, 0);
+ return start;
+ }
+
+ /* Single and multi-block ghash operations */
+ address generate_ghash_processBlocks() {
+ assert(UseGHASHIntrinsics, "need GHASH intrinsics and CLMUL support");
+ __ align(CodeEntryAlignment);
+ Label L_ghash_loop, L_exit;
+ StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ address start = __ pc();
+
+ const Register state = rdi;
+ const Register subkeyH = rsi;
+ const Register data = rdx;
+ const Register blocks = rcx;
+
+ const Address state_param(rbp, 8+0);
+ const Address subkeyH_param(rbp, 8+4);
+ const Address data_param(rbp, 8+8);
+ const Address blocks_param(rbp, 8+12);
+
+ const XMMRegister xmm_temp0 = xmm0;
+ const XMMRegister xmm_temp1 = xmm1;
+ const XMMRegister xmm_temp2 = xmm2;
+ const XMMRegister xmm_temp3 = xmm3;
+ const XMMRegister xmm_temp4 = xmm4;
+ const XMMRegister xmm_temp5 = xmm5;
+ const XMMRegister xmm_temp6 = xmm6;
+ const XMMRegister xmm_temp7 = xmm7;
+
+ __ enter();
+ handleSOERegisters(true); // Save registers
+
+ __ movptr(state, state_param);
+ __ movptr(subkeyH, subkeyH_param);
+ __ movptr(data, data_param);
+ __ movptr(blocks, blocks_param);
+
+ __ movdqu(xmm_temp0, Address(state, 0));
+ __ pshufb(xmm_temp0, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
+
+ __ movdqu(xmm_temp1, Address(subkeyH, 0));
+ __ pshufb(xmm_temp1, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
+
+ __ BIND(L_ghash_loop);
+ __ movdqu(xmm_temp2, Address(data, 0));
+ __ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
+
+ __ pxor(xmm_temp0, xmm_temp2);
+
+ //
+ // Multiply with the hash key
+ //
+ __ movdqu(xmm_temp3, xmm_temp0);
+ __ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
+ __ movdqu(xmm_temp4, xmm_temp0);
+ __ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
+
+ __ movdqu(xmm_temp5, xmm_temp0);
+ __ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
+ __ movdqu(xmm_temp6, xmm_temp0);
+ __ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
+
+ __ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
+
+ __ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
+ __ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
+ __ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
+ __ pxor(xmm_temp3, xmm_temp5);
+ __ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
+ // of the carry-less multiplication of
+ // xmm0 by xmm1.
+
+ // We shift the result of the multiplication by one bit position
+ // to the left to cope for the fact that the bits are reversed.
+ __ movdqu(xmm_temp7, xmm_temp3);
+ __ movdqu(xmm_temp4, xmm_temp6);
+ __ pslld (xmm_temp3, 1);
+ __ pslld(xmm_temp6, 1);
+ __ psrld(xmm_temp7, 31);
+ __ psrld(xmm_temp4, 31);
+ __ movdqu(xmm_temp5, xmm_temp7);
+ __ pslldq(xmm_temp4, 4);
+ __ pslldq(xmm_temp7, 4);
+ __ psrldq(xmm_temp5, 12);
+ __ por(xmm_temp3, xmm_temp7);
+ __ por(xmm_temp6, xmm_temp4);
+ __ por(xmm_temp6, xmm_temp5);
+
+ //
+ // First phase of the reduction
+ //
+ // Move xmm3 into xmm4, xmm5, xmm7 in order to perform the shifts
+ // independently.
+ __ movdqu(xmm_temp7, xmm_temp3);
+ __ movdqu(xmm_temp4, xmm_temp3);
+ __ movdqu(xmm_temp5, xmm_temp3);
+ __ pslld(xmm_temp7, 31); // packed right shift shifting << 31
+ __ pslld(xmm_temp4, 30); // packed right shift shifting << 30
+ __ pslld(xmm_temp5, 25); // packed right shift shifting << 25
+ __ pxor(xmm_temp7, xmm_temp4); // xor the shifted versions
+ __ pxor(xmm_temp7, xmm_temp5);
+ __ movdqu(xmm_temp4, xmm_temp7);
+ __ pslldq(xmm_temp7, 12);
+ __ psrldq(xmm_temp4, 4);
+ __ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
+
+ //
+ // Second phase of the reduction
+ //
+ // Make 3 copies of xmm3 in xmm2, xmm5, xmm7 for doing these
+ // shift operations.
+ __ movdqu(xmm_temp2, xmm_temp3);
+ __ movdqu(xmm_temp7, xmm_temp3);
+ __ movdqu(xmm_temp5, xmm_temp3);
+ __ psrld(xmm_temp2, 1); // packed left shifting >> 1
+ __ psrld(xmm_temp7, 2); // packed left shifting >> 2
+ __ psrld(xmm_temp5, 7); // packed left shifting >> 7
+ __ pxor(xmm_temp2, xmm_temp7); // xor the shifted versions
+ __ pxor(xmm_temp2, xmm_temp5);
+ __ pxor(xmm_temp2, xmm_temp4);
+ __ pxor(xmm_temp3, xmm_temp2);
+ __ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
+
+ __ decrement(blocks);
+ __ jcc(Assembler::zero, L_exit);
+ __ movdqu(xmm_temp0, xmm_temp6);
+ __ addptr(data, 16);
+ __ jmp(L_ghash_loop);
+
+ __ BIND(L_exit);
+ // Byte swap 16-byte result
+ __ pshufb(xmm_temp6, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
+ __ movdqu(Address(state, 0), xmm_temp6); // store the result
+
+ handleSOERegisters(false); // restore registers
+ __ leave();
+ __ ret(0);
+ return start;
+ }
+
/**
* Arguments:
*
@@ -3018,6 +3181,13 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt();
}
+ // Generate GHASH intrinsics code
+ if (UseGHASHIntrinsics) {
+ StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
+ StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask();
+ StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+ }
+
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 1d38af799..c5811b28b 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -3639,6 +3639,175 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+
+ // byte swap x86 long
+ address generate_ghash_long_swap_mask() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
+ address start = __ pc();
+ __ emit_data64(0x0f0e0d0c0b0a0908, relocInfo::none );
+ __ emit_data64(0x0706050403020100, relocInfo::none );
+ return start;
+ }
+
+ // byte swap x86 byte array
+ address generate_ghash_byte_swap_mask() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
+ address start = __ pc();
+ __ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none );
+ __ emit_data64(0x0001020304050607, relocInfo::none );
+ return start;
+ }
+
+ /* Single and multi-block ghash operations */
+ address generate_ghash_processBlocks() {
+ __ align(CodeEntryAlignment);
+ Label L_ghash_loop, L_exit;
+ StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
+ address start = __ pc();
+
+ const Register state = c_rarg0;
+ const Register subkeyH = c_rarg1;
+ const Register data = c_rarg2;
+ const Register blocks = c_rarg3;
+
+#ifdef _WIN64
+ const int XMM_REG_LAST = 10;
+#endif
+
+ const XMMRegister xmm_temp0 = xmm0;
+ const XMMRegister xmm_temp1 = xmm1;
+ const XMMRegister xmm_temp2 = xmm2;
+ const XMMRegister xmm_temp3 = xmm3;
+ const XMMRegister xmm_temp4 = xmm4;
+ const XMMRegister xmm_temp5 = xmm5;
+ const XMMRegister xmm_temp6 = xmm6;
+ const XMMRegister xmm_temp7 = xmm7;
+ const XMMRegister xmm_temp8 = xmm8;
+ const XMMRegister xmm_temp9 = xmm9;
+ const XMMRegister xmm_temp10 = xmm10;
+
+ __ enter();
+
+#ifdef _WIN64
+ // save the xmm registers which must be preserved 6-10
+ __ subptr(rsp, -rsp_after_call_off * wordSize);
+ for (int i = 6; i <= XMM_REG_LAST; i++) {
+ __ movdqu(xmm_save(i), as_XMMRegister(i));
+ }
+#endif
+
+ __ movdqu(xmm_temp10, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
+
+ __ movdqu(xmm_temp0, Address(state, 0));
+ __ pshufb(xmm_temp0, xmm_temp10);
+
+
+ __ BIND(L_ghash_loop);
+ __ movdqu(xmm_temp2, Address(data, 0));
+ __ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
+
+ __ movdqu(xmm_temp1, Address(subkeyH, 0));
+ __ pshufb(xmm_temp1, xmm_temp10);
+
+ __ pxor(xmm_temp0, xmm_temp2);
+
+ //
+ // Multiply with the hash key
+ //
+ __ movdqu(xmm_temp3, xmm_temp0);
+ __ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
+ __ movdqu(xmm_temp4, xmm_temp0);
+ __ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
+
+ __ movdqu(xmm_temp5, xmm_temp0);
+ __ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
+ __ movdqu(xmm_temp6, xmm_temp0);
+ __ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
+
+ __ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
+
+ __ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
+ __ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
+ __ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
+ __ pxor(xmm_temp3, xmm_temp5);
+ __ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
+ // of the carry-less multiplication of
+ // xmm0 by xmm1.
+
+ // We shift the result of the multiplication by one bit position
+ // to the left to cope for the fact that the bits are reversed.
+ __ movdqu(xmm_temp7, xmm_temp3);
+ __ movdqu(xmm_temp8, xmm_temp6);
+ __ pslld(xmm_temp3, 1);
+ __ pslld(xmm_temp6, 1);
+ __ psrld(xmm_temp7, 31);
+ __ psrld(xmm_temp8, 31);
+ __ movdqu(xmm_temp9, xmm_temp7);
+ __ pslldq(xmm_temp8, 4);
+ __ pslldq(xmm_temp7, 4);
+ __ psrldq(xmm_temp9, 12);
+ __ por(xmm_temp3, xmm_temp7);
+ __ por(xmm_temp6, xmm_temp8);
+ __ por(xmm_temp6, xmm_temp9);
+
+ //
+ // First phase of the reduction
+ //
+ // Move xmm3 into xmm7, xmm8, xmm9 in order to perform the shifts
+ // independently.
+ __ movdqu(xmm_temp7, xmm_temp3);
+ __ movdqu(xmm_temp8, xmm_temp3);
+ __ movdqu(xmm_temp9, xmm_temp3);
+ __ pslld(xmm_temp7, 31); // packed right shift shifting << 31
+ __ pslld(xmm_temp8, 30); // packed right shift shifting << 30
+ __ pslld(xmm_temp9, 25); // packed right shift shifting << 25
+ __ pxor(xmm_temp7, xmm_temp8); // xor the shifted versions
+ __ pxor(xmm_temp7, xmm_temp9);
+ __ movdqu(xmm_temp8, xmm_temp7);
+ __ pslldq(xmm_temp7, 12);
+ __ psrldq(xmm_temp8, 4);
+ __ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
+
+ //
+ // Second phase of the reduction
+ //
+ // Make 3 copies of xmm3 in xmm2, xmm4, xmm5 for doing these
+ // shift operations.
+ __ movdqu(xmm_temp2, xmm_temp3);
+ __ movdqu(xmm_temp4, xmm_temp3);
+ __ movdqu(xmm_temp5, xmm_temp3);
+ __ psrld(xmm_temp2, 1); // packed left shifting >> 1
+ __ psrld(xmm_temp4, 2); // packed left shifting >> 2
+ __ psrld(xmm_temp5, 7); // packed left shifting >> 7
+ __ pxor(xmm_temp2, xmm_temp4); // xor the shifted versions
+ __ pxor(xmm_temp2, xmm_temp5);
+ __ pxor(xmm_temp2, xmm_temp8);
+ __ pxor(xmm_temp3, xmm_temp2);
+ __ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
+
+ __ decrement(blocks);
+ __ jcc(Assembler::zero, L_exit);
+ __ movdqu(xmm_temp0, xmm_temp6);
+ __ addptr(data, 16);
+ __ jmp(L_ghash_loop);
+
+ __ BIND(L_exit);
+ __ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result
+ __ movdqu(Address(state, 0), xmm_temp6); // store the result
+
+#ifdef _WIN64
+ // restore xmm regs belonging to calling function
+ for (int i = 6; i <= XMM_REG_LAST; i++) {
+ __ movdqu(as_XMMRegister(i), xmm_save(i));
+ }
+#endif
+ __ leave();
+ __ ret(0);
+ return start;
+ }
+
/**
* Arguments:
*
@@ -4077,6 +4246,13 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
}
+ // Generate GHASH intrinsics code
+ if (UseGHASHIntrinsics) {
+ StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
+ StubRoutines::x86::_ghash_byte_swap_mask_addr = generate_ghash_byte_swap_mask();
+ StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks();
+ }
+
// Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc,
diff --git a/src/cpu/x86/vm/stubRoutines_x86.cpp b/src/cpu/x86/vm/stubRoutines_x86.cpp
index 200f2aff8..9b0d8fc75 100644
--- a/src/cpu/x86/vm/stubRoutines_x86.cpp
+++ b/src/cpu/x86/vm/stubRoutines_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,8 @@
address StubRoutines::x86::_verify_mxcsr_entry = NULL;
address StubRoutines::x86::_key_shuffle_mask_addr = NULL;
+address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL;
+address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL;
uint64_t StubRoutines::x86::_crc_by128_masks[] =
{
diff --git a/src/cpu/x86/vm/stubRoutines_x86.hpp b/src/cpu/x86/vm/stubRoutines_x86.hpp
index d8e52ab3b..bb160486c 100644
--- a/src/cpu/x86/vm/stubRoutines_x86.hpp
+++ b/src/cpu/x86/vm/stubRoutines_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,10 +36,15 @@
// masks and table for CRC32
static uint64_t _crc_by128_masks[];
static juint _crc_table[];
+ // swap mask for ghash
+ static address _ghash_long_swap_mask_addr;
+ static address _ghash_byte_swap_mask_addr;
public:
static address verify_mxcsr_entry() { return _verify_mxcsr_entry; }
static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; }
static address crc_by128_masks_addr() { return (address)_crc_by128_masks; }
+ static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; }
+ static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; }
#endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
diff --git a/src/cpu/x86/vm/vm_version_x86.cpp b/src/cpu/x86/vm/vm_version_x86.cpp
index fd0a68d10..3a4246c68 100644
--- a/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/src/cpu/x86/vm/vm_version_x86.cpp
@@ -553,12 +553,36 @@ void VM_Version::get_processor_features() {
// Use AES instructions if available.
if (supports_aes()) {
if (FLAG_IS_DEFAULT(UseAES)) {
- UseAES = true;
+ FLAG_SET_DEFAULT(UseAES, true);
}
- } else if (UseAES) {
- if (!FLAG_IS_DEFAULT(UseAES))
+ if (!UseAES) {
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
+ }
+ FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ } else {
+ if (UseSSE > 2) {
+ if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ FLAG_SET_DEFAULT(UseAESIntrinsics, true);
+ }
+ } else {
+ // The AES intrinsic stubs require AES instruction support (of course)
+ // but also require sse3 mode or higher for instructions it use.
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("X86 AES intrinsics require SSE3 instructions or higher. Intrinsics will be disabled.");
+ }
+ FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ }
+ }
+ } else if (UseAES || UseAESIntrinsics) {
+ if (UseAES && !FLAG_IS_DEFAULT(UseAES)) {
warning("AES instructions are not available on this CPU");
- FLAG_SET_DEFAULT(UseAES, false);
+ FLAG_SET_DEFAULT(UseAES, false);
+ }
+ if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
+ warning("AES intrinsics are not available on this CPU");
+ FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ }
}
// Use CLMUL instructions if available.
@@ -582,16 +606,15 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
- // The AES intrinsic stubs require AES instruction support (of course)
- // but also require sse3 mode for instructions it use.
- if (UseAES && (UseSSE > 2)) {
- if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
- UseAESIntrinsics = true;
+ // GHASH/GCM intrinsics
+ if (UseCLMUL && (UseSSE > 2)) {
+ if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
+ UseGHASHIntrinsics = true;
}
- } else if (UseAESIntrinsics) {
- if (!FLAG_IS_DEFAULT(UseAESIntrinsics))
- warning("AES intrinsics are not available on this CPU");
- FLAG_SET_DEFAULT(UseAESIntrinsics, false);
+ } else if (UseGHASHIntrinsics) {
+ if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
+ warning("GHASH intrinsic requires CLMUL and SSE2 instructions on this CPU");
+ FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
if (UseSHA) {
diff --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp
index 76086794f..900bd827a 100644
--- a/src/share/vm/c1/c1_LIR.cpp
+++ b/src/share/vm/c1/c1_LIR.cpp
@@ -2112,8 +2112,14 @@ void LIR_OpProfileCall::print_instr(outputStream* out) const {
// LIR_OpProfileType
void LIR_OpProfileType::print_instr(outputStream* out) const {
- out->print("exact = "); exact_klass()->print_name_on(out);
- out->print("current = "); ciTypeEntries::print_ciklass(out, current_klass());
+ out->print("exact = ");
+ if (exact_klass() == NULL) {
+ out->print("unknown");
+ } else {
+ exact_klass()->print_name_on(out);
+ }
+ out->print(" current = "); ciTypeEntries::print_ciklass(out, current_klass());
+ out->print(" ");
mdp()->print(out); out->print(" ");
obj()->print(out); out->print(" ");
tmp()->print(out); out->print(" ");
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
index 7f0e82071..46f2e2d8b 100644
--- a/src/share/vm/classfile/vmSymbols.hpp
+++ b/src/share/vm/classfile/vmSymbols.hpp
@@ -863,6 +863,12 @@
do_name( implCompressMB_name, "implCompressMultiBlock0") \
do_signature(implCompressMB_signature, "([BII)I") \
\
+ /* support for com.sun.crypto.provider.GHASH */ \
+ do_class(com_sun_crypto_provider_ghash, "com/sun/crypto/provider/GHASH") \
+ do_intrinsic(_ghash_processBlocks, com_sun_crypto_provider_ghash, processBlocks_name, ghash_processBlocks_signature, F_S) \
+ do_name(processBlocks_name, "processBlocks") \
+ do_signature(ghash_processBlocks_signature, "([BII[J[J)V") \
+ \
/* support for java.util.zip */ \
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
index e5a3a1106..2a2faa69a 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
@@ -161,6 +161,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
}
_dictionary->set_par_lock(&_parDictionaryAllocLock);
}
+
+ _used_stable = 0;
}
// Like CompactibleSpace forward() but always calls cross_threshold() to
@@ -377,6 +379,14 @@ size_t CompactibleFreeListSpace::used() const {
return capacity() - free();
}
+size_t CompactibleFreeListSpace::used_stable() const {
+ return _used_stable;
+}
+
+void CompactibleFreeListSpace::recalculate_used_stable() {
+ _used_stable = used();
+}
+
size_t CompactibleFreeListSpace::free() const {
// "MT-safe, but not MT-precise"(TM), if you will: i.e.
// if you do this while the structures are in flux you
@@ -1218,6 +1228,13 @@ HeapWord* CompactibleFreeListSpace::allocate(size_t size) {
debug_only(fc->mangleAllocated(size));
}
+ // During GC we do not need to recalculate the stable used value for
+ // every allocation in old gen. It is done once at the end of GC instead
+ // for performance reasons.
+ if (!Universe::heap()->is_gc_active()) {
+ recalculate_used_stable();
+ }
+
return res;
}
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
index 7269068f6..121299d4b 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
@@ -148,6 +148,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// Used to keep track of limit of sweep for the space
HeapWord* _sweep_limit;
+ // Stable value of used().
+ size_t _used_stable;
+
// Support for compacting cms
HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top);
@@ -343,6 +346,17 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// which overestimates the region by returning the entire
// committed region (this is safe, but inefficient).
+ // Returns monotonically increasing stable used space bytes for CMS.
+ // This is required for jstat and other memory monitoring tools
+ // that might otherwise see inconsistent used space values during a garbage
+ // collection, promotion or allocation into compactibleFreeListSpace.
+ // The value returned by this function might be smaller than the
+ // actual value.
+ size_t used_stable() const;
+ // Recalculate and cache the current stable used() value. Only to be called
+ // in places where we can be sure that the result is stable.
+ void recalculate_used_stable();
+
// Returns a subregion of the space containing all the objects in
// the space.
MemRegion used_region() const {
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index 1872e72e3..e7228d313 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -869,6 +869,10 @@ ConcurrentMarkSweepGeneration::unsafe_max_alloc_nogc() const {
return _cmsSpace->max_alloc_in_words() * HeapWordSize;
}
+size_t ConcurrentMarkSweepGeneration::used_stable() const {
+ return cmsSpace()->used_stable();
+}
+
size_t ConcurrentMarkSweepGeneration::max_available() const {
return free() + _virtual_space.uncommitted_size();
}
@@ -1955,6 +1959,8 @@ void CMSCollector::compute_new_size() {
FreelistLocker z(this);
MetaspaceGC::compute_new_size();
_cmsGen->compute_new_size_free_list();
+ // recalculate CMS used space after CMS collection
+ _cmsGen->cmsSpace()->recalculate_used_stable();
}
// A work method used by foreground collection to determine
@@ -2768,6 +2774,7 @@ void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
_capacity_at_prologue = capacity();
_used_at_prologue = used();
+ _cmsSpace->recalculate_used_stable();
// Delegate to CMScollector which knows how to coordinate between
// this and any other CMS generations that it is responsible for
@@ -2837,6 +2844,7 @@ void CMSCollector::gc_epilogue(bool full) {
_eden_chunk_index = 0;
size_t cms_used = _cmsGen->cmsSpace()->used();
+ _cmsGen->cmsSpace()->recalculate_used_stable();
// update performance counters - this uses a special version of
// update_counters() that allows the utilization to be passed as a
@@ -3672,6 +3680,7 @@ void CMSCollector::checkpointRootsInitial(bool asynch) {
_collectorState = Marking;
}
SpecializationStats::print();
+ _cmsGen->cmsSpace()->recalculate_used_stable();
}
void CMSCollector::checkpointRootsInitialWork(bool asynch) {
@@ -5066,10 +5075,12 @@ void CMSCollector::checkpointRootsFinal(bool asynch,
Mutex::_no_safepoint_check_flag);
assert(!init_mark_was_synchronous, "but that's impossible!");
checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);
+ _cmsGen->cmsSpace()->recalculate_used_stable();
} else {
// already have all the locks
checkpointRootsFinalWork(asynch, clear_all_soft_refs,
init_mark_was_synchronous);
+ _cmsGen->cmsSpace()->recalculate_used_stable();
}
verify_work_stacks_empty();
verify_overflow_empty();
@@ -6368,6 +6379,10 @@ void CMSCollector::sweep(bool asynch) {
// Update heap occupancy information which is used as
// input to soft ref clearing policy at the next gc.
Universe::update_heap_info_at_gc();
+
+ // recalculate CMS used space after CMS collection
+ _cmsGen->cmsSpace()->recalculate_used_stable();
+
_collectorState = Resizing;
}
} else {
@@ -6467,6 +6482,7 @@ void ConcurrentMarkSweepGeneration::update_gc_stats(int current_level,
// Gather statistics on the young generation collection.
collector()->stats().record_gc0_end(used());
}
+ _cmsSpace->recalculate_used_stable();
}
CMSAdaptiveSizePolicy* ConcurrentMarkSweepGeneration::size_policy() {
diff --git a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
index a6d06a5dc..a023b9fb9 100644
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
+++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
@@ -1190,6 +1190,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
double occupancy() const { return ((double)used())/((double)capacity()); }
size_t contiguous_available() const;
size_t unsafe_max_alloc_nogc() const;
+ size_t used_stable() const;
// over-rides
MemRegion used_region() const;
diff --git a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index aa6bbc81a..4100b83ef 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -2520,6 +2520,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
}
}
}
+ } else if (GC_locker::should_discard(cause, gc_count_before)) {
+ // Return to be consistent with VMOp failure due to another
+ // collection slipping in after our gc_count but before our
+ // request is processed. _gc_locker collections upgraded by
+ // GCLockerInvokesConcurrent are handled above and never discarded.
+ return;
} else {
if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc
DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {
diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index c4463f50f..b25ab59f2 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -376,7 +376,7 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(
MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
1U);
_sizer_kind = SizerMaxAndNewSize;
- _adaptive_size = _min_desired_young_length == _max_desired_young_length;
+ _adaptive_size = _min_desired_young_length != _max_desired_young_length;
} else {
_sizer_kind = SizerNewSizeOnly;
}
diff --git a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
index 96e4dc63d..d15dee26c 100644
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
+++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp
@@ -133,7 +133,11 @@ private:
SizerKind _sizer_kind;
uint _min_desired_young_length;
uint _max_desired_young_length;
+
+ // False when using a fixed young generation size due to command-line options,
+ // true otherwise.
bool _adaptive_size;
+
uint calculate_default_min_length(uint new_number_of_heap_regions);
uint calculate_default_max_length(uint new_number_of_heap_regions);
diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
index f407f20b7..e13fefa2c 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
@@ -530,6 +530,10 @@ void ParallelScavengeHeap::collect(GCCause::Cause cause) {
full_gc_count = Universe::heap()->total_full_collections();
}
+ if (GC_locker::should_discard(cause, gc_count)) {
+ return;
+ }
+
VM_ParallelGCSystemGC op(gc_count, full_gc_count, cause);
VMThread::execute(&op);
}
diff --git a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
index 9148bb4ff..2d554b397 100644
--- a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
@@ -52,11 +52,16 @@ void VM_ParallelGCFailedAllocation::doit() {
}
}
+static bool is_cause_full(GCCause::Cause cause) {
+ return (cause != GCCause::_gc_locker) && (cause != GCCause::_wb_young_gc)
+ DEBUG_ONLY(&& (cause != GCCause::_scavenge_alot));
+}
+
// Only used for System.gc() calls
VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(uint gc_count,
uint full_gc_count,
GCCause::Cause gc_cause) :
- VM_GC_Operation(gc_count, gc_cause, full_gc_count, true /* full */)
+ VM_GC_Operation(gc_count, gc_cause, full_gc_count, is_cause_full(gc_cause))
{
}
@@ -68,8 +73,7 @@ void VM_ParallelGCSystemGC::doit() {
"must be a ParallelScavengeHeap");
GCCauseSetter gccs(heap, _gc_cause);
- if (_gc_cause == GCCause::_gc_locker || _gc_cause == GCCause::_wb_young_gc
- DEBUG_ONLY(|| _gc_cause == GCCause::_scavenge_alot)) {
+ if (!_full) {
// If (and only if) the scavenge fails, this will invoke a full gc.
heap->invoke_scavenge();
} else {
diff --git a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp
index 7a5fdf9ee..b03430e27 100644
--- a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp
+++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp
@@ -63,7 +63,7 @@ class GSpaceCounters: public CHeapObj<mtGC> {
}
inline void update_used() {
- _used->set_value(_gen->used());
+ _used->set_value(_gen->used_stable());
}
// special version of update_used() to allow the used value to be
@@ -107,7 +107,7 @@ class GenerationUsedHelper : public PerfLongSampleHelper {
GenerationUsedHelper(Generation* g) : _gen(g) { }
inline jlong take_sample() {
- return _gen->used();
+ return _gen->used_stable();
}
};
diff --git a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
index 972099b9c..d60f751af 100644
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
@@ -201,6 +201,19 @@ void VM_GenCollectForAllocation::doit() {
}
}
+static bool is_full_gc(int max_level) {
+ // Return true if max_level is all generations
+ return (max_level == (GenCollectedHeap::heap()->n_gens() - 1));
+}
+
+VM_GenCollectFull::VM_GenCollectFull(uint gc_count_before,
+ uint full_gc_count_before,
+ GCCause::Cause gc_cause,
+ int max_level) :
+ VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before,
+ is_full_gc(max_level) /* full */),
+ _max_level(max_level) { }
+
void VM_GenCollectFull::doit() {
SvcGCMarker sgcm(SvcGCMarker::FULL);
diff --git a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
index b8027a972..cb070bd73 100644
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
+++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
@@ -201,9 +201,7 @@ class VM_GenCollectFull: public VM_GC_Operation {
VM_GenCollectFull(uint gc_count_before,
uint full_gc_count_before,
GCCause::Cause gc_cause,
- int max_level)
- : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
- _max_level(max_level) { }
+ int max_level);
~VM_GenCollectFull() {}
virtual VMOp_Type type() const { return VMOp_GenCollectFull; }
virtual void doit();
diff --git a/src/share/vm/memory/gcLocker.cpp b/src/share/vm/memory/gcLocker.cpp
index 967426379..df8914e50 100644
--- a/src/share/vm/memory/gcLocker.cpp
+++ b/src/share/vm/memory/gcLocker.cpp
@@ -31,6 +31,7 @@
volatile jint GC_locker::_jni_lock_count = 0;
volatile bool GC_locker::_needs_gc = false;
volatile bool GC_locker::_doing_gc = false;
+unsigned int GC_locker::_total_collections = 0;
#ifdef ASSERT
volatile jint GC_locker::_debug_jni_lock_count = 0;
@@ -94,6 +95,11 @@ void GC_locker::stall_until_clear() {
}
}
+bool GC_locker::should_discard(GCCause::Cause cause, uint total_collections) {
+ return (cause == GCCause::_gc_locker) &&
+ (_total_collections != total_collections);
+}
+
void GC_locker::jni_lock(JavaThread* thread) {
assert(!thread->in_critical(), "shouldn't currently be in a critical region");
MutexLocker mu(JNICritical_lock);
@@ -117,7 +123,13 @@ void GC_locker::jni_unlock(JavaThread* thread) {
decrement_debug_jni_lock_count();
thread->exit_critical();
if (needs_gc() && !is_active_internal()) {
- // We're the last thread out. Cause a GC to occur.
+ // We're the last thread out. Request a GC.
+ // Capture the current total collections, to allow detection of
+ // other collections that make this one unnecessary. The value of
+ // total_collections() is only changed at a safepoint, so there
+ // must not be a safepoint between the lock becoming inactive and
+ // getting the count, else there may be unnecessary GCLocker GCs.
+ _total_collections = Universe::heap()->total_collections();
_doing_gc = true;
{
// Must give up the lock while at a safepoint
diff --git a/src/share/vm/memory/gcLocker.hpp b/src/share/vm/memory/gcLocker.hpp
index f12aa6755..068688e93 100644
--- a/src/share/vm/memory/gcLocker.hpp
+++ b/src/share/vm/memory/gcLocker.hpp
@@ -26,6 +26,7 @@
#define SHARE_VM_MEMORY_GCLOCKER_HPP
#include "gc_interface/collectedHeap.hpp"
+#include "gc_interface/gcCause.hpp"
#include "memory/genCollectedHeap.hpp"
#include "memory/universe.hpp"
#include "oops/oop.hpp"
@@ -57,6 +58,7 @@ class GC_locker: public AllStatic {
static volatile bool _needs_gc; // heap is filling, we need a GC
// note: bool is typedef'd as jint
static volatile bool _doing_gc; // unlock_critical() is doing a GC
+ static uint _total_collections; // value for _gc_locker collection
#ifdef ASSERT
// This lock count is updated for all operations and is used to
@@ -116,6 +118,12 @@ class GC_locker: public AllStatic {
// Sets _needs_gc if is_active() is true. Returns is_active().
static bool check_active_before_gc();
+ // Return true if the designated collection is a GCLocker request
+ // that should be discarded. Returns true if cause == GCCause::_gc_locker
+ // and the given total collection value indicates a collection has been
+ // done since the GCLocker request was made.
+ static bool should_discard(GCCause::Cause cause, uint total_collections);
+
// Stalls the caller (who should not be in a jni critical section)
// until needs_gc() clears. Note however that needs_gc() may be
// set at a subsequent safepoint and/or cleared under the
diff --git a/src/share/vm/memory/genCollectedHeap.cpp b/src/share/vm/memory/genCollectedHeap.cpp
index ddf0a860c..daa0a06bf 100644
--- a/src/share/vm/memory/genCollectedHeap.cpp
+++ b/src/share/vm/memory/genCollectedHeap.cpp
@@ -796,8 +796,11 @@ void GenCollectedHeap::collect(GCCause::Cause cause) {
#else // INCLUDE_ALL_GCS
ShouldNotReachHere();
#endif // INCLUDE_ALL_GCS
- } else if (cause == GCCause::_wb_young_gc) {
- // minor collection for WhiteBox API
+ } else if ((cause == GCCause::_wb_young_gc) ||
+ (cause == GCCause::_gc_locker)) {
+ // minor collection for WhiteBox or GCLocker.
+ // _gc_locker collections upgraded by GCLockerInvokesConcurrent
+ // are handled above and never discarded.
collect(cause, 0);
} else {
#ifdef ASSERT
@@ -835,6 +838,11 @@ void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {
// Read the GC count while holding the Heap_lock
unsigned int gc_count_before = total_collections();
unsigned int full_gc_count_before = total_full_collections();
+
+ if (GC_locker::should_discard(cause, gc_count_before)) {
+ return;
+ }
+
{
MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
VM_GenCollectFull op(gc_count_before, full_gc_count_before,
@@ -887,24 +895,16 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
int max_level) {
- int local_max_level;
- if (!incremental_collection_will_fail(false /* don't consult_young */) &&
- gc_cause() == GCCause::_gc_locker) {
- local_max_level = 0;
- } else {
- local_max_level = max_level;
- }
do_collection(true /* full */,
clear_all_soft_refs /* clear_all_soft_refs */,
0 /* size */,
false /* is_tlab */,
- local_max_level /* max_level */);
+ max_level /* max_level */);
// Hack XXX FIX ME !!!
// A scavenge may not have been attempted, or may have
// been attempted and failed, because the old gen was too full
- if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker &&
- incremental_collection_will_fail(false /* don't consult_young */)) {
+ if (gc_cause() == GCCause::_gc_locker && incremental_collection_failed()) {
if (PrintGCDetails) {
gclog_or_tty->print_cr("GC locker: Trying a full collection "
"because scavenge failed");
diff --git a/src/share/vm/memory/generation.cpp b/src/share/vm/memory/generation.cpp
index 3c45a9192..dc4ac0869 100644
--- a/src/share/vm/memory/generation.cpp
+++ b/src/share/vm/memory/generation.cpp
@@ -68,6 +68,12 @@ GenerationSpec* Generation::spec() {
return gch->_gen_specs[level()];
}
+// This is for CMS. It returns stable monotonic used space size.
+// Remove this when CMS is removed.
+size_t Generation::used_stable() const {
+ return used();
+}
+
size_t Generation::max_capacity() const {
return reserved().byte_size();
}
diff --git a/src/share/vm/memory/generation.hpp b/src/share/vm/memory/generation.hpp
index 63dccb70f..ca3fe949d 100644
--- a/src/share/vm/memory/generation.hpp
+++ b/src/share/vm/memory/generation.hpp
@@ -168,6 +168,7 @@ class Generation: public CHeapObj<mtGC> {
virtual size_t capacity() const = 0; // The maximum number of object bytes the
// generation can currently hold.
virtual size_t used() const = 0; // The number of used bytes in the gen.
+ virtual size_t used_stable() const; // The number of used bytes for memory monitoring tools.
virtual size_t free() const = 0; // The number of free bytes in the gen.
// Support for java.lang.Runtime.maxMemory(); see CollectedHeap.
diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
index 0204188ad..4c973d38b 100644
--- a/src/share/vm/oops/instanceKlass.cpp
+++ b/src/share/vm/oops/instanceKlass.cpp
@@ -294,6 +294,7 @@ InstanceKlass::InstanceKlass(int vtable_len,
set_has_unloaded_dependent(false);
set_init_state(InstanceKlass::allocated);
set_init_thread(NULL);
+ set_init_state(allocated);
set_reference_type(rt);
set_oop_map_cache(NULL);
set_jni_ids(NULL);
@@ -978,11 +979,13 @@ void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle
oop init_lock = this_oop->init_lock();
if (init_lock != NULL) {
ObjectLocker ol(init_lock, THREAD);
+ this_oop->set_init_thread(NULL); // reset _init_thread before changing _init_state
this_oop->set_init_state(state);
this_oop->fence_and_clear_init_lock();
ol.notify_all(CHECK);
} else {
assert(init_lock != NULL, "The initialization state should never be set twice");
+ this_oop->set_init_thread(NULL); // reset _init_thread before changing _init_state
this_oop->set_init_state(state);
}
}
@@ -3602,6 +3605,7 @@ void InstanceKlass::set_init_state(ClassState state) {
bool good_state = is_shared() ? (_init_state <= state)
: (_init_state < state);
assert(good_state || state == allocated, "illegal state transition");
+ assert(_init_thread == NULL, "should be cleared before state change");
_init_state = (u1)state;
}
#endif
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
index 444eadd38..49d552822 100644
--- a/src/share/vm/oops/instanceKlass.hpp
+++ b/src/share/vm/oops/instanceKlass.hpp
@@ -241,7 +241,7 @@ class InstanceKlass: public Klass {
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
- Thread* _init_thread; // Pointer to current thread doing initialization (to handle recusive initialization)
+ Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization)
int _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (in words)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
diff --git a/src/share/vm/oops/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp
index 61dd4c21d..b3f477cd0 100644
--- a/src/share/vm/oops/klassVtable.cpp
+++ b/src/share/vm/oops/klassVtable.cpp
@@ -289,22 +289,25 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) {
InstanceKlass* superk = initialsuper;
while (superk != NULL && superk->super() != NULL) {
- InstanceKlass* supersuperklass = InstanceKlass::cast(superk->super());
- klassVtable* ssVtable = supersuperklass->vtable();
+ klassVtable* ssVtable = (superk->super())->vtable();
if (vtable_index < ssVtable->length()) {
Method* super_method = ssVtable->method_at(vtable_index);
+ // get the class holding the matching method
+ // make sure you use that class for is_override
+ InstanceKlass* supermethodholder = super_method->method_holder();
#ifndef PRODUCT
Symbol* name= target_method()->name();
Symbol* signature = target_method()->signature();
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
#endif
- if (supersuperklass->is_override(super_method, target_loader, target_classname, THREAD)) {
+
+ if (supermethodholder->is_override(super_method, target_loader, target_classname, THREAD)) {
#ifndef PRODUCT
if (PrintVtables && Verbose) {
ResourceMark rm(THREAD);
char* sig = target_method()->name_and_sig_as_C_string();
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ",
- supersuperklass->internal_name(),
+ supermethodholder->internal_name(),
_klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) {
@@ -656,7 +659,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
// search through the super class hierarchy to see if we need
// a new entry
- ResourceMark rm;
+ ResourceMark rm(THREAD);
Symbol* name = target_method()->name();
Symbol* signature = target_method()->signature();
Klass* k = super;
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index 77c49ba72..66e5c3365 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -952,6 +952,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
+ strcmp(call->as_CallLeaf()->_name, "ghash_processBlocks") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha1_implCompress") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
@@ -2114,6 +2115,9 @@ bool ConnectionGraph::not_global_escape(Node *n) {
return false;
}
PointsToNode* ptn = ptnode_adr(idx);
+ if (ptn == NULL) {
+ return false; // not in congraph (e.g. ConI)
+ }
PointsToNode::EscapeState es = ptn->escape_state();
// If we have already computed a value, return it.
if (es >= PointsToNode::GlobalEscape)
diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp
index 4bb5ca886..5c5fec586 100644
--- a/src/share/vm/opto/library_call.cpp
+++ b/src/share/vm/opto/library_call.cpp
@@ -311,6 +311,7 @@ class LibraryCallKit : public GraphKit {
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
+ bool inline_ghash_processBlocks();
bool inline_sha_implCompress(vmIntrinsics::ID id);
bool inline_digestBase_implCompressMB(int predicate);
bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA,
@@ -570,6 +571,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
predicates = 3;
break;
+ case vmIntrinsics::_ghash_processBlocks:
+ if (!UseGHASHIntrinsics) return NULL;
+ break;
+
case vmIntrinsics::_updateCRC32:
case vmIntrinsics::_updateBytesCRC32:
case vmIntrinsics::_updateByteBufferCRC32:
@@ -957,6 +962,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_montgomerySquare:
return inline_montgomerySquare();
+ case vmIntrinsics::_ghash_processBlocks:
+ return inline_ghash_processBlocks();
+
case vmIntrinsics::_encodeISOArray:
return inline_encodeISOArray();
@@ -6599,6 +6607,35 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
return _gvn.transform(region);
}
+//------------------------------inline_ghash_processBlocks
+bool LibraryCallKit::inline_ghash_processBlocks() {
+ address stubAddr;
+ const char *stubName;
+ assert(UseGHASHIntrinsics, "need GHASH intrinsics support");
+
+ stubAddr = StubRoutines::ghash_processBlocks();
+ stubName = "ghash_processBlocks";
+
+ Node* data = argument(0);
+ Node* offset = argument(1);
+ Node* len = argument(2);
+ Node* state = argument(3);
+ Node* subkeyH = argument(4);
+
+ Node* state_start = array_element_address(state, intcon(0), T_LONG);
+ assert(state_start, "state is NULL");
+ Node* subkeyH_start = array_element_address(subkeyH, intcon(0), T_LONG);
+ assert(subkeyH_start, "subkeyH is NULL");
+ Node* data_start = array_element_address(data, offset, T_BYTE);
+ assert(data_start, "data is NULL");
+
+ Node* ghash = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::ghash_processBlocks_Type(),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ state_start, subkeyH_start, data_start, len);
+ return true;
+}
+
//------------------------------inline_sha_implCompress-----------------------
//
// Calculate SHA (i.e., SHA-1) for single-block byte[] array.
diff --git a/src/share/vm/opto/loopTransform.cpp b/src/share/vm/opto/loopTransform.cpp
index 7ef67c155..e3637b652 100644
--- a/src/share/vm/opto/loopTransform.cpp
+++ b/src/share/vm/opto/loopTransform.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -2231,6 +2231,13 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
// We also need to replace the original limit to collapse loop exit.
Node* cmp = cl->loopexit()->cmp_node();
assert(cl->limit() == cmp->in(2), "sanity");
+ // Duplicate cmp node if it has other users
+ if (cmp->outcnt() > 1) {
+ cmp = cmp->clone();
+ cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
+ BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
+ phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
+ }
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
}
diff --git a/src/share/vm/opto/loopnode.hpp b/src/share/vm/opto/loopnode.hpp
index 0ce98a063..032f94e67 100644
--- a/src/share/vm/opto/loopnode.hpp
+++ b/src/share/vm/opto/loopnode.hpp
@@ -279,6 +279,7 @@ public:
if (iv_phi == NULL) {
return NULL;
}
+ assert(iv_phi->is_Phi(), "should be PhiNode");
Node *ln = iv_phi->in(0);
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
return (CountedLoopNode*)ln;
diff --git a/src/share/vm/opto/loopopts.cpp b/src/share/vm/opto/loopopts.cpp
index 0452a236e..788e55ef9 100644
--- a/src/share/vm/opto/loopopts.cpp
+++ b/src/share/vm/opto/loopopts.cpp
@@ -309,7 +309,7 @@ Node *PhaseIdealLoop::has_local_phi_input( Node *n ) {
}
return NULL;
}
- assert(m->is_Phi() || is_dominator(get_ctrl(m), n_ctrl), "m has strange control");
+ assert(n->is_Phi() || m->is_Phi() || is_dominator(get_ctrl(m), n_ctrl), "m has strange control");
}
return n_ctrl;
diff --git a/src/share/vm/opto/runtime.cpp b/src/share/vm/opto/runtime.cpp
index 57d2f5764..4562dbcd5 100644
--- a/src/share/vm/opto/runtime.cpp
+++ b/src/share/vm/opto/runtime.cpp
@@ -92,7 +92,25 @@
// At command line specify the parameters: -XX:+FullGCALot -XX:FullGCALotStart=100000000
-
+// GHASH block processing
+const TypeFunc* OptoRuntime::ghash_processBlocks_Type() {
+ int argcnt = 4;
+
+ const Type** fields = TypeTuple::fields(argcnt);
+ int argp = TypeFunc::Parms;
+ fields[argp++] = TypePtr::NOTNULL; // state
+ fields[argp++] = TypePtr::NOTNULL; // subkeyH
+ fields[argp++] = TypePtr::NOTNULL; // data
+ fields[argp++] = TypeInt::INT; // blocks
+ assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+ const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+ // result type needed
+ fields = TypeTuple::fields(1);
+ fields[TypeFunc::Parms+0] = NULL; // void
+ const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+ return TypeFunc::make(domain, range);
+}
// Compiled code entry points
address OptoRuntime::_new_instance_Java = NULL;
diff --git a/src/share/vm/opto/runtime.hpp b/src/share/vm/opto/runtime.hpp
index 99f03f408..58c6bd501 100644
--- a/src/share/vm/opto/runtime.hpp
+++ b/src/share/vm/opto/runtime.hpp
@@ -311,6 +311,8 @@ private:
static const TypeFunc* montgomeryMultiply_Type();
static const TypeFunc* montgomerySquare_Type();
+ static const TypeFunc* ghash_processBlocks_Type();
+
static const TypeFunc* updateBytesCRC32_Type();
// leaf on stack replacement interpreter accessor types
diff --git a/src/share/vm/opto/superword.cpp b/src/share/vm/opto/superword.cpp
index 718f077d0..78d9743ec 100644
--- a/src/share/vm/opto/superword.cpp
+++ b/src/share/vm/opto/superword.cpp
@@ -448,6 +448,7 @@ bool SuperWord::ref_is_alignable(SWPointer& p) {
return true; // no induction variable
}
CountedLoopEndNode* pre_end = get_pre_loop_end(lp()->as_CountedLoop());
+ assert(pre_end != NULL, "we must have a correct pre-loop");
assert(pre_end->stride_is_con(), "pre loop stride is constant");
int preloop_stride = pre_end->stride_con();
@@ -2052,7 +2053,7 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) {
CountedLoopNode *main_head = lp()->as_CountedLoop();
assert(main_head->is_main_loop(), "");
CountedLoopEndNode* pre_end = get_pre_loop_end(main_head);
- assert(pre_end != NULL, "");
+ assert(pre_end != NULL, "we must have a correct pre-loop");
Node *pre_opaq1 = pre_end->limit();
assert(pre_opaq1->Opcode() == Op_Opaque1, "");
Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1;
@@ -2207,16 +2208,27 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) {
//----------------------------get_pre_loop_end---------------------------
// Find pre loop end from main loop. Returns null if none.
-CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode *cl) {
- Node *ctrl = cl->in(LoopNode::EntryControl);
+CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode* cl) {
+ Node* ctrl = cl->in(LoopNode::EntryControl);
if (!ctrl->is_IfTrue() && !ctrl->is_IfFalse()) return NULL;
- Node *iffm = ctrl->in(0);
+ Node* iffm = ctrl->in(0);
if (!iffm->is_If()) return NULL;
- Node *p_f = iffm->in(0);
+ Node* bolzm = iffm->in(1);
+ if (!bolzm->is_Bool()) return NULL;
+ Node* cmpzm = bolzm->in(1);
+ if (!cmpzm->is_Cmp()) return NULL;
+ Node* opqzm = cmpzm->in(2);
+ // Can not optimize a loop if zero-trip Opaque1 node is optimized
+ // away and then another round of loop opts attempted.
+ if (opqzm->Opcode() != Op_Opaque1) {
+ return NULL;
+ }
+ Node* p_f = iffm->in(0);
if (!p_f->is_IfFalse()) return NULL;
if (!p_f->in(0)->is_CountedLoopEnd()) return NULL;
- CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd();
- if (!pre_end->loopnode()->is_pre_loop()) return NULL;
+ CountedLoopEndNode* pre_end = p_f->in(0)->as_CountedLoopEnd();
+ CountedLoopNode* loop_node = pre_end->loopnode();
+ if (loop_node == NULL || !loop_node->is_pre_loop()) return NULL;
return pre_end;
}
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
index 421a3ba13..0fdf47ca9 100644
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
@@ -602,6 +602,9 @@ class CommandLineFlags {
product(bool, UseSHA, false, \
"Control whether SHA instructions can be used on SPARC") \
\
+ product(bool, UseGHASHIntrinsics, false, \
+ "Use intrinsics for GHASH versions of crypto") \
+ \
product(uintx, LargePageSizeInBytes, 0, \
"Large page size (0 to let VM choose the page size)") \
\
diff --git a/src/share/vm/runtime/safepoint.cpp b/src/share/vm/runtime/safepoint.cpp
index be4bb457a..0e82c8b73 100644
--- a/src/share/vm/runtime/safepoint.cpp
+++ b/src/share/vm/runtime/safepoint.cpp
@@ -537,6 +537,7 @@ void SafepointSynchronize::do_cleanup_tasks() {
// rotate log files?
if (UseGCLogFileRotation) {
+ TraceTime t8("rotating gc logs", TraceSafepointCleanupTime);
gclog_or_tty->rotate_log(false);
}
diff --git a/src/share/vm/runtime/stubRoutines.cpp b/src/share/vm/runtime/stubRoutines.cpp
index 6b8f7e754..d943248da 100644
--- a/src/share/vm/runtime/stubRoutines.cpp
+++ b/src/share/vm/runtime/stubRoutines.cpp
@@ -124,6 +124,7 @@ address StubRoutines::_aescrypt_encryptBlock = NULL;
address StubRoutines::_aescrypt_decryptBlock = NULL;
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
+address StubRoutines::_ghash_processBlocks = NULL;
address StubRoutines::_sha1_implCompress = NULL;
address StubRoutines::_sha1_implCompressMB = NULL;
@@ -176,7 +177,7 @@ void StubRoutines::initialize1() {
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");
+ assert(code_size1 == 0 || buffer.insts_remaining() > 200, "increase code_size1");
}
}
@@ -231,7 +232,7 @@ void StubRoutines::initialize2() {
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");
+ assert(code_size2 == 0 || buffer.insts_remaining() > 200, "increase code_size2");
}
#ifdef ASSERT
diff --git a/src/share/vm/runtime/stubRoutines.hpp b/src/share/vm/runtime/stubRoutines.hpp
index 42808a4c6..0f6641c17 100644
--- a/src/share/vm/runtime/stubRoutines.hpp
+++ b/src/share/vm/runtime/stubRoutines.hpp
@@ -197,6 +197,7 @@ class StubRoutines: AllStatic {
static address _aescrypt_decryptBlock;
static address _cipherBlockChaining_encryptAESCrypt;
static address _cipherBlockChaining_decryptAESCrypt;
+ static address _ghash_processBlocks;
static address _sha1_implCompress;
static address _sha1_implCompressMB;
@@ -359,6 +360,7 @@ class StubRoutines: AllStatic {
static address aescrypt_decryptBlock() { return _aescrypt_decryptBlock; }
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
+ static address ghash_processBlocks() { return _ghash_processBlocks; }
static address sha1_implCompress() { return _sha1_implCompress; }
static address sha1_implCompressMB() { return _sha1_implCompressMB; }
diff --git a/src/share/vm/runtime/vmStructs.cpp b/src/share/vm/runtime/vmStructs.cpp
index 161a4c401..7f6f84887 100644
--- a/src/share/vm/runtime/vmStructs.cpp
+++ b/src/share/vm/runtime/vmStructs.cpp
@@ -810,6 +810,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
static_field(StubRoutines, _aescrypt_decryptBlock, address) \
static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \
static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \
+ static_field(StubRoutines, _ghash_processBlocks, address) \
static_field(StubRoutines, _updateBytesCRC32, address) \
static_field(StubRoutines, _crc_table_adr, address) \
static_field(StubRoutines, _multiplyToLen, address) \
diff --git a/src/share/vm/services/allocationSite.hpp b/src/share/vm/services/allocationSite.hpp
index 07f8595f8..d747c1b72 100644
--- a/src/share/vm/services/allocationSite.hpp
+++ b/src/share/vm/services/allocationSite.hpp
@@ -34,8 +34,9 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC {
private:
NativeCallStack _call_stack;
E e;
+ MEMFLAGS _flag;
public:
- AllocationSite(const NativeCallStack& stack) : _call_stack(stack) { }
+ AllocationSite(const NativeCallStack& stack, MEMFLAGS flag) : _call_stack(stack), _flag(flag) { }
int hash() const { return _call_stack.hash(); }
bool equals(const NativeCallStack& stack) const {
return _call_stack.equals(stack);
@@ -52,6 +53,8 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC {
// Information regarding this allocation
E* data() { return &e; }
const E* peek() const { return &e; }
+
+ MEMFLAGS flag() const { return _flag; }
};
#endif // SHARE_VM_SERVICES_ALLOCATION_SITE_HPP
diff --git a/src/share/vm/services/mallocSiteTable.cpp b/src/share/vm/services/mallocSiteTable.cpp
index 94fe1b96f..cb80b3e18 100644
--- a/src/share/vm/services/mallocSiteTable.cpp
+++ b/src/share/vm/services/mallocSiteTable.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -84,12 +84,18 @@ bool MallocSiteTable::initialize() {
// Create pseudo call stack for hashtable entry allocation
address pc[3];
if (NMT_TrackingStackDepth >= 3) {
- pc[2] = (address)MallocSiteTable::allocation_at;
+ uintx *fp = (uintx*)MallocSiteTable::allocation_at;
+ // On ppc64, 'fp' is a pointer to a function descriptor which is a struct of
+ // three native pointers where the first pointer is the real function address.
+ // See: http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES
+ pc[2] = (address)(fp PPC64_ONLY(BIG_ENDIAN_ONLY([0])));
}
if (NMT_TrackingStackDepth >= 2) {
- pc[1] = (address)MallocSiteTable::lookup_or_add;
+ uintx *fp = (uintx*)MallocSiteTable::lookup_or_add;
+ pc[1] = (address)(fp PPC64_ONLY(BIG_ENDIAN_ONLY([0])));
}
- pc[0] = (address)MallocSiteTable::new_entry;
+ uintx *fp = (uintx*)MallocSiteTable::new_entry;
+ pc[0] = (address)(fp PPC64_ONLY(BIG_ENDIAN_ONLY([0])));
// Instantiate NativeCallStack object, have to use placement new operator. (see comments above)
NativeCallStack* stack = ::new ((void*)_hash_entry_allocation_stack)
@@ -158,7 +164,7 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* b
MallocSiteHashtableEntry* head = _table[index];
while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) {
MallocSite* site = head->data();
- if (site->flags() == flags && site->equals(key)) {
+ if (site->flag() == flags && site->equals(key)) {
return head->data();
}
diff --git a/src/share/vm/services/mallocSiteTable.hpp b/src/share/vm/services/mallocSiteTable.hpp
index b2e34affc..819f4e737 100644
--- a/src/share/vm/services/mallocSiteTable.hpp
+++ b/src/share/vm/services/mallocSiteTable.hpp
@@ -37,15 +37,12 @@
// MallocSite represents a code path that eventually calls
// os::malloc() to allocate memory
class MallocSite : public AllocationSite<MemoryCounter> {
- private:
- MEMFLAGS _flags;
-
public:
MallocSite() :
- AllocationSite<MemoryCounter>(NativeCallStack::empty_stack()), _flags(mtNone) {}
+ AllocationSite<MemoryCounter>(NativeCallStack::empty_stack(), mtNone) {}
MallocSite(const NativeCallStack& stack, MEMFLAGS flags) :
- AllocationSite<MemoryCounter>(stack), _flags(flags) {}
+ AllocationSite<MemoryCounter>(stack, flags) {}
void allocate(size_t size) { data()->allocate(size); }
@@ -55,7 +52,6 @@ class MallocSite : public AllocationSite<MemoryCounter> {
size_t size() const { return peek()->size(); }
// The number of calls were made
size_t count() const { return peek()->count(); }
- MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
};
// Malloc site hashtable entry
diff --git a/src/share/vm/services/memBaseline.cpp b/src/share/vm/services/memBaseline.cpp
index f580aada2..1856749a7 100644
--- a/src/share/vm/services/memBaseline.cpp
+++ b/src/share/vm/services/memBaseline.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, 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
@@ -63,7 +63,7 @@ int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) {
int res = compare_malloc_site(s1, s2);
if (res == 0) {
- res = (int)(s1.flags() - s2.flags());
+ res = (int)(s1.flag() - s2.flag());
}
return res;
@@ -209,7 +209,7 @@ bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
const ReservedMemoryRegion* rgn;
VirtualMemoryAllocationSite* site;
while ((rgn = itr.next()) != NULL) {
- VirtualMemoryAllocationSite tmp(*rgn->call_stack());
+ VirtualMemoryAllocationSite tmp(*rgn->call_stack(), rgn->flag());
site = allocation_sites.find(tmp);
if (site == NULL) {
LinkedListNode<VirtualMemoryAllocationSite>* node =
diff --git a/src/share/vm/services/memReporter.cpp b/src/share/vm/services/memReporter.cpp
index 67e3eea09..a324890d3 100644
--- a/src/share/vm/services/memReporter.cpp
+++ b/src/share/vm/services/memReporter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, 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
@@ -205,7 +205,7 @@ void MemDetailReporter::report_malloc_sites() {
const NativeCallStack* stack = malloc_site->call_stack();
stack->print_on(out);
out->print("%29s", " ");
- MEMFLAGS flag = malloc_site->flags();
+ MEMFLAGS flag = malloc_site->flag();
assert((flag >= 0 && flag < (int)mt_number_of_types) && flag != mtNone,
"Must have a valid memory type");
print_malloc(malloc_site->size(), malloc_site->count(),flag);
@@ -231,6 +231,10 @@ void MemDetailReporter::report_virtual_memory_allocation_sites() {
stack->print_on(out);
out->print("%28s (", " ");
print_total(virtual_memory_site->reserved(), virtual_memory_site->committed());
+ MEMFLAGS flag = virtual_memory_site->flag();
+ if (flag != mtNone) {
+ out->print(" Type=%s", NMTUtil::flag_to_name(flag));
+ }
out->print_cr(")\n");
}
}
@@ -562,24 +566,24 @@ void MemDetailDiffReporter::diff_virtual_memory_sites() const {
void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const {
diff_malloc_site(malloc_site->call_stack(), malloc_site->size(), malloc_site->count(),
- 0, 0, malloc_site->flags());
+ 0, 0, malloc_site->flag());
}
void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const {
diff_malloc_site(malloc_site->call_stack(), 0, 0, malloc_site->size(),
- malloc_site->count(), malloc_site->flags());
+ malloc_site->count(), malloc_site->flag());
}
void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early,
const MallocSite* current) const {
- if (early->flags() != current->flags()) {
+ if (early->flag() != current->flag()) {
// 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());
+ early->size(), early->count(), early->flag());
}
}
@@ -603,21 +607,22 @@ void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_
void MemDetailDiffReporter::new_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
- diff_virtual_memory_site(site->call_stack(), site->reserved(), site->committed(), 0, 0);
+ diff_virtual_memory_site(site->call_stack(), site->reserved(), site->committed(), 0, 0, site->flag());
}
void MemDetailDiffReporter::old_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
- diff_virtual_memory_site(site->call_stack(), 0, 0, site->reserved(), site->committed());
+ diff_virtual_memory_site(site->call_stack(), 0, 0, site->reserved(), site->committed(), site->flag());
}
void MemDetailDiffReporter::diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
const VirtualMemoryAllocationSite* current) const {
+ assert(early->flag() == current->flag(), "Should be the same");
diff_virtual_memory_site(current->call_stack(), current->reserved(), current->committed(),
- early->reserved(), early->committed());
+ early->reserved(), early->committed(), current->flag());
}
void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
- size_t current_committed, size_t early_reserved, size_t early_committed) const {
+ size_t current_committed, size_t early_reserved, size_t early_committed, MEMFLAGS flag) const {
outputStream* out = output();
// no change
@@ -631,6 +636,10 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac
print_virtual_memory_diff(current_reserved, current_committed,
early_reserved, early_committed);
+ if (flag != mtNone) {
+ out->print(" Type=%s", NMTUtil::flag_to_name(flag));
+ }
+
out->print_cr(")\n");
}
diff --git a/src/share/vm/services/memReporter.hpp b/src/share/vm/services/memReporter.hpp
index 9b83f8ce4..794804dc2 100644
--- a/src/share/vm/services/memReporter.hpp
+++ b/src/share/vm/services/memReporter.hpp
@@ -218,7 +218,7 @@ class MemDetailDiffReporter : public MemSummaryDiffReporter {
void diff_malloc_site(const NativeCallStack* stack, size_t current_size,
size_t currrent_count, size_t early_size, size_t early_count, MEMFLAGS flags) const;
void diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
- size_t current_committed, size_t early_reserved, size_t early_committed) const;
+ size_t current_committed, size_t early_reserved, size_t early_committed, MEMFLAGS flag) const;
};
#endif // INCLUDE_NMT
diff --git a/src/share/vm/services/memoryPool.hpp b/src/share/vm/services/memoryPool.hpp
index 007366e0b..157b54e73 100644
--- a/src/share/vm/services/memoryPool.hpp
+++ b/src/share/vm/services/memoryPool.hpp
@@ -198,7 +198,7 @@ public:
bool support_usage_threshold);
MemoryUsage get_memory_usage();
- size_t used_in_bytes() { return _space->used(); }
+ size_t used_in_bytes() { return _space->used_stable(); }
};
#endif // INCLUDE_ALL_GCS
diff --git a/src/share/vm/services/virtualMemoryTracker.hpp b/src/share/vm/services/virtualMemoryTracker.hpp
index 1be43b554..16c9be7f9 100644
--- a/src/share/vm/services/virtualMemoryTracker.hpp
+++ b/src/share/vm/services/virtualMemoryTracker.hpp
@@ -69,8 +69,8 @@ class VirtualMemory VALUE_OBJ_CLASS_SPEC {
// Virtual memory allocation site, keeps track where the virtual memory is reserved.
class VirtualMemoryAllocationSite : public AllocationSite<VirtualMemory> {
public:
- VirtualMemoryAllocationSite(const NativeCallStack& stack) :
- AllocationSite<VirtualMemory>(stack) { }
+ VirtualMemoryAllocationSite(const NativeCallStack& stack, MEMFLAGS flag) :
+ AllocationSite<VirtualMemory>(stack, flag) { }
inline void reserve_memory(size_t sz) { data()->reserve_memory(sz); }
inline void commit_memory (size_t sz) { data()->commit_memory(sz); }
diff --git a/src/share/vm/utilities/macros.hpp b/src/share/vm/utilities/macros.hpp
index da206d398..1f1c4df2a 100644
--- a/src/share/vm/utilities/macros.hpp
+++ b/src/share/vm/utilities/macros.hpp
@@ -416,6 +416,14 @@
#define NOT_EMBEDDED(code) code
#endif
+#ifdef VM_LITTLE_ENDIAN
+#define LITTLE_ENDIAN_ONLY(code) code
+#define BIG_ENDIAN_ONLY(code)
+#else
+#define LITTLE_ENDIAN_ONLY(code)
+#define BIG_ENDIAN_ONLY(code) code
+#endif
+
#define define_pd_global(type, name, value) const type pd_##name = value;
#endif // SHARE_VM_UTILITIES_MACROS_HPP
diff --git a/src/share/vm/utilities/taskqueue.hpp b/src/share/vm/utilities/taskqueue.hpp
index d2b39c943..0a2af4cdb 100644
--- a/src/share/vm/utilities/taskqueue.hpp
+++ b/src/share/vm/utilities/taskqueue.hpp
@@ -714,6 +714,11 @@ GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
} else {
// Otherwise, the queue contained exactly one element; we take the slow
// path.
+
+ // The barrier is required to prevent reordering the two reads of _age:
+ // one is the _age.get() below, and the other is _age.top() above the if-stmt.
+ // The algorithm may fail if _age.get() reads an older value than _age.top().
+ OrderAccess::loadload();
return pop_local_slow(localBot, _age.get());
}
}
diff --git a/src/share/vm/utilities/workgroup.cpp b/src/share/vm/utilities/workgroup.cpp
index 3d1f1eef7..08b97aa77 100644
--- a/src/share/vm/utilities/workgroup.cpp
+++ b/src/share/vm/utilities/workgroup.cpp
@@ -464,7 +464,6 @@ bool SubTasksDone::is_task_claimed(uint t) {
if (old == 0) {
old = Atomic::cmpxchg(1, &_tasks[t], 0);
}
- assert(_tasks[t] == 1, "What else?");
bool res = old != 0;
#ifdef ASSERT
if (!res) {
diff --git a/test/compiler/7184394/TestAESBase.java b/test/compiler/7184394/TestAESBase.java
index 4d3204880..5c3e6881e 100644
--- a/test/compiler/7184394/TestAESBase.java
+++ b/test/compiler/7184394/TestAESBase.java
@@ -29,6 +29,7 @@
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
@@ -62,8 +63,12 @@ abstract public class TestAESBase {
Random random = new Random(0);
Cipher cipher;
Cipher dCipher;
- AlgorithmParameters algParams;
+ AlgorithmParameters algParams = null;
SecretKey key;
+ GCMParameterSpec gcm_spec;
+ byte[] aad = { 0x11, 0x22, 0x33, 0x44, 0x55 };
+ int tlen = 12;
+ byte[] iv = new byte[16];
static int numThreads = 0;
int threadId;
@@ -77,7 +82,10 @@ abstract public class TestAESBase {
public void prepare() {
try {
- System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", paddingStr=" + paddingStr + ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit + ", checkOutput=" + checkOutput + ", encInputOffset=" + encInputOffset + ", encOutputOffset=" + encOutputOffset + ", decOutputOffset=" + decOutputOffset + ", lastChunkSize=" +lastChunkSize );
+ System.out.println("\nalgorithm=" + algorithm + ", mode=" + mode + ", paddingStr=" + paddingStr +
+ ", msgSize=" + msgSize + ", keySize=" + keySize + ", noReinit=" + noReinit +
+ ", checkOutput=" + checkOutput + ", encInputOffset=" + encInputOffset + ", encOutputOffset=" +
+ encOutputOffset + ", decOutputOffset=" + decOutputOffset + ", lastChunkSize=" +lastChunkSize );
if (encInputOffset % ALIGN != 0 || encOutputOffset % ALIGN != 0 || decOutputOffset % ALIGN !=0 )
testingMisalignment = true;
@@ -98,16 +106,24 @@ abstract public class TestAESBase {
cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
+ // CBC init
if (mode.equals("CBC")) {
- int ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0);
- IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]);
+ IvParameterSpec initVector = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, key, initVector);
- } else {
algParams = cipher.getParameters();
+ dCipher.init(Cipher.DECRYPT_MODE, key, initVector);
+
+ // GCM init
+ } else if (mode.equals("GCM")) {
+ gcm_init(true);
+ gcm_init(false);
+
+ // ECB init
+ } else {
cipher.init(Cipher.ENCRYPT_MODE, key, algParams);
+ dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
}
- algParams = cipher.getParameters();
- dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
+
if (threadId == 0) {
childShowCipher();
}
@@ -188,4 +204,19 @@ abstract public class TestAESBase {
}
abstract void childShowCipher();
+
+ void gcm_init(boolean encrypt) throws Exception {
+ gcm_spec = new GCMParameterSpec(tlen * 8, iv);
+ if (encrypt) {
+ // Get a new instance everytime because of reuse IV restrictions
+ cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
+ cipher.init(Cipher.ENCRYPT_MODE, key, gcm_spec);
+ cipher.updateAAD(aad);
+ } else {
+ dCipher.init(Cipher.DECRYPT_MODE, key, gcm_spec);
+ dCipher.updateAAD(aad);
+
+
+ }
+ }
}
diff --git a/test/compiler/7184394/TestAESDecode.java b/test/compiler/7184394/TestAESDecode.java
index 21f1f5559..e90ef767e 100644
--- a/test/compiler/7184394/TestAESDecode.java
+++ b/test/compiler/7184394/TestAESDecode.java
@@ -32,7 +32,11 @@ public class TestAESDecode extends TestAESBase {
@Override
public void run() {
try {
- if (!noReinit) dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
+ if (mode.equals("GCM")) {
+ gcm_init(false);
+ } else if (!noReinit) {
+ dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
+ }
decode = new byte[decodeLength];
if (testingMisalignment) {
int tempSize = dCipher.update(encode, encOutputOffset, (decodeMsgSize - lastChunkSize), decode, decOutputOffset);
diff --git a/test/compiler/7184394/TestAESEncode.java b/test/compiler/7184394/TestAESEncode.java
index f1a35bde0..cbfb81795 100644
--- a/test/compiler/7184394/TestAESEncode.java
+++ b/test/compiler/7184394/TestAESEncode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -32,7 +32,11 @@ public class TestAESEncode extends TestAESBase {
@Override
public void run() {
try {
- if (!noReinit) cipher.init(Cipher.ENCRYPT_MODE, key, algParams);
+ if (mode.equals("GCM")) {
+ gcm_init(true);
+ } else if (!noReinit) {
+ cipher.init(Cipher.ENCRYPT_MODE, key, algParams);
+ }
encode = new byte[encodeLength];
if (testingMisalignment) {
int tempSize = cipher.update(input, encInputOffset, (msgSize - lastChunkSize), encode, encOutputOffset);
diff --git a/test/compiler/7184394/TestAESMain.java b/test/compiler/7184394/TestAESMain.java
index 20929e8ba..ddd8eeaef 100644
--- a/test/compiler/7184394/TestAESMain.java
+++ b/test/compiler/7184394/TestAESMain.java
@@ -41,6 +41,13 @@
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1 TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 TestAESMain
* @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=ECB -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencOutputOffset=1 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DdecOutputOffset=1 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 TestAESMain
+ * @run main/othervm/timeout=600 -Xbatch -DcheckOutput=true -Dmode=GCM -DencInputOffset=1 -DencOutputOffset=1 -DdecOutputOffset=1 -DpaddingStr=NoPadding -DmsgSize=640 TestAESMain
*
* @author Tom Deneau
*/
diff --git a/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java b/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
index 6fbaf9cef..9ff45492f 100644
--- a/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
+++ b/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
@@ -22,9 +22,10 @@
*/
import sun.hotspot.WhiteBox;
-import sun.misc.Unsafe;
import sun.misc.IOUtils;
+import sun.misc.Unsafe;
+import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLConnection;
@@ -108,7 +109,13 @@ public class TestAnonymousClassUnloading {
// (1) Load an anonymous version of this class using the corresponding Unsafe method
URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class");
URLConnection connection = classUrl.openConnection();
- byte[] classBytes = IOUtils.readFully(connection.getInputStream(), connection.getContentLength(), true);
+
+ int length = connection.getContentLength();
+ byte[] classBytes = IOUtils.readAllBytes(connection.getInputStream());
+ if (length != -1 && classBytes.length != length) {
+ throw new IOException("Expected:" + length + ", actual: " + classBytes.length);
+ }
+
Class<?> anonymousClass = UNSAFE.defineAnonymousClass(TestAnonymousClassUnloading.class, classBytes, null);
// (2) Make sure all paths of doWork are profiled and compiled
diff --git a/test/compiler/loopopts/StrangeControl.jasm b/test/compiler/loopopts/StrangeControl.jasm
new file mode 100644
index 000000000..c36217ddb
--- /dev/null
+++ b/test/compiler/loopopts/StrangeControl.jasm
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+super public class compiler/loopopts/StrangeControl
+ version 51:0
+{
+
+static Field field:"I";
+
+public static Method test:"(I)V"
+ stack 2 locals 2
+{
+ iconst_0;
+ istore 1;
+ L1: stack_frame_type append;
+ locals_map int;
+ iinc 1, 1;
+ iload 1;
+ iconst_2;
+ if_icmple L1;
+ L2: stack_frame_type same;
+ iload_0;
+ putstatic Field field:"I";
+ goto L1;
+}
+
+} // end Class StrangeControl
diff --git a/test/compiler/loopopts/TestRemoveEmptyLoop.java b/test/compiler/loopopts/TestRemoveEmptyLoop.java
new file mode 100644
index 000000000..d9828e56f
--- /dev/null
+++ b/test/compiler/loopopts/TestRemoveEmptyLoop.java
@@ -0,0 +1,53 @@
+/*
+ * 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 8231988
+ * @summary Unexpected test result caused by C2 IdealLoopTree::do_remove_empty_loop
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation
+ * TestRemoveEmptyLoop
+ */
+
+public class TestRemoveEmptyLoop {
+
+ public void test() {
+ int i = 34;
+ for (; i > 0; i -= 11);
+ if (i < 0) {
+ // do nothing
+ } else {
+ throw new RuntimeException("Test failed.");
+ }
+ }
+
+ public static void main(String[] args) {
+ TestRemoveEmptyLoop _instance = new TestRemoveEmptyLoop();
+ for (int i = 0; i < 50000; i++) {
+ _instance.test();
+ }
+ System.out.println("Test passed.");
+ }
+
+}
diff --git a/test/compiler/loopopts/TestStrangeControl.java b/test/compiler/loopopts/TestStrangeControl.java
new file mode 100644
index 000000000..d93ed9910
--- /dev/null
+++ b/test/compiler/loopopts/TestStrangeControl.java
@@ -0,0 +1,49 @@
+/*
+ * 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 8228888
+ * @summary Test PhaseIdealLoop::has_local_phi_input() with phi input with non-dominating control.
+ * @compile StrangeControl.jasm
+ * @run main/othervm -Xbatch -XX:CompileCommand=inline,compiler.loopopts.StrangeControl::test
+ * compiler.loopopts.TestStrangeControl
+ */
+
+package compiler.loopopts;
+
+public class TestStrangeControl {
+
+ public static void main(String[] args) throws Exception {
+ Thread thread = new Thread() {
+ public void run() {
+ // Run this in an own thread because it's basically an endless loop
+ StrangeControl.test(42);
+ }
+ };
+ thread.start();
+ // Give thread executing strange control loop enough time to trigger OSR compilation
+ Thread.sleep(4000);
+ }
+}
diff --git a/test/compiler/loopopts/superword/TestFuzzPreLoop.java b/test/compiler/loopopts/superword/TestFuzzPreLoop.java
new file mode 100644
index 000000000..61fd78d3a
--- /dev/null
+++ b/test/compiler/loopopts/superword/TestFuzzPreLoop.java
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * @bug 8134739 8010500
+ * @summary SEGV in SuperWord::get_pre_loop_end
+ * @run main/othervm compiler.loopopts.superword.TestFuzzPreLoop
+ */
+
+package compiler.loopopts.superword;
+
+public class TestFuzzPreLoop {
+ static Object sink;
+ short sFld = -19206;
+
+ void doTest() {
+ int[] arr = new int[400];
+
+ for (int i1 = 0; i1 < 200; i1++) {
+ for (int i2 = 0; i2 < 100; i2++) {
+ sink = new int[400];
+ }
+ arr[i1] = 0;
+ }
+
+ float f1 = 0;
+ for (int i3 = 0; i3 < 200; i3++) {
+ f1 += i3 * i3;
+ }
+ for (int i4 = 0; i4 < 200; i4++) {
+ f1 += i4 - sFld;
+ }
+
+ System.out.println(arr);
+ System.out.println(f1);
+ }
+
+ public static void main(String... args) throws Exception {
+ TestFuzzPreLoop test = new TestFuzzPreLoop();
+ for (int i = 0; i < 100; i++) {
+ test.doTest();
+ }
+ }
+}
diff --git a/test/compiler/print/TestProfileReturnTypePrinting.java b/test/compiler/print/TestProfileReturnTypePrinting.java
new file mode 100644
index 000000000..ca57139c3
--- /dev/null
+++ b/test/compiler/print/TestProfileReturnTypePrinting.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8073154
+ * @build TestProfileReturnTypePrinting
+ * @run main/othervm -XX:TypeProfileLevel=020
+ * -XX:CompileOnly=TestProfileReturnTypePrinting.testMethod
+ * -XX:+IgnoreUnrecognizedVMOptions -XX:+PrintLIR
+ * TestProfileReturnTypePrinting
+ * @summary Verify that c1's LIR that contains ProfileType node could be dumped
+ * without a crash disregard to an exact class knowledge.
+ */
+public class TestProfileReturnTypePrinting {
+ private static final int ITERATIONS = 1_000_000;
+
+ public static void main(String args[]) {
+ for (int i = 0; i < ITERATIONS; i++) {
+ TestProfileReturnTypePrinting.testMethod(i);
+ }
+ }
+
+ private static int testMethod(int i) {
+ return TestProfileReturnTypePrinting.foo().hashCode()
+ + TestProfileReturnTypePrinting.bar(i).hashCode();
+ }
+
+ /* Exact class of returned value is known statically. */
+ private static B foo() {
+ return new B();
+ }
+
+ /* Exact class of returned value is not known statically. */
+ private static Object bar(int i) {
+ if (i % 2 == 0) {
+ return new A();
+ } else {
+ return new B();
+ }
+ }
+
+ private static class A {
+ }
+
+ private static class B extends A {
+ }
+}
diff --git a/test/gc/stress/gclocker/TestExcessGCLockerCollections.java b/test/gc/stress/gclocker/TestExcessGCLockerCollections.java
new file mode 100644
index 000000000..7495d5b9e
--- /dev/null
+++ b/test/gc/stress/gclocker/TestExcessGCLockerCollections.java
@@ -0,0 +1,285 @@
+/*
+ * 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 gc.stress.gclocker;
+
+// Based on Kim Barrett;s test for JDK-8048556
+
+/*
+ * @test TestExcessGCLockerCollections
+ * @key gc
+ * @bug 8048556
+ * @summary Check for GC Locker initiated GCs that immediately follow another
+ * GC and so have very little needing to be collected.
+ * @library /testlibrary
+ * @run driver/timeout=1000 gc.stress.gclocker.TestExcessGCLockerCollections 300 4 2
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import java.util.zip.Deflater;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.openmbean.CompositeData;
+import java.lang.management.ManagementFactory;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.MemoryUsage;
+import java.util.List;
+import com.sun.management.GarbageCollectionNotificationInfo;
+import com.sun.management.GcInfo;
+
+import com.oracle.java.testlibrary.Asserts;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+class TestExcessGCLockerCollectionsStringConstants {
+ // Some constant strings used in both GC logging and error detection
+ static public final String GCLOCKER_CAUSE = "GCLocker Initiated GC";
+ static public final String USED_TOO_LOW = "TOO LOW";
+ static public final String USED_OK = "OK";
+}
+
+class TestExcessGCLockerCollectionsAux {
+ static private final int LARGE_MAP_SIZE = 64 * 1024;
+
+ static private final int MAP_ARRAY_LENGTH = 4;
+ static private final int MAP_SIZE = 1024;
+
+ static private final int BYTE_ARRAY_LENGTH = 128 * 1024;
+
+ static private void println(String str) { System.out.println(str); }
+ static private void println() { System.out.println(); }
+
+ static private volatile boolean keepRunning = true;
+
+ static Map<Integer,String> populateMap(int size) {
+ Map<Integer,String> map = new HashMap<Integer,String>();
+ for (int i = 0; i < size; i += 1) {
+ Integer keyInt = Integer.valueOf(i);
+ String valStr = "value is [" + i + "]";
+ map.put(keyInt,valStr);
+ }
+ return map;
+ }
+
+ static private class AllocatingWorker implements Runnable {
+ private final Object[] array = new Object[MAP_ARRAY_LENGTH];
+ private int arrayIndex = 0;
+
+ private void doStep() {
+ Map<Integer,String> map = populateMap(MAP_SIZE);
+ array[arrayIndex] = map;
+ arrayIndex = (arrayIndex + 1) % MAP_ARRAY_LENGTH;
+ }
+
+ public void run() {
+ while (keepRunning) {
+ doStep();
+ }
+ }
+ }
+
+ static private class JNICriticalWorker implements Runnable {
+ private int count;
+
+ private void doStep() {
+ byte[] inputArray = new byte[BYTE_ARRAY_LENGTH];
+ for (int i = 0; i < inputArray.length; i += 1) {
+ inputArray[i] = (byte) (count + i);
+ }
+
+ Deflater deflater = new Deflater();
+ deflater.setInput(inputArray);
+ deflater.finish();
+
+ byte[] outputArray = new byte[2 * inputArray.length];
+ deflater.deflate(outputArray);
+
+ count += 1;
+ }
+
+ public void run() {
+ while (keepRunning) {
+ doStep();
+ }
+ }
+ }
+
+ static class GCNotificationListener implements NotificationListener {
+ static private final double MIN_USED_PERCENT = 40.0;
+
+ static private final List<String> newGenPoolNames = Arrays.asList(
+ "G1 Eden Space", // OpenJDK G1GC: -XX:+UseG1GC
+ "PS Eden Space", // OpenJDK ParallelGC: -XX:+ParallelGC
+ "Par Eden Space", // OpenJDK ConcMarkSweepGC: -XX:+ConcMarkSweepGC
+ "Eden Space" // OpenJDK SerialGC: -XX:+UseSerialGC
+ // OpenJDK ConcMarkSweepGC: -XX:+ConcMarkSweepGC -XX:-UseParNewGC
+ );
+
+ @Override
+ public void handleNotification(Notification notification, Object handback) {
+ try {
+ if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
+ GarbageCollectionNotificationInfo info =
+ GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());
+
+ String gc_cause = info.getGcCause();
+
+ if (gc_cause.equals(TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE)) {
+ Map<String, MemoryUsage> memory_before_gc = info.getGcInfo().getMemoryUsageBeforeGc();
+
+ for (String newGenPoolName : newGenPoolNames) {
+ MemoryUsage usage = memory_before_gc.get(newGenPoolName);
+ if (usage == null) continue;
+
+ double startTime = ((double) info.getGcInfo().getStartTime()) / 1000.0;
+ long used = usage.getUsed();
+ long committed = usage.getCommitted();
+ long max = usage.getMax();
+ double used_percent = (((double) used) / Math.max(committed, max)) * 100.0;
+
+ System.out.printf("%6.3f: (%s) %d/%d/%d, %8.4f%% (%s)\n",
+ startTime, gc_cause, used, committed, max, used_percent,
+ ((used_percent < MIN_USED_PERCENT) ? TestExcessGCLockerCollectionsStringConstants.USED_TOO_LOW
+ : TestExcessGCLockerCollectionsStringConstants.USED_OK));
+ }
+ }
+ }
+ } catch (RuntimeException ex) {
+ System.err.println("Exception during notification processing:" + ex);
+ ex.printStackTrace();
+ }
+ }
+
+ public static boolean register() {
+ try {
+ MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+
+ // Get the list of MX
+ List<GarbageCollectorMXBean> gc_mxbeans = ManagementFactory.getGarbageCollectorMXBeans();
+
+ // Create the notification listener
+ GCNotificationListener gcNotificationListener = new GCNotificationListener();
+
+ for (GarbageCollectorMXBean gcbean : gc_mxbeans) {
+ // Add notification listener for the MXBean
+ mbeanServer.addNotificationListener(gcbean.getObjectName(), gcNotificationListener, null, null);
+ }
+ } catch (Exception ex) {
+ System.err.println("Exception during mbean registration:" + ex);
+ ex.printStackTrace();
+ // We've failed to set up, terminate
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ static public Map<Integer,String> largeMap;
+
+ static public void main(String args[]) {
+ long durationSec = Long.parseLong(args[0]);
+ int allocThreadNum = Integer.parseInt(args[1]);
+ int jniCriticalThreadNum = Integer.parseInt(args[2]);
+
+ println("Running for " + durationSec + " secs");
+
+ if (!GCNotificationListener.register()) {
+ println("failed to register GC notification listener");
+ System.exit(-1);
+ }
+
+ largeMap = populateMap(LARGE_MAP_SIZE);
+
+ println("Starting " + allocThreadNum + " allocating threads");
+ for (int i = 0; i < allocThreadNum; i += 1) {
+ new Thread(new AllocatingWorker()).start();
+ }
+
+ println("Starting " + jniCriticalThreadNum + " jni critical threads");
+ for (int i = 0; i < jniCriticalThreadNum; i += 1) {
+ new Thread(new JNICriticalWorker()).start();
+ }
+
+ long durationMS = (long) (1000 * durationSec);
+ long start = System.currentTimeMillis();
+ long now = start;
+ long soFar = now - start;
+ while (soFar < durationMS) {
+ try {
+ Thread.sleep(durationMS - soFar);
+ } catch (Exception e) {
+ }
+ now = System.currentTimeMillis();
+ soFar = now - start;
+ }
+ println("Done.");
+ keepRunning = false;
+ }
+}
+
+public class TestExcessGCLockerCollections {
+ private static final String USED_OK_LINE =
+ "\\(" + TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE + "\\)"
+ + " .* " +
+ "\\(" + TestExcessGCLockerCollectionsStringConstants.USED_OK + "\\)";
+ private static final String USED_TOO_LOW_LINE =
+ "\\(" + TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE + "\\)"
+ + " .* " +
+ "\\(" + TestExcessGCLockerCollectionsStringConstants.USED_TOO_LOW + "\\)";
+
+ private static final String[] COMMON_OPTIONS = new String[] {
+ "-Xmx1G", "-Xms1G", "-Xmn256M" };
+
+ public static void main(String args[]) throws Exception {
+ if (args.length < 3) {
+ System.out.println("usage: TestExcessGCLockerCollections" +
+ " <duration sec> <alloc threads>" +
+ " <jni critical threads>");
+ throw new RuntimeException("Invalid arguments");
+ }
+
+ ArrayList<String> finalArgs = new ArrayList<String>();
+ finalArgs.addAll(Arrays.asList(COMMON_OPTIONS));
+ finalArgs.add(TestExcessGCLockerCollectionsAux.class.getName());
+ finalArgs.addAll(Arrays.asList(args));
+
+ // GC and other options obtained from test framework.
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ true, finalArgs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ //System.out.println("------------- begin stdout ----------------");
+ //System.out.println(output.getStdout());
+ //System.out.println("------------- end stdout ----------------");
+ output.stdoutShouldMatch(USED_OK_LINE);
+ output.stdoutShouldNotMatch(USED_TOO_LOW_LINE);
+ }
+}
diff --git a/test/runtime/8003720/VictimClassLoader.java b/test/runtime/8003720/VictimClassLoader.java
index 3505f7832..e219fd60f 100644
--- a/test/runtime/8003720/VictimClassLoader.java
+++ b/test/runtime/8003720/VictimClassLoader.java
@@ -22,6 +22,8 @@
*
*/
+import sun.misc.IOUtils;
+
public class VictimClassLoader extends ClassLoader {
public static long counter = 0;
@@ -72,8 +74,10 @@ public class VictimClassLoader extends ClassLoader {
}
static byte[] readFully(java.io.InputStream in, int len) throws java.io.IOException {
- // Warning here:
- return sun.misc.IOUtils.readFully(in, len, true);
+ byte[] b = IOUtils.readAllBytes(in);
+ if (len != -1 && b.length != len)
+ throw new java.io.IOException("Expected:" + len + ", actual:" + b.length);
+ return b;
}
public void finalize() {