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;