comparison src/share/vm/opto/library_call.cpp @ 6894:a3ecd773a7b9

7184394: add intrinsics to use AES instructions Summary: Use new x86 AES instructions for AESCrypt. Reviewed-by: twisti, kvn, roland Contributed-by: tom.deneau@amd.com
author kvn
date Wed, 24 Oct 2012 14:33:22 -0700
parents cfe522e6461c
children beebba0acc11
comparison
equal deleted inserted replaced
6893:b2c669fd8114 6894:a3ecd773a7b9
42 class LibraryIntrinsic : public InlineCallGenerator { 42 class LibraryIntrinsic : public InlineCallGenerator {
43 // Extend the set of intrinsics known to the runtime: 43 // Extend the set of intrinsics known to the runtime:
44 public: 44 public:
45 private: 45 private:
46 bool _is_virtual; 46 bool _is_virtual;
47 bool _is_predicted;
47 vmIntrinsics::ID _intrinsic_id; 48 vmIntrinsics::ID _intrinsic_id;
48 49
49 public: 50 public:
50 LibraryIntrinsic(ciMethod* m, bool is_virtual, vmIntrinsics::ID id) 51 LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, vmIntrinsics::ID id)
51 : InlineCallGenerator(m), 52 : InlineCallGenerator(m),
52 _is_virtual(is_virtual), 53 _is_virtual(is_virtual),
54 _is_predicted(is_predicted),
53 _intrinsic_id(id) 55 _intrinsic_id(id)
54 { 56 {
55 } 57 }
56 virtual bool is_intrinsic() const { return true; } 58 virtual bool is_intrinsic() const { return true; }
57 virtual bool is_virtual() const { return _is_virtual; } 59 virtual bool is_virtual() const { return _is_virtual; }
60 virtual bool is_predicted() const { return _is_predicted; }
58 virtual JVMState* generate(JVMState* jvms); 61 virtual JVMState* generate(JVMState* jvms);
62 virtual Node* generate_predicate(JVMState* jvms);
59 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } 63 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
60 }; 64 };
61 65
62 66
63 // Local helper class for LibraryIntrinsic: 67 // Local helper class for LibraryIntrinsic:
81 ciMethod* callee() const { return _intrinsic->method(); } 85 ciMethod* callee() const { return _intrinsic->method(); }
82 ciSignature* signature() const { return callee()->signature(); } 86 ciSignature* signature() const { return callee()->signature(); }
83 int arg_size() const { return callee()->arg_size(); } 87 int arg_size() const { return callee()->arg_size(); }
84 88
85 bool try_to_inline(); 89 bool try_to_inline();
90 Node* try_to_predicate();
86 91
87 // Helper functions to inline natives 92 // Helper functions to inline natives
88 void push_result(RegionNode* region, PhiNode* value); 93 void push_result(RegionNode* region, PhiNode* value);
89 Node* generate_guard(Node* test, RegionNode* region, float true_prob); 94 Node* generate_guard(Node* test, RegionNode* region, float true_prob);
90 Node* generate_slow_guard(Node* test, RegionNode* region); 95 Node* generate_slow_guard(Node* test, RegionNode* region);
146 return generate_method_call(method_id, false, true); 151 return generate_method_call(method_id, false, true);
147 } 152 }
148 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) { 153 CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
149 return generate_method_call(method_id, true, false); 154 return generate_method_call(method_id, true, false);
150 } 155 }
156 Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static);
151 157
152 Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2); 158 Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
153 Node* make_string_method_node(int opcode, Node* str1, Node* str2); 159 Node* make_string_method_node(int opcode, Node* str1, Node* str2);
154 bool inline_string_compareTo(); 160 bool inline_string_compareTo();
155 bool inline_string_indexOf(); 161 bool inline_string_indexOf();
251 bool inline_numberOfTrailingZeros(vmIntrinsics::ID id); 257 bool inline_numberOfTrailingZeros(vmIntrinsics::ID id);
252 bool inline_bitCount(vmIntrinsics::ID id); 258 bool inline_bitCount(vmIntrinsics::ID id);
253 bool inline_reverseBytes(vmIntrinsics::ID id); 259 bool inline_reverseBytes(vmIntrinsics::ID id);
254 260
255 bool inline_reference_get(); 261 bool inline_reference_get();
262 bool inline_aescrypt_Block(vmIntrinsics::ID id);
263 bool inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id);
264 Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
265 Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
256 }; 266 };
257 267
258 268
259 //---------------------------make_vm_intrinsic---------------------------- 269 //---------------------------make_vm_intrinsic----------------------------
260 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) { 270 CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
304 default: 314 default:
305 return NULL; 315 return NULL;
306 } 316 }
307 } 317 }
308 318
319 bool is_predicted = false;
320
309 switch (id) { 321 switch (id) {
310 case vmIntrinsics::_compareTo: 322 case vmIntrinsics::_compareTo:
311 if (!SpecialStringCompareTo) return NULL; 323 if (!SpecialStringCompareTo) return NULL;
312 break; 324 break;
313 case vmIntrinsics::_indexOf: 325 case vmIntrinsics::_indexOf:
411 #else 423 #else
412 if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL; 424 if (!Matcher::match_rule_supported(Op_GetAndSetP)) return NULL;
413 break; 425 break;
414 #endif 426 #endif
415 427
428 case vmIntrinsics::_aescrypt_encryptBlock:
429 case vmIntrinsics::_aescrypt_decryptBlock:
430 if (!UseAESIntrinsics) return NULL;
431 break;
432
433 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
434 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
435 if (!UseAESIntrinsics) return NULL;
436 // these two require the predicated logic
437 is_predicted = true;
438 break;
439
416 default: 440 default:
417 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); 441 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
418 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); 442 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
419 break; 443 break;
420 } 444 }
442 // -XX:-InlineUnsafeOps disables natives from the Unsafe class. 466 // -XX:-InlineUnsafeOps disables natives from the Unsafe class.
443 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { 467 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) {
444 if (!InlineUnsafeOps) return NULL; 468 if (!InlineUnsafeOps) return NULL;
445 } 469 }
446 470
447 return new LibraryIntrinsic(m, is_virtual, (vmIntrinsics::ID) id); 471 return new LibraryIntrinsic(m, is_virtual, is_predicted, (vmIntrinsics::ID) id);
448 } 472 }
449 473
450 //----------------------register_library_intrinsics----------------------- 474 //----------------------register_library_intrinsics-----------------------
451 // Initialize this file's data structures, for each Compile instance. 475 // Initialize this file's data structures, for each Compile instance.
452 void Compile::register_library_intrinsics() { 476 void Compile::register_library_intrinsics() {
486 const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; 510 const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
487 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg); 511 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg);
488 } else { 512 } else {
489 // Root compile 513 // Root compile
490 tty->print("Did not generate intrinsic %s%s at bci:%d in", 514 tty->print("Did not generate intrinsic %s%s at bci:%d in",
515 vmIntrinsics::name_at(intrinsic_id()),
516 (is_virtual() ? " (virtual)" : ""), kit.bci());
517 }
518 }
519 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
520 return NULL;
521 }
522
523 Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
524 LibraryCallKit kit(jvms, this);
525 Compile* C = kit.C;
526 int nodes = C->unique();
527 #ifndef PRODUCT
528 assert(is_predicted(), "sanity");
529 if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) {
530 char buf[1000];
531 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
532 tty->print_cr("Predicate for intrinsic %s", str);
533 }
534 #endif
535
536 Node* slow_ctl = kit.try_to_predicate();
537 if (!kit.failing()) {
538 if (C->log()) {
539 C->log()->elem("predicate_intrinsic id='%s'%s nodes='%d'",
540 vmIntrinsics::name_at(intrinsic_id()),
541 (is_virtual() ? " virtual='1'" : ""),
542 C->unique() - nodes);
543 }
544 return slow_ctl; // Could be NULL if the check folds.
545 }
546
547 // The intrinsic bailed out
548 if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) {
549 if (jvms->has_method()) {
550 // Not a root compile.
551 const char* msg = "failed to generate predicate for intrinsic";
552 CompileTask::print_inlining(kit.callee(), jvms->depth() - 1, kit.bci(), msg);
553 } else {
554 // Root compile
555 tty->print("Did not generate predicate for intrinsic %s%s at bci:%d in",
491 vmIntrinsics::name_at(intrinsic_id()), 556 vmIntrinsics::name_at(intrinsic_id()),
492 (is_virtual() ? " (virtual)" : ""), kit.bci()); 557 (is_virtual() ? " (virtual)" : ""), kit.bci());
493 } 558 }
494 } 559 }
495 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); 560 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
765 return inline_native_Reflection_getCallerClass(); 830 return inline_native_Reflection_getCallerClass();
766 831
767 case vmIntrinsics::_Reference_get: 832 case vmIntrinsics::_Reference_get:
768 return inline_reference_get(); 833 return inline_reference_get();
769 834
835 case vmIntrinsics::_aescrypt_encryptBlock:
836 case vmIntrinsics::_aescrypt_decryptBlock:
837 return inline_aescrypt_Block(intrinsic_id());
838
839 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
840 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
841 return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
842
770 default: 843 default:
771 // If you get here, it may be that someone has added a new intrinsic 844 // If you get here, it may be that someone has added a new intrinsic
772 // to the list in vmSymbols.hpp without implementing it here. 845 // to the list in vmSymbols.hpp without implementing it here.
773 #ifndef PRODUCT 846 #ifndef PRODUCT
774 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) { 847 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {
775 tty->print_cr("*** Warning: Unimplemented intrinsic %s(%d)", 848 tty->print_cr("*** Warning: Unimplemented intrinsic %s(%d)",
776 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id()); 849 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id());
777 } 850 }
778 #endif 851 #endif
779 return false; 852 return false;
853 }
854 }
855
856 Node* LibraryCallKit::try_to_predicate() {
857 if (!jvms()->has_method()) {
858 // Root JVMState has a null method.
859 assert(map()->memory()->Opcode() == Op_Parm, "");
860 // Insert the memory aliasing node
861 set_all_memory(reset_memory());
862 }
863 assert(merged_memory(), "");
864
865 switch (intrinsic_id()) {
866 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
867 return inline_cipherBlockChaining_AESCrypt_predicate(false);
868 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
869 return inline_cipherBlockChaining_AESCrypt_predicate(true);
870
871 default:
872 // If you get here, it may be that someone has added a new intrinsic
873 // to the list in vmSymbols.hpp without implementing it here.
874 #ifndef PRODUCT
875 if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {
876 tty->print_cr("*** Warning: Unimplemented predicate for intrinsic %s(%d)",
877 vmIntrinsics::name_at(intrinsic_id()), intrinsic_id());
878 }
879 #endif
880 Node* slow_ctl = control();
881 set_control(top()); // No fast path instrinsic
882 return slow_ctl;
780 } 883 }
781 } 884 }
782 885
783 //------------------------------push_result------------------------------ 886 //------------------------------push_result------------------------------
784 // Helper function for finishing intrinsics. 887 // Helper function for finishing intrinsics.
5611 insert_mem_bar(Op_MemBarCPUOrder); 5714 insert_mem_bar(Op_MemBarCPUOrder);
5612 5715
5613 push(result); 5716 push(result);
5614 return true; 5717 return true;
5615 } 5718 }
5719
5720
5721 Node * LibraryCallKit::load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString,
5722 bool is_exact=true, bool is_static=false) {
5723
5724 const TypeInstPtr* tinst = _gvn.type(fromObj)->isa_instptr();
5725 assert(tinst != NULL, "obj is null");
5726 assert(tinst->klass()->is_loaded(), "obj is not loaded");
5727 assert(!is_exact || tinst->klass_is_exact(), "klass not exact");
5728
5729 ciField* field = tinst->klass()->as_instance_klass()->get_field_by_name(ciSymbol::make(fieldName),
5730 ciSymbol::make(fieldTypeString),
5731 is_static);
5732 if (field == NULL) return (Node *) NULL;
5733 assert (field != NULL, "undefined field");
5734
5735 // Next code copied from Parse::do_get_xxx():
5736
5737 // Compute address and memory type.
5738 int offset = field->offset_in_bytes();
5739 bool is_vol = field->is_volatile();
5740 ciType* field_klass = field->type();
5741 assert(field_klass->is_loaded(), "should be loaded");
5742 const TypePtr* adr_type = C->alias_type(field)->adr_type();
5743 Node *adr = basic_plus_adr(fromObj, fromObj, offset);
5744 BasicType bt = field->layout_type();
5745
5746 // Build the resultant type of the load
5747 const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass());
5748
5749 // Build the load.
5750 Node* loadedField = make_load(NULL, adr, type, bt, adr_type, is_vol);
5751 return loadedField;
5752 }
5753
5754
5755 //------------------------------inline_aescrypt_Block-----------------------
5756 bool LibraryCallKit::inline_aescrypt_Block(vmIntrinsics::ID id) {
5757 address stubAddr;
5758 const char *stubName;
5759 assert(UseAES, "need AES instruction support");
5760
5761 switch(id) {
5762 case vmIntrinsics::_aescrypt_encryptBlock:
5763 stubAddr = StubRoutines::aescrypt_encryptBlock();
5764 stubName = "aescrypt_encryptBlock";
5765 break;
5766 case vmIntrinsics::_aescrypt_decryptBlock:
5767 stubAddr = StubRoutines::aescrypt_decryptBlock();
5768 stubName = "aescrypt_decryptBlock";
5769 break;
5770 }
5771 if (stubAddr == NULL) return false;
5772
5773 // Restore the stack and pop off the arguments.
5774 int nargs = 5; // this + 2 oop/offset combos
5775 assert(callee()->signature()->size() == nargs-1, "encryptBlock has 4 arguments");
5776
5777 Node *aescrypt_object = argument(0);
5778 Node *src = argument(1);
5779 Node *src_offset = argument(2);
5780 Node *dest = argument(3);
5781 Node *dest_offset = argument(4);
5782
5783 // (1) src and dest are arrays.
5784 const Type* src_type = src->Value(&_gvn);
5785 const Type* dest_type = dest->Value(&_gvn);
5786 const TypeAryPtr* top_src = src_type->isa_aryptr();
5787 const TypeAryPtr* top_dest = dest_type->isa_aryptr();
5788 assert (top_src != NULL && top_src->klass() != NULL && top_dest != NULL && top_dest->klass() != NULL, "args are strange");
5789
5790 // for the quick and dirty code we will skip all the checks.
5791 // we are just trying to get the call to be generated.
5792 Node* src_start = src;
5793 Node* dest_start = dest;
5794 if (src_offset != NULL || dest_offset != NULL) {
5795 assert(src_offset != NULL && dest_offset != NULL, "");
5796 src_start = array_element_address(src, src_offset, T_BYTE);
5797 dest_start = array_element_address(dest, dest_offset, T_BYTE);
5798 }
5799
5800 // now need to get the start of its expanded key array
5801 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java
5802 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object);
5803 if (k_start == NULL) return false;
5804
5805 // Call the stub.
5806 make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::aescrypt_block_Type(),
5807 stubAddr, stubName, TypePtr::BOTTOM,
5808 src_start, dest_start, k_start);
5809
5810 return true;
5811 }
5812
5813 //------------------------------inline_cipherBlockChaining_AESCrypt-----------------------
5814 bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) {
5815 address stubAddr;
5816 const char *stubName;
5817
5818 assert(UseAES, "need AES instruction support");
5819
5820 switch(id) {
5821 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
5822 stubAddr = StubRoutines::cipherBlockChaining_encryptAESCrypt();
5823 stubName = "cipherBlockChaining_encryptAESCrypt";
5824 break;
5825 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
5826 stubAddr = StubRoutines::cipherBlockChaining_decryptAESCrypt();
5827 stubName = "cipherBlockChaining_decryptAESCrypt";
5828 break;
5829 }
5830 if (stubAddr == NULL) return false;
5831
5832
5833 // Restore the stack and pop off the arguments.
5834 int nargs = 6; // this + oop/offset + len + oop/offset
5835 assert(callee()->signature()->size() == nargs-1, "wrong number of arguments");
5836 Node *cipherBlockChaining_object = argument(0);
5837 Node *src = argument(1);
5838 Node *src_offset = argument(2);
5839 Node *len = argument(3);
5840 Node *dest = argument(4);
5841 Node *dest_offset = argument(5);
5842
5843 // (1) src and dest are arrays.
5844 const Type* src_type = src->Value(&_gvn);
5845 const Type* dest_type = dest->Value(&_gvn);
5846 const TypeAryPtr* top_src = src_type->isa_aryptr();
5847 const TypeAryPtr* top_dest = dest_type->isa_aryptr();
5848 assert (top_src != NULL && top_src->klass() != NULL
5849 && top_dest != NULL && top_dest->klass() != NULL, "args are strange");
5850
5851 // checks are the responsibility of the caller
5852 Node* src_start = src;
5853 Node* dest_start = dest;
5854 if (src_offset != NULL || dest_offset != NULL) {
5855 assert(src_offset != NULL && dest_offset != NULL, "");
5856 src_start = array_element_address(src, src_offset, T_BYTE);
5857 dest_start = array_element_address(dest, dest_offset, T_BYTE);
5858 }
5859
5860 // if we are in this set of code, we "know" the embeddedCipher is an AESCrypt object
5861 // (because of the predicated logic executed earlier).
5862 // so we cast it here safely.
5863 // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java
5864
5865 Node* embeddedCipherObj = load_field_from_object(cipherBlockChaining_object, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
5866 if (embeddedCipherObj == NULL) return false;
5867
5868 // cast it to what we know it will be at runtime
5869 const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr();
5870 assert(tinst != NULL, "CBC obj is null");
5871 assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
5872 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
5873 if (!klass_AESCrypt->is_loaded()) return false;
5874
5875 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
5876 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
5877 const TypeOopPtr* xtype = aklass->as_instance_type();
5878 Node* aescrypt_object = new(C) CheckCastPPNode(control(), embeddedCipherObj, xtype);
5879 aescrypt_object = _gvn.transform(aescrypt_object);
5880
5881 // we need to get the start of the aescrypt_object's expanded key array
5882 Node* k_start = get_key_start_from_aescrypt_object(aescrypt_object);
5883 if (k_start == NULL) return false;
5884
5885 // similarly, get the start address of the r vector
5886 Node* objRvec = load_field_from_object(cipherBlockChaining_object, "r", "[B", /*is_exact*/ false);
5887 if (objRvec == NULL) return false;
5888 Node* r_start = array_element_address(objRvec, intcon(0), T_BYTE);
5889
5890 // Call the stub, passing src_start, dest_start, k_start, r_start and src_len
5891 make_runtime_call(RC_LEAF|RC_NO_FP,
5892 OptoRuntime::cipherBlockChaining_aescrypt_Type(),
5893 stubAddr, stubName, TypePtr::BOTTOM,
5894 src_start, dest_start, k_start, r_start, len);
5895
5896 // return is void so no result needs to be pushed
5897
5898 return true;
5899 }
5900
5901 //------------------------------get_key_start_from_aescrypt_object-----------------------
5902 Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) {
5903 Node* objAESCryptKey = load_field_from_object(aescrypt_object, "K", "[I", /*is_exact*/ false);
5904 assert (objAESCryptKey != NULL, "wrong version of com.sun.crypto.provider.AESCrypt");
5905 if (objAESCryptKey == NULL) return (Node *) NULL;
5906
5907 // now have the array, need to get the start address of the K array
5908 Node* k_start = array_element_address(objAESCryptKey, intcon(0), T_INT);
5909 return k_start;
5910 }
5911
5912 //----------------------------inline_cipherBlockChaining_AESCrypt_predicate----------------------------
5913 // Return node representing slow path of predicate check.
5914 // the pseudo code we want to emulate with this predicate is:
5915 // for encryption:
5916 // if (embeddedCipherObj instanceof AESCrypt) do_intrinsic, else do_javapath
5917 // for decryption:
5918 // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath
5919 // note cipher==plain is more conservative than the original java code but that's OK
5920 //
5921 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) {
5922 // First, check receiver for NULL since it is virtual method.
5923 int nargs = arg_size();
5924 Node* objCBC = argument(0);
5925 _sp += nargs;
5926 objCBC = do_null_check(objCBC, T_OBJECT);
5927 _sp -= nargs;
5928
5929 if (stopped()) return NULL; // Always NULL
5930
5931 // Load embeddedCipher field of CipherBlockChaining object.
5932 Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
5933
5934 // get AESCrypt klass for instanceOf check
5935 // AESCrypt might not be loaded yet if some other SymmetricCipher got us to this compile point
5936 // will have same classloader as CipherBlockChaining object
5937 const TypeInstPtr* tinst = _gvn.type(objCBC)->isa_instptr();
5938 assert(tinst != NULL, "CBCobj is null");
5939 assert(tinst->klass()->is_loaded(), "CBCobj is not loaded");
5940
5941 // we want to do an instanceof comparison against the AESCrypt class
5942 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
5943 if (!klass_AESCrypt->is_loaded()) {
5944 // if AESCrypt is not even loaded, we never take the intrinsic fast path
5945 Node* ctrl = control();
5946 set_control(top()); // no regular fast path
5947 return ctrl;
5948 }
5949 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
5950
5951 _sp += nargs; // gen_instanceof might do an uncommon trap
5952 Node* instof = gen_instanceof(embeddedCipherObj, makecon(TypeKlassPtr::make(instklass_AESCrypt)));
5953 _sp -= nargs;
5954 Node* cmp_instof = _gvn.transform(new (C) CmpINode(instof, intcon(1)));
5955 Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne));
5956
5957 Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
5958
5959 // for encryption, we are done
5960 if (!decrypting)
5961 return instof_false; // even if it is NULL
5962
5963 // for decryption, we need to add a further check to avoid
5964 // taking the intrinsic path when cipher and plain are the same
5965 // see the original java code for why.
5966 RegionNode* region = new(C) RegionNode(3);
5967 region->init_req(1, instof_false);
5968 Node* src = argument(1);
5969 Node *dest = argument(4);
5970 Node* cmp_src_dest = _gvn.transform(new (C) CmpPNode(src, dest));
5971 Node* bool_src_dest = _gvn.transform(new (C) BoolNode(cmp_src_dest, BoolTest::eq));
5972 Node* src_dest_conjoint = generate_guard(bool_src_dest, NULL, PROB_MIN);
5973 region->init_req(2, src_dest_conjoint);
5974
5975 record_for_igvn(region);
5976 return _gvn.transform(region);
5977
5978 }
5979
5980