Skip to content

Commit fead3cf

Browse files
author
Markus Grönlund
committedAug 23, 2024
8338745: Intrinsify Continuation.pin() and Continuation.unpin()
Reviewed-by: kvn
1 parent a5e2800 commit fead3cf

File tree

9 files changed

+109
-4
lines changed

9 files changed

+109
-4
lines changed
 

‎src/hotspot/share/classfile/vmIntrinsics.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) {
242242
case vmIntrinsics::_Reference_get:
243243
case vmIntrinsics::_Continuation_doYield:
244244
case vmIntrinsics::_Continuation_enterSpecial:
245+
case vmIntrinsics::_Continuation_pin:
246+
case vmIntrinsics::_Continuation_unpin:
245247
break;
246248
default:
247249
return true;

‎src/hotspot/share/classfile/vmIntrinsics.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ class methodHandle;
600600
do_alias(continuationOnPinned_signature, int_void_signature) \
601601
do_intrinsic(_Continuation_doYield, jdk_internal_vm_Continuation, doYield_name, continuationDoYield_signature, F_SN) \
602602
do_alias( continuationDoYield_signature, void_int_signature) \
603+
do_intrinsic(_Continuation_pin, jdk_internal_vm_Continuation, pin_name, void_method_signature, F_SN) \
604+
do_intrinsic(_Continuation_unpin, jdk_internal_vm_Continuation, unpin_name, void_method_signature, F_SN) \
603605
\
604606
/* java/lang/VirtualThread */ \
605607
do_intrinsic(_notifyJvmtiVThreadStart, java_lang_VirtualThread, notifyJvmtiStart_name, void_method_signature, F_RN) \

‎src/hotspot/share/classfile/vmSymbols.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -406,6 +406,8 @@ class SerializeClosure;
406406
template(onContinue_name, "onContinue0") \
407407
template(scope_name, "scope") \
408408
template(yieldInfo_name, "yieldInfo") \
409+
template(pin_name, "pin") \
410+
template(unpin_name, "unpin") \
409411
template(tail_name, "tail") \
410412
template(size_name, "size") \
411413
template(bottom_name, "bottom") \

‎src/hotspot/share/jvmci/vmStructs_jvmci.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "oops/methodCounters.hpp"
3636
#include "oops/objArrayKlass.hpp"
3737
#include "prims/jvmtiThreadState.hpp"
38+
#include "runtime/continuationEntry.hpp"
3839
#include "runtime/deoptimization.hpp"
3940
#include "runtime/flags/jvmFlag.hpp"
4041
#include "runtime/osThread.hpp"
@@ -244,10 +245,12 @@
244245
nonstatic_field(JavaThread, _held_monitor_count, intx) \
245246
nonstatic_field(JavaThread, _lock_stack, LockStack) \
246247
nonstatic_field(JavaThread, _om_cache, OMCache) \
248+
nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \
247249
JVMTI_ONLY(nonstatic_field(JavaThread, _is_in_VTMS_transition, bool)) \
248250
JVMTI_ONLY(nonstatic_field(JavaThread, _is_in_tmp_VTMS_transition, bool)) \
249251
JVMTI_ONLY(nonstatic_field(JavaThread, _is_disable_suspend, bool)) \
250252
\
253+
nonstatic_field(ContinuationEntry, _pin_count, uint32_t) \
251254
nonstatic_field(LockStack, _top, uint32_t) \
252255
\
253256
JVMTI_ONLY(static_field(JvmtiVTMSTransitionDisabler, _VTMS_notify_jvmti_events, bool)) \

‎src/hotspot/share/opto/c2compiler.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,8 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) {
731731
case vmIntrinsics::_setCurrentThread:
732732
case vmIntrinsics::_scopedValueCache:
733733
case vmIntrinsics::_setScopedValueCache:
734+
case vmIntrinsics::_Continuation_pin:
735+
case vmIntrinsics::_Continuation_unpin:
734736
#ifdef JFR_HAVE_INTRINSICS
735737
case vmIntrinsics::_counterTime:
736738
case vmIntrinsics::_getEventWriter:

‎src/hotspot/share/opto/library_call.cpp

+90
Original file line numberDiff line numberDiff line change
@@ -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).
37203810
Node* LibraryCallKit::load_mirror_from_klass(Node* klass) {

‎src/hotspot/share/opto/library_call.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ class LibraryCallKit : public GraphKit {
241241
const Type* scopedValueCache_type();
242242
Node* scopedValueCache_helper();
243243
bool inline_native_setScopedValueCache();
244+
bool inline_native_Continuation_pinning(bool unpin);
244245

245246
bool inline_native_time_funcs(address method, const char* funcName);
246247
#if INCLUDE_JVMTI

‎src/hotspot/share/runtime/continuationEntry.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class RegisterMap;
3939

4040
// Metadata stored in the continuation entry frame
4141
class ContinuationEntry {
42+
friend class JVMCIVMStructs;
4243
ContinuationEntryPD _pd;
4344
#ifdef ASSERT
4445
private:
@@ -78,7 +79,7 @@ class ContinuationEntry {
7879
#else
7980
int32_t _parent_held_monitor_count;
8081
#endif
81-
uint _pin_count;
82+
uint32_t _pin_count;
8283

8384
public:
8485
static ByteSize parent_offset() { return byte_offset_of(ContinuationEntry, _parent); }
@@ -108,7 +109,7 @@ class ContinuationEntry {
108109

109110
bool is_pinned() { return _pin_count > 0; }
110111
bool pin() {
111-
if (_pin_count == UINT_MAX) return false;
112+
if (_pin_count == UINT32_MAX) return false;
112113
_pin_count++;
113114
return true;
114115
}

‎src/java.base/share/classes/jdk/internal/vm/Continuation.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -427,13 +427,15 @@ public boolean isPreempted() {
427427
* Pins the current continuation (enters a critical section).
428428
* This increments an internal semaphore that, when greater than 0, pins the continuation.
429429
*/
430+
@IntrinsicCandidate
430431
public static native void pin();
431432

432433
/**
433434
* Unpins the current continuation (exits a critical section).
434435
* This decrements an internal semaphore that, when equal 0, unpins the current continuation
435436
* if pinned with {@link #pin()}.
436437
*/
438+
@IntrinsicCandidate
437439
public static native void unpin();
438440

439441
/**

0 commit comments

Comments
 (0)
Please sign in to comment.