Mercurial > hg > graal-jvmci-8
comparison src/share/vm/c1/c1_GraphBuilder.cpp @ 3900:a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
Reviewed-by: never
author | twisti |
---|---|
date | Thu, 01 Sep 2011 01:31:25 -0700 |
parents | de847cac9235 |
children | aa67216400d3 |
comparison
equal
deleted
inserted
replaced
3899:c124e2e7463e | 3900:a32de5085326 |
---|---|
26 #include "c1/c1_CFGPrinter.hpp" | 26 #include "c1/c1_CFGPrinter.hpp" |
27 #include "c1/c1_Canonicalizer.hpp" | 27 #include "c1/c1_Canonicalizer.hpp" |
28 #include "c1/c1_Compilation.hpp" | 28 #include "c1/c1_Compilation.hpp" |
29 #include "c1/c1_GraphBuilder.hpp" | 29 #include "c1/c1_GraphBuilder.hpp" |
30 #include "c1/c1_InstructionPrinter.hpp" | 30 #include "c1/c1_InstructionPrinter.hpp" |
31 #include "ci/ciCallSite.hpp" | |
31 #include "ci/ciField.hpp" | 32 #include "ci/ciField.hpp" |
32 #include "ci/ciKlass.hpp" | 33 #include "ci/ciKlass.hpp" |
34 #include "ci/ciMethodHandle.hpp" | |
33 #include "compiler/compileBroker.hpp" | 35 #include "compiler/compileBroker.hpp" |
34 #include "interpreter/bytecode.hpp" | 36 #include "interpreter/bytecode.hpp" |
35 #include "runtime/sharedRuntime.hpp" | 37 #include "runtime/sharedRuntime.hpp" |
36 #include "runtime/compilationPolicy.hpp" | 38 #include "runtime/compilationPolicy.hpp" |
37 #include "utilities/bitMap.inline.hpp" | 39 #include "utilities/bitMap.inline.hpp" |
1422 Goto* goto_callee = new Goto(continuation(), false); | 1424 Goto* goto_callee = new Goto(continuation(), false); |
1423 | 1425 |
1424 // See whether this is the first return; if so, store off some | 1426 // See whether this is the first return; if so, store off some |
1425 // of the state for later examination | 1427 // of the state for later examination |
1426 if (num_returns() == 0) { | 1428 if (num_returns() == 0) { |
1427 set_inline_cleanup_info(_block, _last, state()); | 1429 set_inline_cleanup_info(); |
1428 } | 1430 } |
1429 | 1431 |
1430 // The current bci() is in the wrong scope, so use the bci() of | 1432 // The current bci() is in the wrong scope, so use the bci() of |
1431 // the continuation point. | 1433 // the continuation point. |
1432 append_with_bci(goto_callee, scope_data()->continuation()->bci()); | 1434 append_with_bci(goto_callee, scope_data()->continuation()->bci()); |
1579 // convert them directly to an invokespecial. | 1581 // convert them directly to an invokespecial. |
1580 if (target->is_loaded() && !target->is_abstract() && | 1582 if (target->is_loaded() && !target->is_abstract() && |
1581 target->can_be_statically_bound() && code == Bytecodes::_invokevirtual) { | 1583 target->can_be_statically_bound() && code == Bytecodes::_invokevirtual) { |
1582 code = Bytecodes::_invokespecial; | 1584 code = Bytecodes::_invokespecial; |
1583 } | 1585 } |
1586 | |
1587 bool is_invokedynamic = code == Bytecodes::_invokedynamic; | |
1584 | 1588 |
1585 // NEEDS_CLEANUP | 1589 // NEEDS_CLEANUP |
1586 // I've added the target-is_loaded() test below but I don't really understand | 1590 // I've added the target-is_loaded() test below but I don't really understand |
1587 // how klass->is_loaded() can be true and yet target->is_loaded() is false. | 1591 // how klass->is_loaded() can be true and yet target->is_loaded() is false. |
1588 // this happened while running the JCK invokevirtual tests under doit. TKR | 1592 // this happened while running the JCK invokevirtual tests under doit. TKR |
1691 if (!PatchALot && Inline && klass->is_loaded() && | 1695 if (!PatchALot && Inline && klass->is_loaded() && |
1692 (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) | 1696 (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) |
1693 && target->will_link(klass, callee_holder, code)) { | 1697 && target->will_link(klass, callee_holder, code)) { |
1694 // callee is known => check if we have static binding | 1698 // callee is known => check if we have static binding |
1695 assert(target->is_loaded(), "callee must be known"); | 1699 assert(target->is_loaded(), "callee must be known"); |
1696 if (code == Bytecodes::_invokestatic | 1700 if (code == Bytecodes::_invokestatic || |
1697 || code == Bytecodes::_invokespecial | 1701 code == Bytecodes::_invokespecial || |
1698 || code == Bytecodes::_invokevirtual && target->is_final_method() | 1702 code == Bytecodes::_invokevirtual && target->is_final_method() || |
1699 ) { | 1703 code == Bytecodes::_invokedynamic) { |
1700 // static binding => check if callee is ok | 1704 ciMethod* inline_target = (cha_monomorphic_target != NULL) ? cha_monomorphic_target : target; |
1701 ciMethod* inline_target = (cha_monomorphic_target != NULL) | 1705 bool success = false; |
1702 ? cha_monomorphic_target | 1706 if (target->is_method_handle_invoke()) { |
1703 : target; | 1707 // method handle invokes |
1704 bool res = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); | 1708 success = !is_invokedynamic ? for_method_handle_inline(target) : for_invokedynamic_inline(target); |
1709 } | |
1710 if (!success) { | |
1711 // static binding => check if callee is ok | |
1712 success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); | |
1713 } | |
1705 CHECK_BAILOUT(); | 1714 CHECK_BAILOUT(); |
1706 | 1715 |
1707 #ifndef PRODUCT | 1716 #ifndef PRODUCT |
1708 // printing | 1717 // printing |
1709 if (PrintInlining && !res) { | 1718 if (PrintInlining && !success) { |
1710 // if it was successfully inlined, then it was already printed. | 1719 // if it was successfully inlined, then it was already printed. |
1711 print_inline_result(inline_target, res); | 1720 print_inline_result(inline_target, success); |
1712 } | 1721 } |
1713 #endif | 1722 #endif |
1714 clear_inline_bailout(); | 1723 clear_inline_bailout(); |
1715 if (res) { | 1724 if (success) { |
1716 // Register dependence if JVMTI has either breakpoint | 1725 // Register dependence if JVMTI has either breakpoint |
1717 // setting or hotswapping of methods capabilities since they may | 1726 // setting or hotswapping of methods capabilities since they may |
1718 // cause deoptimization. | 1727 // cause deoptimization. |
1719 if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) { | 1728 if (compilation()->env()->jvmti_can_hotswap_or_post_breakpoint()) { |
1720 dependency_recorder()->assert_evol_method(inline_target); | 1729 dependency_recorder()->assert_evol_method(inline_target); |
1738 bool is_loaded = target->is_loaded(); | 1747 bool is_loaded = target->is_loaded(); |
1739 bool has_receiver = | 1748 bool has_receiver = |
1740 code == Bytecodes::_invokespecial || | 1749 code == Bytecodes::_invokespecial || |
1741 code == Bytecodes::_invokevirtual || | 1750 code == Bytecodes::_invokevirtual || |
1742 code == Bytecodes::_invokeinterface; | 1751 code == Bytecodes::_invokeinterface; |
1743 bool is_invokedynamic = code == Bytecodes::_invokedynamic; | |
1744 ValueType* result_type = as_ValueType(target->return_type()); | 1752 ValueType* result_type = as_ValueType(target->return_type()); |
1745 | 1753 |
1746 // We require the debug info to be the "state before" because | 1754 // We require the debug info to be the "state before" because |
1747 // invokedynamics may deoptimize. | 1755 // invokedynamics may deoptimize. |
1748 ValueStack* state_before = is_invokedynamic ? copy_state_before() : copy_state_exhandling(); | 1756 ValueStack* state_before = is_invokedynamic ? copy_state_before() : copy_state_exhandling(); |
3036 } else if (callee->should_not_inline()) { | 3044 } else if (callee->should_not_inline()) { |
3037 // callee is excluded | 3045 // callee is excluded |
3038 INLINE_BAILOUT("disallowed by CompilerOracle") | 3046 INLINE_BAILOUT("disallowed by CompilerOracle") |
3039 } else if (!callee->can_be_compiled()) { | 3047 } else if (!callee->can_be_compiled()) { |
3040 // callee is not compilable (prob. has breakpoints) | 3048 // callee is not compilable (prob. has breakpoints) |
3041 INLINE_BAILOUT("not compilable") | 3049 INLINE_BAILOUT("not compilable (disabled)") |
3042 } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { | 3050 } else if (callee->intrinsic_id() != vmIntrinsics::_none && try_inline_intrinsics(callee)) { |
3043 // intrinsics can be native or not | 3051 // intrinsics can be native or not |
3044 return true; | 3052 return true; |
3045 } else if (callee->is_native()) { | 3053 } else if (callee->is_native()) { |
3046 // non-intrinsic natives cannot be inlined | 3054 // non-intrinsic natives cannot be inlined |
3395 _state = orig_state; | 3403 _state = orig_state; |
3396 _last = orig_last; | 3404 _last = orig_last; |
3397 } | 3405 } |
3398 | 3406 |
3399 | 3407 |
3400 bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { | 3408 bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { |
3401 assert(!callee->is_native(), "callee must not be native"); | 3409 assert(!callee->is_native(), "callee must not be native"); |
3402 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { | 3410 if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { |
3403 INLINE_BAILOUT("inlining prohibited by policy"); | 3411 INLINE_BAILOUT("inlining prohibited by policy"); |
3404 } | 3412 } |
3405 // first perform tests of things it's not possible to inline | 3413 // first perform tests of things it's not possible to inline |
3466 const int args_base = state()->stack_size() - callee->arg_size(); | 3474 const int args_base = state()->stack_size() - callee->arg_size(); |
3467 assert(args_base >= 0, "stack underflow during inlining"); | 3475 assert(args_base >= 0, "stack underflow during inlining"); |
3468 | 3476 |
3469 // Insert null check if necessary | 3477 // Insert null check if necessary |
3470 Value recv = NULL; | 3478 Value recv = NULL; |
3471 if (code() != Bytecodes::_invokestatic) { | 3479 if (code() != Bytecodes::_invokestatic && |
3480 code() != Bytecodes::_invokedynamic) { | |
3472 // note: null check must happen even if first instruction of callee does | 3481 // note: null check must happen even if first instruction of callee does |
3473 // an implicit null check since the callee is in a different scope | 3482 // an implicit null check since the callee is in a different scope |
3474 // and we must make sure exception handling does the right thing | 3483 // and we must make sure exception handling does the right thing |
3475 assert(!callee->is_static(), "callee must not be static"); | 3484 assert(!callee->is_static(), "callee must not be static"); |
3476 assert(callee->arg_size() > 0, "must have at least a receiver"); | 3485 assert(callee->arg_size() > 0, "must have at least a receiver"); |
3494 // Introduce a new callee continuation point - if the callee has | 3503 // Introduce a new callee continuation point - if the callee has |
3495 // more than one return instruction or the return does not allow | 3504 // more than one return instruction or the return does not allow |
3496 // fall-through of control flow, all return instructions of the | 3505 // fall-through of control flow, all return instructions of the |
3497 // callee will need to be replaced by Goto's pointing to this | 3506 // callee will need to be replaced by Goto's pointing to this |
3498 // continuation point. | 3507 // continuation point. |
3499 BlockBegin* cont = block_at(next_bci()); | 3508 BlockBegin* cont = cont_block != NULL ? cont_block : block_at(next_bci()); |
3500 bool continuation_existed = true; | 3509 bool continuation_existed = true; |
3501 if (cont == NULL) { | 3510 if (cont == NULL) { |
3502 cont = new BlockBegin(next_bci()); | 3511 cont = new BlockBegin(next_bci()); |
3503 // low number so that continuation gets parsed as early as possible | 3512 // low number so that continuation gets parsed as early as possible |
3504 cont->set_depth_first_number(0); | 3513 cont->set_depth_first_number(0); |
3606 // off the Goto to the continuation, allowing control to fall | 3615 // off the Goto to the continuation, allowing control to fall |
3607 // through back into the caller block and effectively performing | 3616 // through back into the caller block and effectively performing |
3608 // block merging. This allows load elimination and CSE to take place | 3617 // block merging. This allows load elimination and CSE to take place |
3609 // across multiple callee scopes if they are relatively simple, and | 3618 // across multiple callee scopes if they are relatively simple, and |
3610 // is currently essential to making inlining profitable. | 3619 // is currently essential to making inlining profitable. |
3611 if ( num_returns() == 1 | 3620 if (cont_block == NULL) { |
3612 && block() == orig_block | 3621 if (num_returns() == 1 |
3613 && block() == inline_cleanup_block()) { | 3622 && block() == orig_block |
3614 _last = inline_cleanup_return_prev(); | 3623 && block() == inline_cleanup_block()) { |
3615 _state = inline_cleanup_state(); | 3624 _last = inline_cleanup_return_prev(); |
3616 } else if (continuation_preds == cont->number_of_preds()) { | 3625 _state = inline_cleanup_state(); |
3617 // Inlining caused that the instructions after the invoke in the | 3626 } else if (continuation_preds == cont->number_of_preds()) { |
3618 // caller are not reachable any more. So skip filling this block | 3627 // Inlining caused that the instructions after the invoke in the |
3619 // with instructions! | 3628 // caller are not reachable any more. So skip filling this block |
3620 assert (cont == continuation(), ""); | 3629 // with instructions! |
3621 assert(_last && _last->as_BlockEnd(), ""); | 3630 assert(cont == continuation(), ""); |
3622 _skip_block = true; | |
3623 } else { | |
3624 // Resume parsing in continuation block unless it was already parsed. | |
3625 // Note that if we don't change _last here, iteration in | |
3626 // iterate_bytecodes_for_block will stop when we return. | |
3627 if (!continuation()->is_set(BlockBegin::was_visited_flag)) { | |
3628 // add continuation to work list instead of parsing it immediately | |
3629 assert(_last && _last->as_BlockEnd(), ""); | 3631 assert(_last && _last->as_BlockEnd(), ""); |
3630 scope_data()->parent()->add_to_work_list(continuation()); | |
3631 _skip_block = true; | 3632 _skip_block = true; |
3633 } else { | |
3634 // Resume parsing in continuation block unless it was already parsed. | |
3635 // Note that if we don't change _last here, iteration in | |
3636 // iterate_bytecodes_for_block will stop when we return. | |
3637 if (!continuation()->is_set(BlockBegin::was_visited_flag)) { | |
3638 // add continuation to work list instead of parsing it immediately | |
3639 assert(_last && _last->as_BlockEnd(), ""); | |
3640 scope_data()->parent()->add_to_work_list(continuation()); | |
3641 _skip_block = true; | |
3642 } | |
3632 } | 3643 } |
3633 } | 3644 } |
3634 | 3645 |
3635 // Fill the exception handler for synchronized methods with instructions | 3646 // Fill the exception handler for synchronized methods with instructions |
3636 if (callee->is_synchronized() && sync_handler->state() != NULL) { | 3647 if (callee->is_synchronized() && sync_handler->state() != NULL) { |
3640 } | 3651 } |
3641 | 3652 |
3642 compilation()->notice_inlined_method(callee); | 3653 compilation()->notice_inlined_method(callee); |
3643 | 3654 |
3644 return true; | 3655 return true; |
3656 } | |
3657 | |
3658 | |
3659 bool GraphBuilder::for_method_handle_inline(ciMethod* callee) { | |
3660 assert(!callee->is_static(), "change next line"); | |
3661 int index = state()->stack_size() - (callee->arg_size_no_receiver() + 1); | |
3662 Value receiver = state()->stack_at(index); | |
3663 | |
3664 if (receiver->type()->is_constant()) { | |
3665 ciMethodHandle* method_handle = receiver->type()->as_ObjectType()->constant_value()->as_method_handle(); | |
3666 | |
3667 // Set the callee to have access to the class and signature in | |
3668 // the MethodHandleCompiler. | |
3669 method_handle->set_callee(callee); | |
3670 method_handle->set_caller(method()); | |
3671 | |
3672 // Get an adapter for the MethodHandle. | |
3673 ciMethod* method_handle_adapter = method_handle->get_method_handle_adapter(); | |
3674 if (method_handle_adapter != NULL) { | |
3675 return try_inline(method_handle_adapter, /*holder_known=*/ true); | |
3676 } | |
3677 } else if (receiver->as_CheckCast()) { | |
3678 // Match MethodHandle.selectAlternative idiom | |
3679 Phi* phi = receiver->as_CheckCast()->obj()->as_Phi(); | |
3680 | |
3681 if (phi != NULL && phi->operand_count() == 2) { | |
3682 // Get the two MethodHandle inputs from the Phi. | |
3683 Value op1 = phi->operand_at(0); | |
3684 Value op2 = phi->operand_at(1); | |
3685 ciMethodHandle* mh1 = op1->type()->as_ObjectType()->constant_value()->as_method_handle(); | |
3686 ciMethodHandle* mh2 = op2->type()->as_ObjectType()->constant_value()->as_method_handle(); | |
3687 | |
3688 // Set the callee to have access to the class and signature in | |
3689 // the MethodHandleCompiler. | |
3690 mh1->set_callee(callee); | |
3691 mh1->set_caller(method()); | |
3692 mh2->set_callee(callee); | |
3693 mh2->set_caller(method()); | |
3694 | |
3695 // Get adapters for the MethodHandles. | |
3696 ciMethod* mh1_adapter = mh1->get_method_handle_adapter(); | |
3697 ciMethod* mh2_adapter = mh2->get_method_handle_adapter(); | |
3698 | |
3699 if (mh1_adapter != NULL && mh2_adapter != NULL) { | |
3700 set_inline_cleanup_info(); | |
3701 | |
3702 // Build the If guard | |
3703 BlockBegin* one = new BlockBegin(next_bci()); | |
3704 BlockBegin* two = new BlockBegin(next_bci()); | |
3705 BlockBegin* end = new BlockBegin(next_bci()); | |
3706 Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false)); | |
3707 block()->set_end(iff->as_BlockEnd()); | |
3708 | |
3709 // Connect up the states | |
3710 one->merge(block()->end()->state()); | |
3711 two->merge(block()->end()->state()); | |
3712 | |
3713 // Save the state for the second inlinee | |
3714 ValueStack* state_before = copy_state_before(); | |
3715 | |
3716 // Parse first adapter | |
3717 _last = _block = one; | |
3718 if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { | |
3719 restore_inline_cleanup_info(); | |
3720 block()->clear_end(); // remove appended iff | |
3721 return false; | |
3722 } | |
3723 | |
3724 // Parse second adapter | |
3725 _last = _block = two; | |
3726 _state = state_before; | |
3727 if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { | |
3728 restore_inline_cleanup_info(); | |
3729 block()->clear_end(); // remove appended iff | |
3730 return false; | |
3731 } | |
3732 | |
3733 connect_to_end(end); | |
3734 return true; | |
3735 } | |
3736 } | |
3737 } | |
3738 return false; | |
3739 } | |
3740 | |
3741 | |
3742 bool GraphBuilder::for_invokedynamic_inline(ciMethod* callee) { | |
3743 // Get the MethodHandle from the CallSite. | |
3744 ciCallSite* call_site = stream()->get_call_site(); | |
3745 ciMethodHandle* method_handle = call_site->get_target(); | |
3746 | |
3747 // Inline constant and mutable call sites. We don't inline | |
3748 // volatile call sites optimistically since they are specified | |
3749 // to change their value often and that would result in a lot of | |
3750 // deoptimizations and recompiles. | |
3751 if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) { | |
3752 // Set the callee to have access to the class and signature in the | |
3753 // MethodHandleCompiler. | |
3754 method_handle->set_callee(callee); | |
3755 method_handle->set_caller(method()); | |
3756 | |
3757 // Get an adapter for the MethodHandle. | |
3758 ciMethod* method_handle_adapter = method_handle->get_invokedynamic_adapter(); | |
3759 if (method_handle_adapter != NULL) { | |
3760 if (try_inline(method_handle_adapter, /*holder_known=*/ true)) { | |
3761 // Add a dependence for invalidation of the optimization. | |
3762 if (!call_site->is_constant_call_site()) { | |
3763 dependency_recorder()->assert_call_site_target_value(call_site, method_handle); | |
3764 } | |
3765 return true; | |
3766 } | |
3767 } | |
3768 } | |
3769 return false; | |
3645 } | 3770 } |
3646 | 3771 |
3647 | 3772 |
3648 void GraphBuilder::inline_bailout(const char* msg) { | 3773 void GraphBuilder::inline_bailout(const char* msg) { |
3649 assert(msg != NULL, "inline bailout msg must exist"); | 3774 assert(msg != NULL, "inline bailout msg must exist"); |