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 }