Mercurial > hg > truffle
comparison src/share/vm/interpreter/interpreterRuntime.cpp @ 726:be93aad57795
6655646: dynamic languages need dynamically linked call sites
Summary: invokedynamic instruction (JSR 292 RI)
Reviewed-by: twisti, never
author | jrose |
---|---|
date | Tue, 21 Apr 2009 23:21:04 -0700 |
parents | e5b0439ef4ae |
children | 8b46c4d82093 |
comparison
equal
deleted
inserted
replaced
725:928912ce8438 | 726:be93aad57795 |
---|---|
677 bytecode, | 677 bytecode, |
678 info.resolved_method(), | 678 info.resolved_method(), |
679 info.vtable_index()); | 679 info.vtable_index()); |
680 } | 680 } |
681 IRT_END | 681 IRT_END |
682 | |
683 | |
684 // First time execution: Resolve symbols, create a permanent CallSiteImpl object. | |
685 IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { | |
686 ResourceMark rm(thread); | |
687 | |
688 assert(EnableInvokeDynamic, ""); | |
689 | |
690 const Bytecodes::Code bytecode = Bytecodes::_invokedynamic; | |
691 | |
692 methodHandle caller_method(thread, method(thread)); | |
693 | |
694 // first determine if there is a bootstrap method | |
695 { | |
696 KlassHandle caller_klass(thread, caller_method->method_holder()); | |
697 Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK); | |
698 if (bootm.is_null()) { | |
699 // If there is no bootstrap method, throw IncompatibleClassChangeError. | |
700 // This is a valid generic error type for resolution (JLS 12.3.3). | |
701 char buf[200]; | |
702 jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic", | |
703 (Klass::cast(caller_klass()))->external_name()); | |
704 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | |
705 } | |
706 } | |
707 | |
708 constantPoolHandle pool(thread, caller_method->constants()); | |
709 pool->set_invokedynamic(); // mark header to flag active call sites | |
710 | |
711 int raw_index = four_byte_index(thread); | |
712 assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially"); | |
713 | |
714 // there are two CPC entries that are of interest: | |
715 int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index); | |
716 int main_index = pool->cache()->entry_at(site_index)->main_entry_index(); | |
717 // and there is one CP entry, a NameAndType: | |
718 int nt_index = pool->map_instruction_operand_to_index(raw_index); | |
719 | |
720 // first resolve the signature to a MH.invoke methodOop | |
721 if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) { | |
722 JvmtiHideSingleStepping jhss(thread); | |
723 CallInfo info; | |
724 LinkResolver::resolve_invoke(info, Handle(), pool, | |
725 raw_index, bytecode, CHECK); | |
726 // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves | |
727 // as a common reference point for all invokedynamic call sites with | |
728 // that exact call descriptor. We will link it in the CP cache exactly | |
729 // as if it were an invokevirtual of MethodHandle.invoke. | |
730 pool->cache()->entry_at(main_index)->set_method( | |
731 bytecode, | |
732 info.resolved_method(), | |
733 info.vtable_index()); | |
734 assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop"); | |
735 } | |
736 | |
737 // The method (f2 entry) of the main entry is the MH.invoke for the | |
738 // invokedynamic target call signature. | |
739 intptr_t f2_value = pool->cache()->entry_at(main_index)->f2(); | |
740 methodHandle mh_invdyn(THREAD, (methodOop) f2_value); | |
741 assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(), | |
742 "correct result from LinkResolver::resolve_invokedynamic"); | |
743 | |
744 symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index)); | |
745 Handle call_site | |
746 = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(), | |
747 caller_method->method_idnum(), | |
748 caller_method->bci_from(bcp(thread)), | |
749 call_site_name, | |
750 mh_invdyn, | |
751 CHECK); | |
752 | |
753 // In the secondary entry, the f1 field is the call site, and the f2 (index) | |
754 // field is some data about the invoke site. | |
755 int extra_data = 0; | |
756 pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), extra_data); | |
757 } | |
758 IRT_END | |
759 | |
760 | |
761 // Called on first time execution, and also whenever the CallSite.target is null. | |
762 // FIXME: Do more of this in Java code. | |
763 IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) { | |
764 methodHandle mh_invdyn(thread, (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site)); | |
765 Handle mh_type(thread, mh_invdyn->method_handle_type()); | |
766 objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type())); | |
767 | |
768 // squish the arguments down to a single array | |
769 int nargs = mh_ptypes->length(); | |
770 objArrayHandle arg_array; | |
771 { | |
772 objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK); | |
773 arg_array = objArrayHandle(thread, aaoop); | |
774 } | |
775 frame fr = thread->last_frame(); | |
776 assert(fr.interpreter_frame_bcp() != NULL, "sanity"); | |
777 int tos_offset = 0; | |
778 for (int i = nargs; --i >= 0; ) { | |
779 intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++); | |
780 oop ptype = mh_ptypes->obj_at(i); | |
781 oop arg = NULL; | |
782 if (!java_lang_Class::is_primitive(ptype)) { | |
783 arg = *(oop*) slot_addr; | |
784 } else { | |
785 BasicType bt = java_lang_Class::primitive_type(ptype); | |
786 assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code"); | |
787 jvalue value; | |
788 Interpreter::get_jvalue_in_slot(slot_addr, bt, &value); | |
789 tos_offset += type2size[bt]-1; | |
790 arg = java_lang_boxing_object::create(bt, &value, CHECK); | |
791 // FIXME: These boxing objects are not canonicalized under | |
792 // the Java autoboxing rules. They should be... | |
793 // The best approach would be to push the arglist creation into Java. | |
794 // The JVM should use a lower-level interface to communicate argument lists. | |
795 } | |
796 arg_array->obj_at_put(i, arg); | |
797 } | |
798 | |
799 // now find the bootstrap method | |
800 oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method(); | |
801 assert(bootstrap_mh_oop != NULL, "resolve_invokedynamic ensures a BSM"); | |
802 | |
803 // return the bootstrap method and argument array via vm_result/_2 | |
804 thread->set_vm_result(bootstrap_mh_oop); | |
805 thread->set_vm_result_2(arg_array()); | |
806 } | |
807 IRT_END | |
808 | |
682 | 809 |
683 | 810 |
684 //------------------------------------------------------------------------------------------------------------------------ | 811 //------------------------------------------------------------------------------------------------------------------------ |
685 // Miscellaneous | 812 // Miscellaneous |
686 | 813 |