Print this page
rev 1082 : [mq]: indy.compiler.patch

Split Close
Expand all
Collapse all
          --- old/src/share/vm/opto/callGenerator.cpp
          +++ new/src/share/vm/opto/callGenerator.cpp
   1    1  /*
   2      - * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
        2 + * Copyright 2000-2009 Sun Microsystems, Inc.  All Rights Reserved.
   3    3   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4    4   *
   5    5   * This code is free software; you can redistribute it and/or modify it
   6    6   * under the terms of the GNU General Public License version 2 only, as
   7    7   * published by the Free Software Foundation.
   8    8   *
   9    9   * This code is distributed in the hope that it will be useful, but WITHOUT
  10   10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11   11   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12   12   * version 2 for more details (a copy is included in the LICENSE file that
↓ open down ↓ 116 lines elided ↑ open up ↑
 129  129    if (!is_static) {
 130  130      // Make an explicit receiver null_check as part of this call.
 131  131      // Since we share a map with the caller, his JVMS gets adjusted.
 132  132      kit.null_check_receiver(method());
 133  133      if (kit.stopped()) {
 134  134        // And dump it back to the caller, decorated with any exceptions:
 135  135        return kit.transfer_exceptions_into_jvms();
 136  136      }
 137  137      // Mark the call node as virtual, sort of:
 138  138      call->set_optimized_virtual(true);
      139 +    if (method()->is_method_handle_invoke())
      140 +      call->set_method_handle_invoke(true);
 139  141    }
 140  142    kit.set_arguments_for_java_call(call);
 141  143    kit.set_edges_for_java_call(call, false, _separate_io_proj);
 142  144    Node* ret = kit.set_results_for_java_call(call, _separate_io_proj);
 143  145    kit.push_node(method()->return_type()->basic_type(), ret);
 144  146    _call_node = call;  // Save the call node in case we need it later
 145  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  215  class VirtualCallGenerator : public CallGenerator {
 149  216  private:
 150  217    int _vtable_index;
 151  218  public:
 152  219    VirtualCallGenerator(ciMethod* method, int vtable_index)
 153  220      : CallGenerator(method), _vtable_index(vtable_index)
 154  221    {
 155  222      assert(vtable_index == methodOopDesc::invalid_vtable_index ||
 156  223             vtable_index >= 0, "either invalid or usable");
 157  224    }
 158  225    virtual bool      is_virtual() const          { return true; }
 159  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  229  JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
 165  230    GraphKit kit(jvms);
 166  231    Node* receiver = kit.argument(0);
 167  232  
 168  233    if (kit.C->log() != NULL) {
 169  234      kit.C->log()->elem("virtual_call bci='%d'", jvms->bci());
 170  235    }
 171  236  
 172  237    // If the receiver is a constant null, do not torture the system
 173  238    // by attempting to call through it.  The compile will proceed
↓ open down ↓ 72 lines elided ↑ open up ↑
 246  311    float past_uses = m->interpreter_invocation_count();
 247  312    float expected_uses = past_uses;
 248  313    return new ParseGenerator(m, expected_uses, true);
 249  314  }
 250  315  
 251  316  CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) {
 252  317    assert(!m->is_abstract(), "for_direct_call mismatch");
 253  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  326  CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
 257  327    assert(!m->is_static(), "for_virtual_call mismatch");
      328 +  assert(!m->is_method_handle_invoke(), "should be a direct call");
 258  329    return new VirtualCallGenerator(m, vtable_index);
 259  330  }
 260  331  
 261  332  // Allow inlining decisions to be delayed
 262  333  class LateInlineCallGenerator : public DirectCallGenerator {
 263  334    CallGenerator* _inline_cg;
 264  335  
 265  336   public:
 266  337    LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
 267  338      DirectCallGenerator(method, true), _inline_cg(inline_cg) {}
↓ open down ↓ 532 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX