Thu, 01 Sep 2011 01:31:25 -0700
7079673: JSR 292: C1 should inline bytecoded method handle adapters
Reviewed-by: never
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