@@ -482,6 +482,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
482482 case vmIntrinsics::_scopedValueCache: return inline_native_scopedValueCache ();
483483 case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache ();
484484
485+ case vmIntrinsics::_Continuation_pin: return inline_native_Continuation_pinning (false );
486+ case vmIntrinsics::_Continuation_unpin: return inline_native_Continuation_pinning (true );
487+
485488#if INCLUDE_JVMTI
486489 case vmIntrinsics::_notifyJvmtiVThreadStart: return inline_native_notify_jvmti_funcs (CAST_FROM_FN_PTR (address, OptoRuntime::notify_jvmti_vthread_start ()),
487490 " notifyJvmtiStart" , true , false );
@@ -3715,6 +3718,93 @@ bool LibraryCallKit::inline_native_setScopedValueCache() {
37153718 return true ;
37163719}
37173720
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+
37183808// ---------------------------load_mirror_from_klass----------------------------
37193809// Given a klass oop, load its java mirror (a java.lang.Class oop).
37203810Node* LibraryCallKit::load_mirror_from_klass (Node* klass) {
0 commit comments