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 |