# HG changeset patch # User aoqi # Date 1580811194 -28800 # Node ID 758c0766768231810014cf8ea6535f2b1f5186a2 # Parent c97db0855565dd3dbde76c1ce6beeba2407795a5# Parent 7c9f6b5f8d119dc1ba3c5536595ce3ae7414599d Merge diff -r c97db0855565 -r 758c07667682 .hgtags --- a/.hgtags Tue Feb 04 17:38:01 2020 +0800 +++ b/.hgtags Tue Feb 04 18:13:14 2020 +0800 @@ -1300,8 +1300,18 @@ fa7fe6dae563edaae8a8bbe8ac4bd4fa942bde0c jdk8u232-b03 921c5ee7965fdfde75f578ddda24d5cd16f124dc jdk8u232-b04 b13d7942036329f64c77a93cffc25e1b52523a3c jdk8u232-b05 +760b28d871785cd508239a5f635cfb45451f9202 jdk8u242-b00 fea2c7f50ce8e6aee1e946eaec7b834193747d82 jdk8u232-b06 c751303497d539aa85c6373aa0fa85580d3f3044 jdk8u232-b07 4170228e11e6313e948e6ddcae9af3eed06b1fbe jdk8u232-b08 +12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-b09 +12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-ga 2be326848943a7f2359d78d203193045a2d773b3 mips64el-jdk8u232-b10 17884ee5d05398bbd16013b0e73338aa69479cbf mips64el-jdk8u232-b11 +ce42ae95d4d671f74246091f89bd101d5bcbfd91 jdk8u242-b01 +775e2bf92114e41365cc6baf1480c818454256a4 jdk8u242-b02 +ee19c358e3b8deeda2f64d660a0870df7b1abd49 jdk8u242-b03 +20258ba5a788da55485c0648bcc073f8ad2c26ef jdk8u242-b04 +2c1e9fab6964647f4eeffe55fe5592da6399a3ce jdk8u242-b05 +81ddc1072b923330f84c0ace3124226f63877582 jdk8u242-b06 +8b80409d5840142a27e274d33948f483a6406a50 jdk8u242-b07 diff -r c97db0855565 -r 758c07667682 THIRD_PARTY_README --- a/THIRD_PARTY_README Tue Feb 04 17:38:01 2020 +0800 +++ b/THIRD_PARTY_README Tue Feb 04 18:13:14 2020 +0800 @@ -1334,11 +1334,13 @@ -------------------------------------------------------------------------------- -%% 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 -r c97db0855565 -r 758c07667682 src/cpu/ppc/vm/vm_version_ppc.cpp --- a/src/cpu/ppc/vm/vm_version_ppc.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/ppc/vm/vm_version_ppc.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -194,6 +194,11 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/sparc/vm/assembler_sparc.hpp --- a/src/cpu/sparc/vm/assembler_sparc.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ 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 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -4788,6 +4788,130 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/sparc/vm/vm_version_sparc.cpp --- a/src/cpu/sparc/vm/vm_version_sparc.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -286,39 +286,50 @@ // 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(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."); } - 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); + } else { + // 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("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); - } - } } } 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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/assembler_x86.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -2575,6 +2575,15 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/assembler_x86.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -1527,6 +1527,8 @@ // 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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -2719,6 +2719,169 @@ 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 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 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -3639,6 +3639,175 @@ 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 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 @@ 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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/stubRoutines_x86.cpp --- a/src/cpu/x86/vm/stubRoutines_x86.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/stubRoutines_x86.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/stubRoutines_x86.hpp --- a/src/cpu/x86/vm/stubRoutines_x86.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/stubRoutines_x86.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 src/cpu/x86/vm/vm_version_x86.cpp --- a/src/cpu/x86/vm/vm_version_x86.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -553,12 +553,36 @@ // 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/c1/c1_LIR.cpp --- a/src/share/vm/c1/c1_LIR.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/c1/c1_LIR.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -2370,7 +2370,7 @@ // LIR_OpProfileType void LIR_OpProfileType::print_instr(outputStream* out) const { out->print("exact = "); - if (exact_klass() == NULL) { + if (exact_klass() == NULL) { out->print("unknown"); } else { exact_klass()->print_name_on(out); diff -r c97db0855565 -r 758c07667682 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -161,6 +161,8 @@ } _dictionary->set_par_lock(&_parDictionaryAllocLock); } + + _used_stable = 0; } // Like CompactibleSpace forward() but always calls cross_threshold() to @@ -377,6 +379,14 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -148,6 +148,9 @@ // 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 @@ // 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -869,6 +869,10 @@ 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 @@ 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 @@ _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 @@ _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 @@ _collectorState = Marking; } SpecializationStats::print(); + _cmsGen->cmsSpace()->recalculate_used_stable(); } void CMSCollector::checkpointRootsInitialWork(bool asynch) { @@ -5066,10 +5075,12 @@ 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 @@ // 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 @@ // Gather statistics on the young generation collection. collector()->stats().record_gc0_end(used()); } + _cmsSpace->recalculate_used_stable(); } CMSAdaptiveSizePolicy* ConcurrentMarkSweepGeneration::size_policy() { diff -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -1190,6 +1190,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -2520,6 +2520,12 @@ } } } + } 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -376,7 +376,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -133,7 +133,11 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -530,6 +530,10 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp --- a/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -52,11 +52,16 @@ } } +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 @@ "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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/shared/gSpaceCounters.hpp --- a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -63,7 +63,7 @@ } 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 @@ GenerationUsedHelper(Generation* g) : _gen(g) { } inline jlong take_sample() { - return _gen->used(); + return _gen->used_stable(); } }; diff -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -201,6 +201,19 @@ } } +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 -r c97db0855565 -r 758c07667682 src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -201,9 +201,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/memory/gcLocker.cpp --- a/src/share/vm/memory/gcLocker.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/memory/gcLocker.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ } } +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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/memory/gcLocker.hpp --- a/src/share/vm/memory/gcLocker.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/memory/gcLocker.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ 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 @@ // 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 -r c97db0855565 -r 758c07667682 src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/memory/genCollectedHeap.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -796,8 +796,11 @@ #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 @@ // 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, 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 -r c97db0855565 -r 758c07667682 src/share/vm/memory/generation.cpp --- a/src/share/vm/memory/generation.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/memory/generation.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -68,6 +68,12 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/memory/generation.hpp --- a/src/share/vm/memory/generation.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/memory/generation.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -168,6 +168,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -294,6 +294,7 @@ 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 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -241,7 +241,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/oops/klassVtable.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -289,22 +289,25 @@ 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 @@ // 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/escape.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -952,6 +952,7 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/library_call.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -311,6 +311,7 @@ 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 @@ 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 @@ case vmIntrinsics::_montgomerySquare: return inline_montgomerySquare(); + case vmIntrinsics::_ghash_processBlocks: + return inline_ghash_processBlocks(); + case vmIntrinsics::_encodeISOArray: return inline_encodeISOArray(); @@ -6599,6 +6607,35 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/loopTransform.cpp --- a/src/share/vm/opto/loopTransform.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/loopTransform.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ // 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/loopnode.hpp --- a/src/share/vm/opto/loopnode.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/loopnode.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -279,6 +279,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/loopopts.cpp --- a/src/share/vm/opto/loopopts.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/loopopts.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -309,7 +309,7 @@ } 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/runtime.cpp --- a/src/share/vm/opto/runtime.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/runtime.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -100,7 +100,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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/runtime.hpp --- a/src/share/vm/opto/runtime.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/runtime.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -311,6 +311,8 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/opto/superword.cpp --- a/src/share/vm/opto/superword.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/opto/superword.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -448,6 +448,7 @@ 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 @@ 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 @@ //----------------------------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 -r c97db0855565 -r 758c07667682 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/runtime/globals.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -614,6 +614,9 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/runtime/safepoint.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -547,6 +547,7 @@ // rotate log files? if (UseGCLogFileRotation) { + TraceTime t8("rotating gc logs", TraceSafepointCleanupTime); gclog_or_tty->rotate_log(false); } diff -r c97db0855565 -r 758c07667682 src/share/vm/runtime/stubRoutines.cpp --- a/src/share/vm/runtime/stubRoutines.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/runtime/stubRoutines.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -124,6 +124,7 @@ 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 @@ 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/runtime/stubRoutines.hpp --- a/src/share/vm/runtime/stubRoutines.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/runtime/stubRoutines.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -208,6 +208,7 @@ static address _aescrypt_decryptBlock; static address _cipherBlockChaining_encryptAESCrypt; static address _cipherBlockChaining_decryptAESCrypt; + static address _ghash_processBlocks; static address _sha1_implCompress; static address _sha1_implCompressMB; @@ -370,6 +371,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -824,6 +824,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/allocationSite.hpp --- a/src/share/vm/services/allocationSite.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/allocationSite.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -34,8 +34,9 @@ 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 @@ // 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/mallocSiteTable.cpp --- a/src/share/vm/services/mallocSiteTable.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/mallocSiteTable.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ // 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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/mallocSiteTable.hpp --- a/src/share/vm/services/mallocSiteTable.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/mallocSiteTable.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -37,15 +37,12 @@ // MallocSite represents a code path that eventually calls // os::malloc() to allocate memory class MallocSite : public AllocationSite { - private: - MEMFLAGS _flags; - public: MallocSite() : - AllocationSite(NativeCallStack::empty_stack()), _flags(mtNone) {} + AllocationSite(NativeCallStack::empty_stack(), mtNone) {} MallocSite(const NativeCallStack& stack, MEMFLAGS flags) : - AllocationSite(stack), _flags(flags) {} + AllocationSite(stack, flags) {} void allocate(size_t size) { data()->allocate(size); } @@ -55,7 +52,6 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/memBaseline.cpp --- a/src/share/vm/services/memBaseline.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/memBaseline.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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_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 @@ 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* node = diff -r c97db0855565 -r 758c07667682 src/share/vm/services/memReporter.cpp --- a/src/share/vm/services/memReporter.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/memReporter.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ 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 @@ 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::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::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 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/memReporter.hpp --- a/src/share/vm/services/memReporter.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/memReporter.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -218,7 +218,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/memoryPool.hpp --- a/src/share/vm/services/memoryPool.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/memoryPool.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -198,7 +198,7 @@ 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 -r c97db0855565 -r 758c07667682 src/share/vm/services/virtualMemoryTracker.hpp --- a/src/share/vm/services/virtualMemoryTracker.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/services/virtualMemoryTracker.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -69,8 +69,8 @@ // Virtual memory allocation site, keeps track where the virtual memory is reserved. class VirtualMemoryAllocationSite : public AllocationSite { public: - VirtualMemoryAllocationSite(const NativeCallStack& stack) : - AllocationSite(stack) { } + VirtualMemoryAllocationSite(const NativeCallStack& stack, MEMFLAGS flag) : + AllocationSite(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 -r c97db0855565 -r 758c07667682 src/share/vm/utilities/macros.hpp --- a/src/share/vm/utilities/macros.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/utilities/macros.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -434,6 +434,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 -r c97db0855565 -r 758c07667682 src/share/vm/utilities/taskqueue.hpp --- a/src/share/vm/utilities/taskqueue.hpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/utilities/taskqueue.hpp Tue Feb 04 18:13:14 2020 +0800 @@ -791,6 +791,11 @@ } 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 -r c97db0855565 -r 758c07667682 src/share/vm/utilities/workgroup.cpp --- a/src/share/vm/utilities/workgroup.cpp Tue Feb 04 17:38:01 2020 +0800 +++ b/src/share/vm/utilities/workgroup.cpp Tue Feb 04 18:13:14 2020 +0800 @@ -464,7 +464,6 @@ 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 -r c97db0855565 -r 758c07667682 test/compiler/7184394/TestAESBase.java --- a/test/compiler/7184394/TestAESBase.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/compiler/7184394/TestAESBase.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ 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 @@ 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 @@ 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); + 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 { - algParams = cipher.getParameters(); 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 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 -r c97db0855565 -r 758c07667682 test/compiler/7184394/TestAESDecode.java --- a/test/compiler/7184394/TestAESDecode.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/compiler/7184394/TestAESDecode.java Tue Feb 04 18:13:14 2020 +0800 @@ -32,7 +32,11 @@ @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 -r c97db0855565 -r 758c07667682 test/compiler/7184394/TestAESEncode.java --- a/test/compiler/7184394/TestAESEncode.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/compiler/7184394/TestAESEncode.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 @@ @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 -r c97db0855565 -r 758c07667682 test/compiler/7184394/TestAESMain.java --- a/test/compiler/7184394/TestAESMain.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/compiler/7184394/TestAESMain.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java --- a/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java Tue Feb 04 18:13:14 2020 +0800 @@ -22,9 +22,10 @@ */ import sun.hotspot.WhiteBox; +import sun.misc.IOUtils; import sun.misc.Unsafe; -import sun.misc.IOUtils; +import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLConnection; @@ -108,7 +109,13 @@ // (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 -r c97db0855565 -r 758c07667682 test/compiler/loopopts/StrangeControl.jasm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/loopopts/StrangeControl.jasm Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/compiler/loopopts/TestRemoveEmptyLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/loopopts/TestRemoveEmptyLoop.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/compiler/loopopts/TestStrangeControl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/loopopts/TestStrangeControl.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/compiler/loopopts/superword/TestFuzzPreLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/loopopts/superword/TestFuzzPreLoop.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/compiler/print/TestProfileReturnTypePrinting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/print/TestProfileReturnTypePrinting.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 -r c97db0855565 -r 758c07667682 test/gc/stress/gclocker/TestExcessGCLockerCollections.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/stress/gclocker/TestExcessGCLockerCollections.java Tue Feb 04 18:13:14 2020 +0800 @@ -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 populateMap(int size) { + Map map = new HashMap(); + 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 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 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 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 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 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" + + " " + + " "); + throw new RuntimeException("Invalid arguments"); + } + + ArrayList finalArgs = new ArrayList(); + 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 -r c97db0855565 -r 758c07667682 test/runtime/8003720/VictimClassLoader.java --- a/test/runtime/8003720/VictimClassLoader.java Tue Feb 04 17:38:01 2020 +0800 +++ b/test/runtime/8003720/VictimClassLoader.java Tue Feb 04 18:13:14 2020 +0800 @@ -22,6 +22,8 @@ * */ +import sun.misc.IOUtils; + public class VictimClassLoader extends ClassLoader { public static long counter = 0; @@ -72,8 +74,10 @@ } 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() {