mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-15 08:34:30 +02:00
8035968: Leverage CPU Instructions to Improve SHA Performance on SPARC
Add C2 SHA intrinsics on SPARC Reviewed-by: kvn, roland
This commit is contained in:
parent
83fc2acbd7
commit
395560c428
16 changed files with 881 additions and 12 deletions
|
@ -123,6 +123,7 @@ class Assembler : public AbstractAssembler {
|
|||
fpop2_op3 = 0x35,
|
||||
impdep1_op3 = 0x36,
|
||||
aes3_op3 = 0x36,
|
||||
sha_op3 = 0x36,
|
||||
alignaddr_op3 = 0x36,
|
||||
faligndata_op3 = 0x36,
|
||||
flog3_op3 = 0x36,
|
||||
|
@ -223,7 +224,11 @@ class Assembler : public AbstractAssembler {
|
|||
mwtos_opf = 0x119,
|
||||
|
||||
aes_kexpand0_opf = 0x130,
|
||||
aes_kexpand2_opf = 0x131
|
||||
aes_kexpand2_opf = 0x131,
|
||||
|
||||
sha1_opf = 0x141,
|
||||
sha256_opf = 0x142,
|
||||
sha512_opf = 0x143
|
||||
};
|
||||
|
||||
enum op5s {
|
||||
|
@ -595,6 +600,11 @@ class Assembler : public AbstractAssembler {
|
|||
// AES crypto instructions supported only on certain processors
|
||||
static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); }
|
||||
|
||||
// SHA crypto instructions supported only on certain processors
|
||||
static void sha1_only() { assert( VM_Version::has_sha1(), "This instruction only works on SPARC with SHA1"); }
|
||||
static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); }
|
||||
static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); }
|
||||
|
||||
// instruction only in VIS1
|
||||
static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); }
|
||||
|
||||
|
@ -1179,7 +1189,6 @@ public:
|
|||
u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); }
|
||||
inline void wrfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
|
||||
|
||||
|
||||
// VIS1 instructions
|
||||
|
||||
void alignaddr( Register s1, Register s2, Register d ) { vis1_only(); emit_int32( op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); }
|
||||
|
@ -1203,6 +1212,12 @@ public:
|
|||
void movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
|
||||
void movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
|
||||
|
||||
// Crypto SHA instructions
|
||||
|
||||
void sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
|
||||
void sha256() { sha256_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); }
|
||||
void sha512() { sha512_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); }
|
||||
|
||||
// Creation
|
||||
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
|
||||
#ifdef CHECK_DELAY
|
||||
|
|
|
@ -4575,6 +4575,219 @@ class StubGenerator: public StubCodeGenerator {
|
|||
return start;
|
||||
}
|
||||
|
||||
address generate_sha1_implCompress(bool multi_block, const char *name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_sha1_loop, L_sha1_unaligned_input, L_sha1_unaligned_input_loop;
|
||||
int i;
|
||||
|
||||
Register buf = O0; // byte[] source+offset
|
||||
Register state = O1; // int[] SHA.state
|
||||
Register ofs = O2; // int offset
|
||||
Register limit = O3; // int limit
|
||||
|
||||
// load state into F0-F4
|
||||
for (i = 0; i < 5; i++) {
|
||||
__ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
|
||||
}
|
||||
|
||||
__ andcc(buf, 7, G0);
|
||||
__ br(Assembler::notZero, false, Assembler::pn, L_sha1_unaligned_input);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ BIND(L_sha1_loop);
|
||||
// load buf into F8-F22
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
__ sha1();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 64, ofs);
|
||||
__ add(buf, 64, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F4 into state and return
|
||||
for (i = 0; i < 4; i++) {
|
||||
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
|
||||
|
||||
__ BIND(L_sha1_unaligned_input);
|
||||
__ alignaddr(buf, G0, buf);
|
||||
|
||||
__ BIND(L_sha1_unaligned_input_loop);
|
||||
// load buf into F8-F22
|
||||
for (i = 0; i < 9; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
__ sha1();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 64, ofs);
|
||||
__ add(buf, 64, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_unaligned_input_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F4 into state and return
|
||||
for (i = 0; i < 4; i++) {
|
||||
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
address generate_sha256_implCompress(bool multi_block, const char *name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_sha256_loop, L_sha256_unaligned_input, L_sha256_unaligned_input_loop;
|
||||
int i;
|
||||
|
||||
Register buf = O0; // byte[] source+offset
|
||||
Register state = O1; // int[] SHA2.state
|
||||
Register ofs = O2; // int offset
|
||||
Register limit = O3; // int limit
|
||||
|
||||
// load state into F0-F7
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
|
||||
}
|
||||
|
||||
__ andcc(buf, 7, G0);
|
||||
__ br(Assembler::notZero, false, Assembler::pn, L_sha256_unaligned_input);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ BIND(L_sha256_loop);
|
||||
// load buf into F8-F22
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
__ sha256();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 64, ofs);
|
||||
__ add(buf, 64, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F7 into state and return
|
||||
for (i = 0; i < 7; i++) {
|
||||
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
|
||||
|
||||
__ BIND(L_sha256_unaligned_input);
|
||||
__ alignaddr(buf, G0, buf);
|
||||
|
||||
__ BIND(L_sha256_unaligned_input_loop);
|
||||
// load buf into F8-F22
|
||||
for (i = 0; i < 9; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
|
||||
}
|
||||
__ sha256();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 64, ofs);
|
||||
__ add(buf, 64, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_unaligned_input_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F7 into state and return
|
||||
for (i = 0; i < 7; i++) {
|
||||
__ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
address generate_sha512_implCompress(bool multi_block, const char *name) {
|
||||
__ align(CodeEntryAlignment);
|
||||
StubCodeMark mark(this, "StubRoutines", name);
|
||||
address start = __ pc();
|
||||
|
||||
Label L_sha512_loop, L_sha512_unaligned_input, L_sha512_unaligned_input_loop;
|
||||
int i;
|
||||
|
||||
Register buf = O0; // byte[] source+offset
|
||||
Register state = O1; // long[] SHA5.state
|
||||
Register ofs = O2; // int offset
|
||||
Register limit = O3; // int limit
|
||||
|
||||
// load state into F0-F14
|
||||
for (i = 0; i < 8; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, state, i*8, as_FloatRegister(i*2));
|
||||
}
|
||||
|
||||
__ andcc(buf, 7, G0);
|
||||
__ br(Assembler::notZero, false, Assembler::pn, L_sha512_unaligned_input);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ BIND(L_sha512_loop);
|
||||
// load buf into F16-F46
|
||||
for (i = 0; i < 16; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
|
||||
}
|
||||
__ sha512();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 128, ofs);
|
||||
__ add(buf, 128, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F14 into state and return
|
||||
for (i = 0; i < 7; i++) {
|
||||
__ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
|
||||
|
||||
__ BIND(L_sha512_unaligned_input);
|
||||
__ alignaddr(buf, G0, buf);
|
||||
|
||||
__ BIND(L_sha512_unaligned_input_loop);
|
||||
// load buf into F16-F46
|
||||
for (i = 0; i < 17; i++) {
|
||||
__ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
__ faligndata(as_FloatRegister(i*2 + 16), as_FloatRegister(i*2 + 18), as_FloatRegister(i*2 + 16));
|
||||
}
|
||||
__ sha512();
|
||||
if (multi_block) {
|
||||
__ add(ofs, 128, ofs);
|
||||
__ add(buf, 128, buf);
|
||||
__ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_unaligned_input_loop);
|
||||
__ mov(ofs, O0); // to be returned
|
||||
}
|
||||
|
||||
// store F0-F14 into state and return
|
||||
for (i = 0; i < 7; i++) {
|
||||
__ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
|
||||
}
|
||||
__ retl();
|
||||
__ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
void generate_initial() {
|
||||
// Generates all stubs and initializes the entry points
|
||||
|
||||
|
@ -4647,6 +4860,20 @@ class StubGenerator: public StubCodeGenerator {
|
|||
StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
|
||||
StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
|
||||
}
|
||||
|
||||
// generate SHA1/SHA256/SHA512 intrinsics code
|
||||
if (UseSHA1Intrinsics) {
|
||||
StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress");
|
||||
StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB");
|
||||
}
|
||||
if (UseSHA256Intrinsics) {
|
||||
StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
|
||||
StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
|
||||
}
|
||||
if (UseSHA512Intrinsics) {
|
||||
StubRoutines::_sha512_implCompress = generate_sha512_implCompress(false, "sha512_implCompress");
|
||||
StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true, "sha512_implCompressMB");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ static bool returns_to_call_stub(address return_pc) {
|
|||
enum /* platform_dependent_constants */ {
|
||||
// %%%%%%%% May be able to shrink this a lot
|
||||
code_size1 = 20000, // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
|
||||
code_size2 = 23000 // simply increase if too small (assembler will crash if too small)
|
||||
};
|
||||
|
||||
class Sparc {
|
||||
|
|
|
@ -234,7 +234,7 @@ void VM_Version::initialize() {
|
|||
assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
|
||||
|
||||
char buf[512];
|
||||
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
(has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
|
||||
(has_hardware_popc() ? ", popc" : ""),
|
||||
(has_vis1() ? ", vis1" : ""),
|
||||
|
@ -243,6 +243,9 @@ void VM_Version::initialize() {
|
|||
(has_blk_init() ? ", blk_init" : ""),
|
||||
(has_cbcond() ? ", cbcond" : ""),
|
||||
(has_aes() ? ", aes" : ""),
|
||||
(has_sha1() ? ", sha1" : ""),
|
||||
(has_sha256() ? ", sha256" : ""),
|
||||
(has_sha512() ? ", sha512" : ""),
|
||||
(is_ultra3() ? ", ultra3" : ""),
|
||||
(is_sun4v() ? ", sun4v" : ""),
|
||||
(is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
|
||||
|
@ -301,6 +304,58 @@ void VM_Version::initialize() {
|
|||
}
|
||||
}
|
||||
|
||||
// SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
|
||||
if (has_sha1() || has_sha256() || has_sha512()) {
|
||||
if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
|
||||
if (FLAG_IS_DEFAULT(UseSHA)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, true);
|
||||
}
|
||||
} else {
|
||||
if (UseSHA) {
|
||||
warning("SPARC SHA intrinsics require VIS1 instruction support. Intrinsics will be disabled.");
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
}
|
||||
} else if (UseSHA) {
|
||||
warning("SHA instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
|
||||
if (!UseSHA) {
|
||||
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||
} else {
|
||||
if (has_sha1()) {
|
||||
if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
|
||||
}
|
||||
} else if (UseSHA1Intrinsics) {
|
||||
warning("SHA1 instruction is not available on this CPU.");
|
||||
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||
}
|
||||
if (has_sha256()) {
|
||||
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
|
||||
}
|
||||
} else if (UseSHA256Intrinsics) {
|
||||
warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU.");
|
||||
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||
}
|
||||
|
||||
if (has_sha512()) {
|
||||
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
|
||||
}
|
||||
} else if (UseSHA512Intrinsics) {
|
||||
warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU.");
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||
}
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
|
||||
(cache_line_size > ContendedPaddingWidth))
|
||||
ContendedPaddingWidth = cache_line_size;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -50,7 +50,10 @@ protected:
|
|||
T_family = 16,
|
||||
T1_model = 17,
|
||||
sparc5_instructions = 18,
|
||||
aes_instructions = 19
|
||||
aes_instructions = 19,
|
||||
sha1_instruction = 20,
|
||||
sha256_instruction = 21,
|
||||
sha512_instruction = 22
|
||||
};
|
||||
|
||||
enum Feature_Flag_Set {
|
||||
|
@ -77,6 +80,9 @@ protected:
|
|||
T1_model_m = 1 << T1_model,
|
||||
sparc5_instructions_m = 1 << sparc5_instructions,
|
||||
aes_instructions_m = 1 << aes_instructions,
|
||||
sha1_instruction_m = 1 << sha1_instruction,
|
||||
sha256_instruction_m = 1 << sha256_instruction,
|
||||
sha512_instruction_m = 1 << sha512_instruction,
|
||||
|
||||
generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
|
||||
generic_v9_m = generic_v8_m | v9_instructions_m,
|
||||
|
@ -129,6 +135,9 @@ public:
|
|||
static bool has_cbcond() { return (_features & cbcond_instructions_m) != 0; }
|
||||
static bool has_sparc5_instr() { return (_features & sparc5_instructions_m) != 0; }
|
||||
static bool has_aes() { return (_features & aes_instructions_m) != 0; }
|
||||
static bool has_sha1() { return (_features & sha1_instruction_m) != 0; }
|
||||
static bool has_sha256() { return (_features & sha256_instruction_m) != 0; }
|
||||
static bool has_sha512() { return (_features & sha512_instruction_m) != 0; }
|
||||
|
||||
static bool supports_compare_and_exchange()
|
||||
{ return has_v9(); }
|
||||
|
|
|
@ -590,6 +590,17 @@ void VM_Version::get_processor_features() {
|
|||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
|
||||
if (UseSHA) {
|
||||
warning("SHA instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseSHA, false);
|
||||
}
|
||||
if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
|
||||
warning("SHA intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
|
||||
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
|
||||
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
|
||||
}
|
||||
|
||||
// Adjust RTM (Restricted Transactional Memory) flags
|
||||
if (!supports_rtm() && UseRTMLocking) {
|
||||
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -137,6 +137,21 @@ int VM_Version::platform_features(int features) {
|
|||
#endif
|
||||
if (av & AV_SPARC_AES) features |= aes_instructions_m;
|
||||
|
||||
#ifndef AV_SPARC_SHA1
|
||||
#define AV_SPARC_SHA1 0x00400000 /* sha1 instruction supported */
|
||||
#endif
|
||||
if (av & AV_SPARC_SHA1) features |= sha1_instruction_m;
|
||||
|
||||
#ifndef AV_SPARC_SHA256
|
||||
#define AV_SPARC_SHA256 0x00800000 /* sha256 instruction supported */
|
||||
#endif
|
||||
if (av & AV_SPARC_SHA256) features |= sha256_instruction_m;
|
||||
|
||||
#ifndef AV_SPARC_SHA512
|
||||
#define AV_SPARC_SHA512 0x01000000 /* sha512 instruction supported */
|
||||
#endif
|
||||
if (av & AV_SPARC_SHA512) features |= sha512_instruction_m;
|
||||
|
||||
} else {
|
||||
// getisax(2) failed, use the old legacy code.
|
||||
#ifndef PRODUCT
|
||||
|
|
|
@ -790,6 +790,26 @@
|
|||
do_name( decrypt_name, "decrypt") \
|
||||
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
|
||||
\
|
||||
/* support for sun.security.provider.SHA */ \
|
||||
do_class(sun_security_provider_sha, "sun/security/provider/SHA") \
|
||||
do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \
|
||||
do_name( implCompress_name, "implCompress") \
|
||||
do_signature(implCompress_signature, "([BI)V") \
|
||||
\
|
||||
/* support for sun.security.provider.SHA2 */ \
|
||||
do_class(sun_security_provider_sha2, "sun/security/provider/SHA2") \
|
||||
do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R) \
|
||||
\
|
||||
/* support for sun.security.provider.SHA5 */ \
|
||||
do_class(sun_security_provider_sha5, "sun/security/provider/SHA5") \
|
||||
do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R) \
|
||||
\
|
||||
/* support for sun.security.provider.DigestBase */ \
|
||||
do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \
|
||||
do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \
|
||||
do_name( implCompressMB_name, "implCompressMultiBlock") \
|
||||
do_signature(implCompressMB_signature, "([BII)I") \
|
||||
\
|
||||
/* support for java.util.zip */ \
|
||||
do_class(java_util_zip_CRC32, "java/util/zip/CRC32") \
|
||||
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -939,7 +939,13 @@ void ConnectionGraph::process_call_arguments(CallNode *call) {
|
|||
strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0)
|
||||
strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha1_implCompress") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
|
||||
strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0)
|
||||
))) {
|
||||
call->dump();
|
||||
fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
|
||||
|
|
|
@ -316,6 +316,14 @@ class LibraryCallKit : public GraphKit {
|
|||
Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
|
||||
Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||
Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
|
||||
bool inline_sha_implCompress(vmIntrinsics::ID id);
|
||||
bool inline_digestBase_implCompressMB(int predicate);
|
||||
bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA,
|
||||
bool long_state, address stubAddr, const char *stubName,
|
||||
Node* src_start, Node* ofs, Node* limit);
|
||||
Node* get_state_from_sha_object(Node *sha_object);
|
||||
Node* get_state_from_sha5_object(Node *sha_object);
|
||||
Node* inline_digestBase_implCompressMB_predicate(int predicate);
|
||||
bool inline_encodeISOArray();
|
||||
bool inline_updateCRC32();
|
||||
bool inline_updateBytesCRC32();
|
||||
|
@ -519,6 +527,23 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
|||
predicates = 1;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_sha_implCompress:
|
||||
if (!UseSHA1Intrinsics) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_sha2_implCompress:
|
||||
if (!UseSHA256Intrinsics) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_sha5_implCompress:
|
||||
if (!UseSHA512Intrinsics) return NULL;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_digestBase_implCompressMB:
|
||||
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL;
|
||||
predicates = 3;
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_updateCRC32:
|
||||
case vmIntrinsics::_updateBytesCRC32:
|
||||
case vmIntrinsics::_updateByteBufferCRC32:
|
||||
|
@ -886,6 +911,14 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
|||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_sha_implCompress:
|
||||
case vmIntrinsics::_sha2_implCompress:
|
||||
case vmIntrinsics::_sha5_implCompress:
|
||||
return inline_sha_implCompress(intrinsic_id());
|
||||
|
||||
case vmIntrinsics::_digestBase_implCompressMB:
|
||||
return inline_digestBase_implCompressMB(predicate);
|
||||
|
||||
case vmIntrinsics::_encodeISOArray:
|
||||
return inline_encodeISOArray();
|
||||
|
||||
|
@ -923,6 +956,8 @@ Node* LibraryCallKit::try_to_predicate(int predicate) {
|
|||
return inline_cipherBlockChaining_AESCrypt_predicate(false);
|
||||
case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
|
||||
return inline_cipherBlockChaining_AESCrypt_predicate(true);
|
||||
case vmIntrinsics::_digestBase_implCompressMB:
|
||||
return inline_digestBase_implCompressMB_predicate(predicate);
|
||||
|
||||
default:
|
||||
// If you get here, it may be that someone has added a new intrinsic
|
||||
|
@ -6130,3 +6165,258 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt
|
|||
record_for_igvn(region);
|
||||
return _gvn.transform(region);
|
||||
}
|
||||
|
||||
//------------------------------inline_sha_implCompress-----------------------
|
||||
//
|
||||
// Calculate SHA (i.e., SHA-1) for single-block byte[] array.
|
||||
// void com.sun.security.provider.SHA.implCompress(byte[] buf, int ofs)
|
||||
//
|
||||
// Calculate SHA2 (i.e., SHA-244 or SHA-256) for single-block byte[] array.
|
||||
// void com.sun.security.provider.SHA2.implCompress(byte[] buf, int ofs)
|
||||
//
|
||||
// Calculate SHA5 (i.e., SHA-384 or SHA-512) for single-block byte[] array.
|
||||
// void com.sun.security.provider.SHA5.implCompress(byte[] buf, int ofs)
|
||||
//
|
||||
bool LibraryCallKit::inline_sha_implCompress(vmIntrinsics::ID id) {
|
||||
assert(callee()->signature()->size() == 2, "sha_implCompress has 2 parameters");
|
||||
|
||||
Node* sha_obj = argument(0);
|
||||
Node* src = argument(1); // type oop
|
||||
Node* ofs = argument(2); // type int
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
// 'src_start' points to src array + offset
|
||||
Node* src_start = array_element_address(src, ofs, src_elem);
|
||||
Node* state = NULL;
|
||||
address stubAddr;
|
||||
const char *stubName;
|
||||
|
||||
switch(id) {
|
||||
case vmIntrinsics::_sha_implCompress:
|
||||
assert(UseSHA1Intrinsics, "need SHA1 instruction support");
|
||||
state = get_state_from_sha_object(sha_obj);
|
||||
stubAddr = StubRoutines::sha1_implCompress();
|
||||
stubName = "sha1_implCompress";
|
||||
break;
|
||||
case vmIntrinsics::_sha2_implCompress:
|
||||
assert(UseSHA256Intrinsics, "need SHA256 instruction support");
|
||||
state = get_state_from_sha_object(sha_obj);
|
||||
stubAddr = StubRoutines::sha256_implCompress();
|
||||
stubName = "sha256_implCompress";
|
||||
break;
|
||||
case vmIntrinsics::_sha5_implCompress:
|
||||
assert(UseSHA512Intrinsics, "need SHA512 instruction support");
|
||||
state = get_state_from_sha5_object(sha_obj);
|
||||
stubAddr = StubRoutines::sha512_implCompress();
|
||||
stubName = "sha512_implCompress";
|
||||
break;
|
||||
default:
|
||||
fatal_unexpected_iid(id);
|
||||
return false;
|
||||
}
|
||||
if (state == NULL) return false;
|
||||
|
||||
// Call the stub.
|
||||
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::sha_implCompress_Type(),
|
||||
stubAddr, stubName, TypePtr::BOTTOM,
|
||||
src_start, state);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------inline_digestBase_implCompressMB-----------------------
|
||||
//
|
||||
// Calculate SHA/SHA2/SHA5 for multi-block byte[] array.
|
||||
// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
|
||||
//
|
||||
bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
|
||||
assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
|
||||
"need SHA1/SHA256/SHA512 instruction support");
|
||||
assert((uint)predicate < 3, "sanity");
|
||||
assert(callee()->signature()->size() == 3, "digestBase_implCompressMB has 3 parameters");
|
||||
|
||||
Node* digestBase_obj = argument(0); // The receiver was checked for NULL already.
|
||||
Node* src = argument(1); // byte[] array
|
||||
Node* ofs = argument(2); // type int
|
||||
Node* limit = argument(3); // type int
|
||||
|
||||
const Type* src_type = src->Value(&_gvn);
|
||||
const TypeAryPtr* top_src = src_type->isa_aryptr();
|
||||
if (top_src == NULL || top_src->klass() == NULL) {
|
||||
// failed array check
|
||||
return false;
|
||||
}
|
||||
// Figure out the size and type of the elements we will be copying.
|
||||
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
|
||||
if (src_elem != T_BYTE) {
|
||||
return false;
|
||||
}
|
||||
// 'src_start' points to src array + offset
|
||||
Node* src_start = array_element_address(src, ofs, src_elem);
|
||||
|
||||
const char* klass_SHA_name = NULL;
|
||||
const char* stub_name = NULL;
|
||||
address stub_addr = NULL;
|
||||
bool long_state = false;
|
||||
|
||||
switch (predicate) {
|
||||
case 0:
|
||||
if (UseSHA1Intrinsics) {
|
||||
klass_SHA_name = "sun/security/provider/SHA";
|
||||
stub_name = "sha1_implCompressMB";
|
||||
stub_addr = StubRoutines::sha1_implCompressMB();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (UseSHA256Intrinsics) {
|
||||
klass_SHA_name = "sun/security/provider/SHA2";
|
||||
stub_name = "sha256_implCompressMB";
|
||||
stub_addr = StubRoutines::sha256_implCompressMB();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (UseSHA512Intrinsics) {
|
||||
klass_SHA_name = "sun/security/provider/SHA5";
|
||||
stub_name = "sha512_implCompressMB";
|
||||
stub_addr = StubRoutines::sha512_implCompressMB();
|
||||
long_state = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
|
||||
}
|
||||
if (klass_SHA_name != NULL) {
|
||||
// get DigestBase klass to lookup for SHA klass
|
||||
const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
|
||||
assert(tinst != NULL, "digestBase_obj is not instance???");
|
||||
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||
|
||||
ciKlass* klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
|
||||
assert(klass_SHA->is_loaded(), "predicate checks that this class is loaded");
|
||||
ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
|
||||
return inline_sha_implCompressMB(digestBase_obj, instklass_SHA, long_state, stub_addr, stub_name, src_start, ofs, limit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------inline_sha_implCompressMB-----------------------
|
||||
bool LibraryCallKit::inline_sha_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_SHA,
|
||||
bool long_state, address stubAddr, const char *stubName,
|
||||
Node* src_start, Node* ofs, Node* limit) {
|
||||
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_SHA);
|
||||
const TypeOopPtr* xtype = aklass->as_instance_type();
|
||||
Node* sha_obj = new CheckCastPPNode(control(), digestBase_obj, xtype);
|
||||
sha_obj = _gvn.transform(sha_obj);
|
||||
|
||||
Node* state;
|
||||
if (long_state) {
|
||||
state = get_state_from_sha5_object(sha_obj);
|
||||
} else {
|
||||
state = get_state_from_sha_object(sha_obj);
|
||||
}
|
||||
if (state == NULL) return false;
|
||||
|
||||
// Call the stub.
|
||||
Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
|
||||
OptoRuntime::digestBase_implCompressMB_Type(),
|
||||
stubAddr, stubName, TypePtr::BOTTOM,
|
||||
src_start, state, ofs, limit);
|
||||
// return ofs (int)
|
||||
Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
|
||||
set_result(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------get_state_from_sha_object-----------------------
|
||||
Node * LibraryCallKit::get_state_from_sha_object(Node *sha_object) {
|
||||
Node* sha_state = load_field_from_object(sha_object, "state", "[I", /*is_exact*/ false);
|
||||
assert (sha_state != NULL, "wrong version of sun.security.provider.SHA/SHA2");
|
||||
if (sha_state == NULL) return (Node *) NULL;
|
||||
|
||||
// now have the array, need to get the start address of the state array
|
||||
Node* state = array_element_address(sha_state, intcon(0), T_INT);
|
||||
return state;
|
||||
}
|
||||
|
||||
//------------------------------get_state_from_sha5_object-----------------------
|
||||
Node * LibraryCallKit::get_state_from_sha5_object(Node *sha_object) {
|
||||
Node* sha_state = load_field_from_object(sha_object, "state", "[J", /*is_exact*/ false);
|
||||
assert (sha_state != NULL, "wrong version of sun.security.provider.SHA5");
|
||||
if (sha_state == NULL) return (Node *) NULL;
|
||||
|
||||
// now have the array, need to get the start address of the state array
|
||||
Node* state = array_element_address(sha_state, intcon(0), T_LONG);
|
||||
return state;
|
||||
}
|
||||
|
||||
//----------------------------inline_digestBase_implCompressMB_predicate----------------------------
|
||||
// Return node representing slow path of predicate check.
|
||||
// the pseudo code we want to emulate with this predicate is:
|
||||
// if (digestBaseObj instanceof SHA/SHA2/SHA5) do_intrinsic, else do_javapath
|
||||
//
|
||||
Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) {
|
||||
assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
|
||||
"need SHA1/SHA256/SHA512 instruction support");
|
||||
assert((uint)predicate < 3, "sanity");
|
||||
|
||||
// The receiver was checked for NULL already.
|
||||
Node* digestBaseObj = argument(0);
|
||||
|
||||
// get DigestBase klass for instanceOf check
|
||||
const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr();
|
||||
assert(tinst != NULL, "digestBaseObj is null");
|
||||
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
|
||||
|
||||
const char* klass_SHA_name = NULL;
|
||||
switch (predicate) {
|
||||
case 0:
|
||||
if (UseSHA1Intrinsics) {
|
||||
// we want to do an instanceof comparison against the SHA class
|
||||
klass_SHA_name = "sun/security/provider/SHA";
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (UseSHA256Intrinsics) {
|
||||
// we want to do an instanceof comparison against the SHA2 class
|
||||
klass_SHA_name = "sun/security/provider/SHA2";
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (UseSHA512Intrinsics) {
|
||||
// we want to do an instanceof comparison against the SHA5 class
|
||||
klass_SHA_name = "sun/security/provider/SHA5";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
|
||||
}
|
||||
|
||||
ciKlass* klass_SHA = NULL;
|
||||
if (klass_SHA_name != NULL) {
|
||||
klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
|
||||
}
|
||||
if ((klass_SHA == NULL) || !klass_SHA->is_loaded()) {
|
||||
// if none of SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path
|
||||
Node* ctrl = control();
|
||||
set_control(top()); // no intrinsic path
|
||||
return ctrl;
|
||||
}
|
||||
ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
|
||||
|
||||
Node* instofSHA = gen_instanceof(digestBaseObj, makecon(TypeKlassPtr::make(instklass_SHA)));
|
||||
Node* cmp_instof = _gvn.transform(new CmpINode(instofSHA, intcon(1)));
|
||||
Node* bool_instof = _gvn.transform(new BoolNode(cmp_instof, BoolTest::ne));
|
||||
Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
|
||||
|
||||
return instof_false; // even if it is NULL
|
||||
}
|
||||
|
|
|
@ -896,6 +896,50 @@ const TypeFunc* OptoRuntime::cipherBlockChaining_aescrypt_Type() {
|
|||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
/*
|
||||
* void implCompress(byte[] buf, int ofs)
|
||||
*/
|
||||
const TypeFunc* OptoRuntime::sha_implCompress_Type() {
|
||||
// create input type (domain)
|
||||
int num_args = 2;
|
||||
int argcnt = num_args;
|
||||
const Type** fields = TypeTuple::fields(argcnt);
|
||||
int argp = TypeFunc::Parms;
|
||||
fields[argp++] = TypePtr::NOTNULL; // buf
|
||||
fields[argp++] = TypePtr::NOTNULL; // state
|
||||
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||
|
||||
// no 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* int implCompressMultiBlock(byte[] b, int ofs, int limit)
|
||||
*/
|
||||
const TypeFunc* OptoRuntime::digestBase_implCompressMB_Type() {
|
||||
// create input type (domain)
|
||||
int num_args = 4;
|
||||
int argcnt = num_args;
|
||||
const Type** fields = TypeTuple::fields(argcnt);
|
||||
int argp = TypeFunc::Parms;
|
||||
fields[argp++] = TypePtr::NOTNULL; // buf
|
||||
fields[argp++] = TypePtr::NOTNULL; // state
|
||||
fields[argp++] = TypeInt::INT; // ofs
|
||||
fields[argp++] = TypeInt::INT; // limit
|
||||
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
|
||||
const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
|
||||
|
||||
// returning ofs (int)
|
||||
fields = TypeTuple::fields(1);
|
||||
fields[TypeFunc::Parms+0] = TypeInt::INT; // ofs
|
||||
const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
|
||||
return TypeFunc::make(domain, range);
|
||||
}
|
||||
|
||||
//------------- Interpreter state access for on stack replacement
|
||||
const TypeFunc* OptoRuntime::osr_end_Type() {
|
||||
// create input type (domain)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -300,6 +300,9 @@ private:
|
|||
static const TypeFunc* aescrypt_block_Type();
|
||||
static const TypeFunc* cipherBlockChaining_aescrypt_Type();
|
||||
|
||||
static const TypeFunc* sha_implCompress_Type();
|
||||
static const TypeFunc* digestBase_implCompressMB_Type();
|
||||
|
||||
static const TypeFunc* updateBytesCRC32_Type();
|
||||
|
||||
// leaf on stack replacement interpreter accessor types
|
||||
|
|
|
@ -599,6 +599,9 @@ class CommandLineFlags {
|
|||
product(bool, UseAES, false, \
|
||||
"Control whether AES instructions can be used on x86/x64") \
|
||||
\
|
||||
product(bool, UseSHA, false, \
|
||||
"Control whether SHA instructions can be used on SPARC") \
|
||||
\
|
||||
product(uintx, LargePageSizeInBytes, 0, \
|
||||
"Large page size (0 to let VM choose the page size)") \
|
||||
\
|
||||
|
@ -705,6 +708,15 @@ class CommandLineFlags {
|
|||
product(bool, UseAESIntrinsics, false, \
|
||||
"Use intrinsics for AES versions of crypto") \
|
||||
\
|
||||
product(bool, UseSHA1Intrinsics, false, \
|
||||
"Use intrinsics for SHA-1 crypto hash function") \
|
||||
\
|
||||
product(bool, UseSHA256Intrinsics, false, \
|
||||
"Use intrinsics for SHA-224 and SHA-256 crypto hash functions") \
|
||||
\
|
||||
product(bool, UseSHA512Intrinsics, false, \
|
||||
"Use intrinsics for SHA-384 and SHA-512 crypto hash functions") \
|
||||
\
|
||||
product(bool, UseCRC32Intrinsics, false, \
|
||||
"use intrinsics for java.util.zip.CRC32") \
|
||||
\
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -125,6 +125,13 @@ address StubRoutines::_aescrypt_decryptBlock = NULL;
|
|||
address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
|
||||
address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
|
||||
|
||||
address StubRoutines::_sha1_implCompress = NULL;
|
||||
address StubRoutines::_sha1_implCompressMB = NULL;
|
||||
address StubRoutines::_sha256_implCompress = NULL;
|
||||
address StubRoutines::_sha256_implCompressMB = NULL;
|
||||
address StubRoutines::_sha512_implCompress = NULL;
|
||||
address StubRoutines::_sha512_implCompressMB = NULL;
|
||||
|
||||
address StubRoutines::_updateBytesCRC32 = NULL;
|
||||
address StubRoutines::_crc_table_adr = NULL;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -207,6 +207,13 @@ class StubRoutines: AllStatic {
|
|||
static address _cipherBlockChaining_encryptAESCrypt;
|
||||
static address _cipherBlockChaining_decryptAESCrypt;
|
||||
|
||||
static address _sha1_implCompress;
|
||||
static address _sha1_implCompressMB;
|
||||
static address _sha256_implCompress;
|
||||
static address _sha256_implCompressMB;
|
||||
static address _sha512_implCompress;
|
||||
static address _sha512_implCompressMB;
|
||||
|
||||
static address _updateBytesCRC32;
|
||||
static address _crc_table_adr;
|
||||
|
||||
|
@ -356,6 +363,13 @@ class StubRoutines: AllStatic {
|
|||
static address cipherBlockChaining_encryptAESCrypt() { return _cipherBlockChaining_encryptAESCrypt; }
|
||||
static address cipherBlockChaining_decryptAESCrypt() { return _cipherBlockChaining_decryptAESCrypt; }
|
||||
|
||||
static address sha1_implCompress() { return _sha1_implCompress; }
|
||||
static address sha1_implCompressMB() { return _sha1_implCompressMB; }
|
||||
static address sha256_implCompress() { return _sha256_implCompress; }
|
||||
static address sha256_implCompressMB() { return _sha256_implCompressMB; }
|
||||
static address sha512_implCompress() { return _sha512_implCompress; }
|
||||
static address sha512_implCompressMB() { return _sha512_implCompressMB; }
|
||||
|
||||
static address updateBytesCRC32() { return _updateBytesCRC32; }
|
||||
static address crc_table_addr() { return _crc_table_adr; }
|
||||
|
||||
|
|
141
hotspot/test/compiler/intrinsics/sha/TestSHA.java
Normal file
141
hotspot/test/compiler/intrinsics/sha/TestSHA.java
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8035968
|
||||
* @summary C2 support for SHA on SPARC
|
||||
*
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 TestSHA
|
||||
*
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Doffset=1 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 -Doffset=1 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Doffset=1 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 -Doffset=1 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 -Doffset=1 TestSHA
|
||||
*
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=SHA-256 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=SHA-512 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Dalgorithm2=SHA-512 TestSHA
|
||||
*
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1 -Dalgorithm2=MD5 TestSHA
|
||||
* @run main/othervm/timeout=600 -Xbatch -Dalgorithm=MD5 -Dalgorithm2=SHA-1 TestSHA
|
||||
*/
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class TestSHA {
|
||||
private static final int HASH_LEN = 64; /* up to 512-bit */
|
||||
private static final int ALIGN = 8; /* for different data alignments */
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String provider = System.getProperty("provider", "SUN");
|
||||
String algorithm = System.getProperty("algorithm", "SHA-1");
|
||||
String algorithm2 = System.getProperty("algorithm2", "");
|
||||
int msgSize = Integer.getInteger("msgSize", 1024);
|
||||
int offset = Integer.getInteger("offset", 0) % ALIGN;
|
||||
int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 100000);
|
||||
int warmupIters = (args.length > 1 ? Integer.valueOf(args[1]) : 20000);
|
||||
|
||||
testSHA(provider, algorithm, msgSize, offset, iters, warmupIters);
|
||||
|
||||
if (algorithm2.equals("") == false) {
|
||||
testSHA(provider, algorithm2, msgSize, offset, iters, warmupIters);
|
||||
}
|
||||
}
|
||||
|
||||
static void testSHA(String provider, String algorithm, int msgSize,
|
||||
int offset, int iters, int warmupIters) throws Exception {
|
||||
System.out.println("provider = " + provider);
|
||||
System.out.println("algorithm = " + algorithm);
|
||||
System.out.println("msgSize = " + msgSize + " bytes");
|
||||
System.out.println("offset = " + offset);
|
||||
System.out.println("iters = " + iters);
|
||||
|
||||
byte[] expectedHash = new byte[HASH_LEN];
|
||||
byte[] hash = new byte[HASH_LEN];
|
||||
byte[] data = new byte[msgSize + offset];
|
||||
for (int i = 0; i < (msgSize + offset); i++) {
|
||||
data[i] = (byte)(i & 0xff);
|
||||
}
|
||||
|
||||
try {
|
||||
MessageDigest sha = MessageDigest.getInstance(algorithm, provider);
|
||||
|
||||
/* do once, which doesn't use intrinsics */
|
||||
sha.reset();
|
||||
sha.update(data, offset, msgSize);
|
||||
expectedHash = sha.digest();
|
||||
|
||||
/* warm up */
|
||||
for (int i = 0; i < warmupIters; i++) {
|
||||
sha.reset();
|
||||
sha.update(data, offset, msgSize);
|
||||
hash = sha.digest();
|
||||
}
|
||||
|
||||
/* check result */
|
||||
if (Arrays.equals(hash, expectedHash) == false) {
|
||||
System.out.println("TestSHA Error: ");
|
||||
showArray(expectedHash, "expectedHash");
|
||||
showArray(hash, "computedHash");
|
||||
//System.exit(1);
|
||||
throw new Exception("TestSHA Error");
|
||||
} else {
|
||||
showArray(hash, "hash");
|
||||
}
|
||||
|
||||
/* measure performance */
|
||||
long start = System.nanoTime();
|
||||
for (int i = 0; i < iters; i++) {
|
||||
sha.reset();
|
||||
sha.update(data, offset, msgSize);
|
||||
hash = sha.digest();
|
||||
}
|
||||
long end = System.nanoTime();
|
||||
double total = (double)(end - start)/1e9; /* in seconds */
|
||||
double thruput = (double)msgSize*iters/1e6/total; /* in MB/s */
|
||||
System.out.println("TestSHA runtime = " + total + " seconds");
|
||||
System.out.println("TestSHA throughput = " + thruput + " MB/s");
|
||||
System.out.println();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception: " + e);
|
||||
//System.exit(1);
|
||||
throw new Exception(e);
|
||||
}
|
||||
}
|
||||
|
||||
static void showArray(byte b[], String name) {
|
||||
System.out.format("%s [%d]: ", name, b.length);
|
||||
for (int i = 0; i < Math.min(b.length, HASH_LEN); i++) {
|
||||
System.out.format("%02x ", b[i] & 0xff);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue