提交 bfce3aad 编写于 作者: C Chuansheng Lu

Merge tag 'jdk8u242-ga'

...@@ -1279,6 +1279,16 @@ c963a2881865f6fab5b49a31d22651e8e1b4bf46 jdk8u232-b02 ...@@ -1279,6 +1279,16 @@ c963a2881865f6fab5b49a31d22651e8e1b4bf46 jdk8u232-b02
fa7fe6dae563edaae8a8bbe8ac4bd4fa942bde0c jdk8u232-b03 fa7fe6dae563edaae8a8bbe8ac4bd4fa942bde0c jdk8u232-b03
921c5ee7965fdfde75f578ddda24d5cd16f124dc jdk8u232-b04 921c5ee7965fdfde75f578ddda24d5cd16f124dc jdk8u232-b04
b13d7942036329f64c77a93cffc25e1b52523a3c jdk8u232-b05 b13d7942036329f64c77a93cffc25e1b52523a3c jdk8u232-b05
760b28d871785cd508239a5f635cfb45451f9202 jdk8u242-b00
fea2c7f50ce8e6aee1e946eaec7b834193747d82 jdk8u232-b06 fea2c7f50ce8e6aee1e946eaec7b834193747d82 jdk8u232-b06
c751303497d539aa85c6373aa0fa85580d3f3044 jdk8u232-b07 c751303497d539aa85c6373aa0fa85580d3f3044 jdk8u232-b07
4170228e11e6313e948e6ddcae9af3eed06b1fbe jdk8u232-b08 4170228e11e6313e948e6ddcae9af3eed06b1fbe jdk8u232-b08
12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-b09
12177d88b89c12c14daa5ad681030d7551e8a5a0 jdk8u232-ga
ce42ae95d4d671f74246091f89bd101d5bcbfd91 jdk8u242-b01
775e2bf92114e41365cc6baf1480c818454256a4 jdk8u242-b02
ee19c358e3b8deeda2f64d660a0870df7b1abd49 jdk8u242-b03
20258ba5a788da55485c0648bcc073f8ad2c26ef jdk8u242-b04
2c1e9fab6964647f4eeffe55fe5592da6399a3ce jdk8u242-b05
81ddc1072b923330f84c0ace3124226f63877582 jdk8u242-b06
8b80409d5840142a27e274d33948f483a6406a50 jdk8u242-b07
...@@ -1334,11 +1334,13 @@ SUCH DAMAGE. ...@@ -1334,11 +1334,13 @@ SUCH DAMAGE.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
%% This notice is provided with respect to Joni v1.1.9, which may be %% This notice is provided with respect to Joni v2.1.16, which may be
included with JRE 8, JDK 8, and OpenJDK 8. included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE --- --- begin of LICENSE ---
Copyright (c) 2017 JRuby Team
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
......
...@@ -194,6 +194,11 @@ void VM_Version::initialize() { ...@@ -194,6 +194,11 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseAESIntrinsics, false); 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 (has_vshasig()) {
if (FLAG_IS_DEFAULT(UseSHA)) { if (FLAG_IS_DEFAULT(UseSHA)) {
UseSHA = true; UseSHA = true;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -129,6 +129,7 @@ class Assembler : public AbstractAssembler { ...@@ -129,6 +129,7 @@ class Assembler : public AbstractAssembler {
flog3_op3 = 0x36, flog3_op3 = 0x36,
edge_op3 = 0x36, edge_op3 = 0x36,
fsrc_op3 = 0x36, fsrc_op3 = 0x36,
xmulx_op3 = 0x36,
impdep2_op3 = 0x37, impdep2_op3 = 0x37,
stpartialf_op3 = 0x37, stpartialf_op3 = 0x37,
jmpl_op3 = 0x38, jmpl_op3 = 0x38,
...@@ -220,6 +221,8 @@ class Assembler : public AbstractAssembler { ...@@ -220,6 +221,8 @@ class Assembler : public AbstractAssembler {
mdtox_opf = 0x110, mdtox_opf = 0x110,
mstouw_opf = 0x111, mstouw_opf = 0x111,
mstosw_opf = 0x113, mstosw_opf = 0x113,
xmulx_opf = 0x115,
xmulxhi_opf = 0x116,
mxtod_opf = 0x118, mxtod_opf = 0x118,
mwtos_opf = 0x119, mwtos_opf = 0x119,
...@@ -1212,6 +1215,9 @@ public: ...@@ -1212,6 +1215,9 @@ public:
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); } void 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 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 // Crypto SHA instructions
void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); } void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
......
...@@ -4788,6 +4788,130 @@ class StubGenerator: public StubCodeGenerator { ...@@ -4788,6 +4788,130 @@ class StubGenerator: public StubCodeGenerator {
return start; 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() { void generate_initial() {
// Generates all stubs and initializes the entry points // Generates all stubs and initializes the entry points
...@@ -4860,6 +4984,10 @@ class StubGenerator: public StubCodeGenerator { ...@@ -4860,6 +4984,10 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt(); StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); 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 // generate SHA1/SHA256/SHA512 intrinsics code
if (UseSHA1Intrinsics) { if (UseSHA1Intrinsics) {
......
...@@ -286,39 +286,50 @@ void VM_Version::initialize() { ...@@ -286,39 +286,50 @@ void VM_Version::initialize() {
// SPARC T4 and above should have support for AES instructions // SPARC T4 and above should have support for AES instructions
if (has_aes()) { if (has_aes()) {
if (UseVIS > 2) { // AES intrinsics use MOVxTOd/MOVdTOx which are VIS3
if (FLAG_IS_DEFAULT(UseAES)) { if (FLAG_IS_DEFAULT(UseAES)) {
FLAG_SET_DEFAULT(UseAES, true); FLAG_SET_DEFAULT(UseAES, true);
} }
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) { if (!UseAES) {
FLAG_SET_DEFAULT(UseAESIntrinsics, true); if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
} }
// 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); 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 { } else {
if (UseAES || UseAESIntrinsics) { if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
warning("SPARC AES intrinsics require VIS3 instruction support. Intrinsics will be disabled."); warning("SPARC AES intrinsics require VIS3 instructions. Intrinsics will be disabled.");
if (UseAES) {
FLAG_SET_DEFAULT(UseAES, false);
} }
if (UseAESIntrinsics) {
FLAG_SET_DEFAULT(UseAESIntrinsics, false); FLAG_SET_DEFAULT(UseAESIntrinsics, false);
} }
} }
}
} else if (UseAES || UseAESIntrinsics) { } else if (UseAES || UseAESIntrinsics) {
if (UseAES && !FLAG_IS_DEFAULT(UseAES)) {
warning("AES instructions are not available on this CPU"); warning("AES instructions are not available on this CPU");
if (UseAES) {
FLAG_SET_DEFAULT(UseAES, false); 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); 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 // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
if (has_sha1() || has_sha256() || has_sha512()) { if (has_sha1() || has_sha256() || has_sha512()) {
if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
......
...@@ -2575,6 +2575,15 @@ void Assembler::psrldq(XMMRegister dst, int shift) { ...@@ -2575,6 +2575,15 @@ void Assembler::psrldq(XMMRegister dst, int shift) {
emit_int8(shift); emit_int8(shift);
} }
void Assembler::pslldq(XMMRegister dst, int shift) {
// Shift left 128 bit value in xmm register by number of bytes.
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
int encode = simd_prefix_and_encode(xmm7, dst, dst, VEX_SIMD_66);
emit_int8(0x73);
emit_int8((unsigned char)(0xC0 | encode));
emit_int8(shift);
}
void Assembler::ptest(XMMRegister dst, Address src) { void Assembler::ptest(XMMRegister dst, Address src) {
assert(VM_Version::supports_sse4_1(), ""); assert(VM_Version::supports_sse4_1(), "");
assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes"); assert((UseAVX > 0), "SSE mode requires address alignment 16 bytes");
......
...@@ -1527,6 +1527,8 @@ private: ...@@ -1527,6 +1527,8 @@ private:
// Shift Right by bytes Logical DoubleQuadword Immediate // Shift Right by bytes Logical DoubleQuadword Immediate
void psrldq(XMMRegister dst, int shift); void psrldq(XMMRegister dst, int shift);
// Shift Left by bytes Logical DoubleQuadword Immediate
void pslldq(XMMRegister dst, int shift);
// Logical Compare 128bit // Logical Compare 128bit
void ptest(XMMRegister dst, XMMRegister src); void ptest(XMMRegister dst, XMMRegister src);
......
...@@ -2719,6 +2719,169 @@ class StubGenerator: public StubCodeGenerator { ...@@ -2719,6 +2719,169 @@ class StubGenerator: public StubCodeGenerator {
return start; return start;
} }
// byte swap x86 long
address generate_ghash_long_swap_mask() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
address start = __ pc();
__ emit_data(0x0b0a0908, relocInfo::none, 0);
__ emit_data(0x0f0e0d0c, relocInfo::none, 0);
__ emit_data(0x03020100, relocInfo::none, 0);
__ emit_data(0x07060504, relocInfo::none, 0);
return start;
}
// byte swap x86 byte array
address generate_ghash_byte_swap_mask() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
address start = __ pc();
__ emit_data(0x0c0d0e0f, relocInfo::none, 0);
__ emit_data(0x08090a0b, relocInfo::none, 0);
__ emit_data(0x04050607, relocInfo::none, 0);
__ emit_data(0x00010203, relocInfo::none, 0);
return start;
}
/* Single and multi-block ghash operations */
address generate_ghash_processBlocks() {
assert(UseGHASHIntrinsics, "need GHASH intrinsics and CLMUL support");
__ align(CodeEntryAlignment);
Label L_ghash_loop, L_exit;
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
address start = __ pc();
const Register state = rdi;
const Register subkeyH = rsi;
const Register data = rdx;
const Register blocks = rcx;
const Address state_param(rbp, 8+0);
const Address subkeyH_param(rbp, 8+4);
const Address data_param(rbp, 8+8);
const Address blocks_param(rbp, 8+12);
const XMMRegister xmm_temp0 = xmm0;
const XMMRegister xmm_temp1 = xmm1;
const XMMRegister xmm_temp2 = xmm2;
const XMMRegister xmm_temp3 = xmm3;
const XMMRegister xmm_temp4 = xmm4;
const XMMRegister xmm_temp5 = xmm5;
const XMMRegister xmm_temp6 = xmm6;
const XMMRegister xmm_temp7 = xmm7;
__ enter();
handleSOERegisters(true); // Save registers
__ movptr(state, state_param);
__ movptr(subkeyH, subkeyH_param);
__ movptr(data, data_param);
__ movptr(blocks, blocks_param);
__ movdqu(xmm_temp0, Address(state, 0));
__ pshufb(xmm_temp0, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
__ movdqu(xmm_temp1, Address(subkeyH, 0));
__ pshufb(xmm_temp1, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
__ BIND(L_ghash_loop);
__ movdqu(xmm_temp2, Address(data, 0));
__ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
__ pxor(xmm_temp0, xmm_temp2);
//
// Multiply with the hash key
//
__ movdqu(xmm_temp3, xmm_temp0);
__ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
__ movdqu(xmm_temp4, xmm_temp0);
__ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
__ movdqu(xmm_temp5, xmm_temp0);
__ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
__ movdqu(xmm_temp6, xmm_temp0);
__ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
__ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
__ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
__ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
__ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
__ pxor(xmm_temp3, xmm_temp5);
__ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
// of the carry-less multiplication of
// xmm0 by xmm1.
// We shift the result of the multiplication by one bit position
// to the left to cope for the fact that the bits are reversed.
__ movdqu(xmm_temp7, xmm_temp3);
__ movdqu(xmm_temp4, xmm_temp6);
__ pslld (xmm_temp3, 1);
__ pslld(xmm_temp6, 1);
__ psrld(xmm_temp7, 31);
__ psrld(xmm_temp4, 31);
__ movdqu(xmm_temp5, xmm_temp7);
__ pslldq(xmm_temp4, 4);
__ pslldq(xmm_temp7, 4);
__ psrldq(xmm_temp5, 12);
__ por(xmm_temp3, xmm_temp7);
__ por(xmm_temp6, xmm_temp4);
__ por(xmm_temp6, xmm_temp5);
//
// First phase of the reduction
//
// Move xmm3 into xmm4, xmm5, xmm7 in order to perform the shifts
// independently.
__ movdqu(xmm_temp7, xmm_temp3);
__ movdqu(xmm_temp4, xmm_temp3);
__ movdqu(xmm_temp5, xmm_temp3);
__ pslld(xmm_temp7, 31); // packed right shift shifting << 31
__ pslld(xmm_temp4, 30); // packed right shift shifting << 30
__ pslld(xmm_temp5, 25); // packed right shift shifting << 25
__ pxor(xmm_temp7, xmm_temp4); // xor the shifted versions
__ pxor(xmm_temp7, xmm_temp5);
__ movdqu(xmm_temp4, xmm_temp7);
__ pslldq(xmm_temp7, 12);
__ psrldq(xmm_temp4, 4);
__ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
//
// Second phase of the reduction
//
// Make 3 copies of xmm3 in xmm2, xmm5, xmm7 for doing these
// shift operations.
__ movdqu(xmm_temp2, xmm_temp3);
__ movdqu(xmm_temp7, xmm_temp3);
__ movdqu(xmm_temp5, xmm_temp3);
__ psrld(xmm_temp2, 1); // packed left shifting >> 1
__ psrld(xmm_temp7, 2); // packed left shifting >> 2
__ psrld(xmm_temp5, 7); // packed left shifting >> 7
__ pxor(xmm_temp2, xmm_temp7); // xor the shifted versions
__ pxor(xmm_temp2, xmm_temp5);
__ pxor(xmm_temp2, xmm_temp4);
__ pxor(xmm_temp3, xmm_temp2);
__ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
__ decrement(blocks);
__ jcc(Assembler::zero, L_exit);
__ movdqu(xmm_temp0, xmm_temp6);
__ addptr(data, 16);
__ jmp(L_ghash_loop);
__ BIND(L_exit);
// Byte swap 16-byte result
__ pshufb(xmm_temp6, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
__ movdqu(Address(state, 0), xmm_temp6); // store the result
handleSOERegisters(false); // restore registers
__ leave();
__ ret(0);
return start;
}
/** /**
* Arguments: * Arguments:
* *
...@@ -3018,6 +3181,13 @@ class StubGenerator: public StubCodeGenerator { ...@@ -3018,6 +3181,13 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt(); 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. // Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc, &StubRoutines::_safefetch32_fault_pc,
......
...@@ -3639,6 +3639,175 @@ class StubGenerator: public StubCodeGenerator { ...@@ -3639,6 +3639,175 @@ class StubGenerator: public StubCodeGenerator {
return start; return start;
} }
// byte swap x86 long
address generate_ghash_long_swap_mask() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "ghash_long_swap_mask");
address start = __ pc();
__ emit_data64(0x0f0e0d0c0b0a0908, relocInfo::none );
__ emit_data64(0x0706050403020100, relocInfo::none );
return start;
}
// byte swap x86 byte array
address generate_ghash_byte_swap_mask() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "ghash_byte_swap_mask");
address start = __ pc();
__ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none );
__ emit_data64(0x0001020304050607, relocInfo::none );
return start;
}
/* Single and multi-block ghash operations */
address generate_ghash_processBlocks() {
__ align(CodeEntryAlignment);
Label L_ghash_loop, L_exit;
StubCodeMark mark(this, "StubRoutines", "ghash_processBlocks");
address start = __ pc();
const Register state = c_rarg0;
const Register subkeyH = c_rarg1;
const Register data = c_rarg2;
const Register blocks = c_rarg3;
#ifdef _WIN64
const int XMM_REG_LAST = 10;
#endif
const XMMRegister xmm_temp0 = xmm0;
const XMMRegister xmm_temp1 = xmm1;
const XMMRegister xmm_temp2 = xmm2;
const XMMRegister xmm_temp3 = xmm3;
const XMMRegister xmm_temp4 = xmm4;
const XMMRegister xmm_temp5 = xmm5;
const XMMRegister xmm_temp6 = xmm6;
const XMMRegister xmm_temp7 = xmm7;
const XMMRegister xmm_temp8 = xmm8;
const XMMRegister xmm_temp9 = xmm9;
const XMMRegister xmm_temp10 = xmm10;
__ enter();
#ifdef _WIN64
// save the xmm registers which must be preserved 6-10
__ subptr(rsp, -rsp_after_call_off * wordSize);
for (int i = 6; i <= XMM_REG_LAST; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
#endif
__ movdqu(xmm_temp10, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr()));
__ movdqu(xmm_temp0, Address(state, 0));
__ pshufb(xmm_temp0, xmm_temp10);
__ BIND(L_ghash_loop);
__ movdqu(xmm_temp2, Address(data, 0));
__ pshufb(xmm_temp2, ExternalAddress(StubRoutines::x86::ghash_byte_swap_mask_addr()));
__ movdqu(xmm_temp1, Address(subkeyH, 0));
__ pshufb(xmm_temp1, xmm_temp10);
__ pxor(xmm_temp0, xmm_temp2);
//
// Multiply with the hash key
//
__ movdqu(xmm_temp3, xmm_temp0);
__ pclmulqdq(xmm_temp3, xmm_temp1, 0); // xmm3 holds a0*b0
__ movdqu(xmm_temp4, xmm_temp0);
__ pclmulqdq(xmm_temp4, xmm_temp1, 16); // xmm4 holds a0*b1
__ movdqu(xmm_temp5, xmm_temp0);
__ pclmulqdq(xmm_temp5, xmm_temp1, 1); // xmm5 holds a1*b0
__ movdqu(xmm_temp6, xmm_temp0);
__ pclmulqdq(xmm_temp6, xmm_temp1, 17); // xmm6 holds a1*b1
__ pxor(xmm_temp4, xmm_temp5); // xmm4 holds a0*b1 + a1*b0
__ movdqu(xmm_temp5, xmm_temp4); // move the contents of xmm4 to xmm5
__ psrldq(xmm_temp4, 8); // shift by xmm4 64 bits to the right
__ pslldq(xmm_temp5, 8); // shift by xmm5 64 bits to the left
__ pxor(xmm_temp3, xmm_temp5);
__ pxor(xmm_temp6, xmm_temp4); // Register pair <xmm6:xmm3> holds the result
// of the carry-less multiplication of
// xmm0 by xmm1.
// We shift the result of the multiplication by one bit position
// to the left to cope for the fact that the bits are reversed.
__ movdqu(xmm_temp7, xmm_temp3);
__ movdqu(xmm_temp8, xmm_temp6);
__ pslld(xmm_temp3, 1);
__ pslld(xmm_temp6, 1);
__ psrld(xmm_temp7, 31);
__ psrld(xmm_temp8, 31);
__ movdqu(xmm_temp9, xmm_temp7);
__ pslldq(xmm_temp8, 4);
__ pslldq(xmm_temp7, 4);
__ psrldq(xmm_temp9, 12);
__ por(xmm_temp3, xmm_temp7);
__ por(xmm_temp6, xmm_temp8);
__ por(xmm_temp6, xmm_temp9);
//
// First phase of the reduction
//
// Move xmm3 into xmm7, xmm8, xmm9 in order to perform the shifts
// independently.
__ movdqu(xmm_temp7, xmm_temp3);
__ movdqu(xmm_temp8, xmm_temp3);
__ movdqu(xmm_temp9, xmm_temp3);
__ pslld(xmm_temp7, 31); // packed right shift shifting << 31
__ pslld(xmm_temp8, 30); // packed right shift shifting << 30
__ pslld(xmm_temp9, 25); // packed right shift shifting << 25
__ pxor(xmm_temp7, xmm_temp8); // xor the shifted versions
__ pxor(xmm_temp7, xmm_temp9);
__ movdqu(xmm_temp8, xmm_temp7);
__ pslldq(xmm_temp7, 12);
__ psrldq(xmm_temp8, 4);
__ pxor(xmm_temp3, xmm_temp7); // first phase of the reduction complete
//
// Second phase of the reduction
//
// Make 3 copies of xmm3 in xmm2, xmm4, xmm5 for doing these
// shift operations.
__ movdqu(xmm_temp2, xmm_temp3);
__ movdqu(xmm_temp4, xmm_temp3);
__ movdqu(xmm_temp5, xmm_temp3);
__ psrld(xmm_temp2, 1); // packed left shifting >> 1
__ psrld(xmm_temp4, 2); // packed left shifting >> 2
__ psrld(xmm_temp5, 7); // packed left shifting >> 7
__ pxor(xmm_temp2, xmm_temp4); // xor the shifted versions
__ pxor(xmm_temp2, xmm_temp5);
__ pxor(xmm_temp2, xmm_temp8);
__ pxor(xmm_temp3, xmm_temp2);
__ pxor(xmm_temp6, xmm_temp3); // the result is in xmm6
__ decrement(blocks);
__ jcc(Assembler::zero, L_exit);
__ movdqu(xmm_temp0, xmm_temp6);
__ addptr(data, 16);
__ jmp(L_ghash_loop);
__ BIND(L_exit);
__ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result
__ movdqu(Address(state, 0), xmm_temp6); // store the result
#ifdef _WIN64
// restore xmm regs belonging to calling function
for (int i = 6; i <= XMM_REG_LAST; i++) {
__ movdqu(as_XMMRegister(i), xmm_save(i));
}
#endif
__ leave();
__ ret(0);
return start;
}
/** /**
* Arguments: * Arguments:
* *
...@@ -4077,6 +4246,13 @@ class StubGenerator: public StubCodeGenerator { ...@@ -4077,6 +4246,13 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel(); 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. // Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc, &StubRoutines::_safefetch32_fault_pc,
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
address StubRoutines::x86::_verify_mxcsr_entry = NULL; address StubRoutines::x86::_verify_mxcsr_entry = NULL;
address StubRoutines::x86::_key_shuffle_mask_addr = 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[] = uint64_t StubRoutines::x86::_crc_by128_masks[] =
{ {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -36,10 +36,15 @@ ...@@ -36,10 +36,15 @@
// masks and table for CRC32 // masks and table for CRC32
static uint64_t _crc_by128_masks[]; static uint64_t _crc_by128_masks[];
static juint _crc_table[]; static juint _crc_table[];
// swap mask for ghash
static address _ghash_long_swap_mask_addr;
static address _ghash_byte_swap_mask_addr;
public: public:
static address verify_mxcsr_entry() { return _verify_mxcsr_entry; } static address verify_mxcsr_entry() { return _verify_mxcsr_entry; }
static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; } static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; }
static address crc_by128_masks_addr() { return (address)_crc_by128_masks; } 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 #endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
...@@ -553,13 +553,37 @@ void VM_Version::get_processor_features() { ...@@ -553,13 +553,37 @@ void VM_Version::get_processor_features() {
// Use AES instructions if available. // Use AES instructions if available.
if (supports_aes()) { if (supports_aes()) {
if (FLAG_IS_DEFAULT(UseAES)) { if (FLAG_IS_DEFAULT(UseAES)) {
UseAES = true; FLAG_SET_DEFAULT(UseAES, true);
} }
} else if (UseAES) { if (!UseAES) {
if (!FLAG_IS_DEFAULT(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"); 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. // Use CLMUL instructions if available.
if (supports_clmul()) { if (supports_clmul()) {
...@@ -582,16 +606,15 @@ void VM_Version::get_processor_features() { ...@@ -582,16 +606,15 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
} }
// The AES intrinsic stubs require AES instruction support (of course) // GHASH/GCM intrinsics
// but also require sse3 mode for instructions it use. if (UseCLMUL && (UseSSE > 2)) {
if (UseAES && (UseSSE > 2)) { if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) { UseGHASHIntrinsics = true;
UseAESIntrinsics = true;
} }
} else if (UseAESIntrinsics) { } else if (UseGHASHIntrinsics) {
if (!FLAG_IS_DEFAULT(UseAESIntrinsics)) if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
warning("AES intrinsics are not available on this CPU"); warning("GHASH intrinsic requires CLMUL and SSE2 instructions on this CPU");
FLAG_SET_DEFAULT(UseAESIntrinsics, false); FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
} }
if (UseSHA) { if (UseSHA) {
......
...@@ -2112,8 +2112,14 @@ void LIR_OpProfileCall::print_instr(outputStream* out) const { ...@@ -2112,8 +2112,14 @@ void LIR_OpProfileCall::print_instr(outputStream* out) const {
// LIR_OpProfileType // LIR_OpProfileType
void LIR_OpProfileType::print_instr(outputStream* out) const { void LIR_OpProfileType::print_instr(outputStream* out) const {
out->print("exact = "); exact_klass()->print_name_on(out); out->print("exact = ");
out->print("current = "); ciTypeEntries::print_ciklass(out, current_klass()); if (exact_klass() == NULL) {
out->print("unknown");
} else {
exact_klass()->print_name_on(out);
}
out->print(" current = "); ciTypeEntries::print_ciklass(out, current_klass());
out->print(" ");
mdp()->print(out); out->print(" "); mdp()->print(out); out->print(" ");
obj()->print(out); out->print(" "); obj()->print(out); out->print(" ");
tmp()->print(out); out->print(" "); tmp()->print(out); out->print(" ");
......
...@@ -881,6 +881,12 @@ ...@@ -881,6 +881,12 @@
do_name( implCompressMB_name, "implCompressMultiBlock0") \ do_name( implCompressMB_name, "implCompressMultiBlock0") \
do_signature(implCompressMB_signature, "([BII)I") \ 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 */ \ /* support for java.util.zip */ \
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \ do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
......
...@@ -161,6 +161,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, ...@@ -161,6 +161,8 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs,
} }
_dictionary->set_par_lock(&_parDictionaryAllocLock); _dictionary->set_par_lock(&_parDictionaryAllocLock);
} }
_used_stable = 0;
} }
// Like CompactibleSpace forward() but always calls cross_threshold() to // Like CompactibleSpace forward() but always calls cross_threshold() to
...@@ -377,6 +379,14 @@ size_t CompactibleFreeListSpace::used() const { ...@@ -377,6 +379,14 @@ size_t CompactibleFreeListSpace::used() const {
return capacity() - free(); 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 { size_t CompactibleFreeListSpace::free() const {
// "MT-safe, but not MT-precise"(TM), if you will: i.e. // "MT-safe, but not MT-precise"(TM), if you will: i.e.
// if you do this while the structures are in flux you // if you do this while the structures are in flux you
...@@ -1218,6 +1228,13 @@ HeapWord* CompactibleFreeListSpace::allocate(size_t size) { ...@@ -1218,6 +1228,13 @@ HeapWord* CompactibleFreeListSpace::allocate(size_t size) {
debug_only(fc->mangleAllocated(size)); debug_only(fc->mangleAllocated(size));
} }
// During GC we do not need to recalculate the stable used value for
// every allocation in old gen. It is done once at the end of GC instead
// for performance reasons.
if (!Universe::heap()->is_gc_active()) {
recalculate_used_stable();
}
return res; return res;
} }
......
...@@ -148,6 +148,9 @@ class CompactibleFreeListSpace: public CompactibleSpace { ...@@ -148,6 +148,9 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// Used to keep track of limit of sweep for the space // Used to keep track of limit of sweep for the space
HeapWord* _sweep_limit; HeapWord* _sweep_limit;
// Stable value of used().
size_t _used_stable;
// Support for compacting cms // Support for compacting cms
HeapWord* cross_threshold(HeapWord* start, HeapWord* end); HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top);
...@@ -343,6 +346,17 @@ class CompactibleFreeListSpace: public CompactibleSpace { ...@@ -343,6 +346,17 @@ class CompactibleFreeListSpace: public CompactibleSpace {
// which overestimates the region by returning the entire // which overestimates the region by returning the entire
// committed region (this is safe, but inefficient). // 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 // Returns a subregion of the space containing all the objects in
// the space. // the space.
MemRegion used_region() const { MemRegion used_region() const {
......
...@@ -869,6 +869,10 @@ ConcurrentMarkSweepGeneration::unsafe_max_alloc_nogc() const { ...@@ -869,6 +869,10 @@ ConcurrentMarkSweepGeneration::unsafe_max_alloc_nogc() const {
return _cmsSpace->max_alloc_in_words() * HeapWordSize; return _cmsSpace->max_alloc_in_words() * HeapWordSize;
} }
size_t ConcurrentMarkSweepGeneration::used_stable() const {
return cmsSpace()->used_stable();
}
size_t ConcurrentMarkSweepGeneration::max_available() const { size_t ConcurrentMarkSweepGeneration::max_available() const {
return free() + _virtual_space.uncommitted_size(); return free() + _virtual_space.uncommitted_size();
} }
...@@ -1955,6 +1959,8 @@ void CMSCollector::compute_new_size() { ...@@ -1955,6 +1959,8 @@ void CMSCollector::compute_new_size() {
FreelistLocker z(this); FreelistLocker z(this);
MetaspaceGC::compute_new_size(); MetaspaceGC::compute_new_size();
_cmsGen->compute_new_size_free_list(); _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 // A work method used by foreground collection to determine
...@@ -2768,6 +2774,7 @@ void ConcurrentMarkSweepGeneration::gc_prologue(bool full) { ...@@ -2768,6 +2774,7 @@ void ConcurrentMarkSweepGeneration::gc_prologue(bool full) {
_capacity_at_prologue = capacity(); _capacity_at_prologue = capacity();
_used_at_prologue = used(); _used_at_prologue = used();
_cmsSpace->recalculate_used_stable();
// Delegate to CMScollector which knows how to coordinate between // Delegate to CMScollector which knows how to coordinate between
// this and any other CMS generations that it is responsible for // this and any other CMS generations that it is responsible for
...@@ -2837,6 +2844,7 @@ void CMSCollector::gc_epilogue(bool full) { ...@@ -2837,6 +2844,7 @@ void CMSCollector::gc_epilogue(bool full) {
_eden_chunk_index = 0; _eden_chunk_index = 0;
size_t cms_used = _cmsGen->cmsSpace()->used(); size_t cms_used = _cmsGen->cmsSpace()->used();
_cmsGen->cmsSpace()->recalculate_used_stable();
// update performance counters - this uses a special version of // update performance counters - this uses a special version of
// update_counters() that allows the utilization to be passed as a // update_counters() that allows the utilization to be passed as a
...@@ -3684,6 +3692,7 @@ void CMSCollector::checkpointRootsInitial(bool asynch) { ...@@ -3684,6 +3692,7 @@ void CMSCollector::checkpointRootsInitial(bool asynch) {
_collectorState = Marking; _collectorState = Marking;
} }
SpecializationStats::print(); SpecializationStats::print();
_cmsGen->cmsSpace()->recalculate_used_stable();
} }
void CMSCollector::checkpointRootsInitialWork(bool asynch) { void CMSCollector::checkpointRootsInitialWork(bool asynch) {
...@@ -5089,10 +5098,12 @@ void CMSCollector::checkpointRootsFinal(bool asynch, ...@@ -5089,10 +5098,12 @@ void CMSCollector::checkpointRootsFinal(bool asynch,
Mutex::_no_safepoint_check_flag); Mutex::_no_safepoint_check_flag);
assert(!init_mark_was_synchronous, "but that's impossible!"); assert(!init_mark_was_synchronous, "but that's impossible!");
checkpointRootsFinalWork(asynch, clear_all_soft_refs, false); checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);
_cmsGen->cmsSpace()->recalculate_used_stable();
} else { } else {
// already have all the locks // already have all the locks
checkpointRootsFinalWork(asynch, clear_all_soft_refs, checkpointRootsFinalWork(asynch, clear_all_soft_refs,
init_mark_was_synchronous); init_mark_was_synchronous);
_cmsGen->cmsSpace()->recalculate_used_stable();
} }
verify_work_stacks_empty(); verify_work_stacks_empty();
verify_overflow_empty(); verify_overflow_empty();
...@@ -6413,6 +6424,10 @@ void CMSCollector::sweep(bool asynch) { ...@@ -6413,6 +6424,10 @@ void CMSCollector::sweep(bool asynch) {
// Update heap occupancy information which is used as // Update heap occupancy information which is used as
// input to soft ref clearing policy at the next gc. // input to soft ref clearing policy at the next gc.
Universe::update_heap_info_at_gc(); Universe::update_heap_info_at_gc();
// recalculate CMS used space after CMS collection
_cmsGen->cmsSpace()->recalculate_used_stable();
_collectorState = Resizing; _collectorState = Resizing;
} }
} else { } else {
...@@ -6512,6 +6527,7 @@ void ConcurrentMarkSweepGeneration::update_gc_stats(int current_level, ...@@ -6512,6 +6527,7 @@ void ConcurrentMarkSweepGeneration::update_gc_stats(int current_level,
// Gather statistics on the young generation collection. // Gather statistics on the young generation collection.
collector()->stats().record_gc0_end(used()); collector()->stats().record_gc0_end(used());
} }
_cmsSpace->recalculate_used_stable();
} }
CMSAdaptiveSizePolicy* ConcurrentMarkSweepGeneration::size_policy() { CMSAdaptiveSizePolicy* ConcurrentMarkSweepGeneration::size_policy() {
......
...@@ -1190,6 +1190,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { ...@@ -1190,6 +1190,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
double occupancy() const { return ((double)used())/((double)capacity()); } double occupancy() const { return ((double)used())/((double)capacity()); }
size_t contiguous_available() const; size_t contiguous_available() const;
size_t unsafe_max_alloc_nogc() const; size_t unsafe_max_alloc_nogc() const;
size_t used_stable() const;
// over-rides // over-rides
MemRegion used_region() const; MemRegion used_region() const;
......
...@@ -2591,6 +2591,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) { ...@@ -2591,6 +2591,12 @@ void G1CollectedHeap::collect(GCCause::Cause cause) {
} }
} }
} }
} else if (GC_locker::should_discard(cause, gc_count_before)) {
// Return to be consistent with VMOp failure due to another
// collection slipping in after our gc_count but before our
// request is processed. _gc_locker collections upgraded by
// GCLockerInvokesConcurrent are handled above and never discarded.
return;
} else { } else {
if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc
|| cause == GCCause::_g1_elastic_heap_trigger_gc || cause == GCCause::_g1_elastic_heap_trigger_gc
......
...@@ -387,7 +387,7 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size( ...@@ -387,7 +387,7 @@ G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(
MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes), MAX2((uint) (MaxNewSize / HeapRegion::GrainBytes),
1U); 1U);
_sizer_kind = SizerMaxAndNewSize; _sizer_kind = SizerMaxAndNewSize;
_adaptive_size = _min_desired_young_length == _max_desired_young_length; _adaptive_size = _min_desired_young_length != _max_desired_young_length;
} else { } else {
_sizer_kind = SizerNewSizeOnly; _sizer_kind = SizerNewSizeOnly;
} }
......
...@@ -135,7 +135,11 @@ private: ...@@ -135,7 +135,11 @@ private:
SizerKind _sizer_kind; SizerKind _sizer_kind;
uint _min_desired_young_length; uint _min_desired_young_length;
uint _max_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; bool _adaptive_size;
uint calculate_default_min_length(uint new_number_of_heap_regions); uint calculate_default_min_length(uint new_number_of_heap_regions);
uint calculate_default_max_length(uint new_number_of_heap_regions); uint calculate_default_max_length(uint new_number_of_heap_regions);
......
...@@ -530,6 +530,10 @@ void ParallelScavengeHeap::collect(GCCause::Cause cause) { ...@@ -530,6 +530,10 @@ void ParallelScavengeHeap::collect(GCCause::Cause cause) {
full_gc_count = Universe::heap()->total_full_collections(); 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); VM_ParallelGCSystemGC op(gc_count, full_gc_count, cause);
VMThread::execute(&op); VMThread::execute(&op);
} }
......
...@@ -52,11 +52,16 @@ void VM_ParallelGCFailedAllocation::doit() { ...@@ -52,11 +52,16 @@ void VM_ParallelGCFailedAllocation::doit() {
} }
} }
static bool is_cause_full(GCCause::Cause cause) {
return (cause != GCCause::_gc_locker) && (cause != GCCause::_wb_young_gc)
DEBUG_ONLY(&& (cause != GCCause::_scavenge_alot));
}
// Only used for System.gc() calls // Only used for System.gc() calls
VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(uint gc_count, VM_ParallelGCSystemGC::VM_ParallelGCSystemGC(uint gc_count,
uint full_gc_count, uint full_gc_count,
GCCause::Cause gc_cause) : GCCause::Cause gc_cause) :
VM_GC_Operation(gc_count, gc_cause, full_gc_count, true /* full */) VM_GC_Operation(gc_count, gc_cause, full_gc_count, is_cause_full(gc_cause))
{ {
} }
...@@ -68,8 +73,7 @@ void VM_ParallelGCSystemGC::doit() { ...@@ -68,8 +73,7 @@ void VM_ParallelGCSystemGC::doit() {
"must be a ParallelScavengeHeap"); "must be a ParallelScavengeHeap");
GCCauseSetter gccs(heap, _gc_cause); GCCauseSetter gccs(heap, _gc_cause);
if (_gc_cause == GCCause::_gc_locker || _gc_cause == GCCause::_wb_young_gc if (!_full) {
DEBUG_ONLY(|| _gc_cause == GCCause::_scavenge_alot)) {
// If (and only if) the scavenge fails, this will invoke a full gc. // If (and only if) the scavenge fails, this will invoke a full gc.
heap->invoke_scavenge(); heap->invoke_scavenge();
} else { } else {
......
...@@ -63,7 +63,7 @@ class GSpaceCounters: public CHeapObj<mtGC> { ...@@ -63,7 +63,7 @@ class GSpaceCounters: public CHeapObj<mtGC> {
} }
inline void update_used() { 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 // special version of update_used() to allow the used value to be
...@@ -107,7 +107,7 @@ class GenerationUsedHelper : public PerfLongSampleHelper { ...@@ -107,7 +107,7 @@ class GenerationUsedHelper : public PerfLongSampleHelper {
GenerationUsedHelper(Generation* g) : _gen(g) { } GenerationUsedHelper(Generation* g) : _gen(g) { }
inline jlong take_sample() { inline jlong take_sample() {
return _gen->used(); return _gen->used_stable();
} }
}; };
......
...@@ -201,6 +201,19 @@ void VM_GenCollectForAllocation::doit() { ...@@ -201,6 +201,19 @@ void VM_GenCollectForAllocation::doit() {
} }
} }
static bool is_full_gc(int max_level) {
// Return true if max_level is all generations
return (max_level == (GenCollectedHeap::heap()->n_gens() - 1));
}
VM_GenCollectFull::VM_GenCollectFull(uint gc_count_before,
uint full_gc_count_before,
GCCause::Cause gc_cause,
int max_level) :
VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before,
is_full_gc(max_level) /* full */),
_max_level(max_level) { }
void VM_GenCollectFull::doit() { void VM_GenCollectFull::doit() {
SvcGCMarker sgcm(SvcGCMarker::FULL); SvcGCMarker sgcm(SvcGCMarker::FULL);
......
...@@ -201,9 +201,7 @@ class VM_GenCollectFull: public VM_GC_Operation { ...@@ -201,9 +201,7 @@ class VM_GenCollectFull: public VM_GC_Operation {
VM_GenCollectFull(uint gc_count_before, VM_GenCollectFull(uint gc_count_before,
uint full_gc_count_before, uint full_gc_count_before,
GCCause::Cause gc_cause, GCCause::Cause gc_cause,
int max_level) int max_level);
: VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),
_max_level(max_level) { }
~VM_GenCollectFull() {} ~VM_GenCollectFull() {}
virtual VMOp_Type type() const { return VMOp_GenCollectFull; } virtual VMOp_Type type() const { return VMOp_GenCollectFull; }
virtual void doit(); virtual void doit();
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
volatile jint GC_locker::_jni_lock_count = 0; volatile jint GC_locker::_jni_lock_count = 0;
volatile bool GC_locker::_needs_gc = false; volatile bool GC_locker::_needs_gc = false;
volatile bool GC_locker::_doing_gc = false; volatile bool GC_locker::_doing_gc = false;
unsigned int GC_locker::_total_collections = 0;
#ifdef ASSERT #ifdef ASSERT
volatile jint GC_locker::_debug_jni_lock_count = 0; volatile jint GC_locker::_debug_jni_lock_count = 0;
...@@ -94,6 +95,11 @@ void GC_locker::stall_until_clear() { ...@@ -94,6 +95,11 @@ void GC_locker::stall_until_clear() {
} }
} }
bool GC_locker::should_discard(GCCause::Cause cause, uint total_collections) {
return (cause == GCCause::_gc_locker) &&
(_total_collections != total_collections);
}
void GC_locker::jni_lock(JavaThread* thread) { void GC_locker::jni_lock(JavaThread* thread) {
assert(!thread->in_critical(), "shouldn't currently be in a critical region"); assert(!thread->in_critical(), "shouldn't currently be in a critical region");
MutexLocker mu(JNICritical_lock); MutexLocker mu(JNICritical_lock);
...@@ -117,7 +123,13 @@ void GC_locker::jni_unlock(JavaThread* thread) { ...@@ -117,7 +123,13 @@ void GC_locker::jni_unlock(JavaThread* thread) {
decrement_debug_jni_lock_count(); decrement_debug_jni_lock_count();
thread->exit_critical(); thread->exit_critical();
if (needs_gc() && !is_active_internal()) { 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; _doing_gc = true;
{ {
// Must give up the lock while at a safepoint // Must give up the lock while at a safepoint
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define SHARE_VM_MEMORY_GCLOCKER_HPP #define SHARE_VM_MEMORY_GCLOCKER_HPP
#include "gc_interface/collectedHeap.hpp" #include "gc_interface/collectedHeap.hpp"
#include "gc_interface/gcCause.hpp"
#include "memory/genCollectedHeap.hpp" #include "memory/genCollectedHeap.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/oop.hpp" #include "oops/oop.hpp"
...@@ -57,6 +58,7 @@ class GC_locker: public AllStatic { ...@@ -57,6 +58,7 @@ class GC_locker: public AllStatic {
static volatile bool _needs_gc; // heap is filling, we need a GC static volatile bool _needs_gc; // heap is filling, we need a GC
// note: bool is typedef'd as jint // note: bool is typedef'd as jint
static volatile bool _doing_gc; // unlock_critical() is doing a GC static volatile bool _doing_gc; // unlock_critical() is doing a GC
static uint _total_collections; // value for _gc_locker collection
#ifdef ASSERT #ifdef ASSERT
// This lock count is updated for all operations and is used to // This lock count is updated for all operations and is used to
...@@ -116,6 +118,12 @@ class GC_locker: public AllStatic { ...@@ -116,6 +118,12 @@ class GC_locker: public AllStatic {
// Sets _needs_gc if is_active() is true. Returns is_active(). // Sets _needs_gc if is_active() is true. Returns is_active().
static bool check_active_before_gc(); 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) // Stalls the caller (who should not be in a jni critical section)
// until needs_gc() clears. Note however that needs_gc() may be // until needs_gc() clears. Note however that needs_gc() may be
// set at a subsequent safepoint and/or cleared under the // set at a subsequent safepoint and/or cleared under the
......
...@@ -850,8 +850,11 @@ void GenCollectedHeap::collect(GCCause::Cause cause) { ...@@ -850,8 +850,11 @@ void GenCollectedHeap::collect(GCCause::Cause cause) {
#else // INCLUDE_ALL_GCS #else // INCLUDE_ALL_GCS
ShouldNotReachHere(); ShouldNotReachHere();
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
} else if (cause == GCCause::_wb_young_gc) { } else if ((cause == GCCause::_wb_young_gc) ||
// minor collection for WhiteBox API (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); collect(cause, 0);
} else { } else {
#ifdef ASSERT #ifdef ASSERT
...@@ -889,6 +892,11 @@ void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) { ...@@ -889,6 +892,11 @@ void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {
// Read the GC count while holding the Heap_lock // Read the GC count while holding the Heap_lock
unsigned int gc_count_before = total_collections(); unsigned int gc_count_before = total_collections();
unsigned int full_gc_count_before = total_full_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 MutexUnlocker mu(Heap_lock); // give up heap lock, execute gets it back
VM_GenCollectFull op(gc_count_before, full_gc_count_before, VM_GenCollectFull op(gc_count_before, full_gc_count_before,
...@@ -941,24 +949,16 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { ...@@ -941,24 +949,16 @@ void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs, void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,
int max_level) { 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 */, do_collection(true /* full */,
clear_all_soft_refs /* clear_all_soft_refs */, clear_all_soft_refs /* clear_all_soft_refs */,
0 /* size */, 0 /* size */,
false /* is_tlab */, false /* is_tlab */,
local_max_level /* max_level */); max_level /* max_level */);
// Hack XXX FIX ME !!! // Hack XXX FIX ME !!!
// A scavenge may not have been attempted, or may have // A scavenge may not have been attempted, or may have
// been attempted and failed, because the old gen was too full // been attempted and failed, because the old gen was too full
if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker && if (gc_cause() == GCCause::_gc_locker && incremental_collection_failed()) {
incremental_collection_will_fail(false /* don't consult_young */)) {
if (PrintGCDetails) { if (PrintGCDetails) {
gclog_or_tty->print_cr("GC locker: Trying a full collection " gclog_or_tty->print_cr("GC locker: Trying a full collection "
"because scavenge failed"); "because scavenge failed");
......
...@@ -68,6 +68,12 @@ GenerationSpec* Generation::spec() { ...@@ -68,6 +68,12 @@ GenerationSpec* Generation::spec() {
return gch->_gen_specs[level()]; 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 { size_t Generation::max_capacity() const {
return reserved().byte_size(); return reserved().byte_size();
} }
......
...@@ -168,6 +168,7 @@ class Generation: public CHeapObj<mtGC> { ...@@ -168,6 +168,7 @@ class Generation: public CHeapObj<mtGC> {
virtual size_t capacity() const = 0; // The maximum number of object bytes the virtual size_t capacity() const = 0; // The maximum number of object bytes the
// generation can currently hold. // generation can currently hold.
virtual size_t used() const = 0; // The number of used bytes in the gen. 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. virtual size_t free() const = 0; // The number of free bytes in the gen.
// Support for java.lang.Runtime.maxMemory(); see CollectedHeap. // Support for java.lang.Runtime.maxMemory(); see CollectedHeap.
......
...@@ -295,6 +295,7 @@ InstanceKlass::InstanceKlass(int vtable_len, ...@@ -295,6 +295,7 @@ InstanceKlass::InstanceKlass(int vtable_len,
set_has_unloaded_dependent(false); set_has_unloaded_dependent(false);
set_init_state(InstanceKlass::allocated); set_init_state(InstanceKlass::allocated);
set_init_thread(NULL); set_init_thread(NULL);
set_init_state(allocated);
set_reference_type(rt); set_reference_type(rt);
set_oop_map_cache(NULL); set_oop_map_cache(NULL);
set_jni_ids(NULL); set_jni_ids(NULL);
...@@ -997,11 +998,13 @@ void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle ...@@ -997,11 +998,13 @@ void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle
oop init_lock = this_oop->init_lock(); oop init_lock = this_oop->init_lock();
if (init_lock != NULL) { if (init_lock != NULL) {
ObjectLocker ol(init_lock, THREAD); 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->set_init_state(state);
this_oop->fence_and_clear_init_lock(); this_oop->fence_and_clear_init_lock();
ol.notify_all(CHECK); ol.notify_all(CHECK);
} else { } else {
assert(init_lock != NULL, "The initialization state should never be set twice"); 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); this_oop->set_init_state(state);
} }
} }
...@@ -3621,6 +3624,7 @@ void InstanceKlass::set_init_state(ClassState state) { ...@@ -3621,6 +3624,7 @@ void InstanceKlass::set_init_state(ClassState state) {
bool good_state = is_shared() ? (_init_state <= state) bool good_state = is_shared() ? (_init_state <= state)
: (_init_state < state); : (_init_state < state);
assert(good_state || state == allocated, "illegal state transition"); assert(good_state || state == allocated, "illegal state transition");
assert(_init_thread == NULL, "should be cleared before state change");
_init_state = (u1)state; _init_state = (u1)state;
} }
#endif #endif
......
...@@ -256,7 +256,7 @@ class InstanceKlass: public Klass { ...@@ -256,7 +256,7 @@ class InstanceKlass: public Klass {
u2 _misc_flags; u2 _misc_flags;
u2 _minor_version; // minor version number of class file u2 _minor_version; // minor version number of class file
u2 _major_version; // major 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 _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (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) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
......
...@@ -289,22 +289,25 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper ...@@ -289,22 +289,25 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper
int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) { int vtable_index, Handle target_loader, Symbol* target_classname, Thread * THREAD) {
InstanceKlass* superk = initialsuper; InstanceKlass* superk = initialsuper;
while (superk != NULL && superk->super() != NULL) { while (superk != NULL && superk->super() != NULL) {
InstanceKlass* supersuperklass = InstanceKlass::cast(superk->super()); klassVtable* ssVtable = (superk->super())->vtable();
klassVtable* ssVtable = supersuperklass->vtable();
if (vtable_index < ssVtable->length()) { if (vtable_index < ssVtable->length()) {
Method* super_method = ssVtable->method_at(vtable_index); 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 #ifndef PRODUCT
Symbol* name= target_method()->name(); Symbol* name= target_method()->name();
Symbol* signature = target_method()->signature(); Symbol* signature = target_method()->signature();
assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch"); assert(super_method->name() == name && super_method->signature() == signature, "vtable entry name/sig mismatch");
#endif #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 #ifndef PRODUCT
if (PrintVtables && Verbose) { if (PrintVtables && Verbose) {
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
char* sig = target_method()->name_and_sig_as_C_string(); char* sig = target_method()->name_and_sig_as_C_string();
tty->print("transitive overriding superclass %s with %s::%s index %d, original flags: ", 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); _klass->internal_name(), sig, vtable_index);
super_method->access_flags().print_on(tty); super_method->access_flags().print_on(tty);
if (super_method->is_default_method()) { if (super_method->is_default_method()) {
...@@ -656,7 +659,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method, ...@@ -656,7 +659,7 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method,
// search through the super class hierarchy to see if we need // search through the super class hierarchy to see if we need
// a new entry // a new entry
ResourceMark rm; ResourceMark rm(THREAD);
Symbol* name = target_method()->name(); Symbol* name = target_method()->name();
Symbol* signature = target_method()->signature(); Symbol* signature = target_method()->signature();
Klass* k = super; Klass* k = super;
......
...@@ -952,6 +952,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { ...@@ -952,6 +952,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 || strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 || strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 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_implCompress") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 || strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
...@@ -2114,6 +2115,9 @@ bool ConnectionGraph::not_global_escape(Node *n) { ...@@ -2114,6 +2115,9 @@ bool ConnectionGraph::not_global_escape(Node *n) {
return false; return false;
} }
PointsToNode* ptn = ptnode_adr(idx); PointsToNode* ptn = ptnode_adr(idx);
if (ptn == NULL) {
return false; // not in congraph (e.g. ConI)
}
PointsToNode::EscapeState es = ptn->escape_state(); PointsToNode::EscapeState es = ptn->escape_state();
// If we have already computed a value, return it. // If we have already computed a value, return it.
if (es >= PointsToNode::GlobalEscape) if (es >= PointsToNode::GlobalEscape)
......
...@@ -311,6 +311,7 @@ class LibraryCallKit : public GraphKit { ...@@ -311,6 +311,7 @@ class LibraryCallKit : public GraphKit {
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
Node* get_original_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_sha_implCompress(vmIntrinsics::ID id);
bool inline_digestBase_implCompressMB(int predicate); bool inline_digestBase_implCompressMB(int predicate);
bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA, bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA,
...@@ -570,6 +571,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { ...@@ -570,6 +571,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
predicates = 3; predicates = 3;
break; break;
case vmIntrinsics::_ghash_processBlocks:
if (!UseGHASHIntrinsics) return NULL;
break;
case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateCRC32:
case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateBytesCRC32:
case vmIntrinsics::_updateByteBufferCRC32: case vmIntrinsics::_updateByteBufferCRC32:
...@@ -957,6 +962,9 @@ bool LibraryCallKit::try_to_inline(int predicate) { ...@@ -957,6 +962,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_montgomerySquare: case vmIntrinsics::_montgomerySquare:
return inline_montgomerySquare(); return inline_montgomerySquare();
case vmIntrinsics::_ghash_processBlocks:
return inline_ghash_processBlocks();
case vmIntrinsics::_encodeISOArray: case vmIntrinsics::_encodeISOArray:
return inline_encodeISOArray(); return inline_encodeISOArray();
...@@ -6632,6 +6640,35 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt ...@@ -6632,6 +6640,35 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
return _gvn.transform(region); 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----------------------- //------------------------------inline_sha_implCompress-----------------------
// //
// Calculate SHA (i.e., SHA-1) for single-block byte[] array. // Calculate SHA (i.e., SHA-1) for single-block byte[] array.
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2231,6 +2231,13 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { ...@@ -2231,6 +2231,13 @@ bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
// We also need to replace the original limit to collapse loop exit. // We also need to replace the original limit to collapse loop exit.
Node* cmp = cl->loopexit()->cmp_node(); Node* cmp = cl->loopexit()->cmp_node();
assert(cl->limit() == cmp->in(2), "sanity"); 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._worklist.push(cmp->in(2)); // put limit on worklist
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
} }
......
...@@ -279,6 +279,7 @@ public: ...@@ -279,6 +279,7 @@ public:
if (iv_phi == NULL) { if (iv_phi == NULL) {
return NULL; return NULL;
} }
assert(iv_phi->is_Phi(), "should be PhiNode");
Node *ln = iv_phi->in(0); Node *ln = iv_phi->in(0);
if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) { if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) {
return (CountedLoopNode*)ln; return (CountedLoopNode*)ln;
......
...@@ -309,7 +309,7 @@ Node *PhaseIdealLoop::has_local_phi_input( Node *n ) { ...@@ -309,7 +309,7 @@ Node *PhaseIdealLoop::has_local_phi_input( Node *n ) {
} }
return NULL; 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; return n_ctrl;
......
...@@ -93,7 +93,25 @@ ...@@ -93,7 +93,25 @@
// At command line specify the parameters: -XX:+FullGCALot -XX:FullGCALotStart=100000000 // 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 // Compiled code entry points
address OptoRuntime::_new_instance_Java = NULL; address OptoRuntime::_new_instance_Java = NULL;
......
...@@ -315,6 +315,8 @@ private: ...@@ -315,6 +315,8 @@ private:
static const TypeFunc* montgomeryMultiply_Type(); static const TypeFunc* montgomeryMultiply_Type();
static const TypeFunc* montgomerySquare_Type(); static const TypeFunc* montgomerySquare_Type();
static const TypeFunc* ghash_processBlocks_Type();
static const TypeFunc* updateBytesCRC32_Type(); static const TypeFunc* updateBytesCRC32_Type();
// leaf on stack replacement interpreter accessor types // leaf on stack replacement interpreter accessor types
......
...@@ -2208,15 +2208,25 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) { ...@@ -2208,15 +2208,25 @@ void SuperWord::align_initial_loop_index(MemNode* align_to_ref) {
//----------------------------get_pre_loop_end--------------------------- //----------------------------get_pre_loop_end---------------------------
// Find pre loop end from main loop. Returns null if none. // Find pre loop end from main loop. Returns null if none.
CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode *cl) { CountedLoopEndNode* SuperWord::get_pre_loop_end(CountedLoopNode* cl) {
Node *ctrl = cl->in(LoopNode::EntryControl); Node* ctrl = cl->in(LoopNode::EntryControl);
if (!ctrl->is_IfTrue() && !ctrl->is_IfFalse()) return NULL; 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; 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->is_IfFalse()) return NULL;
if (!p_f->in(0)->is_CountedLoopEnd()) return NULL; if (!p_f->in(0)->is_CountedLoopEnd()) return NULL;
CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); CountedLoopEndNode* pre_end = p_f->in(0)->as_CountedLoopEnd();
CountedLoopNode* loop_node = pre_end->loopnode(); CountedLoopNode* loop_node = pre_end->loopnode();
if (loop_node == NULL || !loop_node->is_pre_loop()) return NULL; if (loop_node == NULL || !loop_node->is_pre_loop()) return NULL;
return pre_end; return pre_end;
......
...@@ -620,6 +620,9 @@ class CommandLineFlags { ...@@ -620,6 +620,9 @@ class CommandLineFlags {
product(bool, UseSHA, false, \ product(bool, UseSHA, false, \
"Control whether SHA instructions can be used on SPARC") \ "Control whether SHA instructions can be used on SPARC") \
\ \
product(bool, UseGHASHIntrinsics, false, \
"Use intrinsics for GHASH versions of crypto") \
\
product(uintx, LargePageSizeInBytes, 0, \ product(uintx, LargePageSizeInBytes, 0, \
"Large page size (0 to let VM choose the page size)") \ "Large page size (0 to let VM choose the page size)") \
\ \
......
...@@ -616,6 +616,7 @@ void SafepointSynchronize::do_cleanup_tasks() { ...@@ -616,6 +616,7 @@ void SafepointSynchronize::do_cleanup_tasks() {
if (UseGCLogFileRotation) { if (UseGCLogFileRotation) {
const char* name = "rotate gc log"; const char* name = "rotate gc log";
EventSafepointCleanupTask event; EventSafepointCleanupTask event;
TraceTime t8("rotating gc logs", TraceSafepointCleanupTime);
gclog_or_tty->rotate_log(false); gclog_or_tty->rotate_log(false);
event_safepoint_cleanup_task_commit(event, name); event_safepoint_cleanup_task_commit(event, name);
} }
......
...@@ -124,6 +124,7 @@ address StubRoutines::_aescrypt_encryptBlock = NULL; ...@@ -124,6 +124,7 @@ address StubRoutines::_aescrypt_encryptBlock = NULL;
address StubRoutines::_aescrypt_decryptBlock = NULL; address StubRoutines::_aescrypt_decryptBlock = NULL;
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL; address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL; address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
address StubRoutines::_ghash_processBlocks = NULL;
address StubRoutines::_sha1_implCompress = NULL; address StubRoutines::_sha1_implCompress = NULL;
address StubRoutines::_sha1_implCompressMB = NULL; address StubRoutines::_sha1_implCompressMB = NULL;
...@@ -176,7 +177,7 @@ void StubRoutines::initialize1() { ...@@ -176,7 +177,7 @@ void StubRoutines::initialize1() {
StubGenerator_generate(&buffer, false); StubGenerator_generate(&buffer, false);
// When new stubs added we need to make sure there is some space left // When new stubs added we need to make sure there is some space left
// to catch situation when we should increase size again. // to catch situation when we should increase size again.
assert(buffer.insts_remaining() > 200, "increase code_size1"); assert(code_size1 == 0 || buffer.insts_remaining() > 200, "increase code_size1");
} }
} }
...@@ -231,7 +232,7 @@ void StubRoutines::initialize2() { ...@@ -231,7 +232,7 @@ void StubRoutines::initialize2() {
StubGenerator_generate(&buffer, true); StubGenerator_generate(&buffer, true);
// When new stubs added we need to make sure there is some space left // When new stubs added we need to make sure there is some space left
// to catch situation when we should increase size again. // 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 #ifdef ASSERT
......
...@@ -197,6 +197,7 @@ class StubRoutines: AllStatic { ...@@ -197,6 +197,7 @@ class StubRoutines: AllStatic {
static address _aescrypt_decryptBlock; static address _aescrypt_decryptBlock;
static address _cipherBlockChaining_encryptAESCrypt; static address _cipherBlockChaining_encryptAESCrypt;
static address _cipherBlockChaining_decryptAESCrypt; static address _cipherBlockChaining_decryptAESCrypt;
static address _ghash_processBlocks;
static address _sha1_implCompress; static address _sha1_implCompress;
static address _sha1_implCompressMB; static address _sha1_implCompressMB;
...@@ -359,6 +360,7 @@ class StubRoutines: AllStatic { ...@@ -359,6 +360,7 @@ class StubRoutines: AllStatic {
static address aescrypt_decryptBlock() { return _aescrypt_decryptBlock; } static address aescrypt_decryptBlock() { return _aescrypt_decryptBlock; }
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; } static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; } static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
static address ghash_processBlocks() { return _ghash_processBlocks; }
static address sha1_implCompress() { return _sha1_implCompress; } static address sha1_implCompress() { return _sha1_implCompress; }
static address sha1_implCompressMB() { return _sha1_implCompressMB; } static address sha1_implCompressMB() { return _sha1_implCompressMB; }
......
...@@ -810,6 +810,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable; ...@@ -810,6 +810,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
static_field(StubRoutines, _aescrypt_decryptBlock, address) \ static_field(StubRoutines, _aescrypt_decryptBlock, address) \
static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \ static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \
static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \ static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \
static_field(StubRoutines, _ghash_processBlocks, address) \
static_field(StubRoutines, _updateBytesCRC32, address) \ static_field(StubRoutines, _updateBytesCRC32, address) \
static_field(StubRoutines, _crc_table_adr, address) \ static_field(StubRoutines, _crc_table_adr, address) \
static_field(StubRoutines, _multiplyToLen, address) \ static_field(StubRoutines, _multiplyToLen, address) \
......
...@@ -34,8 +34,9 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC { ...@@ -34,8 +34,9 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC {
private: private:
NativeCallStack _call_stack; NativeCallStack _call_stack;
E e; E e;
MEMFLAGS _flag;
public: 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(); } int hash() const { return _call_stack.hash(); }
bool equals(const NativeCallStack& stack) const { bool equals(const NativeCallStack& stack) const {
return _call_stack.equals(stack); return _call_stack.equals(stack);
...@@ -52,6 +53,8 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC { ...@@ -52,6 +53,8 @@ template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC {
// Information regarding this allocation // Information regarding this allocation
E* data() { return &e; } E* data() { return &e; }
const E* peek() const { return &e; } const E* peek() const { return &e; }
MEMFLAGS flag() const { return _flag; }
}; };
#endif // SHARE_VM_SERVICES_ALLOCATION_SITE_HPP #endif // SHARE_VM_SERVICES_ALLOCATION_SITE_HPP
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -84,12 +84,18 @@ bool MallocSiteTable::initialize() { ...@@ -84,12 +84,18 @@ bool MallocSiteTable::initialize() {
// Create pseudo call stack for hashtable entry allocation // Create pseudo call stack for hashtable entry allocation
address pc[3]; address pc[3];
if (NMT_TrackingStackDepth >= 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) { 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) // Instantiate NativeCallStack object, have to use placement new operator. (see comments above)
NativeCallStack* stack = ::new ((void*)_hash_entry_allocation_stack) NativeCallStack* stack = ::new ((void*)_hash_entry_allocation_stack)
...@@ -158,7 +164,7 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* b ...@@ -158,7 +164,7 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* b
MallocSiteHashtableEntry* head = _table[index]; MallocSiteHashtableEntry* head = _table[index];
while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) { while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) {
MallocSite* site = head->data(); MallocSite* site = head->data();
if (site->flags() == flags && site->equals(key)) { if (site->flag() == flags && site->equals(key)) {
return head->data(); return head->data();
} }
......
...@@ -37,15 +37,12 @@ ...@@ -37,15 +37,12 @@
// MallocSite represents a code path that eventually calls // MallocSite represents a code path that eventually calls
// os::malloc() to allocate memory // os::malloc() to allocate memory
class MallocSite : public AllocationSite<MemoryCounter> { class MallocSite : public AllocationSite<MemoryCounter> {
private:
MEMFLAGS _flags;
public: public:
MallocSite() : MallocSite() :
AllocationSite<MemoryCounter>(NativeCallStack::empty_stack()), _flags(mtNone) {} AllocationSite<MemoryCounter>(NativeCallStack::empty_stack(), mtNone) {}
MallocSite(const NativeCallStack& stack, MEMFLAGS flags) : MallocSite(const NativeCallStack& stack, MEMFLAGS flags) :
AllocationSite<MemoryCounter>(stack), _flags(flags) {} AllocationSite<MemoryCounter>(stack, flags) {}
void allocate(size_t size) { data()->allocate(size); } void allocate(size_t size) { data()->allocate(size); }
...@@ -55,7 +52,6 @@ class MallocSite : public AllocationSite<MemoryCounter> { ...@@ -55,7 +52,6 @@ class MallocSite : public AllocationSite<MemoryCounter> {
size_t size() const { return peek()->size(); } size_t size() const { return peek()->size(); }
// The number of calls were made // The number of calls were made
size_t count() const { return peek()->count(); } size_t count() const { return peek()->count(); }
MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
}; };
// Malloc site hashtable entry // Malloc site hashtable entry
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -63,7 +63,7 @@ int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) { ...@@ -63,7 +63,7 @@ int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) { int compare_malloc_site_and_type(const MallocSite& s1, const MallocSite& s2) {
int res = compare_malloc_site(s1, s2); int res = compare_malloc_site(s1, s2);
if (res == 0) { if (res == 0) {
res = (int)(s1.flags() - s2.flags()); res = (int)(s1.flag() - s2.flag());
} }
return res; return res;
...@@ -209,7 +209,7 @@ bool MemBaseline::aggregate_virtual_memory_allocation_sites() { ...@@ -209,7 +209,7 @@ bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
const ReservedMemoryRegion* rgn; const ReservedMemoryRegion* rgn;
VirtualMemoryAllocationSite* site; VirtualMemoryAllocationSite* site;
while ((rgn = itr.next()) != NULL) { while ((rgn = itr.next()) != NULL) {
VirtualMemoryAllocationSite tmp(*rgn->call_stack()); VirtualMemoryAllocationSite tmp(*rgn->call_stack(), rgn->flag());
site = allocation_sites.find(tmp); site = allocation_sites.find(tmp);
if (site == NULL) { if (site == NULL) {
LinkedListNode<VirtualMemoryAllocationSite>* node = LinkedListNode<VirtualMemoryAllocationSite>* node =
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -205,7 +205,7 @@ void MemDetailReporter::report_malloc_sites() { ...@@ -205,7 +205,7 @@ void MemDetailReporter::report_malloc_sites() {
const NativeCallStack* stack = malloc_site->call_stack(); const NativeCallStack* stack = malloc_site->call_stack();
stack->print_on(out); stack->print_on(out);
out->print("%29s", " "); out->print("%29s", " ");
MEMFLAGS flag = malloc_site->flags(); MEMFLAGS flag = malloc_site->flag();
assert((flag >= 0 && flag < (int)mt_number_of_types) && flag != mtNone, assert((flag >= 0 && flag < (int)mt_number_of_types) && flag != mtNone,
"Must have a valid memory type"); "Must have a valid memory type");
print_malloc(malloc_site->size(), malloc_site->count(),flag); print_malloc(malloc_site->size(), malloc_site->count(),flag);
...@@ -231,6 +231,10 @@ void MemDetailReporter::report_virtual_memory_allocation_sites() { ...@@ -231,6 +231,10 @@ void MemDetailReporter::report_virtual_memory_allocation_sites() {
stack->print_on(out); stack->print_on(out);
out->print("%28s (", " "); out->print("%28s (", " ");
print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); 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"); out->print_cr(")\n");
} }
} }
...@@ -562,24 +566,24 @@ void MemDetailDiffReporter::diff_virtual_memory_sites() const { ...@@ -562,24 +566,24 @@ void MemDetailDiffReporter::diff_virtual_memory_sites() const {
void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const { void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const {
diff_malloc_site(malloc_site->call_stack(), malloc_site->size(), malloc_site->count(), 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 { void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const {
diff_malloc_site(malloc_site->call_stack(), 0, 0, malloc_site->size(), 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, void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early,
const MallocSite* current) const { 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 // If malloc site type changed, treat it as deallocation of old type and
// allocation of new type. // allocation of new type.
old_malloc_site(early); old_malloc_site(early);
new_malloc_site(current); new_malloc_site(current);
} else { } else {
diff_malloc_site(current->call_stack(), current->size(), current->count(), diff_malloc_site(current->call_stack(), current->size(), current->count(),
early->size(), early->count(), early->flags()); early->size(), early->count(), early->flag());
} }
} }
...@@ -603,21 +607,22 @@ void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_ ...@@ -603,21 +607,22 @@ void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_
void MemDetailDiffReporter::new_virtual_memory_site(const VirtualMemoryAllocationSite* site) const { 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 { 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, void MemDetailDiffReporter::diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
const VirtualMemoryAllocationSite* current) const { const VirtualMemoryAllocationSite* current) const {
assert(early->flag() == current->flag(), "Should be the same");
diff_virtual_memory_site(current->call_stack(), current->reserved(), current->committed(), 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, 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(); outputStream* out = output();
// no change // no change
...@@ -631,6 +636,10 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac ...@@ -631,6 +636,10 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac
print_virtual_memory_diff(current_reserved, current_committed, print_virtual_memory_diff(current_reserved, current_committed,
early_reserved, early_committed); early_reserved, early_committed);
if (flag != mtNone) {
out->print(" Type=%s", NMTUtil::flag_to_name(flag));
}
out->print_cr(")\n"); out->print_cr(")\n");
} }
...@@ -218,7 +218,7 @@ class MemDetailDiffReporter : public MemSummaryDiffReporter { ...@@ -218,7 +218,7 @@ class MemDetailDiffReporter : public MemSummaryDiffReporter {
void diff_malloc_site(const NativeCallStack* stack, size_t current_size, 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; 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, 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 #endif // INCLUDE_NMT
......
...@@ -198,7 +198,7 @@ public: ...@@ -198,7 +198,7 @@ public:
bool support_usage_threshold); bool support_usage_threshold);
MemoryUsage get_memory_usage(); 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 #endif // INCLUDE_ALL_GCS
......
...@@ -69,8 +69,8 @@ class VirtualMemory VALUE_OBJ_CLASS_SPEC { ...@@ -69,8 +69,8 @@ class VirtualMemory VALUE_OBJ_CLASS_SPEC {
// Virtual memory allocation site, keeps track where the virtual memory is reserved. // Virtual memory allocation site, keeps track where the virtual memory is reserved.
class VirtualMemoryAllocationSite : public AllocationSite<VirtualMemory> { class VirtualMemoryAllocationSite : public AllocationSite<VirtualMemory> {
public: public:
VirtualMemoryAllocationSite(const NativeCallStack& stack) : VirtualMemoryAllocationSite(const NativeCallStack& stack, MEMFLAGS flag) :
AllocationSite<VirtualMemory>(stack) { } AllocationSite<VirtualMemory>(stack, flag) { }
inline void reserve_memory(size_t sz) { data()->reserve_memory(sz); } inline void reserve_memory(size_t sz) { data()->reserve_memory(sz); }
inline void commit_memory (size_t sz) { data()->commit_memory(sz); } inline void commit_memory (size_t sz) { data()->commit_memory(sz); }
......
...@@ -420,6 +420,14 @@ ...@@ -420,6 +420,14 @@
#define NOT_EMBEDDED(code) code #define NOT_EMBEDDED(code) code
#endif #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; #define define_pd_global(type, name, value) const type pd_##name = value;
#endif // SHARE_VM_UTILITIES_MACROS_HPP #endif // SHARE_VM_UTILITIES_MACROS_HPP
...@@ -714,6 +714,11 @@ GenericTaskQueue<E, F, N>::pop_local(volatile E& t) { ...@@ -714,6 +714,11 @@ GenericTaskQueue<E, F, N>::pop_local(volatile E& t) {
} else { } else {
// Otherwise, the queue contained exactly one element; we take the slow // Otherwise, the queue contained exactly one element; we take the slow
// path. // 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()); return pop_local_slow(localBot, _age.get());
} }
} }
......
...@@ -464,7 +464,6 @@ bool SubTasksDone::is_task_claimed(uint t) { ...@@ -464,7 +464,6 @@ bool SubTasksDone::is_task_claimed(uint t) {
if (old == 0) { if (old == 0) {
old = Atomic::cmpxchg(1, &_tasks[t], 0); old = Atomic::cmpxchg(1, &_tasks[t], 0);
} }
assert(_tasks[t] == 1, "What else?");
bool res = old != 0; bool res = old != 0;
#ifdef ASSERT #ifdef ASSERT
if (!res) { if (!res) {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator; import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters; import java.security.AlgorithmParameters;
...@@ -62,8 +63,12 @@ abstract public class TestAESBase { ...@@ -62,8 +63,12 @@ abstract public class TestAESBase {
Random random = new Random(0); Random random = new Random(0);
Cipher cipher; Cipher cipher;
Cipher dCipher; Cipher dCipher;
AlgorithmParameters algParams; AlgorithmParameters algParams = null;
SecretKey key; SecretKey key;
GCMParameterSpec gcm_spec;
byte[] aad = { 0x11, 0x22, 0x33, 0x44, 0x55 };
int tlen = 12;
byte[] iv = new byte[16];
static int numThreads = 0; static int numThreads = 0;
int threadId; int threadId;
...@@ -77,7 +82,10 @@ abstract public class TestAESBase { ...@@ -77,7 +82,10 @@ abstract public class TestAESBase {
public void prepare() { public void prepare() {
try { 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 ) if (encInputOffset % ALIGN != 0 || encOutputOffset % ALIGN != 0 || decOutputOffset % ALIGN !=0 )
testingMisalignment = true; testingMisalignment = true;
...@@ -98,16 +106,24 @@ abstract public class TestAESBase { ...@@ -98,16 +106,24 @@ abstract public class TestAESBase {
cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); cipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE"); dCipher = Cipher.getInstance(algorithm + "/" + mode + "/" + paddingStr, "SunJCE");
// CBC init
if (mode.equals("CBC")) { if (mode.equals("CBC")) {
int ivLen = (algorithm.equals("AES") ? 16 : algorithm.equals("DES") ? 8 : 0); IvParameterSpec initVector = new IvParameterSpec(iv);
IvParameterSpec initVector = new IvParameterSpec(new byte[ivLen]);
cipher.init(Cipher.ENCRYPT_MODE, key, initVector); cipher.init(Cipher.ENCRYPT_MODE, key, initVector);
} else {
algParams = cipher.getParameters(); algParams = cipher.getParameters();
dCipher.init(Cipher.DECRYPT_MODE, key, initVector);
// GCM init
} else if (mode.equals("GCM")) {
gcm_init(true);
gcm_init(false);
// ECB init
} else {
cipher.init(Cipher.ENCRYPT_MODE, key, algParams); cipher.init(Cipher.ENCRYPT_MODE, key, algParams);
}
algParams = cipher.getParameters();
dCipher.init(Cipher.DECRYPT_MODE, key, algParams); dCipher.init(Cipher.DECRYPT_MODE, key, algParams);
}
if (threadId == 0) { if (threadId == 0) {
childShowCipher(); childShowCipher();
} }
...@@ -188,4 +204,19 @@ abstract public class TestAESBase { ...@@ -188,4 +204,19 @@ abstract public class TestAESBase {
} }
abstract void childShowCipher(); 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);
}
}
} }
...@@ -32,7 +32,11 @@ public class TestAESDecode extends TestAESBase { ...@@ -32,7 +32,11 @@ public class TestAESDecode extends TestAESBase {
@Override @Override
public void run() { public void run() {
try { 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]; decode = new byte[decodeLength];
if (testingMisalignment) { if (testingMisalignment) {
int tempSize = dCipher.update(encode, encOutputOffset, (decodeMsgSize - lastChunkSize), decode, decOutputOffset); int tempSize = dCipher.update(encode, encOutputOffset, (decodeMsgSize - lastChunkSize), decode, decOutputOffset);
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -32,7 +32,11 @@ public class TestAESEncode extends TestAESBase { ...@@ -32,7 +32,11 @@ public class TestAESEncode extends TestAESBase {
@Override @Override
public void run() { public void run() {
try { 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]; encode = new byte[encodeLength];
if (testingMisalignment) { if (testingMisalignment) {
int tempSize = cipher.update(input, encInputOffset, (msgSize - lastChunkSize), encode, encOutputOffset); int tempSize = cipher.update(input, encInputOffset, (msgSize - lastChunkSize), encode, encOutputOffset);
......
...@@ -41,6 +41,13 @@ ...@@ -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 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 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=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 * @author Tom Deneau
*/ */
......
...@@ -22,9 +22,10 @@ ...@@ -22,9 +22,10 @@
*/ */
import sun.hotspot.WhiteBox; import sun.hotspot.WhiteBox;
import sun.misc.Unsafe;
import sun.misc.IOUtils; import sun.misc.IOUtils;
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
...@@ -108,7 +109,13 @@ public class TestAnonymousClassUnloading { ...@@ -108,7 +109,13 @@ public class TestAnonymousClassUnloading {
// (1) Load an anonymous version of this class using the corresponding Unsafe method // (1) Load an anonymous version of this class using the corresponding Unsafe method
URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class"); URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class");
URLConnection connection = classUrl.openConnection(); 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); Class<?> anonymousClass = UNSAFE.defineAnonymousClass(TestAnonymousClassUnloading.class, classBytes, null);
// (2) Make sure all paths of doWork are profiled and compiled // (2) Make sure all paths of doWork are profiled and compiled
......
/*
* 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
/*
* 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.");
}
}
/*
* 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);
}
}
/*
* 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();
}
}
}
/*
* 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 {
}
}
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package gc.stress.gclocker;
// Based on Kim Barrett;s test for JDK-8048556
/*
* @test TestExcessGCLockerCollections
* @key gc
* @bug 8048556
* @summary Check for GC Locker initiated GCs that immediately follow another
* GC and so have very little needing to be collected.
* @library /testlibrary
* @run driver/timeout=1000 gc.stress.gclocker.TestExcessGCLockerCollections 300 4 2
*/
import java.util.HashMap;
import java.util.Map;
import java.util.zip.Deflater;
import java.util.ArrayList;
import java.util.Arrays;
import javax.management.MBeanServer;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.openmbean.CompositeData;
import java.lang.management.ManagementFactory;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.MemoryUsage;
import java.util.List;
import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GcInfo;
import com.oracle.java.testlibrary.Asserts;
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
class TestExcessGCLockerCollectionsStringConstants {
// Some constant strings used in both GC logging and error detection
static public final String GCLOCKER_CAUSE = "GCLocker Initiated GC";
static public final String USED_TOO_LOW = "TOO LOW";
static public final String USED_OK = "OK";
}
class TestExcessGCLockerCollectionsAux {
static private final int LARGE_MAP_SIZE = 64 * 1024;
static private final int MAP_ARRAY_LENGTH = 4;
static private final int MAP_SIZE = 1024;
static private final int BYTE_ARRAY_LENGTH = 128 * 1024;
static private void println(String str) { System.out.println(str); }
static private void println() { System.out.println(); }
static private volatile boolean keepRunning = true;
static Map<Integer,String> populateMap(int size) {
Map<Integer,String> map = new HashMap<Integer,String>();
for (int i = 0; i < size; i += 1) {
Integer keyInt = Integer.valueOf(i);
String valStr = "value is [" + i + "]";
map.put(keyInt,valStr);
}
return map;
}
static private class AllocatingWorker implements Runnable {
private final Object[] array = new Object[MAP_ARRAY_LENGTH];
private int arrayIndex = 0;
private void doStep() {
Map<Integer,String> map = populateMap(MAP_SIZE);
array[arrayIndex] = map;
arrayIndex = (arrayIndex + 1) % MAP_ARRAY_LENGTH;
}
public void run() {
while (keepRunning) {
doStep();
}
}
}
static private class JNICriticalWorker implements Runnable {
private int count;
private void doStep() {
byte[] inputArray = new byte[BYTE_ARRAY_LENGTH];
for (int i = 0; i < inputArray.length; i += 1) {
inputArray[i] = (byte) (count + i);
}
Deflater deflater = new Deflater();
deflater.setInput(inputArray);
deflater.finish();
byte[] outputArray = new byte[2 * inputArray.length];
deflater.deflate(outputArray);
count += 1;
}
public void run() {
while (keepRunning) {
doStep();
}
}
}
static class GCNotificationListener implements NotificationListener {
static private final double MIN_USED_PERCENT = 40.0;
static private final List<String> newGenPoolNames = Arrays.asList(
"G1 Eden Space", // OpenJDK G1GC: -XX:+UseG1GC
"PS Eden Space", // OpenJDK ParallelGC: -XX:+ParallelGC
"Par Eden Space", // OpenJDK ConcMarkSweepGC: -XX:+ConcMarkSweepGC
"Eden Space" // OpenJDK SerialGC: -XX:+UseSerialGC
// OpenJDK ConcMarkSweepGC: -XX:+ConcMarkSweepGC -XX:-UseParNewGC
);
@Override
public void handleNotification(Notification notification, Object handback) {
try {
if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) {
GarbageCollectionNotificationInfo info =
GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData());
String gc_cause = info.getGcCause();
if (gc_cause.equals(TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE)) {
Map<String, MemoryUsage> memory_before_gc = info.getGcInfo().getMemoryUsageBeforeGc();
for (String newGenPoolName : newGenPoolNames) {
MemoryUsage usage = memory_before_gc.get(newGenPoolName);
if (usage == null) continue;
double startTime = ((double) info.getGcInfo().getStartTime()) / 1000.0;
long used = usage.getUsed();
long committed = usage.getCommitted();
long max = usage.getMax();
double used_percent = (((double) used) / Math.max(committed, max)) * 100.0;
System.out.printf("%6.3f: (%s) %d/%d/%d, %8.4f%% (%s)\n",
startTime, gc_cause, used, committed, max, used_percent,
((used_percent < MIN_USED_PERCENT) ? TestExcessGCLockerCollectionsStringConstants.USED_TOO_LOW
: TestExcessGCLockerCollectionsStringConstants.USED_OK));
}
}
}
} catch (RuntimeException ex) {
System.err.println("Exception during notification processing:" + ex);
ex.printStackTrace();
}
}
public static boolean register() {
try {
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
// Get the list of MX
List<GarbageCollectorMXBean> gc_mxbeans = ManagementFactory.getGarbageCollectorMXBeans();
// Create the notification listener
GCNotificationListener gcNotificationListener = new GCNotificationListener();
for (GarbageCollectorMXBean gcbean : gc_mxbeans) {
// Add notification listener for the MXBean
mbeanServer.addNotificationListener(gcbean.getObjectName(), gcNotificationListener, null, null);
}
} catch (Exception ex) {
System.err.println("Exception during mbean registration:" + ex);
ex.printStackTrace();
// We've failed to set up, terminate
return false;
}
return true;
}
}
static public Map<Integer,String> largeMap;
static public void main(String args[]) {
long durationSec = Long.parseLong(args[0]);
int allocThreadNum = Integer.parseInt(args[1]);
int jniCriticalThreadNum = Integer.parseInt(args[2]);
println("Running for " + durationSec + " secs");
if (!GCNotificationListener.register()) {
println("failed to register GC notification listener");
System.exit(-1);
}
largeMap = populateMap(LARGE_MAP_SIZE);
println("Starting " + allocThreadNum + " allocating threads");
for (int i = 0; i < allocThreadNum; i += 1) {
new Thread(new AllocatingWorker()).start();
}
println("Starting " + jniCriticalThreadNum + " jni critical threads");
for (int i = 0; i < jniCriticalThreadNum; i += 1) {
new Thread(new JNICriticalWorker()).start();
}
long durationMS = (long) (1000 * durationSec);
long start = System.currentTimeMillis();
long now = start;
long soFar = now - start;
while (soFar < durationMS) {
try {
Thread.sleep(durationMS - soFar);
} catch (Exception e) {
}
now = System.currentTimeMillis();
soFar = now - start;
}
println("Done.");
keepRunning = false;
}
}
public class TestExcessGCLockerCollections {
private static final String USED_OK_LINE =
"\\(" + TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE + "\\)"
+ " .* " +
"\\(" + TestExcessGCLockerCollectionsStringConstants.USED_OK + "\\)";
private static final String USED_TOO_LOW_LINE =
"\\(" + TestExcessGCLockerCollectionsStringConstants.GCLOCKER_CAUSE + "\\)"
+ " .* " +
"\\(" + TestExcessGCLockerCollectionsStringConstants.USED_TOO_LOW + "\\)";
private static final String[] COMMON_OPTIONS = new String[] {
"-Xmx1G", "-Xms1G", "-Xmn256M" };
public static void main(String args[]) throws Exception {
if (args.length < 3) {
System.out.println("usage: TestExcessGCLockerCollections" +
" <duration sec> <alloc threads>" +
" <jni critical threads>");
throw new RuntimeException("Invalid arguments");
}
ArrayList<String> finalArgs = new ArrayList<String>();
finalArgs.addAll(Arrays.asList(COMMON_OPTIONS));
finalArgs.add(TestExcessGCLockerCollectionsAux.class.getName());
finalArgs.addAll(Arrays.asList(args));
// GC and other options obtained from test framework.
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
true, finalArgs.toArray(new String[0]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldHaveExitValue(0);
//System.out.println("------------- begin stdout ----------------");
//System.out.println(output.getStdout());
//System.out.println("------------- end stdout ----------------");
output.stdoutShouldMatch(USED_OK_LINE);
output.stdoutShouldNotMatch(USED_TOO_LOW_LINE);
}
}
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
* *
*/ */
import sun.misc.IOUtils;
public class VictimClassLoader extends ClassLoader { public class VictimClassLoader extends ClassLoader {
public static long counter = 0; public static long counter = 0;
...@@ -72,8 +74,10 @@ public class VictimClassLoader extends ClassLoader { ...@@ -72,8 +74,10 @@ public class VictimClassLoader extends ClassLoader {
} }
static byte[] readFully(java.io.InputStream in, int len) throws java.io.IOException { static byte[] readFully(java.io.InputStream in, int len) throws java.io.IOException {
// Warning here: byte[] b = IOUtils.readAllBytes(in);
return sun.misc.IOUtils.readFully(in, len, true); if (len != -1 && b.length != len)
throw new java.io.IOException("Expected:" + len + ", actual:" + b.length);
return b;
} }
public void finalize() { public void finalize() {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册