< prev index next >
src/hotspot/share/opto/library_call.cpp
Print this page
rev 60737 : 8252204: AArch64: Implement SHA3 accelerator/intrinsic
Reviewed-by: duke
Contributed-by: dongbo4@huawei.com
*** 306,319 ****
bool inline_ghash_processBlocks();
bool inline_base64_encodeBlock();
bool inline_digestBase_implCompress(vmIntrinsics::ID id);
bool inline_digestBase_implCompressMB(int predicate);
bool inline_digestBase_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass,
! bool long_state, address stubAddr, const char *stubName,
Node* src_start, Node* ofs, Node* limit);
! Node* get_state_from_digest_object(Node *digestBase_object);
! Node* get_long_state_from_digest_object(Node *digestBase_object);
Node* inline_digestBase_implCompressMB_predicate(int predicate);
bool inline_encodeISOArray();
bool inline_updateCRC32();
bool inline_updateBytesCRC32();
bool inline_updateByteBufferCRC32();
--- 306,319 ----
bool inline_ghash_processBlocks();
bool inline_base64_encodeBlock();
bool inline_digestBase_implCompress(vmIntrinsics::ID id);
bool inline_digestBase_implCompressMB(int predicate);
bool inline_digestBase_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass,
! const char* state_type, address stubAddr, const char *stubName,
Node* src_start, Node* ofs, Node* limit);
! Node* get_state_from_digest_object(Node *digestBase_object, const char* state_type);
! Node* get_digest_length_from_digest_object(Node *digestBase_object);
Node* inline_digestBase_implCompressMB_predicate(int predicate);
bool inline_encodeISOArray();
bool inline_updateCRC32();
bool inline_updateBytesCRC32();
bool inline_updateByteBufferCRC32();
*** 828,837 ****
--- 828,838 ----
case vmIntrinsics::_md5_implCompress:
case vmIntrinsics::_sha_implCompress:
case vmIntrinsics::_sha2_implCompress:
case vmIntrinsics::_sha5_implCompress:
+ case vmIntrinsics::_sha3_implCompress:
return inline_digestBase_implCompress(intrinsic_id());
case vmIntrinsics::_digestBase_implCompressMB:
return inline_digestBase_implCompressMB(predicate);
*** 6426,6435 ****
--- 6427,6439 ----
// 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)
//
+ // Calculate SHA3 (i.e., SHA3-224 or SHA3-256 or SHA3-384 or SHA3-512) for single-block byte[] array.
+ // void com.sun.security.provider.SHA3.implCompress(byte[] buf, int ofs)
+ //
bool LibraryCallKit::inline_digestBase_implCompress(vmIntrinsics::ID id) {
assert(callee()->signature()->size() == 2, "sha_implCompress has 2 parameters");
Node* digestBase_obj = argument(0);
Node* src = argument(1); // type oop
*** 6448,6511 ****
}
// 'src_start' points to src array + offset
src = must_be_not_null(src, true);
Node* src_start = array_element_address(src, ofs, src_elem);
Node* state = NULL;
address stubAddr;
const char *stubName;
switch(id) {
case vmIntrinsics::_md5_implCompress:
assert(UseMD5Intrinsics, "need MD5 instruction support");
! state = get_state_from_digest_object(digestBase_obj);
stubAddr = StubRoutines::md5_implCompress();
stubName = "md5_implCompress";
break;
case vmIntrinsics::_sha_implCompress:
assert(UseSHA1Intrinsics, "need SHA1 instruction support");
! state = get_state_from_digest_object(digestBase_obj);
stubAddr = StubRoutines::sha1_implCompress();
stubName = "sha1_implCompress";
break;
case vmIntrinsics::_sha2_implCompress:
assert(UseSHA256Intrinsics, "need SHA256 instruction support");
! state = get_state_from_digest_object(digestBase_obj);
stubAddr = StubRoutines::sha256_implCompress();
stubName = "sha256_implCompress";
break;
case vmIntrinsics::_sha5_implCompress:
assert(UseSHA512Intrinsics, "need SHA512 instruction support");
! state = get_long_state_from_digest_object(digestBase_obj);
stubAddr = StubRoutines::sha512_implCompress();
stubName = "sha512_implCompress";
break;
default:
fatal_unexpected_iid(id);
return false;
}
if (state == NULL) return false;
assert(stubAddr != NULL, "Stub is generated");
if (stubAddr == NULL) return false;
// Call the stub.
! Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::digestBase_implCompress_Type(),
stubAddr, stubName, TypePtr::BOTTOM,
src_start, state);
return true;
}
//------------------------------inline_digestBase_implCompressMB-----------------------
//
! // Calculate MD5/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(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
! "need MD5/SHA1/SHA256/SHA512 instruction support");
! assert((uint)predicate < 4, "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
--- 6452,6531 ----
}
// 'src_start' points to src array + offset
src = must_be_not_null(src, true);
Node* src_start = array_element_address(src, ofs, src_elem);
Node* state = NULL;
+ Node* digest_length = NULL;
address stubAddr;
const char *stubName;
switch(id) {
case vmIntrinsics::_md5_implCompress:
assert(UseMD5Intrinsics, "need MD5 instruction support");
! state = get_state_from_digest_object(digestBase_obj, "[I");
stubAddr = StubRoutines::md5_implCompress();
stubName = "md5_implCompress";
break;
case vmIntrinsics::_sha_implCompress:
assert(UseSHA1Intrinsics, "need SHA1 instruction support");
! state = get_state_from_digest_object(digestBase_obj, "[I");
stubAddr = StubRoutines::sha1_implCompress();
stubName = "sha1_implCompress";
break;
case vmIntrinsics::_sha2_implCompress:
assert(UseSHA256Intrinsics, "need SHA256 instruction support");
! state = get_state_from_digest_object(digestBase_obj, "[I");
stubAddr = StubRoutines::sha256_implCompress();
stubName = "sha256_implCompress";
break;
case vmIntrinsics::_sha5_implCompress:
assert(UseSHA512Intrinsics, "need SHA512 instruction support");
! state = get_state_from_digest_object(digestBase_obj, "[J");
stubAddr = StubRoutines::sha512_implCompress();
stubName = "sha512_implCompress";
break;
+ case vmIntrinsics::_sha3_implCompress:
+ assert(UseSHA3Intrinsics, "need SHA3 instruction support");
+ state = get_state_from_digest_object(digestBase_obj, "[B");
+ stubAddr = StubRoutines::sha3_implCompress();
+ stubName = "sha3_implCompress";
+ digest_length = get_digest_length_from_digest_object(digestBase_obj);
+ if (digest_length == NULL) return false;
+ break;
default:
fatal_unexpected_iid(id);
return false;
}
if (state == NULL) return false;
assert(stubAddr != NULL, "Stub is generated");
if (stubAddr == NULL) return false;
// Call the stub.
! Node* call;
! if (digest_length == NULL) {
! call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::digestBase_implCompress_Type(false),
stubAddr, stubName, TypePtr::BOTTOM,
src_start, state);
+ } else {
+ call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::digestBase_implCompress_Type(true),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ src_start, state, digest_length);
+ }
return true;
}
//------------------------------inline_digestBase_implCompressMB-----------------------
//
! // Calculate MD5/SHA/SHA2/SHA5/SHA3 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(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics || UseSHA3Intrinsics,
! "need MD5/SHA1/SHA256/SHA512/SHA3 instruction support");
! assert((uint)predicate < 5, "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
*** 6527,6537 ****
Node* src_start = array_element_address(src, ofs, src_elem);
const char* klass_digestBase_name = NULL;
const char* stub_name = NULL;
address stub_addr = NULL;
! bool long_state = false;
switch (predicate) {
case 0:
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_md5_implCompress)) {
klass_digestBase_name = "sun/security/provider/MD5";
--- 6547,6557 ----
Node* src_start = array_element_address(src, ofs, src_elem);
const char* klass_digestBase_name = NULL;
const char* stub_name = NULL;
address stub_addr = NULL;
! const char* state_type = "[I";
switch (predicate) {
case 0:
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_md5_implCompress)) {
klass_digestBase_name = "sun/security/provider/MD5";
*** 6556,6566 ****
case 3:
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha5_implCompress)) {
klass_digestBase_name = "sun/security/provider/SHA5";
stub_name = "sha512_implCompressMB";
stub_addr = StubRoutines::sha512_implCompressMB();
! long_state = true;
}
break;
default:
fatal("unknown DigestBase intrinsic predicate: %d", predicate);
}
--- 6576,6594 ----
case 3:
if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha5_implCompress)) {
klass_digestBase_name = "sun/security/provider/SHA5";
stub_name = "sha512_implCompressMB";
stub_addr = StubRoutines::sha512_implCompressMB();
! state_type = "[J";
! }
! break;
! case 4:
! if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_sha3_implCompress)) {
! klass_digestBase_name = "sun/security/provider/SHA3";
! stub_name = "sha3_implCompressMB";
! stub_addr = StubRoutines::sha3_implCompressMB();
! state_type = "[B";
}
break;
default:
fatal("unknown DigestBase intrinsic predicate: %d", predicate);
}
*** 6574,6648 ****
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
ciKlass* klass_digestBase = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
assert(klass_digestBase->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_digestBase = klass_digestBase->as_instance_klass();
! return inline_digestBase_implCompressMB(digestBase_obj, instklass_digestBase, long_state, stub_addr, stub_name, src_start, ofs, limit);
}
return false;
}
//------------------------------inline_digestBase_implCompressMB-----------------------
bool LibraryCallKit::inline_digestBase_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_digestBase,
! bool long_state, address stubAddr, const char *stubName,
Node* src_start, Node* ofs, Node* limit) {
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_digestBase);
const TypeOopPtr* xtype = aklass->as_instance_type();
Node* digest_obj = new CheckCastPPNode(control(), digestBase_obj, xtype);
digest_obj = _gvn.transform(digest_obj);
! Node* state;
! if (long_state) {
! state = get_long_state_from_digest_object(digest_obj);
! } else {
! state = get_state_from_digest_object(digest_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_digest_object-----------------------
! Node * LibraryCallKit::get_state_from_digest_object(Node *digest_object) {
! Node* digest_state = load_field_from_object(digest_object, "state", "[I", /*is_exact*/ false);
! assert (digest_state != NULL, "wrong version of sun.security.provider.MD5/SHA/SHA2");
if (digest_state == NULL) return (Node *) NULL;
// now have the array, need to get the start address of the state array
Node* state = array_element_address(digest_state, intcon(0), T_INT);
return state;
}
! //------------------------------get_long_state_from_digest_object-----------------------
! Node * LibraryCallKit::get_long_state_from_digest_object(Node *digest_object) {
! Node* digest_state = load_field_from_object(digest_object, "state", "[J", /*is_exact*/ false);
! assert (digest_state != NULL, "wrong version of sun.security.provider.SHA5");
! if (digest_state == NULL) return (Node *) NULL;
!
! // now have the array, need to get the start address of the state array
! Node* state = array_element_address(digest_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 MD5/SHA/SHA2/SHA5) do_intrinsic, else do_javapath
//
Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) {
! assert(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
! "need MD5/SHA1/SHA256/SHA512 instruction support");
! assert((uint)predicate < 4, "sanity");
// The receiver was checked for NULL already.
Node* digestBaseObj = argument(0);
// get DigestBase klass for instanceOf check
--- 6602,6682 ----
assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
ciKlass* klass_digestBase = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_digestBase_name));
assert(klass_digestBase->is_loaded(), "predicate checks that this class is loaded");
ciInstanceKlass* instklass_digestBase = klass_digestBase->as_instance_klass();
! return inline_digestBase_implCompressMB(digestBase_obj, instklass_digestBase, state_type, stub_addr, stub_name, src_start, ofs, limit);
}
return false;
}
//------------------------------inline_digestBase_implCompressMB-----------------------
bool LibraryCallKit::inline_digestBase_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_digestBase,
! const char* state_type, address stubAddr, const char *stubName,
Node* src_start, Node* ofs, Node* limit) {
const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_digestBase);
const TypeOopPtr* xtype = aklass->as_instance_type();
Node* digest_obj = new CheckCastPPNode(control(), digestBase_obj, xtype);
digest_obj = _gvn.transform(digest_obj);
! Node* state = get_state_from_digest_object(digest_obj, state_type);
if (state == NULL) return false;
+ Node* digest_length = NULL;
+ if (strcmp("sha3_implCompressMB", stubName) == 0) {
+ digest_length = get_digest_length_from_digest_object(digest_obj);
+ if (digest_length == NULL) return false;
+ }
+
// Call the stub.
! Node* call;
! if (digest_length == NULL) {
! call = make_runtime_call(RC_LEAF|RC_NO_FP,
! OptoRuntime::digestBase_implCompressMB_Type(false),
stubAddr, stubName, TypePtr::BOTTOM,
src_start, state, ofs, limit);
+ } else {
+ call = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::digestBase_implCompressMB_Type(true),
+ stubAddr, stubName, TypePtr::BOTTOM,
+ src_start, state, digest_length, ofs, limit);
+ }
+
// return ofs (int)
Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
set_result(result);
return true;
}
//------------------------------get_state_from_digest_object-----------------------
! Node * LibraryCallKit::get_state_from_digest_object(Node *digest_object, const char *state_type) {
! Node* digest_state = load_field_from_object(digest_object, "state", state_type, /*is_exact*/ false);
! assert (digest_state != NULL, "wrong version of sun.security.provider.MD5/SHA/SHA2/SHA5/SHA3");
if (digest_state == NULL) return (Node *) NULL;
// now have the array, need to get the start address of the state array
Node* state = array_element_address(digest_state, intcon(0), T_INT);
return state;
}
! //------------------------------get_digest_length_from_sha3_object----------------------------------
! Node * LibraryCallKit::get_digest_length_from_digest_object(Node *digest_object) {
! Node* digest_length = load_field_from_object(digest_object, "digestLength", "I", /*is_exact*/ false);
! assert (digest_length != NULL, "sanity");
! return digest_length;
}
//----------------------------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 MD5/SHA/SHA2/SHA5/SHA3) do_intrinsic, else do_javapath
//
Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) {
! assert(UseMD5Intrinsics || UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics || UseSHA3Intrinsics,
! "need MD5/SHA1/SHA256/SHA512/SHA3 instruction support");
! assert((uint)predicate < 5, "sanity");
// The receiver was checked for NULL already.
Node* digestBaseObj = argument(0);
// get DigestBase klass for instanceOf check
*** 6674,6683 ****
--- 6708,6723 ----
if (UseSHA512Intrinsics) {
// we want to do an instanceof comparison against the SHA5 class
klass_name = "sun/security/provider/SHA5";
}
break;
+ case 4:
+ if (UseSHA3Intrinsics) {
+ // we want to do an instanceof comparison against the SHA3 class
+ klass_name = "sun/security/provider/SHA3";
+ }
+ break;
default:
fatal("unknown SHA intrinsic predicate: %d", predicate);
}
ciKlass* klass = NULL;
< prev index next >