< prev index next >

src/share/vm/opto/library_call.cpp

Print this page

        

*** 279,289 **** --- 279,291 ---- bool inline_number_methods(vmIntrinsics::ID id); bool inline_reference_get(); bool inline_Class_cast(); bool inline_aescrypt_Block(vmIntrinsics::ID id); bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id); + bool inline_counterMode_AESCrypt(vmIntrinsics::ID id); Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting); + Node* inline_counterMode_AESCrypt_predicate(); Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object); bool inline_ghash_processBlocks(); bool inline_sha_implCompress(vmIntrinsics::ID id); bool inline_digestBase_implCompressMB(int predicate);
*** 690,699 **** --- 692,704 ---- case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt(intrinsic_id()); + case vmIntrinsics::_counterMode_AESCrypt: + return inline_counterMode_AESCrypt(intrinsic_id()); + case vmIntrinsics::_sha_implCompress: case vmIntrinsics::_sha2_implCompress: case vmIntrinsics::_sha5_implCompress: return inline_sha_implCompress(intrinsic_id());
*** 771,780 **** --- 776,787 ---- switch (intrinsic_id()) { case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: return inline_cipherBlockChaining_AESCrypt_predicate(false); case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt_predicate(true); + case vmIntrinsics::_counterMode_AESCrypt: + return inline_counterMode_AESCrypt_predicate(); 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
*** 6060,6069 **** --- 6067,6155 ---- Node* retvalue = _gvn.transform(new ProjNode(cbcCrypt, TypeFunc::Parms)); set_result(retvalue); return true; } + //------------------------------inline_counterMode_AESCrypt----------------------- + bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) { + assert(UseAES, "need AES instruction support"); + if (!UseCTRAESIntrinsics) return false; + + address stubAddr = NULL; + const char *stubName = NULL; + if (id == vmIntrinsics::_counterMode_AESCrypt) { + stubAddr = StubRoutines::counterMode_AESCrypt(); + stubName = "counterMode_AESCrypt"; + } + if (stubAddr == NULL) return false; + + Node* counterMode_object = argument(0); + Node* src = argument(1); + Node* src_offset = argument(2); + Node* len = argument(3); + Node* dest = argument(4); + Node* dest_offset = argument(5); + + // (1) src and dest are arrays. + const Type* src_type = src->Value(&_gvn); + const Type* dest_type = dest->Value(&_gvn); + const TypeAryPtr* top_src = src_type->isa_aryptr(); + const TypeAryPtr* top_dest = dest_type->isa_aryptr(); + assert(top_src != NULL && top_src->klass() != NULL + && top_dest != NULL && top_dest->klass() != NULL, "args are strange"); + + // checks are the responsibility of the caller + Node* src_start = src; + Node* dest_start = dest; + if (src_offset != NULL || dest_offset != NULL) { + assert(src_offset != NULL && dest_offset != NULL, ""); + src_start = array_element_address(src, src_offset, T_BYTE); + dest_start = array_element_address(dest, dest_offset, T_BYTE); + } + + // if we are in this set of code, we "know" the embeddedCipher is an AESCrypt object + // (because of the predicated logic executed earlier). + // so we cast it here safely. + // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java + Node* embeddedCipherObj = load_field_from_object(counterMode_object, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); + if (embeddedCipherObj == NULL) return false; + // cast it to what we know it will be at runtime + const TypeInstPtr* tinst = _gvn.type(counterMode_object)->isa_instptr(); + assert(tinst != NULL, "CTR obj is null"); + assert(tinst->klass()->is_loaded(), "CTR obj is not loaded"); + ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); + assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); + ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); + const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); + const TypeOopPtr* xtype = aklass->as_instance_type(); + Node* aescrypt_object = new CheckCastPPNode(control(), embeddedCipherObj, xtype); + aescrypt_object = _gvn.transform(aescrypt_object); + // we need to get the start of the aescrypt_object's expanded key array + Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object); + if (k_start == NULL) return false; + // similarly, get the start address of the r vector + Node* obj_counter = load_field_from_object(counterMode_object, "counter", "[B", /*is_exact*/ false); + if (obj_counter == NULL) return false; + Node* cnt_start = array_element_address(obj_counter, intcon(0), T_BYTE); + + Node* ctrCrypt; + if (Matcher::pass_original_key_for_aes()) { + // no SPARC version for AES/CTR intrinsics now. + return false; + } + // Call the stub, passing src_start, dest_start, k_start, r_start and src_len + ctrCrypt = make_runtime_call(RC_LEAF|RC_NO_FP, + OptoRuntime::counterMode_aescrypt_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + src_start, dest_start, k_start, cnt_start, len); + + // return cipher length (int) + Node* retvalue = _gvn.transform(new ProjNode(ctrCrypt, TypeFunc::Parms)); + set_result(retvalue); + return true; + } + //------------------------------get_key_start_from_aescrypt_object----------------------- Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) { Node* objAESCryptKey = load_field_from_object(aescrypt_object, "K", "[I", /*is_exact*/ false); assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt"); if (objAESCryptKey == NULL) return (Node *) NULL;
*** 6141,6150 **** --- 6227,6278 ---- record_for_igvn(region); return _gvn.transform(region); } + //----------------------------inline_counterMode_AESCrypt_predicate---------------------------- + // Return node representing slow path of predicate check. + // the pseudo code we want to emulate with this predicate is: + // for encryption: + // if (embeddedCipherObj instanceof AESCrypt) do_intrinsic, else do_javapath + // for decryption: + // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath + // note cipher==plain is more conservative than the original java code but that's OK + // + + Node* LibraryCallKit::inline_counterMode_AESCrypt_predicate() { + // The receiver was checked for NULL already. + Node* objCTR = argument(0); + + // Load embeddedCipher field of CipherBlockChaining object. + Node* embeddedCipherObj = load_field_from_object(objCTR, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); + + // get AESCrypt klass for instanceOf check + // AESCrypt might not be loaded yet if some other SymmetricCipher got us to this compile point + // will have same classloader as CipherBlockChaining object + const TypeInstPtr* tinst = _gvn.type(objCTR)->isa_instptr(); + assert(tinst != NULL, "CTRobj is null"); + assert(tinst->klass()->is_loaded(), "CTRobj is not loaded"); + + // we want to do an instanceof comparison against the AESCrypt class + ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); + if (!klass_AESCrypt->is_loaded()) { + // if AESCrypt is not even loaded, we never take the intrinsic fast path + Node* ctrl = control(); + set_control(top()); // no regular fast path + return ctrl; + } + + ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); + Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt))); + Node* cmp_instof = _gvn.transform(new CmpINode(instof, 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 + } + //------------------------------inline_ghash_processBlocks bool LibraryCallKit::inline_ghash_processBlocks() { address stubAddr; const char *stubName; assert(UseGHASHIntrinsics, "need GHASH intrinsics support");
< prev index next >