44 class LibraryIntrinsic : public InlineCallGenerator { |
44 class LibraryIntrinsic : public InlineCallGenerator { |
45 // Extend the set of intrinsics known to the runtime: |
45 // Extend the set of intrinsics known to the runtime: |
46 public: |
46 public: |
47 private: |
47 private: |
48 bool _is_virtual; |
48 bool _is_virtual; |
49 bool _is_predicted; |
|
50 bool _does_virtual_dispatch; |
49 bool _does_virtual_dispatch; |
|
50 int8_t _predicates_count; // Intrinsic is predicated by several conditions |
|
51 int8_t _last_predicate; // Last generated predicate |
51 vmIntrinsics::ID _intrinsic_id; |
52 vmIntrinsics::ID _intrinsic_id; |
52 |
53 |
53 public: |
54 public: |
54 LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id) |
55 LibraryIntrinsic(ciMethod* m, bool is_virtual, int predicates_count, bool does_virtual_dispatch, vmIntrinsics::ID id) |
55 : InlineCallGenerator(m), |
56 : InlineCallGenerator(m), |
56 _is_virtual(is_virtual), |
57 _is_virtual(is_virtual), |
57 _is_predicted(is_predicted), |
|
58 _does_virtual_dispatch(does_virtual_dispatch), |
58 _does_virtual_dispatch(does_virtual_dispatch), |
|
59 _predicates_count((int8_t)predicates_count), |
|
60 _last_predicate((int8_t)-1), |
59 _intrinsic_id(id) |
61 _intrinsic_id(id) |
60 { |
62 { |
61 } |
63 } |
62 virtual bool is_intrinsic() const { return true; } |
64 virtual bool is_intrinsic() const { return true; } |
63 virtual bool is_virtual() const { return _is_virtual; } |
65 virtual bool is_virtual() const { return _is_virtual; } |
64 virtual bool is_predicted() const { return _is_predicted; } |
66 virtual bool is_predicated() const { return _predicates_count > 0; } |
|
67 virtual int predicates_count() const { return _predicates_count; } |
65 virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; } |
68 virtual bool does_virtual_dispatch() const { return _does_virtual_dispatch; } |
66 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
69 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
67 virtual Node* generate_predicate(JVMState* jvms); |
70 virtual Node* generate_predicate(JVMState* jvms, int predicate); |
68 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } |
71 vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; } |
69 }; |
72 }; |
70 |
73 |
71 |
74 |
72 // Local helper class for LibraryIntrinsic: |
75 // Local helper class for LibraryIntrinsic: |
105 int bci() const { return jvms()->bci(); } |
108 int bci() const { return jvms()->bci(); } |
106 LibraryIntrinsic* intrinsic() const { return _intrinsic; } |
109 LibraryIntrinsic* intrinsic() const { return _intrinsic; } |
107 vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } |
110 vmIntrinsics::ID intrinsic_id() const { return _intrinsic->intrinsic_id(); } |
108 ciMethod* callee() const { return _intrinsic->method(); } |
111 ciMethod* callee() const { return _intrinsic->method(); } |
109 |
112 |
110 bool try_to_inline(); |
113 bool try_to_inline(int predicate); |
111 Node* try_to_predicate(); |
114 Node* try_to_predicate(int predicate); |
112 |
115 |
113 void push_result() { |
116 void push_result() { |
114 // Push the result onto the stack. |
117 // Push the result onto the stack. |
115 if (!stopped() && result() != NULL) { |
118 if (!stopped() && result() != NULL) { |
116 BasicType bt = result()->bottom_type()->basic_type(); |
119 BasicType bt = result()->bottom_type()->basic_type(); |
506 |
509 |
507 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
510 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: |
508 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
511 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: |
509 if (!UseAESIntrinsics) return NULL; |
512 if (!UseAESIntrinsics) return NULL; |
510 // these two require the predicated logic |
513 // these two require the predicated logic |
511 is_predicted = true; |
514 predicates = 1; |
512 break; |
515 break; |
513 |
516 |
514 case vmIntrinsics::_updateCRC32: |
517 case vmIntrinsics::_updateCRC32: |
515 case vmIntrinsics::_updateBytesCRC32: |
518 case vmIntrinsics::_updateBytesCRC32: |
516 case vmIntrinsics::_updateByteBufferCRC32: |
519 case vmIntrinsics::_updateByteBufferCRC32: |
575 // -XX:-InlineUnsafeOps disables natives from the Unsafe class. |
578 // -XX:-InlineUnsafeOps disables natives from the Unsafe class. |
576 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { |
579 if (m->holder()->name() == ciSymbol::sun_misc_Unsafe()) { |
577 if (!InlineUnsafeOps) return NULL; |
580 if (!InlineUnsafeOps) return NULL; |
578 } |
581 } |
579 |
582 |
580 return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id); |
583 return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id); |
581 } |
584 } |
582 |
585 |
583 //----------------------register_library_intrinsics----------------------- |
586 //----------------------register_library_intrinsics----------------------- |
584 // Initialize this file's data structures, for each Compile instance. |
587 // Initialize this file's data structures, for each Compile instance. |
585 void Compile::register_library_intrinsics() { |
588 void Compile::register_library_intrinsics() { |
599 #endif |
602 #endif |
600 ciMethod* callee = kit.callee(); |
603 ciMethod* callee = kit.callee(); |
601 const int bci = kit.bci(); |
604 const int bci = kit.bci(); |
602 |
605 |
603 // Try to inline the intrinsic. |
606 // Try to inline the intrinsic. |
604 if (kit.try_to_inline()) { |
607 if (kit.try_to_inline(_last_predicate)) { |
605 if (C->print_intrinsics() || C->print_inlining()) { |
608 if (C->print_intrinsics() || C->print_inlining()) { |
606 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
609 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
607 } |
610 } |
608 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
611 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
609 if (C->log()) { |
612 if (C->log()) { |
632 } |
635 } |
633 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); |
636 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); |
634 return NULL; |
637 return NULL; |
635 } |
638 } |
636 |
639 |
637 Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { |
640 Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) { |
638 LibraryCallKit kit(jvms, this); |
641 LibraryCallKit kit(jvms, this); |
639 Compile* C = kit.C; |
642 Compile* C = kit.C; |
640 int nodes = C->unique(); |
643 int nodes = C->unique(); |
|
644 _last_predicate = predicate; |
641 #ifndef PRODUCT |
645 #ifndef PRODUCT |
642 assert(is_predicted(), "sanity"); |
646 assert(is_predicated() && predicate < predicates_count(), "sanity"); |
643 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
647 if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { |
644 char buf[1000]; |
648 char buf[1000]; |
645 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); |
649 const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); |
646 tty->print_cr("Predicate for intrinsic %s", str); |
650 tty->print_cr("Predicate for intrinsic %s", str); |
647 } |
651 } |
648 #endif |
652 #endif |
649 ciMethod* callee = kit.callee(); |
653 ciMethod* callee = kit.callee(); |
650 const int bci = kit.bci(); |
654 const int bci = kit.bci(); |
651 |
655 |
652 Node* slow_ctl = kit.try_to_predicate(); |
656 Node* slow_ctl = kit.try_to_predicate(predicate); |
653 if (!kit.failing()) { |
657 if (!kit.failing()) { |
654 if (C->print_intrinsics() || C->print_inlining()) { |
658 if (C->print_intrinsics() || C->print_inlining()) { |
655 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); |
659 C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual, predicate)" : "(intrinsic, predicate)"); |
656 } |
660 } |
657 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
661 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); |
658 if (C->log()) { |
662 if (C->log()) { |
659 C->log()->elem("predicate_intrinsic id='%s'%s nodes='%d'", |
663 C->log()->elem("predicate_intrinsic id='%s'%s nodes='%d'", |
660 vmIntrinsics::name_at(intrinsic_id()), |
664 vmIntrinsics::name_at(intrinsic_id()), |
679 } |
683 } |
680 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); |
684 C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed); |
681 return NULL; |
685 return NULL; |
682 } |
686 } |
683 |
687 |
684 bool LibraryCallKit::try_to_inline() { |
688 bool LibraryCallKit::try_to_inline(int predicate) { |
685 // Handle symbolic names for otherwise undistinguished boolean switches: |
689 // Handle symbolic names for otherwise undistinguished boolean switches: |
686 const bool is_store = true; |
690 const bool is_store = true; |
687 const bool is_native_ptr = true; |
691 const bool is_native_ptr = true; |
688 const bool is_static = true; |
692 const bool is_static = true; |
689 const bool is_volatile = true; |
693 const bool is_volatile = true; |
896 #endif |
900 #endif |
897 return false; |
901 return false; |
898 } |
902 } |
899 } |
903 } |
900 |
904 |
901 Node* LibraryCallKit::try_to_predicate() { |
905 Node* LibraryCallKit::try_to_predicate(int predicate) { |
902 if (!jvms()->has_method()) { |
906 if (!jvms()->has_method()) { |
903 // Root JVMState has a null method. |
907 // Root JVMState has a null method. |
904 assert(map()->memory()->Opcode() == Op_Parm, ""); |
908 assert(map()->memory()->Opcode() == Op_Parm, ""); |
905 // Insert the memory aliasing node |
909 // Insert the memory aliasing node |
906 set_all_memory(reset_memory()); |
910 set_all_memory(reset_memory()); |
5864 const TypePtr* adr_type = C->alias_type(field)->adr_type(); |
5868 const TypePtr* adr_type = C->alias_type(field)->adr_type(); |
5865 Node *adr = basic_plus_adr(fromObj, fromObj, offset); |
5869 Node *adr = basic_plus_adr(fromObj, fromObj, offset); |
5866 BasicType bt = field->layout_type(); |
5870 BasicType bt = field->layout_type(); |
5867 |
5871 |
5868 // Build the resultant type of the load |
5872 // Build the resultant type of the load |
5869 const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass()); |
5873 const Type *type; |
|
5874 if (bt == T_OBJECT) { |
|
5875 type = TypeOopPtr::make_from_klass(field_klass->as_klass()); |
|
5876 } else { |
|
5877 type = Type::get_const_basic_type(bt); |
|
5878 } |
5870 |
5879 |
5871 // Build the load. |
5880 // Build the load. |
5872 Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); |
5881 Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol); |
5873 return loadedField; |
5882 return loadedField; |
5874 } |
5883 } |
5994 // cast it to what we know it will be at runtime |
6003 // cast it to what we know it will be at runtime |
5995 const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr(); |
6004 const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr(); |
5996 assert(tinst != NULL, "CBC obj is null"); |
6005 assert(tinst != NULL, "CBC obj is null"); |
5997 assert(tinst->klass()->is_loaded(), "CBC obj is not loaded"); |
6006 assert(tinst->klass()->is_loaded(), "CBC obj is not loaded"); |
5998 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); |
6007 ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); |
5999 if (!klass_AESCrypt->is_loaded()) return false; |
6008 assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); |
6000 |
6009 |
6001 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); |
6010 ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); |
6002 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); |
6011 const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); |
6003 const TypeOopPtr* xtype = aklass->as_instance_type(); |
6012 const TypeOopPtr* xtype = aklass->as_instance_type(); |
6004 Node* aescrypt_object = new(C) CheckCastPPNode(control(), embeddedCipherObj, xtype); |
6013 Node* aescrypt_object = new(C) CheckCastPPNode(control(), embeddedCipherObj, xtype); |
6069 // for decryption: |
6078 // for decryption: |
6070 // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath |
6079 // if ((embeddedCipherObj instanceof AESCrypt) && (cipher!=plain)) do_intrinsic, else do_javapath |
6071 // note cipher==plain is more conservative than the original java code but that's OK |
6080 // note cipher==plain is more conservative than the original java code but that's OK |
6072 // |
6081 // |
6073 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) { |
6082 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) { |
6074 // First, check receiver for NULL since it is virtual method. |
6083 // The receiver was checked for NULL already. |
6075 Node* objCBC = argument(0); |
6084 Node* objCBC = argument(0); |
6076 objCBC = null_check(objCBC); |
|
6077 |
|
6078 if (stopped()) return NULL; // Always NULL |
|
6079 |
6085 |
6080 // Load embeddedCipher field of CipherBlockChaining object. |
6086 // Load embeddedCipher field of CipherBlockChaining object. |
6081 Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); |
6087 Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false); |
6082 |
6088 |
6083 // get AESCrypt klass for instanceOf check |
6089 // get AESCrypt klass for instanceOf check |