1 /* 2 * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_RUNTIME_CONTINUATIONWRAPPER_INLINE_HPP 26 #define SHARE_VM_RUNTIME_CONTINUATIONWRAPPER_INLINE_HPP 27 28 // There is no continuationWrapper.hpp file 29 30 #include "classfile/javaClasses.inline.hpp" 31 #include "oops/oop.inline.hpp" 32 #include "memory/allocation.hpp" 33 #include "oops/oopsHierarchy.hpp" 34 #include "oops/stackChunkOop.hpp" 35 #include "runtime/continuationEntry.inline.hpp" 36 #include "runtime/continuationJavaClasses.inline.hpp" 37 #include "runtime/javaThread.hpp" 38 39 ///////////////////////////////////////////////////////////////////// 40 41 // Intermediary to the jdk.internal.vm.Continuation objects and ContinuationEntry 42 // This object is created when we begin a operation for a continuation, and is destroyed when the operation completes. 43 // Contents are read from the Java object at the entry points of this module, and written at exit or calls into Java 44 // It also serves as a custom NoSafepointVerifier 45 class ContinuationWrapper : public StackObj { 46 private: 47 JavaThread* const _thread; // Thread being frozen/thawed 48 ContinuationEntry* _entry; 49 // These oops are managed by SafepointOp 50 oop _continuation; // jdk.internal.vm.Continuation instance 51 stackChunkOop _tail; 52 bool _done; 53 54 ContinuationWrapper(const ContinuationWrapper& cont); // no copy constructor 55 56 private: 57 DEBUG_ONLY(Thread* _current_thread;) 58 friend class SafepointOp; 59 60 void disallow_safepoint() { 61 #ifdef ASSERT 62 assert(!_done, ""); 63 assert(_continuation != nullptr, ""); 64 _current_thread = Thread::current(); 65 if (_current_thread->is_Java_thread()) { 66 JavaThread::cast(_current_thread)->inc_no_safepoint_count(); 67 } 68 #endif 69 } 70 71 void allow_safepoint() { 72 #ifdef ASSERT 73 // we could have already allowed safepoints in done 74 if (!_done && _current_thread->is_Java_thread()) { 75 JavaThread::cast(_current_thread)->dec_no_safepoint_count(); 76 } 77 #endif 78 } 79 80 ContinuationWrapper(JavaThread* thread, ContinuationEntry* entry, oop continuation); 81 82 public: 83 void done() { 84 allow_safepoint(); // must be done first 85 _done = true; 86 *reinterpret_cast<intptr_t*>(&_continuation) = badHeapOopVal; 87 *reinterpret_cast<intptr_t*>(&_tail) = badHeapOopVal; 88 } 89 90 class SafepointOp : public StackObj { 91 ContinuationWrapper& _cont; 92 Handle _conth; 93 public: 94 SafepointOp(Thread* current, ContinuationWrapper& cont) 95 : _cont(cont), _conth(current, cont._continuation) { 96 _cont.allow_safepoint(); 97 } 98 inline ~SafepointOp() { // reload oops 99 _cont._continuation = _conth(); 100 _cont._tail = jdk_internal_vm_Continuation::tail(_cont._continuation); 101 _cont.disallow_safepoint(); 102 } 103 }; 104 105 public: 106 ~ContinuationWrapper() { allow_safepoint(); } 107 108 ContinuationWrapper(JavaThread* thread, oop continuation); 109 ContinuationWrapper(oop continuation); 110 ContinuationWrapper(const RegisterMap* map); 111 112 JavaThread* thread() const { return _thread; } 113 oop continuation() { return _continuation; } 114 stackChunkOop tail() const { return _tail; } 115 void set_tail(stackChunkOop chunk) { _tail = chunk; } 116 117 inline bool is_preempted(); 118 inline void set_preempted(bool value); 119 inline void read(); 120 inline void write(); 121 122 NOT_PRODUCT(intptr_t hash();) 123 124 ContinuationEntry* entry() const { return _entry; } 125 bool is_mounted() const { return _entry != nullptr; } 126 intptr_t* entrySP() const { return _entry->entry_sp(); } 127 intptr_t* entryFP() const { return _entry->entry_fp(); } 128 address entryPC() const { return _entry->entry_pc(); } 129 int argsize() const { assert(_entry->argsize() >= 0, ""); return _entry->argsize(); } 130 int entry_frame_extension() const { 131 // the entry frame is extended if the bottom frame has stack arguments 132 assert(_entry->argsize() >= 0, ""); 133 return _entry->argsize() == 0 ? _entry->argsize() : _entry->argsize() + frame::metadata_words_at_top; 134 } 135 void set_argsize(int value) { _entry->set_argsize(value); } 136 137 bool is_empty() const { return last_nonempty_chunk() == nullptr; } 138 const frame last_frame(); 139 140 inline stackChunkOop last_nonempty_chunk() const; 141 stackChunkOop find_chunk_by_address(void* p) const; 142 143 #ifdef ASSERT 144 bool is_entry_frame(const frame& f); 145 bool chunk_invariant() const; 146 #endif 147 }; 148 149 inline ContinuationWrapper::ContinuationWrapper(JavaThread* thread, ContinuationEntry* entry, oop continuation) 150 : _thread(thread), _entry(entry), _continuation(continuation), _done(false) { 151 assert(oopDesc::is_oop(_continuation), 152 "Invalid continuation object: " INTPTR_FORMAT, p2i((void*)_continuation)); 153 disallow_safepoint(); 154 read(); 155 } 156 157 inline ContinuationWrapper::ContinuationWrapper(JavaThread* thread, oop continuation) 158 : ContinuationWrapper(thread, thread->last_continuation(), continuation) {} 159 160 inline ContinuationWrapper::ContinuationWrapper(oop continuation) 161 : ContinuationWrapper(nullptr, nullptr, continuation) {} 162 163 inline bool ContinuationWrapper::is_preempted() { 164 return jdk_internal_vm_Continuation::is_preempted(_continuation); 165 } 166 167 inline void ContinuationWrapper::set_preempted(bool value) { 168 jdk_internal_vm_Continuation::set_preempted(_continuation, value); 169 } 170 171 inline void ContinuationWrapper::read() { 172 _tail = jdk_internal_vm_Continuation::tail(_continuation); 173 } 174 175 inline void ContinuationWrapper::write() { 176 assert(oopDesc::is_oop(_continuation), "bad oop"); 177 assert(oopDesc::is_oop_or_null(_tail), "bad oop"); 178 jdk_internal_vm_Continuation::set_tail(_continuation, _tail); 179 } 180 181 inline stackChunkOop ContinuationWrapper::last_nonempty_chunk() const { 182 assert(chunk_invariant(), ""); 183 stackChunkOop chunk = _tail; 184 if (chunk != nullptr && chunk->is_empty()) { 185 chunk = chunk->parent(); 186 } 187 assert(chunk == nullptr || !chunk->is_empty(), ""); 188 return chunk; 189 } 190 191 #endif // SHARE_VM_RUNTIME_CONTINUATIONWRAPPER_INLINE_HPP