Mercurial > hg > truffle
comparison src/share/vm/opto/callGenerator.cpp @ 1162:d749b1813f40
Merge
author | trims |
---|---|
date | Fri, 15 Jan 2010 14:25:44 -0800 |
parents | dd57230ba8fe |
children | b4b440360f1e |
comparison
equal
deleted
inserted
replaced
1130:1bc68593a110 | 1162:d749b1813f40 |
---|---|
1 /* | 1 /* |
2 * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. | 2 * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
134 // And dump it back to the caller, decorated with any exceptions: | 134 // And dump it back to the caller, decorated with any exceptions: |
135 return kit.transfer_exceptions_into_jvms(); | 135 return kit.transfer_exceptions_into_jvms(); |
136 } | 136 } |
137 // Mark the call node as virtual, sort of: | 137 // Mark the call node as virtual, sort of: |
138 call->set_optimized_virtual(true); | 138 call->set_optimized_virtual(true); |
139 if (method()->is_method_handle_invoke()) | |
140 call->set_method_handle_invoke(true); | |
139 } | 141 } |
140 kit.set_arguments_for_java_call(call); | 142 kit.set_arguments_for_java_call(call); |
141 kit.set_edges_for_java_call(call, false, _separate_io_proj); | 143 kit.set_edges_for_java_call(call, false, _separate_io_proj); |
142 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); | 144 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); |
143 kit.push_node(method()->return_type()->basic_type(), ret); | 145 kit.push_node(method()->return_type()->basic_type(), ret); |
144 _call_node = call; // Save the call node in case we need it later | 146 _call_node = call; // Save the call node in case we need it later |
145 return kit.transfer_exceptions_into_jvms(); | 147 return kit.transfer_exceptions_into_jvms(); |
146 } | 148 } |
147 | 149 |
150 //---------------------------DynamicCallGenerator----------------------------- | |
151 // Internal class which handles all out-of-line invokedynamic calls. | |
152 class DynamicCallGenerator : public CallGenerator { | |
153 public: | |
154 DynamicCallGenerator(ciMethod* method) | |
155 : CallGenerator(method) | |
156 { | |
157 } | |
158 virtual JVMState* generate(JVMState* jvms); | |
159 }; | |
160 | |
161 JVMState* DynamicCallGenerator::generate(JVMState* jvms) { | |
162 GraphKit kit(jvms); | |
163 | |
164 if (kit.C->log() != NULL) { | |
165 kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci()); | |
166 } | |
167 | |
168 // Get the constant pool cache from the caller class. | |
169 ciMethod* caller_method = jvms->method(); | |
170 ciBytecodeStream str(caller_method); | |
171 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. | |
172 assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); | |
173 ciCPCache* cpcache = str.get_cpcache(); | |
174 | |
175 // Get the offset of the CallSite from the constant pool cache | |
176 // pointer. | |
177 int index = str.get_method_index(); | |
178 size_t call_site_offset = cpcache->get_f1_offset(index); | |
179 | |
180 // Load the CallSite object from the constant pool cache. | |
181 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); | |
182 Node* cpcache_adr = kit.makecon(cpcache_ptr); | |
183 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); | |
184 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); | |
185 | |
186 // Load the target MethodHandle from the CallSite object. | |
187 Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); | |
188 Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); | |
189 | |
190 address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); | |
191 | |
192 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); | |
193 // invokedynamic is treated as an optimized invokevirtual. | |
194 call->set_optimized_virtual(true); | |
195 // Take extra care (in the presence of argument motion) not to trash the SP: | |
196 call->set_method_handle_invoke(true); | |
197 | |
198 // Pass the target MethodHandle as first argument and shift the | |
199 // other arguments. | |
200 call->init_req(0 + TypeFunc::Parms, target_mh); | |
201 uint nargs = call->method()->arg_size(); | |
202 for (uint i = 1; i < nargs; i++) { | |
203 Node* arg = kit.argument(i - 1); | |
204 call->init_req(i + TypeFunc::Parms, arg); | |
205 } | |
206 | |
207 kit.set_edges_for_java_call(call); | |
208 Node* ret = kit.set_results_for_java_call(call); | |
209 kit.push_node(method()->return_type()->basic_type(), ret); | |
210 return kit.transfer_exceptions_into_jvms(); | |
211 } | |
212 | |
213 //--------------------------VirtualCallGenerator------------------------------ | |
214 // Internal class which handles all out-of-line calls checking receiver type. | |
148 class VirtualCallGenerator : public CallGenerator { | 215 class VirtualCallGenerator : public CallGenerator { |
149 private: | 216 private: |
150 int _vtable_index; | 217 int _vtable_index; |
151 public: | 218 public: |
152 VirtualCallGenerator(ciMethod* method, int vtable_index) | 219 VirtualCallGenerator(ciMethod* method, int vtable_index) |
157 } | 224 } |
158 virtual bool is_virtual() const { return true; } | 225 virtual bool is_virtual() const { return true; } |
159 virtual JVMState* generate(JVMState* jvms); | 226 virtual JVMState* generate(JVMState* jvms); |
160 }; | 227 }; |
161 | 228 |
162 //--------------------------VirtualCallGenerator------------------------------ | |
163 // Internal class which handles all out-of-line calls checking receiver type. | |
164 JVMState* VirtualCallGenerator::generate(JVMState* jvms) { | 229 JVMState* VirtualCallGenerator::generate(JVMState* jvms) { |
165 GraphKit kit(jvms); | 230 GraphKit kit(jvms); |
166 Node* receiver = kit.argument(0); | 231 Node* receiver = kit.argument(0); |
167 | 232 |
168 if (kit.C->log() != NULL) { | 233 if (kit.C->log() != NULL) { |
251 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { | 316 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { |
252 assert(!m->is_abstract(), "for_direct_call mismatch"); | 317 assert(!m->is_abstract(), "for_direct_call mismatch"); |
253 return new DirectCallGenerator(m, separate_io_proj); | 318 return new DirectCallGenerator(m, separate_io_proj); |
254 } | 319 } |
255 | 320 |
321 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { | |
322 assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch"); | |
323 return new DynamicCallGenerator(m); | |
324 } | |
325 | |
256 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { | 326 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { |
257 assert(!m->is_static(), "for_virtual_call mismatch"); | 327 assert(!m->is_static(), "for_virtual_call mismatch"); |
328 assert(!m->is_method_handle_invoke(), "should be a direct call"); | |
258 return new VirtualCallGenerator(m, vtable_index); | 329 return new VirtualCallGenerator(m, vtable_index); |
259 } | 330 } |
260 | 331 |
261 // Allow inlining decisions to be delayed | 332 // Allow inlining decisions to be delayed |
262 class LateInlineCallGenerator : public DirectCallGenerator { | 333 class LateInlineCallGenerator : public DirectCallGenerator { |
574 } | 645 } |
575 return kit.transfer_exceptions_into_jvms(); | 646 return kit.transfer_exceptions_into_jvms(); |
576 } | 647 } |
577 | 648 |
578 | 649 |
650 //------------------------PredictedDynamicCallGenerator----------------------- | |
651 // Internal class which handles all out-of-line calls checking receiver type. | |
652 class PredictedDynamicCallGenerator : public CallGenerator { | |
653 ciMethodHandle* _predicted_method_handle; | |
654 CallGenerator* _if_missed; | |
655 CallGenerator* _if_hit; | |
656 float _hit_prob; | |
657 | |
658 public: | |
659 PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, | |
660 CallGenerator* if_missed, | |
661 CallGenerator* if_hit, | |
662 float hit_prob) | |
663 : CallGenerator(if_missed->method()), | |
664 _predicted_method_handle(predicted_method_handle), | |
665 _if_missed(if_missed), | |
666 _if_hit(if_hit), | |
667 _hit_prob(hit_prob) | |
668 {} | |
669 | |
670 virtual bool is_inline() const { return _if_hit->is_inline(); } | |
671 virtual bool is_deferred() const { return _if_hit->is_deferred(); } | |
672 | |
673 virtual JVMState* generate(JVMState* jvms); | |
674 }; | |
675 | |
676 | |
677 CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, | |
678 CallGenerator* if_missed, | |
679 CallGenerator* if_hit, | |
680 float hit_prob) { | |
681 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); | |
682 } | |
683 | |
684 | |
685 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { | |
686 GraphKit kit(jvms); | |
687 PhaseGVN& gvn = kit.gvn(); | |
688 | |
689 CompileLog* log = kit.C->log(); | |
690 if (log != NULL) { | |
691 log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); | |
692 } | |
693 | |
694 // Get the constant pool cache from the caller class. | |
695 ciMethod* caller_method = jvms->method(); | |
696 ciBytecodeStream str(caller_method); | |
697 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. | |
698 ciCPCache* cpcache = str.get_cpcache(); | |
699 | |
700 // Get the offset of the CallSite from the constant pool cache | |
701 // pointer. | |
702 int index = str.get_method_index(); | |
703 size_t call_site_offset = cpcache->get_f1_offset(index); | |
704 | |
705 // Load the CallSite object from the constant pool cache. | |
706 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); | |
707 Node* cpcache_adr = kit.makecon(cpcache_ptr); | |
708 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); | |
709 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); | |
710 | |
711 // Load the target MethodHandle from the CallSite object. | |
712 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); | |
713 Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); | |
714 | |
715 // Check if the MethodHandle is still the same. | |
716 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); | |
717 Node* predicted_mh = kit.makecon(predicted_mh_ptr); | |
718 | |
719 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); | |
720 Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); | |
721 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); | |
722 kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); | |
723 Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); | |
724 | |
725 SafePointNode* slow_map = NULL; | |
726 JVMState* slow_jvms; | |
727 { PreserveJVMState pjvms(&kit); | |
728 kit.set_control(slow_ctl); | |
729 if (!kit.stopped()) { | |
730 slow_jvms = _if_missed->generate(kit.sync_jvms()); | |
731 assert(slow_jvms != NULL, "miss path must not fail to generate"); | |
732 kit.add_exception_states_from(slow_jvms); | |
733 kit.set_map(slow_jvms->map()); | |
734 if (!kit.stopped()) | |
735 slow_map = kit.stop(); | |
736 } | |
737 } | |
738 | |
739 if (kit.stopped()) { | |
740 // Instance exactly does not matches the desired type. | |
741 kit.set_jvms(slow_jvms); | |
742 return kit.transfer_exceptions_into_jvms(); | |
743 } | |
744 | |
745 // Make the hot call: | |
746 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); | |
747 if (new_jvms == NULL) { | |
748 // Inline failed, so make a direct call. | |
749 assert(_if_hit->is_inline(), "must have been a failed inline"); | |
750 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); | |
751 new_jvms = cg->generate(kit.sync_jvms()); | |
752 } | |
753 kit.add_exception_states_from(new_jvms); | |
754 kit.set_jvms(new_jvms); | |
755 | |
756 // Need to merge slow and fast? | |
757 if (slow_map == NULL) { | |
758 // The fast path is the only path remaining. | |
759 return kit.transfer_exceptions_into_jvms(); | |
760 } | |
761 | |
762 if (kit.stopped()) { | |
763 // Inlined method threw an exception, so it's just the slow path after all. | |
764 kit.set_jvms(slow_jvms); | |
765 return kit.transfer_exceptions_into_jvms(); | |
766 } | |
767 | |
768 // Finish the diamond. | |
769 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization | |
770 RegionNode* region = new (kit.C, 3) RegionNode(3); | |
771 region->init_req(1, kit.control()); | |
772 region->init_req(2, slow_map->control()); | |
773 kit.set_control(gvn.transform(region)); | |
774 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); | |
775 iophi->set_req(2, slow_map->i_o()); | |
776 kit.set_i_o(gvn.transform(iophi)); | |
777 kit.merge_memory(slow_map->merged_memory(), region, 2); | |
778 uint tos = kit.jvms()->stkoff() + kit.sp(); | |
779 uint limit = slow_map->req(); | |
780 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
781 // Skip unused stack slots; fast forward to monoff(); | |
782 if (i == tos) { | |
783 i = kit.jvms()->monoff(); | |
784 if( i >= limit ) break; | |
785 } | |
786 Node* m = kit.map()->in(i); | |
787 Node* n = slow_map->in(i); | |
788 if (m != n) { | |
789 const Type* t = gvn.type(m)->meet(gvn.type(n)); | |
790 Node* phi = PhiNode::make(region, m, t); | |
791 phi->set_req(2, n); | |
792 kit.map()->set_req(i, gvn.transform(phi)); | |
793 } | |
794 } | |
795 return kit.transfer_exceptions_into_jvms(); | |
796 } | |
797 | |
798 | |
579 //-------------------------UncommonTrapCallGenerator----------------------------- | 799 //-------------------------UncommonTrapCallGenerator----------------------------- |
580 // Internal class which handles all out-of-line calls checking receiver type. | 800 // Internal class which handles all out-of-line calls checking receiver type. |
581 class UncommonTrapCallGenerator : public CallGenerator { | 801 class UncommonTrapCallGenerator : public CallGenerator { |
582 Deoptimization::DeoptReason _reason; | 802 Deoptimization::DeoptReason _reason; |
583 Deoptimization::DeoptAction _action; | 803 Deoptimization::DeoptAction _action; |