< 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 >