src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6498151 Sdiff src/share/vm/opto

src/share/vm/opto/library_call.cpp

Print this page
6498581: ThreadInterruptTest3 produces wrong output on Windows


3219   Node* value = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+0));
3220 #ifdef ASSERT
3221   Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+1));
3222   assert(value_top == top(), "second value must be top");
3223 #endif
3224   set_result(value);
3225   return true;
3226 }
3227 
3228 //------------------------inline_native_currentThread------------------
3229 bool LibraryCallKit::inline_native_currentThread() {
3230   Node* junk = NULL;
3231   set_result(generate_current_thread(junk));
3232   return true;
3233 }
3234 
3235 //------------------------inline_native_isInterrupted------------------
3236 // private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted);
3237 bool LibraryCallKit::inline_native_isInterrupted() {
3238   // Add a fast path to t.isInterrupted(clear_int):
3239   //   (t == Thread.current() && (!TLS._osthread._interrupted || !clear_int))

3240   //   ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int)
3241   // So, in the common case that the interrupt bit is false,
3242   // we avoid making a call into the VM.  Even if the interrupt bit
3243   // is true, if the clear_int argument is false, we avoid the VM call.
3244   // However, if the receiver is not currentThread, we must call the VM,
3245   // because there must be some locking done around the operation.
3246 
3247   // We only go to the fast case code if we pass two guards.
3248   // Paths which do not pass are accumulated in the slow_region.
3249 
3250   enum {
3251     no_int_result_path   = 1, // t == Thread.current() && !TLS._osthread._interrupted
3252     no_clear_result_path = 2, // t == Thread.current() &&  TLS._osthread._interrupted && !clear_int
3253     slow_result_path     = 3, // slow path: t.isInterrupted(clear_int)
3254     PATH_LIMIT
3255   };
3256 
3257   // Ensure that it's not possible to move the load of TLS._osthread._interrupted flag
3258   // out of the function.
3259   insert_mem_bar(Op_MemBarCPUOrder);


3282   Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
3283   Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0)));
3284   Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne));
3285 
3286   IfNode* iff_bit = create_and_map_if(control(), bol_bit, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
3287 
3288   // First fast path:  if (!TLS._interrupted) return false;
3289   Node* false_bit = _gvn.transform(new (C) IfFalseNode(iff_bit));
3290   result_rgn->init_req(no_int_result_path, false_bit);
3291   result_val->init_req(no_int_result_path, intcon(0));
3292 
3293   // drop through to next case
3294   set_control( _gvn.transform(new (C) IfTrueNode(iff_bit)));
3295 
3296   // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path.
3297   Node* clr_arg = argument(1);
3298   Node* cmp_arg = _gvn.transform(new (C) CmpINode(clr_arg, intcon(0)));
3299   Node* bol_arg = _gvn.transform(new (C) BoolNode(cmp_arg, BoolTest::ne));
3300   IfNode* iff_arg = create_and_map_if(control(), bol_arg, PROB_FAIR, COUNT_UNKNOWN);
3301 






3302   // Second fast path:  ... else if (!clear_int) return true;
3303   Node* false_arg = _gvn.transform(new (C) IfFalseNode(iff_arg));
3304   result_rgn->init_req(no_clear_result_path, false_arg);
3305   result_val->init_req(no_clear_result_path, intcon(1));
3306 
3307   // drop through to next case
3308   set_control( _gvn.transform(new (C) IfTrueNode(iff_arg)));
3309 
3310   // (d) Otherwise, go to the slow path.
3311   slow_region->add_req(control());
3312   set_control( _gvn.transform(slow_region));

3313 
3314   if (stopped()) {
3315     // There is no slow path.
3316     result_rgn->init_req(slow_result_path, top());
3317     result_val->init_req(slow_result_path, top());
3318   } else {
3319     // non-virtual because it is a private non-static
3320     CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted);
3321 
3322     Node* slow_val = set_results_for_java_call(slow_call);
3323     // this->control() comes from set_results_for_java_call
3324 
3325     Node* fast_io  = slow_call->in(TypeFunc::I_O);
3326     Node* fast_mem = slow_call->in(TypeFunc::Memory);
3327 
3328     // These two phis are pre-filled with copies of of the fast IO and Memory
3329     PhiNode* result_mem  = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM);
3330     PhiNode* result_io   = PhiNode::make(result_rgn, fast_io,  Type::ABIO);
3331 
3332     result_rgn->init_req(slow_result_path, control());




3219   Node* value = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+0));
3220 #ifdef ASSERT
3221   Node* value_top = _gvn.transform(new (C) ProjNode(time, TypeFunc::Parms+1));
3222   assert(value_top == top(), "second value must be top");
3223 #endif
3224   set_result(value);
3225   return true;
3226 }
3227 
3228 //------------------------inline_native_currentThread------------------
3229 bool LibraryCallKit::inline_native_currentThread() {
3230   Node* junk = NULL;
3231   set_result(generate_current_thread(junk));
3232   return true;
3233 }
3234 
3235 //------------------------inline_native_isInterrupted------------------
3236 // private native boolean java.lang.Thread.isInterrupted(boolean ClearInterrupted);
3237 bool LibraryCallKit::inline_native_isInterrupted() {
3238   // Add a fast path to t.isInterrupted(clear_int):
3239   //   (t == Thread.current() && 
3240   //    (!TLS._osthread._interrupted || WINDOWS_ONLY(false) NOT_WINDOWS(!clear_int)))
3241   //   ? TLS._osthread._interrupted : /*slow path:*/ t.isInterrupted(clear_int)
3242   // So, in the common case that the interrupt bit is false,
3243   // we avoid making a call into the VM.  Even if the interrupt bit
3244   // is true, if the clear_int argument is false, we avoid the VM call.
3245   // However, if the receiver is not currentThread, we must call the VM,
3246   // because there must be some locking done around the operation.
3247 
3248   // We only go to the fast case code if we pass two guards.
3249   // Paths which do not pass are accumulated in the slow_region.
3250 
3251   enum {
3252     no_int_result_path   = 1, // t == Thread.current() && !TLS._osthread._interrupted
3253     no_clear_result_path = 2, // t == Thread.current() &&  TLS._osthread._interrupted && !clear_int
3254     slow_result_path     = 3, // slow path: t.isInterrupted(clear_int)
3255     PATH_LIMIT
3256   };
3257 
3258   // Ensure that it's not possible to move the load of TLS._osthread._interrupted flag
3259   // out of the function.
3260   insert_mem_bar(Op_MemBarCPUOrder);


3283   Node* int_bit = make_load(control(), p, TypeInt::BOOL, T_INT);
3284   Node* cmp_bit = _gvn.transform(new (C) CmpINode(int_bit, intcon(0)));
3285   Node* bol_bit = _gvn.transform(new (C) BoolNode(cmp_bit, BoolTest::ne));
3286 
3287   IfNode* iff_bit = create_and_map_if(control(), bol_bit, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
3288 
3289   // First fast path:  if (!TLS._interrupted) return false;
3290   Node* false_bit = _gvn.transform(new (C) IfFalseNode(iff_bit));
3291   result_rgn->init_req(no_int_result_path, false_bit);
3292   result_val->init_req(no_int_result_path, intcon(0));
3293 
3294   // drop through to next case
3295   set_control( _gvn.transform(new (C) IfTrueNode(iff_bit)));
3296 
3297   // (c) Or, if interrupt bit is set and clear_int is false, use 2nd fast path.
3298   Node* clr_arg = argument(1);
3299   Node* cmp_arg = _gvn.transform(new (C) CmpINode(clr_arg, intcon(0)));
3300   Node* bol_arg = _gvn.transform(new (C) BoolNode(cmp_arg, BoolTest::ne));
3301   IfNode* iff_arg = create_and_map_if(control(), bol_arg, PROB_FAIR, COUNT_UNKNOWN);
3302 
3303 #ifdef TARGET_OS_FAMILY_windows
3304   // To return true on Windows you must read the _interrupted field
3305   // and check the the event state i.e. take the slow path. 
3306   result_rgn->init_req(no_clear_result_path, top());
3307   result_val->init_req(no_clear_result_path, top());
3308 #else 
3309   // Second fast path:  ... else if (!clear_int) return true;
3310   Node* false_arg = _gvn.transform(new (C) IfFalseNode(iff_arg));
3311   result_rgn->init_req(no_clear_result_path, false_arg);
3312   result_val->init_req(no_clear_result_path, intcon(1));
3313 
3314   // drop through to next case
3315   set_control( _gvn.transform(new (C) IfTrueNode(iff_arg)));
3316 
3317   // (d) Otherwise, go to the slow path.
3318   slow_region->add_req(control());
3319   set_control( _gvn.transform(slow_region));
3320 #endif
3321 
3322   if (stopped()) {
3323     // There is no slow path.
3324     result_rgn->init_req(slow_result_path, top());
3325     result_val->init_req(slow_result_path, top());
3326   } else {
3327     // non-virtual because it is a private non-static
3328     CallJavaNode* slow_call = generate_method_call(vmIntrinsics::_isInterrupted);
3329 
3330     Node* slow_val = set_results_for_java_call(slow_call);
3331     // this->control() comes from set_results_for_java_call
3332 
3333     Node* fast_io  = slow_call->in(TypeFunc::I_O);
3334     Node* fast_mem = slow_call->in(TypeFunc::Memory);
3335 
3336     // These two phis are pre-filled with copies of of the fast IO and Memory
3337     PhiNode* result_mem  = PhiNode::make(result_rgn, fast_mem, Type::MEMORY, TypePtr::BOTTOM);
3338     PhiNode* result_io   = PhiNode::make(result_rgn, fast_io,  Type::ABIO);
3339 
3340     result_rgn->init_req(slow_result_path, control());


src/share/vm/opto/library_call.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File