src/share/vm/opto/callGenerator.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6829187 Sdiff src/share/vm/opto

src/share/vm/opto/callGenerator.cpp

Print this page
rev 1082 : [mq]: indy.compiler.patch
   1 /*
   2  * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *


 119   GraphKit kit(jvms);
 120   bool is_static = method()->is_static();
 121   address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
 122                              : SharedRuntime::get_resolve_opt_virtual_call_stub();
 123 
 124   if (kit.C->log() != NULL) {
 125     kit.C->log()->elem("direct_call bci='%d'", jvms->bci());
 126   }
 127 
 128   CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
 129   if (!is_static) {
 130     // Make an explicit receiver null_check as part of this call.
 131     // Since we share a map with the caller, his JVMS gets adjusted.
 132     kit.null_check_receiver(method());
 133     if (kit.stopped()) {
 134       // And dump it back to the caller, decorated with any exceptions:
 135       return kit.transfer_exceptions_into_jvms();
 136     }
 137     // Mark the call node as virtual, sort of:
 138     call->set_optimized_virtual(true);


 139   }
 140   kit.set_arguments_for_java_call(call);
 141   kit.set_edges_for_java_call(call, false, _separate_io_proj);
 142   Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
 143   kit.push_node(method()->return_type()->basic_type(), ret);
 144   _call_node = call;  // Save the call node in case we need it later
 145   return kit.transfer_exceptions_into_jvms();
 146 }
 147 

































































 148 class VirtualCallGenerator : public CallGenerator {
 149 private:
 150   int _vtable_index;
 151 public:
 152   VirtualCallGenerator(ciMethod* method, int vtable_index)
 153     : CallGenerator(method), _vtable_index(vtable_index)
 154   {
 155     assert(vtable_index == methodOopDesc::invalid_vtable_index ||
 156            vtable_index >= 0, "either invalid or usable");
 157   }
 158   virtual bool      is_virtual() const          { return true; }
 159   virtual JVMState* generate(JVMState* jvms);
 160 };
 161 
 162 //--------------------------VirtualCallGenerator------------------------------
 163 // Internal class which handles all out-of-line calls checking receiver type.
 164 JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
 165   GraphKit kit(jvms);
 166   Node* receiver = kit.argument(0);
 167 
 168   if (kit.C->log() != NULL) {
 169     kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
 170   }
 171 
 172   // If the receiver is a constant null, do not torture the system
 173   // by attempting to call through it.  The compile will proceed
 174   // correctly, but may bail out in final_graph_reshaping, because
 175   // the call instruction will have a seemingly deficient out-count.
 176   // (The bailout says something misleading about an "infinite loop".)
 177   if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
 178     kit.inc_sp(method()->arg_size());  // restore arguments
 179     kit.uncommon_trap(Deoptimization::Reason_null_check,
 180                       Deoptimization::Action_none,
 181                       NULL, "null receiver");
 182     return kit.transfer_exceptions_into_jvms();
 183   }


 236 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
 237   if (!ParseGenerator::can_parse(m))  return NULL;
 238   return new ParseGenerator(m, expected_uses);
 239 }
 240 
 241 // As a special case, the JVMS passed to this CallGenerator is
 242 // for the method execution already in progress, not just the JVMS
 243 // of the caller.  Thus, this CallGenerator cannot be mixed with others!
 244 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
 245   if (!ParseGenerator::can_parse(m, true))  return NULL;
 246   float past_uses = m->interpreter_invocation_count();
 247   float expected_uses = past_uses;
 248   return new ParseGenerator(m, expected_uses, true);
 249 }
 250 
 251 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
 252   assert(!m->is_abstract(), "for_direct_call mismatch");
 253   return new DirectCallGenerator(m, separate_io_proj);
 254 }
 255 





 256 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
 257   assert(!m->is_static(), "for_virtual_call mismatch");

 258   return new VirtualCallGenerator(m, vtable_index);
 259 }
 260 
 261 // Allow inlining decisions to be delayed
 262 class LateInlineCallGenerator : public DirectCallGenerator {
 263   CallGenerator* _inline_cg;
 264 
 265  public:
 266   LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
 267     DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
 268 
 269   virtual bool      is_late_inline() const { return true; }
 270 
 271   // Convert the CallStaticJava into an inline
 272   virtual void do_late_inline();
 273 
 274   JVMState* generate(JVMState* jvms) {
 275     // Record that this call site should be revisited once the main
 276     // parse is finished.
 277     Compile::current()->add_late_inline(this);


   1 /*
   2  * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *


 119   GraphKit kit(jvms);
 120   bool is_static = method()->is_static();
 121   address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
 122                              : SharedRuntime::get_resolve_opt_virtual_call_stub();
 123 
 124   if (kit.C->log() != NULL) {
 125     kit.C->log()->elem("direct_call bci='%d'", jvms->bci());
 126   }
 127 
 128   CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci());
 129   if (!is_static) {
 130     // Make an explicit receiver null_check as part of this call.
 131     // Since we share a map with the caller, his JVMS gets adjusted.
 132     kit.null_check_receiver(method());
 133     if (kit.stopped()) {
 134       // And dump it back to the caller, decorated with any exceptions:
 135       return kit.transfer_exceptions_into_jvms();
 136     }
 137     // Mark the call node as virtual, sort of:
 138     call->set_optimized_virtual(true);
 139     if (method()->is_method_handle_invoke())
 140       call->set_method_handle_invoke(true);
 141   }
 142   kit.set_arguments_for_java_call(call);
 143   kit.set_edges_for_java_call(call, false, _separate_io_proj);
 144   Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
 145   kit.push_node(method()->return_type()->basic_type(), ret);
 146   _call_node = call;  // Save the call node in case we need it later
 147   return kit.transfer_exceptions_into_jvms();
 148 }
 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.
 215 class VirtualCallGenerator : public CallGenerator {
 216 private:
 217   int _vtable_index;
 218 public:
 219   VirtualCallGenerator(ciMethod* method, int vtable_index)
 220     : CallGenerator(method), _vtable_index(vtable_index)
 221   {
 222     assert(vtable_index == methodOopDesc::invalid_vtable_index ||
 223            vtable_index >= 0, "either invalid or usable");
 224   }
 225   virtual bool      is_virtual() const          { return true; }
 226   virtual JVMState* generate(JVMState* jvms);
 227 };
 228 


 229 JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
 230   GraphKit kit(jvms);
 231   Node* receiver = kit.argument(0);
 232 
 233   if (kit.C->log() != NULL) {
 234     kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
 235   }
 236 
 237   // If the receiver is a constant null, do not torture the system
 238   // by attempting to call through it.  The compile will proceed
 239   // correctly, but may bail out in final_graph_reshaping, because
 240   // the call instruction will have a seemingly deficient out-count.
 241   // (The bailout says something misleading about an "infinite loop".)
 242   if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
 243     kit.inc_sp(method()->arg_size());  // restore arguments
 244     kit.uncommon_trap(Deoptimization::Reason_null_check,
 245                       Deoptimization::Action_none,
 246                       NULL, "null receiver");
 247     return kit.transfer_exceptions_into_jvms();
 248   }


 301 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
 302   if (!ParseGenerator::can_parse(m))  return NULL;
 303   return new ParseGenerator(m, expected_uses);
 304 }
 305 
 306 // As a special case, the JVMS passed to this CallGenerator is
 307 // for the method execution already in progress, not just the JVMS
 308 // of the caller.  Thus, this CallGenerator cannot be mixed with others!
 309 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
 310   if (!ParseGenerator::can_parse(m, true))  return NULL;
 311   float past_uses = m->interpreter_invocation_count();
 312   float expected_uses = past_uses;
 313   return new ParseGenerator(m, expected_uses, true);
 314 }
 315 
 316 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
 317   assert(!m->is_abstract(), "for_direct_call mismatch");
 318   return new DirectCallGenerator(m, separate_io_proj);
 319 }
 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 
 326 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
 327   assert(!m->is_static(), "for_virtual_call mismatch");
 328   assert(!m->is_method_handle_invoke(), "should be a direct call");
 329   return new VirtualCallGenerator(m, vtable_index);
 330 }
 331 
 332 // Allow inlining decisions to be delayed
 333 class LateInlineCallGenerator : public DirectCallGenerator {
 334   CallGenerator* _inline_cg;
 335 
 336  public:
 337   LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
 338     DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
 339 
 340   virtual bool      is_late_inline() const { return true; }
 341 
 342   // Convert the CallStaticJava into an inline
 343   virtual void do_late_inline();
 344 
 345   JVMState* generate(JVMState* jvms) {
 346     // Record that this call site should be revisited once the main
 347     // parse is finished.
 348     Compile::current()->add_late_inline(this);


src/share/vm/opto/callGenerator.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File