@@ -482,6 +482,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
482
482
case vmIntrinsics::_scopedValueCache: return inline_native_scopedValueCache ();
483
483
case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache ();
484
484
485
+ case vmIntrinsics::_Continuation_pin: return inline_native_Continuation_pinning (false );
486
+ case vmIntrinsics::_Continuation_unpin: return inline_native_Continuation_pinning (true );
487
+
485
488
#if INCLUDE_JVMTI
486
489
case vmIntrinsics::_notifyJvmtiVThreadStart: return inline_native_notify_jvmti_funcs (CAST_FROM_FN_PTR (address, OptoRuntime::notify_jvmti_vthread_start ()),
487
490
" notifyJvmtiStart" , true , false );
@@ -3715,6 +3718,93 @@ bool LibraryCallKit::inline_native_setScopedValueCache() {
3715
3718
return true ;
3716
3719
}
3717
3720
3721
+ // ------------------------inline_native_Continuation_pin and unpin-----------
3722
+
3723
+ // Shared implementation routine for both pin and unpin.
3724
+ bool LibraryCallKit::inline_native_Continuation_pinning (bool unpin) {
3725
+ enum { _true_path = 1 , _false_path = 2 , PATH_LIMIT };
3726
+
3727
+ // Save input memory.
3728
+ Node* input_memory_state = reset_memory ();
3729
+ set_all_memory (input_memory_state);
3730
+
3731
+ // TLS
3732
+ Node* tls_ptr = _gvn.transform (new ThreadLocalNode ());
3733
+ Node* last_continuation_offset = basic_plus_adr (top (), tls_ptr, in_bytes (JavaThread::cont_entry_offset ()));
3734
+ Node* last_continuation = make_load (control (), last_continuation_offset, last_continuation_offset->get_ptr_type (), T_ADDRESS, MemNode::unordered);
3735
+
3736
+ // Null check the last continuation object.
3737
+ Node* continuation_cmp_null = _gvn.transform (new CmpPNode (last_continuation, null ()));
3738
+ Node* test_continuation_not_equal_null = _gvn.transform (new BoolNode (continuation_cmp_null, BoolTest::ne));
3739
+ IfNode* iff_continuation_not_equal_null = create_and_map_if (control (), test_continuation_not_equal_null, PROB_MAX, COUNT_UNKNOWN);
3740
+
3741
+ // False path, last continuation is null.
3742
+ Node* continuation_is_null = _gvn.transform (new IfFalseNode (iff_continuation_not_equal_null));
3743
+
3744
+ // True path, last continuation is not null.
3745
+ Node* continuation_is_not_null = _gvn.transform (new IfTrueNode (iff_continuation_not_equal_null));
3746
+
3747
+ set_control (continuation_is_not_null);
3748
+
3749
+ // Load the pin count from the last continuation.
3750
+ Node* pin_count_offset = basic_plus_adr (top (), last_continuation, in_bytes (ContinuationEntry::pin_count_offset ()));
3751
+ Node* pin_count = make_load (control (), pin_count_offset, TypeInt::INT, T_INT, MemNode::unordered);
3752
+
3753
+ // The loaded pin count is compared against a context specific rhs for over/underflow detection.
3754
+ Node* pin_count_rhs;
3755
+ if (unpin) {
3756
+ pin_count_rhs = _gvn.intcon (0 );
3757
+ } else {
3758
+ pin_count_rhs = _gvn.intcon (UINT32_MAX);
3759
+ }
3760
+ Node* pin_count_cmp = _gvn.transform (new CmpUNode (_gvn.transform (pin_count), pin_count_rhs));
3761
+ Node* test_pin_count_over_underflow = _gvn.transform (new BoolNode (pin_count_cmp, BoolTest::eq));
3762
+ IfNode* iff_pin_count_over_underflow = create_and_map_if (control (), test_pin_count_over_underflow, PROB_MIN, COUNT_UNKNOWN);
3763
+
3764
+ // False branch, no pin count over/underflow. Increment or decrement pin count and store back.
3765
+ Node* valid_pin_count = _gvn.transform (new IfFalseNode (iff_pin_count_over_underflow));
3766
+ set_control (valid_pin_count);
3767
+
3768
+ Node* next_pin_count;
3769
+ if (unpin) {
3770
+ next_pin_count = _gvn.transform (new SubINode (pin_count, _gvn.intcon (1 )));
3771
+ } else {
3772
+ next_pin_count = _gvn.transform (new AddINode (pin_count, _gvn.intcon (1 )));
3773
+ }
3774
+
3775
+ Node* updated_pin_count_memory = store_to_memory (control (), pin_count_offset, next_pin_count, T_INT, Compile::AliasIdxRaw, MemNode::unordered);
3776
+
3777
+ // True branch, pin count over/underflow.
3778
+ Node* pin_count_over_underflow = _gvn.transform (new IfTrueNode (iff_pin_count_over_underflow));
3779
+ {
3780
+ // Trap (but not deoptimize (Action_none)) and continue in the interpreter
3781
+ // which will throw IllegalStateException for pin count over/underflow.
3782
+ PreserveJVMState pjvms (this );
3783
+ set_control (pin_count_over_underflow);
3784
+ set_all_memory (input_memory_state);
3785
+ uncommon_trap_exact (Deoptimization::Reason_intrinsic,
3786
+ Deoptimization::Action_none);
3787
+ assert (stopped (), " invariant" );
3788
+ }
3789
+
3790
+ // Result of top level CFG and Memory.
3791
+ RegionNode* result_rgn = new RegionNode (PATH_LIMIT);
3792
+ record_for_igvn (result_rgn);
3793
+ PhiNode* result_mem = new PhiNode (result_rgn, Type::MEMORY, TypePtr::BOTTOM);
3794
+ record_for_igvn (result_mem);
3795
+
3796
+ result_rgn->init_req (_true_path, _gvn.transform (valid_pin_count));
3797
+ result_rgn->init_req (_false_path, _gvn.transform (continuation_is_null));
3798
+ result_mem->init_req (_true_path, _gvn.transform (updated_pin_count_memory));
3799
+ result_mem->init_req (_false_path, _gvn.transform (input_memory_state));
3800
+
3801
+ // Set output state.
3802
+ set_control (_gvn.transform (result_rgn));
3803
+ set_all_memory (_gvn.transform (result_mem));
3804
+
3805
+ return true ;
3806
+ }
3807
+
3718
3808
// ---------------------------load_mirror_from_klass----------------------------
3719
3809
// Given a klass oop, load its java mirror (a java.lang.Class oop).
3720
3810
Node* LibraryCallKit::load_mirror_from_klass (Node* klass) {
0 commit comments