Mercurial > hg > truffle
comparison src/share/vm/opto/library_call.cpp @ 7422:eb409f2f146e
8003135: HotSpot inlines and hoists the Thread.currentThread().isInterrupted() out of the loop
Summary: Make the load of TLS._osthread._interrupted flag in Thread.isInterrupted(Z)Z intrinsic effectively volatile.
Reviewed-by: kvn, jrose
author | vlivanov |
---|---|
date | Tue, 18 Dec 2012 06:52:00 -0800 |
parents | dd38cfd12c3a |
children | 620e502e3f47 |
comparison
equal
deleted
inserted
replaced
7420:18d56ca3e901 | 7422:eb409f2f146e |
---|---|
2950 // However, if the receiver is not currentThread, we must call the VM, | 2950 // However, if the receiver is not currentThread, we must call the VM, |
2951 // because there must be some locking done around the operation. | 2951 // because there must be some locking done around the operation. |
2952 | 2952 |
2953 // We only go to the fast case code if we pass two guards. | 2953 // We only go to the fast case code if we pass two guards. |
2954 // Paths which do not pass are accumulated in the slow_region. | 2954 // Paths which do not pass are accumulated in the slow_region. |
2955 | |
2956 enum { | |
2957 no_int_result_path = 1, // t == Thread.current() && !TLS._osthread._interrupted | |
2958 no_clear_result_path = 2, // t == Thread.current() && TLS._osthread._interrupted && !clear_int | |
2959 slow_result_path = 3, // slow path: t.isInterrupted(clear_int) | |
2960 PATH_LIMIT | |
2961 }; | |
2962 | |
2963 // Ensure that it's not possible to move the load of TLS._osthread._interrupted flag | |
2964 // out of the function. | |
2965 insert_mem_bar(Op_MemBarCPUOrder); | |
2966 | |
2967 RegionNode* result_rgn = new (C) RegionNode(PATH_LIMIT); | |
2968 PhiNode* result_val = new (C) PhiNode(result_rgn, TypeInt::BOOL); | |
2969 | |
2955 RegionNode* slow_region = new (C) RegionNode(1); | 2970 RegionNode* slow_region = new (C) RegionNode(1); |
2956 record_for_igvn(slow_region); | 2971 record_for_igvn(slow_region); |
2957 RegionNode* result_rgn = new (C) RegionNode(1+3); // fast1, fast2, slow | |
2958 PhiNode* result_val = new (C) PhiNode(result_rgn, TypeInt::BOOL); | |
2959 enum { no_int_result_path = 1, | |
2960 no_clear_result_path = 2, | |
2961 slow_result_path = 3 | |
2962 }; | |
2963 | 2972 |
2964 // (a) Receiving thread must be the current thread. | 2973 // (a) Receiving thread must be the current thread. |
2965 Node* rec_thr = argument(0); | 2974 Node* rec_thr = argument(0); |
2966 Node* tls_ptr = NULL; | 2975 Node* tls_ptr = NULL; |
2967 Node* cur_thr = generate_current_thread(tls_ptr); | 2976 Node* cur_thr = generate_current_thread(tls_ptr); |
2968 Node* cmp_thr = _gvn.transform( new (C) CmpPNode(cur_thr, rec_thr) ); | 2977 Node* cmp_thr = _gvn.transform( new (C) CmpPNode(cur_thr, rec_thr) ); |
2969 Node* bol_thr = _gvn.transform( new (C) BoolNode(cmp_thr, BoolTest::ne) ); | 2978 Node* bol_thr = _gvn.transform( new (C) BoolNode(cmp_thr, BoolTest::ne) ); |
2970 | 2979 |
2971 bool known_current_thread = (_gvn.type(bol_thr) == TypeInt::ZERO); | 2980 generate_slow_guard(bol_thr, slow_region); |
2972 if (!known_current_thread) | |
2973 generate_slow_guard(bol_thr, slow_region); | |
2974 | 2981 |
2975 // (b) Interrupt bit on TLS must be false. | 2982 // (b) Interrupt bit on TLS must be false. |
2976 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); | 2983 Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); |
2977 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); | 2984 Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS); |
2978 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); | 2985 p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::interrupted_offset())); |
2986 | |
2979 // Set the control input on the field _interrupted read to prevent it floating up. | 2987 // Set the control input on the field _interrupted read to prevent it floating up. |
2980 Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); | 2988 Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT); |
2981 Node* cmp_bit = _gvn.transform( new (C) CmpINode(int_bit, intcon(0)) ); | 2989 Node* cmp_bit = _gvn.transform( new (C) CmpINode(int_bit, intcon(0)) ); |
2982 Node* bol_bit = _gvn.transform( new (C) BoolNode(cmp_bit, BoolTest::ne) ); | 2990 Node* bol_bit = _gvn.transform( new (C) BoolNode(cmp_bit, BoolTest::ne) ); |
2983 | 2991 |
3018 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted); | 3026 CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted); |
3019 | 3027 |
3020 Node* slow_val = set_results_for_java_call(slow_call); | 3028 Node* slow_val = set_results_for_java_call(slow_call); |
3021 // this->control() comes from set_results_for_java_call | 3029 // this->control() comes from set_results_for_java_call |
3022 | 3030 |
3023 // If we know that the result of the slow call will be true, tell the optimizer! | |
3024 if (known_current_thread) slow_val = intcon(1); | |
3025 | |
3026 Node* fast_io = slow_call->in(TypeFunc::I_O); | 3031 Node* fast_io = slow_call->in(TypeFunc::I_O); |
3027 Node* fast_mem = slow_call->in(TypeFunc::Memory); | 3032 Node* fast_mem = slow_call->in(TypeFunc::Memory); |
3033 | |
3028 // These two phis are pre-filled with copies of of the fast IO and Memory | 3034 // These two phis are pre-filled with copies of of the fast IO and Memory |
3029 Node* io_phi = PhiNode::make(result_rgn, fast_io, Type::ABIO); | 3035 PhiNode* result_mem = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM); |
3030 Node* mem_phi = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM); | 3036 PhiNode* result_io = PhiNode::make(result_rgn, fast_io, Type::ABIO); |
3031 | 3037 |
3032 result_rgn->init_req(slow_result_path, control()); | 3038 result_rgn->init_req(slow_result_path, control()); |
3033 io_phi ->init_req(slow_result_path, i_o()); | 3039 result_io ->init_req(slow_result_path, i_o()); |
3034 mem_phi ->init_req(slow_result_path, reset_memory()); | 3040 result_mem->init_req(slow_result_path, reset_memory()); |
3035 result_val->init_req(slow_result_path, slow_val); | 3041 result_val->init_req(slow_result_path, slow_val); |
3036 | 3042 |
3037 set_all_memory( _gvn.transform(mem_phi) ); | 3043 set_all_memory(_gvn.transform(result_mem)); |
3038 set_i_o( _gvn.transform(io_phi) ); | 3044 set_i_o( _gvn.transform(result_io)); |
3039 } | 3045 } |
3040 | 3046 |
3041 C->set_has_split_ifs(true); // Has chance for split-if optimization | 3047 C->set_has_split_ifs(true); // Has chance for split-if optimization |
3042 set_result(result_rgn, result_val); | 3048 set_result(result_rgn, result_val); |
3043 return true; | 3049 return true; |