7079673: JSR 292: C1 should inline bytecoded method handle adapters

Thu, 01 Sep 2011 01:31:25 -0700

author
twisti
date
Thu, 01 Sep 2011 01:31:25 -0700
changeset 3100
a32de5085326
parent 3099
c124e2e7463e
child 3101
aa67216400d3

7079673: JSR 292: C1 should inline bytecoded method handle adapters
Reviewed-by: never

src/share/vm/c1/c1_GraphBuilder.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_GraphBuilder.hpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_Instruction.cpp file | annotate | diff | comparison | revisions
src/share/vm/c1/c1_Instruction.hpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/javaClasses.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/vmSymbols.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/bytecodeInfo.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/callGenerator.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/parse.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Aug 31 16:46:11 2011 -0700
     1.2 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Sep 01 01:31:25 2011 -0700
     1.3 @@ -28,8 +28,10 @@
     1.4  #include "c1/c1_Compilation.hpp"
     1.5  #include "c1/c1_GraphBuilder.hpp"
     1.6  #include "c1/c1_InstructionPrinter.hpp"
     1.7 +#include "ci/ciCallSite.hpp"
     1.8  #include "ci/ciField.hpp"
     1.9  #include "ci/ciKlass.hpp"
    1.10 +#include "ci/ciMethodHandle.hpp"
    1.11  #include "compiler/compileBroker.hpp"
    1.12  #include "interpreter/bytecode.hpp"
    1.13  #include "runtime/sharedRuntime.hpp"
    1.14 @@ -1424,7 +1426,7 @@
    1.15      // See whether this is the first return; if so, store off some
    1.16      // of the state for later examination
    1.17      if (num_returns() == 0) {
    1.18 -      set_inline_cleanup_info(_block, _last, state());
    1.19 +      set_inline_cleanup_info();
    1.20      }
    1.21  
    1.22      // The current bci() is in the wrong scope, so use the bci() of
    1.23 @@ -1582,6 +1584,8 @@
    1.24      code = Bytecodes::_invokespecial;
    1.25    }
    1.26  
    1.27 +  bool is_invokedynamic = code == Bytecodes::_invokedynamic;
    1.28 +
    1.29    // NEEDS_CLEANUP
    1.30    // I've added the target-is_loaded() test below but I don't really understand
    1.31    // how klass->is_loaded() can be true and yet target->is_loaded() is false.
    1.32 @@ -1693,26 +1697,31 @@
    1.33        && target->will_link(klass, callee_holder, code)) {
    1.34      // callee is known => check if we have static binding
    1.35      assert(target->is_loaded(), "callee must be known");
    1.36 -    if (code == Bytecodes::_invokestatic
    1.37 -     || code == Bytecodes::_invokespecial
    1.38 -     || code == Bytecodes::_invokevirtual && target->is_final_method()
    1.39 -    ) {
    1.40 -      // static binding => check if callee is ok
    1.41 -      ciMethod* inline_target = (cha_monomorphic_target != NULL)
    1.42 -                                  ? cha_monomorphic_target
    1.43 -                                  : target;
    1.44 -      bool res = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL));
    1.45 +    if (code == Bytecodes::_invokestatic  ||
    1.46 +        code == Bytecodes::_invokespecial ||
    1.47 +        code == Bytecodes::_invokevirtual && target->is_final_method() ||
    1.48 +        code == Bytecodes::_invokedynamic) {
    1.49 +      ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target;
    1.50 +      bool success = false;
    1.51 +      if (target->is_method_handle_invoke()) {
    1.52 +        // method handle invokes
    1.53 +        success = !is_invokedynamic ? for_method_handle_inline(target) : for_invokedynamic_inline(target);
    1.54 +      }
    1.55 +      if (!success) {
    1.56 +        // static binding => check if callee is ok
    1.57 +        success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL));
    1.58 +      }
    1.59        CHECK_BAILOUT();
    1.60  
    1.61  #ifndef PRODUCT
    1.62        // printing
    1.63 -      if (PrintInlining && !res) {
    1.64 +      if (PrintInlining && !success) {
    1.65          // if it was successfully inlined, then it was already printed.
    1.66 -        print_inline_result(inline_target, res);
    1.67 +        print_inline_result(inline_target, success);
    1.68        }
    1.69  #endif
    1.70        clear_inline_bailout();
    1.71 -      if (res) {
    1.72 +      if (success) {
    1.73          // Register dependence if JVMTI has either breakpoint
    1.74          // setting or hotswapping of methods capabilities since they may
    1.75          // cause deoptimization.
    1.76 @@ -1740,7 +1749,6 @@
    1.77      code == Bytecodes::_invokespecial   ||
    1.78      code == Bytecodes::_invokevirtual   ||
    1.79      code == Bytecodes::_invokeinterface;
    1.80 -  bool is_invokedynamic = code == Bytecodes::_invokedynamic;
    1.81    ValueType* result_type = as_ValueType(target->return_type());
    1.82  
    1.83    // We require the debug info to be the "state before" because
    1.84 @@ -3038,7 +3046,7 @@
    1.85      INLINE_BAILOUT("disallowed by CompilerOracle")
    1.86    } else if (!callee->can_be_compiled()) {
    1.87      // callee is not compilable (prob. has breakpoints)
    1.88 -    INLINE_BAILOUT("not compilable")
    1.89 +    INLINE_BAILOUT("not compilable (disabled)")
    1.90    } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) {
    1.91      // intrinsics can be native or not
    1.92      return true;
    1.93 @@ -3397,7 +3405,7 @@
    1.94  }
    1.95  
    1.96  
    1.97 -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
    1.98 +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) {
    1.99    assert(!callee->is_native(), "callee must not be native");
   1.100    if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) {
   1.101      INLINE_BAILOUT("inlining prohibited by policy");
   1.102 @@ -3468,7 +3476,8 @@
   1.103  
   1.104    // Insert null check if necessary
   1.105    Value recv = NULL;
   1.106 -  if (code() != Bytecodes::_invokestatic) {
   1.107 +  if (code() != Bytecodes::_invokestatic &&
   1.108 +      code() != Bytecodes::_invokedynamic) {
   1.109      // note: null check must happen even if first instruction of callee does
   1.110      //       an implicit null check since the callee is in a different scope
   1.111      //       and we must make sure exception handling does the right thing
   1.112 @@ -3496,7 +3505,7 @@
   1.113    // fall-through of control flow, all return instructions of the
   1.114    // callee will need to be replaced by Goto's pointing to this
   1.115    // continuation point.
   1.116 -  BlockBegin* cont = block_at(next_bci());
   1.117 +  BlockBegin* cont = cont_block != NULL ? cont_block : block_at(next_bci());
   1.118    bool continuation_existed = true;
   1.119    if (cont == NULL) {
   1.120      cont = new BlockBegin(next_bci());
   1.121 @@ -3608,27 +3617,29 @@
   1.122    // block merging. This allows load elimination and CSE to take place
   1.123    // across multiple callee scopes if they are relatively simple, and
   1.124    // is currently essential to making inlining profitable.
   1.125 -  if (   num_returns() == 1
   1.126 -      && block() == orig_block
   1.127 -      && block() == inline_cleanup_block()) {
   1.128 -    _last = inline_cleanup_return_prev();
   1.129 -    _state = inline_cleanup_state();
   1.130 -  } else if (continuation_preds == cont->number_of_preds()) {
   1.131 -    // Inlining caused that the instructions after the invoke in the
   1.132 -    // caller are not reachable any more. So skip filling this block
   1.133 -    // with instructions!
   1.134 -    assert (cont == continuation(), "");
   1.135 -    assert(_last && _last->as_BlockEnd(), "");
   1.136 -    _skip_block = true;
   1.137 -  } else {
   1.138 -    // Resume parsing in continuation block unless it was already parsed.
   1.139 -    // Note that if we don't change _last here, iteration in
   1.140 -    // iterate_bytecodes_for_block will stop when we return.
   1.141 -    if (!continuation()->is_set(BlockBegin::was_visited_flag)) {
   1.142 -      // add continuation to work list instead of parsing it immediately
   1.143 +  if (cont_block == NULL) {
   1.144 +    if (num_returns() == 1
   1.145 +        && block() == orig_block
   1.146 +        && block() == inline_cleanup_block()) {
   1.147 +      _last  = inline_cleanup_return_prev();
   1.148 +      _state = inline_cleanup_state();
   1.149 +    } else if (continuation_preds == cont->number_of_preds()) {
   1.150 +      // Inlining caused that the instructions after the invoke in the
   1.151 +      // caller are not reachable any more. So skip filling this block
   1.152 +      // with instructions!
   1.153 +      assert(cont == continuation(), "");
   1.154        assert(_last && _last->as_BlockEnd(), "");
   1.155 -      scope_data()->parent()->add_to_work_list(continuation());
   1.156        _skip_block = true;
   1.157 +    } else {
   1.158 +      // Resume parsing in continuation block unless it was already parsed.
   1.159 +      // Note that if we don't change _last here, iteration in
   1.160 +      // iterate_bytecodes_for_block will stop when we return.
   1.161 +      if (!continuation()->is_set(BlockBegin::was_visited_flag)) {
   1.162 +        // add continuation to work list instead of parsing it immediately
   1.163 +        assert(_last && _last->as_BlockEnd(), "");
   1.164 +        scope_data()->parent()->add_to_work_list(continuation());
   1.165 +        _skip_block = true;
   1.166 +      }
   1.167      }
   1.168    }
   1.169  
   1.170 @@ -3645,6 +3656,120 @@
   1.171  }
   1.172  
   1.173  
   1.174 +bool GraphBuilder::for_method_handle_inline(ciMethod* callee) {
   1.175 +  assert(!callee->is_static(), "change next line");
   1.176 +  int index = state()->stack_size() - (callee->arg_size_no_receiver() + 1);
   1.177 +  Value receiver = state()->stack_at(index);
   1.178 +
   1.179 +  if (receiver->type()->is_constant()) {
   1.180 +    ciMethodHandle* method_handle = receiver->type()->as_ObjectType()->constant_value()->as_method_handle();
   1.181 +
   1.182 +    // Set the callee to have access to the class and signature in
   1.183 +    // the MethodHandleCompiler.
   1.184 +    method_handle->set_callee(callee);
   1.185 +    method_handle->set_caller(method());
   1.186 +
   1.187 +    // Get an adapter for the MethodHandle.
   1.188 +    ciMethod* method_handle_adapter = method_handle->get_method_handle_adapter();
   1.189 +    if (method_handle_adapter != NULL) {
   1.190 +      return try_inline(method_handle_adapter, /*holder_known=*/ true);
   1.191 +    }
   1.192 +  } else if (receiver->as_CheckCast()) {
   1.193 +    // Match MethodHandle.selectAlternative idiom
   1.194 +    Phi* phi = receiver->as_CheckCast()->obj()->as_Phi();
   1.195 +
   1.196 +    if (phi != NULL && phi->operand_count() == 2) {
   1.197 +      // Get the two MethodHandle inputs from the Phi.
   1.198 +      Value op1 = phi->operand_at(0);
   1.199 +      Value op2 = phi->operand_at(1);
   1.200 +      ciMethodHandle* mh1 = op1->type()->as_ObjectType()->constant_value()->as_method_handle();
   1.201 +      ciMethodHandle* mh2 = op2->type()->as_ObjectType()->constant_value()->as_method_handle();
   1.202 +
   1.203 +      // Set the callee to have access to the class and signature in
   1.204 +      // the MethodHandleCompiler.
   1.205 +      mh1->set_callee(callee);
   1.206 +      mh1->set_caller(method());
   1.207 +      mh2->set_callee(callee);
   1.208 +      mh2->set_caller(method());
   1.209 +
   1.210 +      // Get adapters for the MethodHandles.
   1.211 +      ciMethod* mh1_adapter = mh1->get_method_handle_adapter();
   1.212 +      ciMethod* mh2_adapter = mh2->get_method_handle_adapter();
   1.213 +
   1.214 +      if (mh1_adapter != NULL && mh2_adapter != NULL) {
   1.215 +        set_inline_cleanup_info();
   1.216 +
   1.217 +        // Build the If guard
   1.218 +        BlockBegin* one = new BlockBegin(next_bci());
   1.219 +        BlockBegin* two = new BlockBegin(next_bci());
   1.220 +        BlockBegin* end = new BlockBegin(next_bci());
   1.221 +        Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false));
   1.222 +        block()->set_end(iff->as_BlockEnd());
   1.223 +
   1.224 +        // Connect up the states
   1.225 +        one->merge(block()->end()->state());
   1.226 +        two->merge(block()->end()->state());
   1.227 +
   1.228 +        // Save the state for the second inlinee
   1.229 +        ValueStack* state_before = copy_state_before();
   1.230 +
   1.231 +        // Parse first adapter
   1.232 +        _last = _block = one;
   1.233 +        if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) {
   1.234 +          restore_inline_cleanup_info();
   1.235 +          block()->clear_end();  // remove appended iff
   1.236 +          return false;
   1.237 +        }
   1.238 +
   1.239 +        // Parse second adapter
   1.240 +        _last = _block = two;
   1.241 +        _state = state_before;
   1.242 +        if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) {
   1.243 +          restore_inline_cleanup_info();
   1.244 +          block()->clear_end();  // remove appended iff
   1.245 +          return false;
   1.246 +        }
   1.247 +
   1.248 +        connect_to_end(end);
   1.249 +        return true;
   1.250 +      }
   1.251 +    }
   1.252 +  }
   1.253 +  return false;
   1.254 +}
   1.255 +
   1.256 +
   1.257 +bool GraphBuilder::for_invokedynamic_inline(ciMethod* callee) {
   1.258 +  // Get the MethodHandle from the CallSite.
   1.259 +  ciCallSite*     call_site     = stream()->get_call_site();
   1.260 +  ciMethodHandle* method_handle = call_site->get_target();
   1.261 +
   1.262 +  // Inline constant and mutable call sites.  We don't inline
   1.263 +  // volatile call sites optimistically since they are specified
   1.264 +  // to change their value often and that would result in a lot of
   1.265 +  // deoptimizations and recompiles.
   1.266 +  if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) {
   1.267 +    // Set the callee to have access to the class and signature in the
   1.268 +    // MethodHandleCompiler.
   1.269 +    method_handle->set_callee(callee);
   1.270 +    method_handle->set_caller(method());
   1.271 +
   1.272 +    // Get an adapter for the MethodHandle.
   1.273 +    ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter();
   1.274 +    if (method_handle_adapter != NULL) {
   1.275 +      if (try_inline(method_handle_adapter, /*holder_known=*/ true)) {
   1.276 +        // Add a dependence for invalidation of the optimization.
   1.277 +        if (!call_site->is_constant_call_site()) {
   1.278 +          dependency_recorder()->assert_call_site_target_value(call_site, method_handle);
   1.279 +        }
   1.280 +        return true;
   1.281 +      }
   1.282 +    }
   1.283 +  }
   1.284 +  return false;
   1.285 +}
   1.286 +
   1.287 +
   1.288  void GraphBuilder::inline_bailout(const char* msg) {
   1.289    assert(msg != NULL, "inline bailout msg must exist");
   1.290    _inline_bailout_msg = msg;
     2.1 --- a/src/share/vm/c1/c1_GraphBuilder.hpp	Wed Aug 31 16:46:11 2011 -0700
     2.2 +++ b/src/share/vm/c1/c1_GraphBuilder.hpp	Thu Sep 01 01:31:25 2011 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -315,9 +315,17 @@
    2.11                                 ValueStack* return_state) { scope_data()->set_inline_cleanup_info(block,
    2.12                                                                                                    return_prev,
    2.13                                                                                                    return_state); }
    2.14 +  void set_inline_cleanup_info() {
    2.15 +    set_inline_cleanup_info(_block, _last, _state);
    2.16 +  }
    2.17    BlockBegin*  inline_cleanup_block() const              { return scope_data()->inline_cleanup_block();  }
    2.18    Instruction* inline_cleanup_return_prev() const        { return scope_data()->inline_cleanup_return_prev(); }
    2.19    ValueStack*  inline_cleanup_state() const              { return scope_data()->inline_cleanup_state();  }
    2.20 +  void restore_inline_cleanup_info() {
    2.21 +    _block = inline_cleanup_block();
    2.22 +    _last  = inline_cleanup_return_prev();
    2.23 +    _state = inline_cleanup_state();
    2.24 +  }
    2.25    void incr_num_returns()                                { scope_data()->incr_num_returns();             }
    2.26    int  num_returns() const                               { return scope_data()->num_returns();           }
    2.27    intx max_inline_size() const                           { return scope_data()->max_inline_size();       }
    2.28 @@ -329,11 +337,15 @@
    2.29    void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false);
    2.30  
    2.31    // inliners
    2.32 -  bool try_inline(ciMethod* callee, bool holder_known);
    2.33 +  bool try_inline(           ciMethod* callee, bool holder_known);
    2.34    bool try_inline_intrinsics(ciMethod* callee);
    2.35 -  bool try_inline_full      (ciMethod* callee, bool holder_known);
    2.36 +  bool try_inline_full(      ciMethod* callee, bool holder_known, BlockBegin* cont_block = NULL);
    2.37    bool try_inline_jsr(int jsr_dest_bci);
    2.38  
    2.39 +  // JSR 292 support
    2.40 +  bool for_method_handle_inline(ciMethod* callee);
    2.41 +  bool for_invokedynamic_inline(ciMethod* callee);
    2.42 +
    2.43    // helpers
    2.44    void inline_bailout(const char* msg);
    2.45    BlockBegin* header_block(BlockBegin* entry, BlockBegin::Flag f, ValueStack* state);
     3.1 --- a/src/share/vm/c1/c1_Instruction.cpp	Wed Aug 31 16:46:11 2011 -0700
     3.2 +++ b/src/share/vm/c1/c1_Instruction.cpp	Thu Sep 01 01:31:25 2011 -0700
     3.3 @@ -514,28 +514,17 @@
     3.4  
     3.5  void BlockBegin::set_end(BlockEnd* end) {
     3.6    assert(end != NULL, "should not reset block end to NULL");
     3.7 -  BlockEnd* old_end = _end;
     3.8 -  if (end == old_end) {
     3.9 +  if (end == _end) {
    3.10      return;
    3.11    }
    3.12 -  // Must make the predecessors/successors match up with the
    3.13 -  // BlockEnd's notion.
    3.14 -  int i, n;
    3.15 -  if (old_end != NULL) {
    3.16 -    // disconnect from the old end
    3.17 -    old_end->set_begin(NULL);
    3.18 +  clear_end();
    3.19  
    3.20 -    // disconnect this block from it's current successors
    3.21 -    for (i = 0; i < _successors.length(); i++) {
    3.22 -      _successors.at(i)->remove_predecessor(this);
    3.23 -    }
    3.24 -  }
    3.25 +  // Set the new end
    3.26    _end = end;
    3.27  
    3.28    _successors.clear();
    3.29    // Now reset successors list based on BlockEnd
    3.30 -  n = end->number_of_sux();
    3.31 -  for (i = 0; i < n; i++) {
    3.32 +  for (int i = 0; i < end->number_of_sux(); i++) {
    3.33      BlockBegin* sux = end->sux_at(i);
    3.34      _successors.append(sux);
    3.35      sux->_predecessors.append(this);
    3.36 @@ -544,6 +533,22 @@
    3.37  }
    3.38  
    3.39  
    3.40 +void BlockBegin::clear_end() {
    3.41 +  // Must make the predecessors/successors match up with the
    3.42 +  // BlockEnd's notion.
    3.43 +  if (_end != NULL) {
    3.44 +    // disconnect from the old end
    3.45 +    _end->set_begin(NULL);
    3.46 +
    3.47 +    // disconnect this block from it's current successors
    3.48 +    for (int i = 0; i < _successors.length(); i++) {
    3.49 +      _successors.at(i)->remove_predecessor(this);
    3.50 +    }
    3.51 +    _end = NULL;
    3.52 +  }
    3.53 +}
    3.54 +
    3.55 +
    3.56  void BlockBegin::disconnect_edge(BlockBegin* from, BlockBegin* to) {
    3.57    // disconnect any edges between from and to
    3.58  #ifndef PRODUCT
     4.1 --- a/src/share/vm/c1/c1_Instruction.hpp	Wed Aug 31 16:46:11 2011 -0700
     4.2 +++ b/src/share/vm/c1/c1_Instruction.hpp	Thu Sep 01 01:31:25 2011 -0700
     4.3 @@ -1601,6 +1601,7 @@
     4.4    void set_depth_first_number(int dfn)           { _depth_first_number = dfn; }
     4.5    void set_linear_scan_number(int lsn)           { _linear_scan_number = lsn; }
     4.6    void set_end(BlockEnd* end);
     4.7 +  void clear_end();
     4.8    void disconnect_from_graph();
     4.9    static void disconnect_edge(BlockBegin* from, BlockBegin* to);
    4.10    BlockBegin* insert_block_between(BlockBegin* sux);
     5.1 --- a/src/share/vm/classfile/javaClasses.cpp	Wed Aug 31 16:46:11 2011 -0700
     5.2 +++ b/src/share/vm/classfile/javaClasses.cpp	Thu Sep 01 01:31:25 2011 -0700
     5.3 @@ -28,6 +28,7 @@
     5.4  #include "classfile/vmSymbols.hpp"
     5.5  #include "code/debugInfo.hpp"
     5.6  #include "code/pcDesc.hpp"
     5.7 +#include "compiler/compilerOracle.hpp"
     5.8  #include "interpreter/interpreter.hpp"
     5.9  #include "memory/oopFactory.hpp"
    5.10  #include "memory/resourceArea.hpp"
    5.11 @@ -2674,6 +2675,17 @@
    5.12    if (k != NULL) {
    5.13      compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_lang_invoke_MethodHandle_signature());
    5.14    }
    5.15 +
    5.16 +  // Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile
    5.17 +  // (For C2:  keep this until we have throttling logic for uncommon traps.)
    5.18 +  if (k != NULL) {
    5.19 +    instanceKlass* ik = instanceKlass::cast(k);
    5.20 +    methodOop m_normal   = ik->lookup_method(vmSymbols::setTargetNormal_name(),   vmSymbols::setTarget_signature());
    5.21 +    methodOop m_volatile = ik->lookup_method(vmSymbols::setTargetVolatile_name(), vmSymbols::setTarget_signature());
    5.22 +    guarantee(m_normal && m_volatile, "must exist");
    5.23 +    m_normal->set_not_compilable_quietly();
    5.24 +    m_volatile->set_not_compilable_quietly();
    5.25 +  }
    5.26  }
    5.27  
    5.28  oop java_lang_invoke_CallSite::target(oop site) {
     6.1 --- a/src/share/vm/classfile/vmSymbols.hpp	Wed Aug 31 16:46:11 2011 -0700
     6.2 +++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Sep 01 01:31:25 2011 -0700
     6.3 @@ -258,6 +258,9 @@
     6.4    template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
     6.5    template(makeDynamicCallSite_name,                  "makeDynamicCallSite")                      \
     6.6    template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \
     6.7 +  template(setTargetNormal_name,                      "setTargetNormal")                          \
     6.8 +  template(setTargetVolatile_name,                    "setTargetVolatile")                        \
     6.9 +  template(setTarget_signature,                       "(Ljava/lang/invoke/MethodHandle;)V")       \
    6.10    NOT_LP64(  do_alias(machine_word_signature,         int_signature)  )                           \
    6.11    LP64_ONLY( do_alias(machine_word_signature,         long_signature) )                           \
    6.12                                                                                                    \
     7.1 --- a/src/share/vm/opto/bytecodeInfo.cpp	Wed Aug 31 16:46:11 2011 -0700
     7.2 +++ b/src/share/vm/opto/bytecodeInfo.cpp	Thu Sep 01 01:31:25 2011 -0700
     7.3 @@ -394,6 +394,16 @@
     7.4    return true;
     7.5  }
     7.6  
     7.7 +//------------------------------check_can_parse--------------------------------
     7.8 +const char* InlineTree::check_can_parse(ciMethod* callee) {
     7.9 +  // Certain methods cannot be parsed at all:
    7.10 +  if ( callee->is_native())                     return "native method";
    7.11 +  if (!callee->can_be_compiled())               return "not compilable (disabled)";
    7.12 +  if (!callee->has_balanced_monitors())         return "not compilable (unbalanced monitors)";
    7.13 +  if ( callee->get_flow_analysis()->failing())  return "not compilable (flow analysis failed)";
    7.14 +  return NULL;
    7.15 +}
    7.16 +
    7.17  //------------------------------print_inlining---------------------------------
    7.18  // Really, the failure_msg can be a success message also.
    7.19  void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const {
    7.20 @@ -423,14 +433,22 @@
    7.21    int         caller_bci    = jvms->bci();
    7.22    ciMethod   *caller_method = jvms->method();
    7.23  
    7.24 -  if( !pass_initial_checks(caller_method, caller_bci, callee_method)) {
    7.25 -    if( PrintInlining ) {
    7.26 +  // Do some initial checks.
    7.27 +  if (!pass_initial_checks(caller_method, caller_bci, callee_method)) {
    7.28 +    if (PrintInlining) {
    7.29        failure_msg = "failed_initial_checks";
    7.30 -      print_inlining( callee_method, caller_bci, failure_msg);
    7.31 +      print_inlining(callee_method, caller_bci, failure_msg);
    7.32      }
    7.33      return NULL;
    7.34    }
    7.35  
    7.36 +  // Do some parse checks.
    7.37 +  failure_msg = check_can_parse(callee_method);
    7.38 +  if (failure_msg != NULL) {
    7.39 +    if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
    7.40 +    return NULL;
    7.41 +  }
    7.42 +
    7.43    // Check if inlining policy says no.
    7.44    WarmCallInfo wci = *(initial_wci);
    7.45    failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
    7.46 @@ -471,7 +489,7 @@
    7.47      if (failure_msg == NULL)  failure_msg = "inline (hot)";
    7.48  
    7.49      // Inline!
    7.50 -    if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg);
    7.51 +    if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
    7.52      if (UseOldInlining)
    7.53        build_inline_tree_for_callee(callee_method, jvms, caller_bci);
    7.54      if (InlineWarmCalls && !wci.is_hot())
    7.55 @@ -481,7 +499,7 @@
    7.56  
    7.57    // Do not inline
    7.58    if (failure_msg == NULL)  failure_msg = "too cold to inline";
    7.59 -  if( PrintInlining ) print_inlining( callee_method, caller_bci, failure_msg);
    7.60 +  if (PrintInlining)  print_inlining(callee_method, caller_bci, failure_msg);
    7.61    return NULL;
    7.62  }
    7.63  
     8.1 --- a/src/share/vm/opto/callGenerator.cpp	Wed Aug 31 16:46:11 2011 -0700
     8.2 +++ b/src/share/vm/opto/callGenerator.cpp	Thu Sep 01 01:31:25 2011 -0700
     8.3 @@ -61,12 +61,9 @@
     8.4    {
     8.5      _is_osr        = is_osr;
     8.6      _expected_uses = expected_uses;
     8.7 -    assert(can_parse(method, is_osr), "parse must be possible");
     8.8 +    assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible");
     8.9    }
    8.10  
    8.11 -  // Can we build either an OSR or a regular parser for this method?
    8.12 -  static bool can_parse(ciMethod* method, int is_osr = false);
    8.13 -
    8.14    virtual bool      is_parse() const           { return true; }
    8.15    virtual JVMState* generate(JVMState* jvms);
    8.16    int is_osr() { return _is_osr; }
    8.17 @@ -303,20 +300,8 @@
    8.18    return kit.transfer_exceptions_into_jvms();
    8.19  }
    8.20  
    8.21 -bool ParseGenerator::can_parse(ciMethod* m, int entry_bci) {
    8.22 -  // Certain methods cannot be parsed at all:
    8.23 -  if (!m->can_be_compiled())              return false;
    8.24 -  if (!m->has_balanced_monitors())        return false;
    8.25 -  if (m->get_flow_analysis()->failing())  return false;
    8.26 -
    8.27 -  // (Methods may bail out for other reasons, after the parser is run.
    8.28 -  // We try to avoid this, but if forced, we must return (Node*)NULL.
    8.29 -  // The user of the CallGenerator must check for this condition.)
    8.30 -  return true;
    8.31 -}
    8.32 -
    8.33  CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
    8.34 -  if (!ParseGenerator::can_parse(m))  return NULL;
    8.35 +  if (InlineTree::check_can_parse(m) != NULL)  return NULL;
    8.36    return new ParseGenerator(m, expected_uses);
    8.37  }
    8.38  
    8.39 @@ -324,7 +309,7 @@
    8.40  // for the method execution already in progress, not just the JVMS
    8.41  // of the caller.  Thus, this CallGenerator cannot be mixed with others!
    8.42  CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) {
    8.43 -  if (!ParseGenerator::can_parse(m, true))  return NULL;
    8.44 +  if (InlineTree::check_can_parse(m) != NULL)  return NULL;
    8.45    float past_uses = m->interpreter_invocation_count();
    8.46    float expected_uses = past_uses;
    8.47    return new ParseGenerator(m, expected_uses, true);
     9.1 --- a/src/share/vm/opto/parse.hpp	Wed Aug 31 16:46:11 2011 -0700
     9.2 +++ b/src/share/vm/opto/parse.hpp	Thu Sep 01 01:31:25 2011 -0700
     9.3 @@ -78,6 +78,8 @@
     9.4    int         stack_depth()       const { return _caller_jvms ? _caller_jvms->depth() : 0; }
     9.5  
     9.6  public:
     9.7 +  static const char* check_can_parse(ciMethod* callee);
     9.8 +
     9.9    static InlineTree* build_inline_tree_root();
    9.10    static InlineTree* find_subtree_from_root(InlineTree* root, JVMState* jvms, ciMethod* callee, bool create_if_not_found = false);
    9.11  

mercurial