Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/library_call.cpp @ 20312:922c87c9aed4
8035605: Expand functionality of PredictedIntrinsicGenerator
Summary: Allow several predicates and separate intrinsic methods per one intrinsified (virtual) method.
Reviewed-by: roland
author | kvn |
---|---|
date | Tue, 10 Jun 2014 12:28:06 -0700 |
parents | 00c8a1255912 |
children | b20a35eae442 |
comparison
equal
deleted
inserted
replaced
20311:b1bc1af04c6e | 20312:922c87c9aed4 |
---|---|
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(); |
365 default: | 368 default: |
366 return NULL; | 369 return NULL; |
367 } | 370 } |
368 } | 371 } |
369 | 372 |
370 bool is_predicted = false; | 373 int predicates = 0; |
371 bool does_virtual_dispatch = false; | 374 bool does_virtual_dispatch = false; |
372 | 375 |
373 switch (id) { | 376 switch (id) { |
374 case vmIntrinsics::_compareTo: | 377 case vmIntrinsics::_compareTo: |
375 if (!SpecialStringCompareTo) return NULL; | 378 if (!SpecialStringCompareTo) return NULL; |
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 |