Mercurial > hg > truffle
comparison src/share/vm/opto/callGenerator.cpp @ 1137:97125851f396
6829187: compiler optimizations required for JSR 292
Summary: C2 implementation for invokedynamic support.
Reviewed-by: kvn, never
author | twisti |
---|---|
date | Tue, 05 Jan 2010 13:05:58 +0100 |
parents | 7c57aead6d3e |
children | dd57230ba8fe |
comparison
equal
deleted
inserted
replaced
1136:4b84186a8248 | 1137:97125851f396 |
---|---|
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 dynamic 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* cpc = kit.makecon(cpcache_ptr); | |
183 Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset); | |
184 Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); | |
185 | |
186 // Load the MethodHandle (target) from the CallSite object. | |
187 Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes()); | |
188 Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); | |
189 | |
190 address stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); | |
191 | |
192 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), 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 MethodHandle as first argument and shift the other | |
199 // arguments. | |
200 call->init_req(0 + TypeFunc::Parms, 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 { |