1 /*
  2  * Copyright (c) 2018, 2021, 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_CONTINUATION_HPP
 26 #define SHARE_VM_RUNTIME_CONTINUATION_HPP
 27 
 28 #include "oops/access.hpp"
 29 #include "oops/oopsHierarchy.hpp"
 30 #include "memory/iterator.hpp"
 31 #include "runtime/frame.hpp"
 32 #include "runtime/globals.hpp"
 33 #include "jni.h"
 34 
 35 // The order of this struct matters as it's directly manipulated by assembly code (push/pop)
 36 
 37 class ContinuationEntry;
 38 
 39 // TODO: remove
 40 class Continuations : public AllStatic {
 41 public:
 42   static void print_statistics();
 43   static void init();
 44 };
 45 
 46 void continuations_init();
 47 
 48 class javaVFrame;
 49 class JavaThread;
 50 
 51 class Continuation : AllStatic {
 52 public:
 53   static void init();
 54 
 55   static int freeze(JavaThread* thread, intptr_t* sp);
 56   static int prepare_thaw(JavaThread* thread, bool return_barrier);
 57   static intptr_t* thaw(JavaThread* thread, int kind);
 58   static int try_force_yield(JavaThread* thread, oop cont);
 59   static void jump_from_safepoint(JavaThread* thread);
 60 
 61   static void notify_deopt(JavaThread* thread, intptr_t* sp);
 62 
 63   static oop  get_continuation_for_frame(JavaThread* thread, const frame& f);
 64   static ContinuationEntry* last_continuation(const JavaThread* thread, oop cont_scope);
 65   static bool is_mounted(JavaThread* thread, oop cont_scope);
 66   static bool is_continuation_enterSpecial(const frame& f);
 67   static bool is_continuation_entry_frame(const frame& f, const RegisterMap *map);
 68   static bool is_cont_barrier_frame(const frame& f);
 69   static bool is_return_barrier_entry(const address pc);
 70   static bool is_frame_in_continuation(ContinuationEntry* cont, const frame& f);
 71   static bool is_frame_in_continuation(JavaThread* thread, const frame& f);
 72   static bool fix_continuation_bottom_sender(JavaThread* thread, const frame& callee, address* sender_pc, intptr_t** sender_sp);
 73   static address get_top_return_pc_post_barrier(JavaThread* thread, address pc);
 74 
 75   static frame top_frame(const frame& callee, RegisterMap* map);
 76   static frame continuation_parent_frame(RegisterMap* map);
 77 
 78   static bool has_last_Java_frame(oop continuation);
 79   static stackChunkOop last_nonempty_chunk(oop continuation);
 80   static frame last_frame(oop continuation, RegisterMap *map);
 81   static javaVFrame* last_java_vframe(Handle continuation, RegisterMap *map);
 82 
 83   // pins/unpins the innermost mounted continuation; returns true on success or false if there's no continuation or the operation failed
 84   static bool pin(JavaThread* current);
 85   static bool unpin(JavaThread* current);
 86 
 87   // access frame data
 88   static bool is_in_usable_stack(address addr, const RegisterMap* map);
 89 
 90   static stackChunkOop continuation_parent_chunk(stackChunkOop chunk);
 91   static oop continuation_scope(oop cont);
 92   static bool is_scope_bottom(oop cont_scope, const frame& fr, const RegisterMap* map);
 93 
 94   static void set_cont_fastpath_thread_state(JavaThread* thread);
 95 
 96   static ContinuationEntry* get_continuation_entry_for_continuation(JavaThread* thread, oop cont);
 97 
 98 #ifndef PRODUCT
 99   static void describe(FrameValues &values);
100 #endif
101 
102 private:
103   // declared here as it's used in friend declarations
104   static address oop_address(objArrayOop ref_stack, int ref_sp, int index);
105   static address oop_address(objArrayOop ref_stack, int ref_sp, address stack_address);
106 
107 private:
108   friend class InstanceStackChunkKlass;
109   static void emit_chunk_iterate_event(oop chunk, int num_frames, int num_oops);
110 
111 #ifdef ASSERT
112 public:
113   static bool debug_is_stack_chunk(Klass* klass);
114   static bool debug_is_stack_chunk(oop obj);
115   static bool debug_is_continuation(Klass* klass);
116   static bool debug_is_continuation(oop obj);
117   static bool debug_verify_continuation(oop cont);
118   static void debug_print_continuation(oop cont, outputStream* st = NULL);
119   static bool debug_is_continuation_run_frame(const frame& f);
120 #endif
121 };
122 
123 // Metadata stored in the continuation entry frame
124 class ContinuationEntry {
125 public:
126 #ifdef ASSERT
127   int cookie;
128   static ByteSize cookie_offset() { return byte_offset_of(ContinuationEntry, cookie); }
129   void verify_cookie() { assert(this->cookie == 0x1234, ""); }
130 #endif
131 
132 public:
133   static int return_pc_offset; // friend gen_continuation_enter
134   static void set_enter_nmethod(nmethod* nm); // friend SharedRuntime::generate_native_wrapper
135 
136 private:
137   static nmethod* continuation_enter;
138   static address return_pc;
139 
140 private:
141   ContinuationEntry* _parent;
142   oopDesc* _cont;
143   oopDesc* _chunk;
144   int _argsize;
145   intptr_t* _parent_cont_fastpath;
146   int _parent_held_monitor_count;
147 
148 public:
149   static ByteSize parent_offset()   { return byte_offset_of(ContinuationEntry, _parent); }
150   static ByteSize cont_offset()     { return byte_offset_of(ContinuationEntry, _cont); }
151   static ByteSize chunk_offset()    { return byte_offset_of(ContinuationEntry, _chunk); }
152   static ByteSize argsize_offset()  { return byte_offset_of(ContinuationEntry, _argsize); }
153 
154   static void setup_oopmap(OopMap* map) {
155     map->set_oop(VMRegImpl::stack2reg(in_bytes(cont_offset())  / VMRegImpl::stack_slot_size));
156     map->set_oop(VMRegImpl::stack2reg(in_bytes(chunk_offset()) / VMRegImpl::stack_slot_size));
157   }
158 
159   static ByteSize parent_cont_fastpath_offset()      { return byte_offset_of(ContinuationEntry, _parent_cont_fastpath); }
160   static ByteSize parent_held_monitor_count_offset() { return byte_offset_of(ContinuationEntry, _parent_held_monitor_count); }
161 
162 public:
163   static size_t size() { return align_up((int)sizeof(ContinuationEntry), 2*wordSize); }
164 
165   ContinuationEntry* parent() { return _parent; }
166 
167   static address entry_pc() { return return_pc; }
168   intptr_t* entry_sp() { return (intptr_t*)this; }
169   intptr_t* entry_fp() { return *(intptr_t**)((address)this + size()); } // TODO PD
170 
171   int argsize() { return _argsize; }
172   void set_argsize(int value) { _argsize = value; }
173 
174   intptr_t* parent_cont_fastpath() { return _parent_cont_fastpath; }
175   void set_parent_cont_fastpath(intptr_t* x) { _parent_cont_fastpath = x; }
176 
177   static ContinuationEntry* from_frame(const frame& f);
178   frame to_frame();
179   void update_register_map(RegisterMap* map);
180 
181   intptr_t* bottom_sender_sp() {
182     intptr_t* sp = entry_sp() - argsize();
183 #ifdef _LP64
184     sp = align_down(sp, 16);
185 #endif
186     return sp;
187   }
188 
189   oop continuation() {
190     oop snapshot = _cont;
191     return NativeAccess<>::oop_load(&snapshot);
192   }
193 
194   oop cont_oop() { return this != NULL ? continuation() : (oop)NULL; }
195   oop cont_raw() { return _cont; }
196   oop chunk()        { return _chunk; }
197   void set_continuation(oop c) { _cont = c;  }
198   void set_chunk(oop c)        { _chunk = c; }
199 
200 #ifdef ASSERT
201   static bool assert_entry_frame_laid_out(JavaThread* thread);
202 #endif
203 };
204 
205 void CONT_RegisterNativeMethods(JNIEnv *env, jclass cls);
206 
207 #endif // SHARE_VM_RUNTIME_CONTINUATION_HPP