--- old/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp 2014-07-09 16:46:17.379589264 -0400 +++ new/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp 2014-07-09 16:46:16.895132954 -0400 @@ -3606,4 +3606,8 @@ } } +void LIR_Assembler::emit_crypto_cbc_aes (LIR_OpCrypto_CBC_AES * op) { + ShouldNotReachHere(); +} + #undef __ --- old/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp 2014-07-09 16:46:20.815688568 -0400 +++ new/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp 2014-07-09 16:46:20.338928119 -0400 @@ -753,6 +753,9 @@ } } +void LIRGenerator::do_CryptoIntrinsic(Intrinsic* x) { + ShouldNotReachHere(); +} void LIRGenerator::do_ArrayCopy(Intrinsic* x) { assert(x->number_of_arguments() == 5, "wrong type"); --- old/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp 2014-07-09 16:46:23.061929669 -0400 +++ new/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp 2014-07-09 16:46:22.557513769 -0400 @@ -4183,4 +4183,8 @@ ShouldNotReachHere(); } } + +void LIR_Assembler::emit_crypto_cbc_aes (LIR_OpCrypto_CBC_AES * op) { + ShouldNotReachHere(); +} #undef __ --- old/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp 2014-07-09 16:46:25.374426833 -0400 +++ new/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp 2014-07-09 16:46:24.801798354 -0400 @@ -880,6 +880,9 @@ } } +void LIRGenerator::do_CryptoIntrinsic(Intrinsic* x) { + ShouldNotReachHere(); +} void LIRGenerator::do_ArrayCopy(Intrinsic* x) { assert(x->number_of_arguments() == 5, "wrong type"); --- old/src/share/vm/c1/c1_GraphBuilder.cpp 2014-07-09 16:46:28.037937151 -0400 +++ new/src/share/vm/c1/c1_GraphBuilder.cpp 2014-07-09 16:46:27.544725197 -0400 @@ -3635,6 +3635,13 @@ case vmIntrinsics::_fullFence : break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + if (VM_Version::supports_crypto_acceleration_client()) { + return (append_crypto_cbc_aes(callee)); + } + return false; + default : return false; // do not inline } // create intrinsic node @@ -4447,6 +4454,44 @@ return InlineUnsafeOps; } +bool GraphBuilder::append_crypto_cbc_aes(ciMethod* callee) { + + if (!UseAESIntrinsics) return false; + + ciInstanceKlass* inst = callee->holder()->as_instance_klass(); + ciField* cipher = inst->get_field_by_name(ciSymbol::make("embeddedCipher"), ciSymbol::make("Lcom/sun/crypto/provider/SymmetricCipher;"), false); + if (cipher == NULL) return false; + + ciKlass* klass_AESCrypt = inst->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); + + // if AESCrypt is not even loaded, we never take the intrinsic fast path + if (klass_AESCrypt == NULL || !klass_AESCrypt->is_loaded()) return false; + + ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); + + Value recv = state()->stack_at(0); + Value cipher_inst = append(new LoadField(recv, cipher->offset(), cipher, false, copy_state_for_exception(), false /*needs_patching*/)); + + // generate InstanceOf check for further evaluation in LIRAssember + Value insof = append_split(new InstanceOf(instklass_AESCrypt, cipher_inst, copy_state_exhandling())); + + Values* args = state()->pop_arguments(callee->arg_size()); + + args->push(insof); + + // create intrinsic node + ValueType* result_type = as_ValueType(callee->return_type()); + ValueStack* state_before = copy_state_for_exception(); + + Intrinsic* result = new Intrinsic(result_type, callee->intrinsic_id(), args, true /*has_receiver*/, state_before, + true /*preserves_state*/, false /*cantrap*/); + // append instruction & push result + Value value = append_split(result); + push(result_type, value); + + return true; +} + #ifndef PRODUCT void GraphBuilder::print_stats() { vmap()->print(); --- old/src/share/vm/c1/c1_GraphBuilder.hpp 2014-07-09 16:46:30.291790429 -0400 +++ new/src/share/vm/c1/c1_GraphBuilder.hpp 2014-07-09 16:46:29.797582682 -0400 @@ -371,6 +371,7 @@ bool append_unsafe_prefetch(ciMethod* callee, bool is_store, bool is_static); void append_unsafe_CAS(ciMethod* callee); bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add); + bool append_crypto_cbc_aes(ciMethod* callee); void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true); --- old/src/share/vm/c1/c1_LIR.cpp 2014-07-09 16:46:32.407995801 -0400 +++ new/src/share/vm/c1/c1_LIR.cpp 2014-07-09 16:46:31.916664144 -0400 @@ -1006,6 +1006,29 @@ do_temp(opProfileType->_tmp); break; } + +// LIR_OpCrypto_CBC_AES + case lir_crypto_cbc_aes: { + assert(op->as_OpCrypto_CBC_AES() != NULL, "must be"); + LIR_OpCrypto_CBC_AES* opCrypto_CBC_AES = (LIR_OpCrypto_CBC_AES*)op; + + do_input(opCrypto_CBC_AES->_recv); + do_input(opCrypto_CBC_AES->_src); + do_input(opCrypto_CBC_AES->_src_off); + do_input(opCrypto_CBC_AES->_src_len); + do_input(opCrypto_CBC_AES->_dst); + do_input(opCrypto_CBC_AES->_dst_off); + do_input(opCrypto_CBC_AES->_insof); + + do_temp(opCrypto_CBC_AES->_recv); + + if (opCrypto_CBC_AES->_info) do_info(opCrypto_CBC_AES->_info); + do_call(); + if (opCrypto_CBC_AES->_result->is_valid()) do_output(opCrypto_CBC_AES->_result); + + break; + } + default: ShouldNotReachHere(); } @@ -1131,6 +1154,10 @@ masm->emit_compare_and_swap(this); } +void LIR_OpCrypto_CBC_AES::emit_code(LIR_Assembler* masm) { + masm->emit_crypto_cbc_aes(this); +} + void LIR_Op3::emit_code(LIR_Assembler* masm) { masm->emit_op3(this); } @@ -2107,6 +2134,13 @@ tmp()->print(out); out->print(" "); } +void LIR_OpCrypto_CBC_AES::print_instr(outputStream* out) const { + src()->print(out); out->print(" "); + src_off()->print(out); out->print(" "); + src_len()->print(out); out->print(" "); + dst()->print(out); out->print(" "); + dst_off()->print(out); out->print(" "); +} #endif // PRODUCT // Implementation of LIR_InsertionBuffer --- old/src/share/vm/c1/c1_LIR.hpp 2014-07-09 16:46:34.607163224 -0400 +++ new/src/share/vm/c1/c1_LIR.hpp 2014-07-09 16:46:34.113406725 -0400 @@ -883,6 +883,7 @@ class LIR_OpCompareAndSwap; class LIR_OpProfileCall; class LIR_OpProfileType; +class LIR_OpCrypto_CBC_AES; #ifdef ASSERT class LIR_OpAssert; #endif @@ -1011,6 +1012,9 @@ , begin_opAssert , lir_assert , end_opAssert + , begin_opCrypto + , lir_crypto_cbc_aes + , end_opCrypto }; @@ -1149,6 +1153,7 @@ virtual LIR_OpCompareAndSwap* as_OpCompareAndSwap() { return NULL; } virtual LIR_OpProfileCall* as_OpProfileCall() { return NULL; } virtual LIR_OpProfileType* as_OpProfileType() { return NULL; } + virtual LIR_OpCrypto_CBC_AES* as_OpCrypto_CBC_AES() { return NULL; } #ifdef ASSERT virtual LIR_OpAssert* as_OpAssert() { return NULL; } #endif @@ -1991,6 +1996,55 @@ virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; +class LIR_OpCrypto_CBC_AES: public LIR_Op { + friend class LIR_OpVisitState; + + private: + LIR_Opr _insof; + LIR_Opr _recv; + LIR_Opr _src; + LIR_Opr _dst; + LIR_Opr _src_len; + LIR_Opr _src_off; + LIR_Opr _dst_off; + bool _encrypt; + + public: + LIR_OpCrypto_CBC_AES(bool encrypt, + LIR_Opr result, + LIR_Opr insof, + LIR_Opr recv, + LIR_Opr src, + LIR_Opr src_off, + LIR_Opr src_len, + LIR_Opr dst, + LIR_Opr dst_off, + CodeEmitInfo* info) + : LIR_Op(lir_crypto_cbc_aes, result, info) + , _encrypt(encrypt) + , _insof(insof) + , _recv(recv) + , _src(src) + , _src_off(src_off) + , _src_len(src_len) + , _dst(dst) + , _dst_off(dst_off) + { } + + LIR_Opr src() const { return _src; } + LIR_Opr src_len() const { return _src_len; } + LIR_Opr src_off() const { return _src_off; } + LIR_Opr dst() const { return _dst; } + LIR_Opr dst_off() const { return _dst_off; } + LIR_Opr insof() const { return _insof; } + LIR_Opr recv() const { return _recv; } + bool is_encrypt() const { return _encrypt; } + + virtual void emit_code(LIR_Assembler* masm); + virtual LIR_OpCrypto_CBC_AES* as_OpCrypto_CBC_AES() { return this; } + virtual void print_instr(outputStream* out) const PRODUCT_RETURN; +}; + class LIR_InsertionBuffer; //--------------------------------LIR_List--------------------------------------------------- @@ -2298,6 +2352,16 @@ void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); } void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); } + + void crypto_cbc_aes(bool encrypt, LIR_Opr result, + LIR_Opr insof, LIR_Opr recv, + LIR_Opr src, LIR_Opr src_offset, + LIR_Opr src_len, + LIR_Opr dst, LIR_Opr dst_offset, + CodeEmitInfo* info) { + append(new LIR_OpCrypto_CBC_AES(encrypt, result, insof, recv, src, src_offset, src_len, dst, dst_offset, info)); + } + #ifdef ASSERT void lir_assert(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, const char* msg, bool halt) { append(new LIR_OpAssert(condition, opr1, opr2, msg, halt)); } #endif --- old/src/share/vm/c1/c1_LIRAssembler.hpp 2014-07-09 16:46:36.817829652 -0400 +++ new/src/share/vm/c1/c1_LIRAssembler.hpp 2014-07-09 16:46:36.336750889 -0400 @@ -211,6 +211,7 @@ void emit_profile_call(LIR_OpProfileCall* op); void emit_profile_type(LIR_OpProfileType* op); void emit_delay(LIR_OpDelay* op); + void emit_crypto_cbc_aes(LIR_OpCrypto_CBC_AES* op); void arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack); void arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info); --- old/src/share/vm/c1/c1_LIRGenerator.cpp 2014-07-09 16:46:39.134570164 -0400 +++ new/src/share/vm/c1/c1_LIRGenerator.cpp 2014-07-09 16:46:38.537396891 -0400 @@ -3152,6 +3152,11 @@ do_update_CRC32(x); break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + do_CryptoIntrinsic(x); + break; + default: ShouldNotReachHere(); break; } } --- old/src/share/vm/c1/c1_LIRGenerator.hpp 2014-07-09 16:46:41.331336117 -0400 +++ new/src/share/vm/c1/c1_LIRGenerator.hpp 2014-07-09 16:46:40.854470766 -0400 @@ -248,6 +248,7 @@ void do_FPIntrinsics(Intrinsic* x); void do_Reference_get(Intrinsic* x); void do_update_CRC32(Intrinsic* x); + void do_CryptoIntrinsic(Intrinsic* x); void do_UnsafePrefetch(UnsafePrefetch* x, bool is_store); --- old/src/share/vm/runtime/vm_version.cpp 2014-07-09 16:46:43.436970108 -0400 +++ new/src/share/vm/runtime/vm_version.cpp 2014-07-09 16:46:42.961873282 -0400 @@ -51,7 +51,7 @@ bool Abstract_VM_Version::_supports_atomic_getadd8 = false; unsigned int Abstract_VM_Version::_logical_processors_per_package = 1U; int Abstract_VM_Version::_reserve_for_allocation_prefetch = 0; - +bool Abstract_VM_Version::_supports_crypto_acceleration_client = false; #ifndef HOTSPOT_RELEASE_VERSION #error HOTSPOT_RELEASE_VERSION must be defined #endif --- old/src/share/vm/runtime/vm_version.hpp 2014-07-09 16:46:45.531782079 -0400 +++ new/src/share/vm/runtime/vm_version.hpp 2014-07-09 16:46:45.056916720 -0400 @@ -49,6 +49,7 @@ static int _parallel_worker_threads; static bool _parallel_worker_threads_initialized; static int _reserve_for_allocation_prefetch; + static bool _supports_crypto_acceleration_client; static unsigned int nof_parallel_worker_threads(unsigned int num, unsigned int dem, @@ -92,6 +93,11 @@ static bool supports_atomic_getadd4() {return _supports_atomic_getadd4;} static bool supports_atomic_getadd8() {return _supports_atomic_getadd8;} + // does client VM support crypto acceleration? + static bool supports_crypto_acceleration_client() { + return _supports_crypto_acceleration_client; + } + static unsigned int logical_processors_per_package() { return _logical_processors_per_package; }