src/share/vm/opto/callGenerator.cpp

changeset 1572
97125851f396
parent 1515
7c57aead6d3e
child 1573
dd57230ba8fe
     1.1 --- a/src/share/vm/opto/callGenerator.cpp	Mon Jan 04 15:21:09 2010 -0800
     1.2 +++ b/src/share/vm/opto/callGenerator.cpp	Tue Jan 05 13:05:58 2010 +0100
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -136,6 +136,8 @@
    1.11      }
    1.12      // Mark the call node as virtual, sort of:
    1.13      call->set_optimized_virtual(true);
    1.14 +    if (method()->is_method_handle_invoke())
    1.15 +      call->set_method_handle_invoke(true);
    1.16    }
    1.17    kit.set_arguments_for_java_call(call);
    1.18    kit.set_edges_for_java_call(call, false, _separate_io_proj);
    1.19 @@ -145,6 +147,71 @@
    1.20    return kit.transfer_exceptions_into_jvms();
    1.21  }
    1.22  
    1.23 +//---------------------------DynamicCallGenerator-----------------------------
    1.24 +// Internal class which handles all out-of-line dynamic calls.
    1.25 +class DynamicCallGenerator : public CallGenerator {
    1.26 +public:
    1.27 +  DynamicCallGenerator(ciMethod* method)
    1.28 +    : CallGenerator(method)
    1.29 +  {
    1.30 +  }
    1.31 +  virtual JVMState* generate(JVMState* jvms);
    1.32 +};
    1.33 +
    1.34 +JVMState* DynamicCallGenerator::generate(JVMState* jvms) {
    1.35 +  GraphKit kit(jvms);
    1.36 +
    1.37 +  if (kit.C->log() != NULL) {
    1.38 +    kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci());
    1.39 +  }
    1.40 +
    1.41 +  // Get the constant pool cache from the caller class.
    1.42 +  ciMethod* caller_method = jvms->method();
    1.43 +  ciBytecodeStream str(caller_method);
    1.44 +  str.force_bci(jvms->bci());  // Set the stream to the invokedynamic bci.
    1.45 +  assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!");
    1.46 +  ciCPCache* cpcache = str.get_cpcache();
    1.47 +
    1.48 +  // Get the offset of the CallSite from the constant pool cache
    1.49 +  // pointer.
    1.50 +  int index = str.get_method_index();
    1.51 +  size_t call_site_offset = cpcache->get_f1_offset(index);
    1.52 +
    1.53 +  // Load the CallSite object from the constant pool cache.
    1.54 +  const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
    1.55 +  Node* cpc = kit.makecon(cpcache_ptr);
    1.56 +  Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset);
    1.57 +  Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
    1.58 +
    1.59 +  // Load the MethodHandle (target) from the CallSite object.
    1.60 +  Node* mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
    1.61 +  Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
    1.62 +
    1.63 +  address stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
    1.64 +
    1.65 +  CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci());
    1.66 +  // invokedynamic is treated as an optimized invokevirtual.
    1.67 +  call->set_optimized_virtual(true);
    1.68 +  // Take extra care (in the presence of argument motion) not to trash the SP:
    1.69 +  call->set_method_handle_invoke(true);
    1.70 +
    1.71 +  // Pass the MethodHandle as first argument and shift the other
    1.72 +  // arguments.
    1.73 +  call->init_req(0 + TypeFunc::Parms, mh);
    1.74 +  uint nargs = call->method()->arg_size();
    1.75 +  for (uint i = 1; i < nargs; i++) {
    1.76 +    Node* arg = kit.argument(i - 1);
    1.77 +    call->init_req(i + TypeFunc::Parms, arg);
    1.78 +  }
    1.79 +
    1.80 +  kit.set_edges_for_java_call(call);
    1.81 +  Node* ret = kit.set_results_for_java_call(call);
    1.82 +  kit.push_node(method()->return_type()->basic_type(), ret);
    1.83 +  return kit.transfer_exceptions_into_jvms();
    1.84 +}
    1.85 +
    1.86 +//--------------------------VirtualCallGenerator------------------------------
    1.87 +// Internal class which handles all out-of-line calls checking receiver type.
    1.88  class VirtualCallGenerator : public CallGenerator {
    1.89  private:
    1.90    int _vtable_index;
    1.91 @@ -159,8 +226,6 @@
    1.92    virtual JVMState* generate(JVMState* jvms);
    1.93  };
    1.94  
    1.95 -//--------------------------VirtualCallGenerator------------------------------
    1.96 -// Internal class which handles all out-of-line calls checking receiver type.
    1.97  JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
    1.98    GraphKit kit(jvms);
    1.99    Node* receiver = kit.argument(0);
   1.100 @@ -253,8 +318,14 @@
   1.101    return new DirectCallGenerator(m, separate_io_proj);
   1.102  }
   1.103  
   1.104 +CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
   1.105 +  assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch");
   1.106 +  return new DynamicCallGenerator(m);
   1.107 +}
   1.108 +
   1.109  CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
   1.110    assert(!m->is_static(), "for_virtual_call mismatch");
   1.111 +  assert(!m->is_method_handle_invoke(), "should be a direct call");
   1.112    return new VirtualCallGenerator(m, vtable_index);
   1.113  }
   1.114  

mercurial