Mercurial > hg > truffle
comparison src/share/vm/interpreter/interpreterRuntime.cpp @ 6266:1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
6984705: JSR 292 method handle creation should not go through JNI
Summary: remove assembly code for JDK 7 chained method handles
Reviewed-by: jrose, twisti, kvn, mhaupt
Contributed-by: John Rose <john.r.rose@oracle.com>, Christian Thalinger <christian.thalinger@oracle.com>, Michael Haupt <michael.haupt@oracle.com>
author | twisti |
---|---|
date | Tue, 24 Jul 2012 10:51:00 -0700 |
parents | dd785aabe02b |
children | 957c266d8bc5 da91efe96a93 |
comparison
equal
deleted
inserted
replaced
6241:aba91a731143 | 6266:1d7922586cf6 |
---|---|
143 #ifdef ASSERT | 143 #ifdef ASSERT |
144 { | 144 { |
145 // The bytecode wrappers aren't GC-safe so construct a new one | 145 // The bytecode wrappers aren't GC-safe so construct a new one |
146 Bytecode_loadconstant ldc2(m, bci(thread)); | 146 Bytecode_loadconstant ldc2(m, bci(thread)); |
147 ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc2.cache_index()); | 147 ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc2.cache_index()); |
148 assert(result == cpce->f1(), "expected result for assembly code"); | 148 assert(result == cpce->f1_as_instance(), "expected result for assembly code"); |
149 } | 149 } |
150 #endif | 150 #endif |
151 } | 151 } |
152 IRT_END | 152 IRT_END |
153 | 153 |
654 | 654 |
655 IRT_ENTRY(void, InterpreterRuntime::_breakpoint(JavaThread* thread, methodOopDesc* method, address bcp)) | 655 IRT_ENTRY(void, InterpreterRuntime::_breakpoint(JavaThread* thread, methodOopDesc* method, address bcp)) |
656 JvmtiExport::post_raw_breakpoint(thread, method, bcp); | 656 JvmtiExport::post_raw_breakpoint(thread, method, bcp); |
657 IRT_END | 657 IRT_END |
658 | 658 |
659 IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) | 659 IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) { |
660 // extract receiver from the outgoing argument list if necessary | 660 // extract receiver from the outgoing argument list if necessary |
661 Handle receiver(thread, NULL); | 661 Handle receiver(thread, NULL); |
662 if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { | 662 if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) { |
663 ResourceMark rm(thread); | 663 ResourceMark rm(thread); |
664 methodHandle m (thread, method(thread)); | 664 methodHandle m (thread, method(thread)); |
722 cache_entry(thread)->set_method( | 722 cache_entry(thread)->set_method( |
723 bytecode, | 723 bytecode, |
724 info.resolved_method(), | 724 info.resolved_method(), |
725 info.vtable_index()); | 725 info.vtable_index()); |
726 } | 726 } |
727 } | |
728 IRT_END | |
729 | |
730 | |
731 // First time execution: Resolve symbols, create a permanent MethodType object. | |
732 IRT_ENTRY(void, InterpreterRuntime::resolve_invokehandle(JavaThread* thread)) { | |
733 assert(EnableInvokeDynamic, ""); | |
734 const Bytecodes::Code bytecode = Bytecodes::_invokehandle; | |
735 | |
736 // resolve method | |
737 CallInfo info; | |
738 constantPoolHandle pool(thread, method(thread)->constants()); | |
739 | |
740 { | |
741 JvmtiHideSingleStepping jhss(thread); | |
742 LinkResolver::resolve_invoke(info, Handle(), pool, | |
743 get_index_u2_cpcache(thread, bytecode), bytecode, CHECK); | |
744 } // end JvmtiHideSingleStepping | |
745 | |
746 cache_entry(thread)->set_method_handle( | |
747 info.resolved_method(), | |
748 info.resolved_appendix()); | |
749 } | |
727 IRT_END | 750 IRT_END |
728 | 751 |
729 | 752 |
730 // First time execution: Resolve symbols, create a permanent CallSite object. | 753 // First time execution: Resolve symbols, create a permanent CallSite object. |
731 IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { | 754 IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { |
732 ResourceMark rm(thread); | |
733 | |
734 assert(EnableInvokeDynamic, ""); | 755 assert(EnableInvokeDynamic, ""); |
735 | |
736 const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; | 756 const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; |
737 | 757 |
738 methodHandle caller_method(thread, method(thread)); | 758 //TO DO: consider passing BCI to Java. |
739 | 759 // int caller_bci = method(thread)->bci_from(bcp(thread)); |
740 constantPoolHandle pool(thread, caller_method->constants()); | 760 |
741 pool->set_invokedynamic(); // mark header to flag active call sites | 761 // resolve method |
742 | 762 CallInfo info; |
743 int caller_bci = 0; | 763 constantPoolHandle pool(thread, method(thread)->constants()); |
744 int site_index = 0; | 764 int index = get_index_u4(thread, bytecode); |
745 { address caller_bcp = bcp(thread); | 765 |
746 caller_bci = caller_method->bci_from(caller_bcp); | 766 { |
747 site_index = Bytes::get_native_u4(caller_bcp+1); | |
748 } | |
749 assert(site_index == InterpreterRuntime::bytecode(thread).get_index_u4(bytecode), ""); | |
750 assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format"); | |
751 // there is a second CPC entries that is of interest; it caches signature info: | |
752 int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index(); | |
753 int pool_index = pool->cache()->entry_at(main_index)->constant_pool_index(); | |
754 | |
755 // first resolve the signature to a MH.invoke methodOop | |
756 if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) { | |
757 JvmtiHideSingleStepping jhss(thread); | 767 JvmtiHideSingleStepping jhss(thread); |
758 CallInfo callinfo; | 768 LinkResolver::resolve_invoke(info, Handle(), pool, |
759 LinkResolver::resolve_invoke(callinfo, Handle(), pool, | 769 index, bytecode, CHECK); |
760 site_index, bytecode, CHECK); | 770 } // end JvmtiHideSingleStepping |
761 // The main entry corresponds to a JVM_CONSTANT_InvokeDynamic, and serves | 771 |
762 // as a common reference point for all invokedynamic call sites with | 772 pool->cache()->secondary_entry_at(index)->set_dynamic_call( |
763 // that exact call descriptor. We will link it in the CP cache exactly | 773 info.resolved_method(), |
764 // as if it were an invokevirtual of MethodHandle.invoke. | 774 info.resolved_appendix()); |
765 pool->cache()->entry_at(main_index)->set_method( | |
766 bytecode, | |
767 callinfo.resolved_method(), | |
768 callinfo.vtable_index()); | |
769 } | |
770 | |
771 // The method (f2 entry) of the main entry is the MH.invoke for the | |
772 // invokedynamic target call signature. | |
773 oop f1_value = pool->cache()->entry_at(main_index)->f1(); | |
774 methodHandle signature_invoker(THREAD, (methodOop) f1_value); | |
775 assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(), | |
776 "correct result from LinkResolver::resolve_invokedynamic"); | |
777 | |
778 Handle info; // optional argument(s) in JVM_CONSTANT_InvokeDynamic | |
779 Handle bootm = SystemDictionary::find_bootstrap_method(caller_method, caller_bci, | |
780 main_index, info, CHECK); | |
781 if (!java_lang_invoke_MethodHandle::is_instance(bootm())) { | |
782 THROW_MSG(vmSymbols::java_lang_IllegalStateException(), | |
783 "no bootstrap method found for invokedynamic"); | |
784 } | |
785 | |
786 // Short circuit if CallSite has been bound already: | |
787 if (!pool->cache()->secondary_entry_at(site_index)->is_f1_null()) | |
788 return; | |
789 | |
790 Symbol* call_site_name = pool->name_ref_at(site_index); | |
791 | |
792 Handle call_site | |
793 = SystemDictionary::make_dynamic_call_site(bootm, | |
794 // Callee information: | |
795 call_site_name, | |
796 signature_invoker, | |
797 info, | |
798 // Caller information: | |
799 caller_method, | |
800 caller_bci, | |
801 CHECK); | |
802 | |
803 // In the secondary entry, the f1 field is the call site, and the f2 (index) | |
804 // field is some data about the invoke site. Currently, it is just the BCI. | |
805 // Later, it might be changed to help manage inlining dependencies. | |
806 pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site, signature_invoker); | |
807 } | 775 } |
808 IRT_END | 776 IRT_END |
809 | 777 |
810 | 778 |
811 //------------------------------------------------------------------------------------------------------------------------ | 779 //------------------------------------------------------------------------------------------------------------------------ |
973 IRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread *thread, oopDesc* obj, | 941 IRT_ENTRY(void, InterpreterRuntime::post_field_access(JavaThread *thread, oopDesc* obj, |
974 ConstantPoolCacheEntry *cp_entry)) | 942 ConstantPoolCacheEntry *cp_entry)) |
975 | 943 |
976 // check the access_flags for the field in the klass | 944 // check the access_flags for the field in the klass |
977 | 945 |
978 instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1())); | 946 instanceKlass* ik = instanceKlass::cast(java_lang_Class::as_klassOop(cp_entry->f1_as_klass_mirror())); |
979 int index = cp_entry->field_index(); | 947 int index = cp_entry->field_index(); |
980 if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; | 948 if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; |
981 | 949 |
982 switch(cp_entry->flag_state()) { | 950 switch(cp_entry->flag_state()) { |
983 case btos: // fall through | 951 case btos: // fall through |
996 Handle h_obj; | 964 Handle h_obj; |
997 if (!is_static) { | 965 if (!is_static) { |
998 // non-static field accessors have an object, but we need a handle | 966 // non-static field accessors have an object, but we need a handle |
999 h_obj = Handle(thread, obj); | 967 h_obj = Handle(thread, obj); |
1000 } | 968 } |
1001 instanceKlassHandle h_cp_entry_f1(thread, java_lang_Class::as_klassOop(cp_entry->f1())); | 969 instanceKlassHandle h_cp_entry_f1(thread, java_lang_Class::as_klassOop(cp_entry->f1_as_klass_mirror())); |
1002 jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_cp_entry_f1, cp_entry->f2(), is_static); | 970 jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_cp_entry_f1, cp_entry->f2_as_index(), is_static); |
1003 JvmtiExport::post_field_access(thread, method(thread), bcp(thread), h_cp_entry_f1, h_obj, fid); | 971 JvmtiExport::post_field_access(thread, method(thread), bcp(thread), h_cp_entry_f1, h_obj, fid); |
1004 IRT_END | 972 IRT_END |
1005 | 973 |
1006 IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, | 974 IRT_ENTRY(void, InterpreterRuntime::post_field_modification(JavaThread *thread, |
1007 oopDesc* obj, ConstantPoolCacheEntry *cp_entry, jvalue *value)) | 975 oopDesc* obj, ConstantPoolCacheEntry *cp_entry, jvalue *value)) |
1008 | 976 |
1009 klassOop k = java_lang_Class::as_klassOop(cp_entry->f1()); | 977 klassOop k = java_lang_Class::as_klassOop(cp_entry->f1_as_klass_mirror()); |
1010 | 978 |
1011 // check the access_flags for the field in the klass | 979 // check the access_flags for the field in the klass |
1012 instanceKlass* ik = instanceKlass::cast(k); | 980 instanceKlass* ik = instanceKlass::cast(k); |
1013 int index = cp_entry->field_index(); | 981 int index = cp_entry->field_index(); |
1014 // bail out if field modifications are not watched | 982 // bail out if field modifications are not watched |
1029 } | 997 } |
1030 bool is_static = (obj == NULL); | 998 bool is_static = (obj == NULL); |
1031 | 999 |
1032 HandleMark hm(thread); | 1000 HandleMark hm(thread); |
1033 instanceKlassHandle h_klass(thread, k); | 1001 instanceKlassHandle h_klass(thread, k); |
1034 jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_klass, cp_entry->f2(), is_static); | 1002 jfieldID fid = jfieldIDWorkaround::to_jfieldID(h_klass, cp_entry->f2_as_index(), is_static); |
1035 jvalue fvalue; | 1003 jvalue fvalue; |
1036 #ifdef _LP64 | 1004 #ifdef _LP64 |
1037 fvalue = *value; | 1005 fvalue = *value; |
1038 #else | 1006 #else |
1039 // Long/double values are stored unaligned and also noncontiguously with | 1007 // Long/double values are stored unaligned and also noncontiguously with |