Mercurial > hg > graal-compiler
comparison src/share/vm/opto/library_call.cpp @ 20313:b20a35eae442
8035968: Leverage CPU Instructions to Improve SHA Performance on SPARC
Summary: Add C2 SHA intrinsics on SPARC
Reviewed-by: kvn, roland
Contributed-by: james.cheng@oracle.com
author | kvn |
---|---|
date | Wed, 11 Jun 2014 11:05:10 -0700 |
parents | 922c87c9aed4 |
children | 411e30e5fbb8 |
comparison
equal
deleted
inserted
replaced
20312:922c87c9aed4 | 20313:b20a35eae442 |
---|---|
308 bool inline_aescrypt_Block(vmIntrinsics::ID id); | 308 bool inline_aescrypt_Block(vmIntrinsics::ID id); |
309 bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); | 309 bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); |
310 Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); | 310 Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); |
311 Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); | 311 Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); |
312 Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object); | 312 Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object); |
313 bool inline_sha_implCompress(vmIntrinsics::ID id); | |
314 bool inline_digestBase_implCompressMB(int predicate); | |
315 bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA, | |
316 bool long_state, address stubAddr, const char *stubName, | |
317 Node* src_start, Node* ofs, Node* limit); | |
318 Node* get_state_from_sha_object(Node *sha_object); | |
319 Node* get_state_from_sha5_object(Node *sha_object); | |
320 Node* inline_digestBase_implCompressMB_predicate(int predicate); | |
313 bool inline_encodeISOArray(); | 321 bool inline_encodeISOArray(); |
314 bool inline_updateCRC32(); | 322 bool inline_updateCRC32(); |
315 bool inline_updateBytesCRC32(); | 323 bool inline_updateBytesCRC32(); |
316 bool inline_updateByteBufferCRC32(); | 324 bool inline_updateByteBufferCRC32(); |
317 }; | 325 }; |
512 if (!UseAESIntrinsics) return NULL; | 520 if (!UseAESIntrinsics) return NULL; |
513 // these two require the predicated logic | 521 // these two require the predicated logic |
514 predicates = 1; | 522 predicates = 1; |
515 break; | 523 break; |
516 | 524 |
525 case vmIntrinsics::_sha_implCompress: | |
526 if (!UseSHA1Intrinsics) return NULL; | |
527 break; | |
528 | |
529 case vmIntrinsics::_sha2_implCompress: | |
530 if (!UseSHA256Intrinsics) return NULL; | |
531 break; | |
532 | |
533 case vmIntrinsics::_sha5_implCompress: | |
534 if (!UseSHA512Intrinsics) return NULL; | |
535 break; | |
536 | |
537 case vmIntrinsics::_digestBase_implCompressMB: | |
538 if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL; | |
539 predicates = 3; | |
540 break; | |
541 | |
517 case vmIntrinsics::_updateCRC32: | 542 case vmIntrinsics::_updateCRC32: |
518 case vmIntrinsics::_updateBytesCRC32: | 543 case vmIntrinsics::_updateBytesCRC32: |
519 case vmIntrinsics::_updateByteBufferCRC32: | 544 case vmIntrinsics::_updateByteBufferCRC32: |
520 if (!UseCRC32Intrinsics) return NULL; | 545 if (!UseCRC32Intrinsics) return NULL; |
521 break; | 546 break; |
877 | 902 |
878 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | 903 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
879 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | 904 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
880 return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); | 905 return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); |
881 | 906 |
907 case vmIntrinsics::_sha_implCompress: | |
908 case vmIntrinsics::_sha2_implCompress: | |
909 case vmIntrinsics::_sha5_implCompress: | |
910 return inline_sha_implCompress(intrinsic_id()); | |
911 | |
912 case vmIntrinsics::_digestBase_implCompressMB: | |
913 return inline_digestBase_implCompressMB(predicate); | |
914 | |
882 case vmIntrinsics::_encodeISOArray: | 915 case vmIntrinsics::_encodeISOArray: |
883 return inline_encodeISOArray(); | 916 return inline_encodeISOArray(); |
884 | 917 |
885 case vmIntrinsics::_updateCRC32: | 918 case vmIntrinsics::_updateCRC32: |
886 return inline_updateCRC32(); | 919 return inline_updateCRC32(); |
914 switch (intrinsic_id()) { | 947 switch (intrinsic_id()) { |
915 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: | 948 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
916 return inline_cipherBlockChaining_AESCrypt_predicate(false); | 949 return inline_cipherBlockChaining_AESCrypt_predicate(false); |
917 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: | 950 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
918 return inline_cipherBlockChaining_AESCrypt_predicate(true); | 951 return inline_cipherBlockChaining_AESCrypt_predicate(true); |
952 case vmIntrinsics::_digestBase_implCompressMB: | |
953 return inline_digestBase_implCompressMB_predicate(predicate); | |
919 | 954 |
920 default: | 955 default: |
921 // If you get here, it may be that someone has added a new intrinsic | 956 // If you get here, it may be that someone has added a new intrinsic |
922 // to the list in vmSymbols.hpp without implementing it here. | 957 // to the list in vmSymbols.hpp without implementing it here. |
923 #ifndef PRODUCT | 958 #ifndef PRODUCT |
6126 region->init_req(2, src_dest_conjoint); | 6161 region->init_req(2, src_dest_conjoint); |
6127 | 6162 |
6128 record_for_igvn(region); | 6163 record_for_igvn(region); |
6129 return _gvn.transform(region); | 6164 return _gvn.transform(region); |
6130 } | 6165 } |
6166 | |
6167 //------------------------------inline_sha_implCompress----------------------- | |
6168 // | |
6169 // Calculate SHA (i.e., SHA-1) for single-block byte[] array. | |
6170 // void com.sun.security.provider.SHA.implCompress(byte[] buf, int ofs) | |
6171 // | |
6172 // Calculate SHA2 (i.e., SHA-244 or SHA-256) for single-block byte[] array. | |
6173 // void com.sun.security.provider.SHA2.implCompress(byte[] buf, int ofs) | |
6174 // | |
6175 // Calculate SHA5 (i.e., SHA-384 or SHA-512) for single-block byte[] array. | |
6176 // void com.sun.security.provider.SHA5.implCompress(byte[] buf, int ofs) | |
6177 // | |
6178 bool LibraryCallKit::inline_sha_implCompress(vmIntrinsics::ID id) { | |
6179 assert(callee()->signature()->size() == 2, "sha_implCompress has 2 parameters"); | |
6180 | |
6181 Node* sha_obj = argument(0); | |
6182 Node* src = argument(1); // type oop | |
6183 Node* ofs = argument(2); // type int | |
6184 | |
6185 const Type* src_type = src->Value(&_gvn); | |
6186 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
6187 if (top_src == NULL || top_src->klass() == NULL) { | |
6188 // failed array check | |
6189 return false; | |
6190 } | |
6191 // Figure out the size and type of the elements we will be copying. | |
6192 BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); | |
6193 if (src_elem != T_BYTE) { | |
6194 return false; | |
6195 } | |
6196 // 'src_start' points to src array + offset | |
6197 Node* src_start = array_element_address(src, ofs, src_elem); | |
6198 Node* state = NULL; | |
6199 address stubAddr; | |
6200 const char *stubName; | |
6201 | |
6202 switch(id) { | |
6203 case vmIntrinsics::_sha_implCompress: | |
6204 assert(UseSHA1Intrinsics, "need SHA1 instruction support"); | |
6205 state = get_state_from_sha_object(sha_obj); | |
6206 stubAddr = StubRoutines::sha1_implCompress(); | |
6207 stubName = "sha1_implCompress"; | |
6208 break; | |
6209 case vmIntrinsics::_sha2_implCompress: | |
6210 assert(UseSHA256Intrinsics, "need SHA256 instruction support"); | |
6211 state = get_state_from_sha_object(sha_obj); | |
6212 stubAddr = StubRoutines::sha256_implCompress(); | |
6213 stubName = "sha256_implCompress"; | |
6214 break; | |
6215 case vmIntrinsics::_sha5_implCompress: | |
6216 assert(UseSHA512Intrinsics, "need SHA512 instruction support"); | |
6217 state = get_state_from_sha5_object(sha_obj); | |
6218 stubAddr = StubRoutines::sha512_implCompress(); | |
6219 stubName = "sha512_implCompress"; | |
6220 break; | |
6221 default: | |
6222 fatal_unexpected_iid(id); | |
6223 return false; | |
6224 } | |
6225 if (state == NULL) return false; | |
6226 | |
6227 // Call the stub. | |
6228 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::sha_implCompress_Type(), | |
6229 stubAddr, stubName, TypePtr::BOTTOM, | |
6230 src_start, state); | |
6231 | |
6232 return true; | |
6233 } | |
6234 | |
6235 //------------------------------inline_digestBase_implCompressMB----------------------- | |
6236 // | |
6237 // Calculate SHA/SHA2/SHA5 for multi-block byte[] array. | |
6238 // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) | |
6239 // | |
6240 bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) { | |
6241 assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics, | |
6242 "need SHA1/SHA256/SHA512 instruction support"); | |
6243 assert((uint)predicate < 3, "sanity"); | |
6244 assert(callee()->signature()->size() == 3, "digestBase_implCompressMB has 3 parameters"); | |
6245 | |
6246 Node* digestBase_obj = argument(0); // The receiver was checked for NULL already. | |
6247 Node* src = argument(1); // byte[] array | |
6248 Node* ofs = argument(2); // type int | |
6249 Node* limit = argument(3); // type int | |
6250 | |
6251 const Type* src_type = src->Value(&_gvn); | |
6252 const TypeAryPtr* top_src = src_type->isa_aryptr(); | |
6253 if (top_src == NULL || top_src->klass() == NULL) { | |
6254 // failed array check | |
6255 return false; | |
6256 } | |
6257 // Figure out the size and type of the elements we will be copying. | |
6258 BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); | |
6259 if (src_elem != T_BYTE) { | |
6260 return false; | |
6261 } | |
6262 // 'src_start' points to src array + offset | |
6263 Node* src_start = array_element_address(src, ofs, src_elem); | |
6264 | |
6265 const char* klass_SHA_name = NULL; | |
6266 const char* stub_name = NULL; | |
6267 address stub_addr = NULL; | |
6268 bool long_state = false; | |
6269 | |
6270 switch (predicate) { | |
6271 case 0: | |
6272 if (UseSHA1Intrinsics) { | |
6273 klass_SHA_name = "sun/security/provider/SHA"; | |
6274 stub_name = "sha1_implCompressMB"; | |
6275 stub_addr = StubRoutines::sha1_implCompressMB(); | |
6276 } | |
6277 break; | |
6278 case 1: | |
6279 if (UseSHA256Intrinsics) { | |
6280 klass_SHA_name = "sun/security/provider/SHA2"; | |
6281 stub_name = "sha256_implCompressMB"; | |
6282 stub_addr = StubRoutines::sha256_implCompressMB(); | |
6283 } | |
6284 break; | |
6285 case 2: | |
6286 if (UseSHA512Intrinsics) { | |
6287 klass_SHA_name = "sun/security/provider/SHA5"; | |
6288 stub_name = "sha512_implCompressMB"; | |
6289 stub_addr = StubRoutines::sha512_implCompressMB(); | |
6290 long_state = true; | |
6291 } | |
6292 break; | |
6293 default: | |
6294 fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate)); | |
6295 } | |
6296 if (klass_SHA_name != NULL) { | |
6297 // get DigestBase klass to lookup for SHA klass | |
6298 const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr(); | |
6299 assert(tinst != NULL, "digestBase_obj is not instance???"); | |
6300 assert(tinst->klass()->is_loaded(), "DigestBase is not loaded"); | |
6301 | |
6302 ciKlass* klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name)); | |
6303 assert(klass_SHA->is_loaded(), "predicate checks that this class is loaded"); | |
6304 ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass(); | |
6305 return inline_sha_implCompressMB(digestBase_obj, instklass_SHA, long_state, stub_addr, stub_name, src_start, ofs, limit); | |
6306 } | |
6307 return false; | |
6308 } | |
6309 //------------------------------inline_sha_implCompressMB----------------------- | |
6310 bool LibraryCallKit::inline_sha_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_SHA, | |
6311 bool long_state, address stubAddr, const char *stubName, | |
6312 Node* src_start, Node* ofs, Node* limit) { | |
6313 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_SHA); | |
6314 const TypeOopPtr* xtype = aklass->as_instance_type(); | |
6315 Node* sha_obj = new (C) CheckCastPPNode(control(), digestBase_obj, xtype); | |
6316 sha_obj = _gvn.transform(sha_obj); | |
6317 | |
6318 Node* state; | |
6319 if (long_state) { | |
6320 state = get_state_from_sha5_object(sha_obj); | |
6321 } else { | |
6322 state = get_state_from_sha_object(sha_obj); | |
6323 } | |
6324 if (state == NULL) return false; | |
6325 | |
6326 // Call the stub. | |
6327 Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, | |
6328 OptoRuntime::digestBase_implCompressMB_Type(), | |
6329 stubAddr, stubName, TypePtr::BOTTOM, | |
6330 src_start, state, ofs, limit); | |
6331 // return ofs (int) | |
6332 Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms)); | |
6333 set_result(result); | |
6334 | |
6335 return true; | |
6336 } | |
6337 | |
6338 //------------------------------get_state_from_sha_object----------------------- | |
6339 Node * LibraryCallKit::get_state_from_sha_object(Node *sha_object) { | |
6340 Node* sha_state = load_field_from_object(sha_object, "state", "[I", /*is_exact*/ false); | |
6341 assert (sha_state != NULL, "wrong version of sun.security.provider.SHA/SHA2"); | |
6342 if (sha_state == NULL) return (Node *) NULL; | |
6343 | |
6344 // now have the array, need to get the start address of the state array | |
6345 Node* state = array_element_address(sha_state, intcon(0), T_INT); | |
6346 return state; | |
6347 } | |
6348 | |
6349 //------------------------------get_state_from_sha5_object----------------------- | |
6350 Node * LibraryCallKit::get_state_from_sha5_object(Node *sha_object) { | |
6351 Node* sha_state = load_field_from_object(sha_object, "state", "[J", /*is_exact*/ false); | |
6352 assert (sha_state != NULL, "wrong version of sun.security.provider.SHA5"); | |
6353 if (sha_state == NULL) return (Node *) NULL; | |
6354 | |
6355 // now have the array, need to get the start address of the state array | |
6356 Node* state = array_element_address(sha_state, intcon(0), T_LONG); | |
6357 return state; | |
6358 } | |
6359 | |
6360 //----------------------------inline_digestBase_implCompressMB_predicate---------------------------- | |
6361 // Return node representing slow path of predicate check. | |
6362 // the pseudo code we want to emulate with this predicate is: | |
6363 // if (digestBaseObj instanceof SHA/SHA2/SHA5) do_intrinsic, else do_javapath | |
6364 // | |
6365 Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) { | |
6366 assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics, | |
6367 "need SHA1/SHA256/SHA512 instruction support"); | |
6368 assert((uint)predicate < 3, "sanity"); | |
6369 | |
6370 // The receiver was checked for NULL already. | |
6371 Node* digestBaseObj = argument(0); | |
6372 | |
6373 // get DigestBase klass for instanceOf check | |
6374 const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr(); | |
6375 assert(tinst != NULL, "digestBaseObj is null"); | |
6376 assert(tinst->klass()->is_loaded(), "DigestBase is not loaded"); | |
6377 | |
6378 const char* klass_SHA_name = NULL; | |
6379 switch (predicate) { | |
6380 case 0: | |
6381 if (UseSHA1Intrinsics) { | |
6382 // we want to do an instanceof comparison against the SHA class | |
6383 klass_SHA_name = "sun/security/provider/SHA"; | |
6384 } | |
6385 break; | |
6386 case 1: | |
6387 if (UseSHA256Intrinsics) { | |
6388 // we want to do an instanceof comparison against the SHA2 class | |
6389 klass_SHA_name = "sun/security/provider/SHA2"; | |
6390 } | |
6391 break; | |
6392 case 2: | |
6393 if (UseSHA512Intrinsics) { | |
6394 // we want to do an instanceof comparison against the SHA5 class | |
6395 klass_SHA_name = "sun/security/provider/SHA5"; | |
6396 } | |
6397 break; | |
6398 default: | |
6399 fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate)); | |
6400 } | |
6401 | |
6402 ciKlass* klass_SHA = NULL; | |
6403 if (klass_SHA_name != NULL) { | |
6404 klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name)); | |
6405 } | |
6406 if ((klass_SHA == NULL) || !klass_SHA->is_loaded()) { | |
6407 // if none of SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path | |
6408 Node* ctrl = control(); | |
6409 set_control(top()); // no intrinsic path | |
6410 return ctrl; | |
6411 } | |
6412 ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass(); | |
6413 | |
6414 Node* instofSHA = gen_instanceof(digestBaseObj, makecon(TypeKlassPtr::make(instklass_SHA))); | |
6415 Node* cmp_instof = _gvn.transform(new (C) CmpINode(instofSHA, intcon(1))); | |
6416 Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne)); | |
6417 Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN); | |
6418 | |
6419 return instof_false; // even if it is NULL | |
6420 } |