1 /* 2 * Copyright (c) 2022, 2024, 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 #include "asm/assembler.hpp" 26 #include "asm/codeBuffer.hpp" 27 #include "memory/allocation.hpp" 28 #include "opto/c2_MacroAssembler.hpp" 29 #include "opto/compile.hpp" 30 #include "opto/output.hpp" 31 #include "utilities/growableArray.hpp" 32 #include "utilities/tuple.hpp" 33 34 #ifndef SHARE_OPTO_C2_CODESTUBS_HPP 35 #define SHARE_OPTO_C2_CODESTUBS_HPP 36 37 template <class... Ts> 38 class C2GeneralStub; 39 40 class C2CodeStub : public ArenaObj { 41 private: 42 Label _entry; 43 Label _continuation; 44 45 void add_to_stub_list(); 46 protected: 47 C2CodeStub() : 48 _entry(), 49 _continuation() {} 50 51 public: 52 Label& entry() { return _entry; } 53 Label& continuation() { return _continuation; } 54 55 virtual void emit(C2_MacroAssembler& masm) = 0; 56 virtual int max_size() const = 0; 57 58 template <class... Ts> 59 static C2GeneralStub<Ts...>* make(const Ts&... data, int max_size, 60 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)); 61 }; 62 63 class C2CodeStubList { 64 private: 65 GrowableArray<C2CodeStub*> _stubs; 66 67 public: 68 C2CodeStubList(); 69 70 void add_stub(C2CodeStub* stub) { _stubs.append(stub); } 71 void emit(C2_MacroAssembler& masm); 72 }; 73 74 class C2SafepointPollStub : public C2CodeStub { 75 private: 76 uintptr_t _safepoint_offset; 77 78 public: 79 C2SafepointPollStub(uintptr_t safepoint_offset) : 80 _safepoint_offset(safepoint_offset) {} 81 int max_size() const; 82 void emit(C2_MacroAssembler& masm); 83 }; 84 85 // We move non-hot code of the nmethod entry barrier to an out-of-line stub 86 class C2EntryBarrierStub: public C2CodeStub { 87 private: 88 Label _guard; // Used on AArch64 and RISCV 89 90 public: 91 C2EntryBarrierStub() : C2CodeStub(), 92 _guard() {} 93 94 Label& guard() { return _guard; } 95 96 int max_size() const; 97 void emit(C2_MacroAssembler& masm); 98 }; 99 100 class C2FastUnlockLightweightStub : public C2CodeStub { 101 private: 102 Register _obj; 103 Register _mark; 104 Register _t; 105 Register _thread; 106 Label _push_and_slow_path; 107 Label _check_successor; 108 Label _unlocked_continuation; 109 public: 110 C2FastUnlockLightweightStub(Register obj, Register mark, Register t, Register thread) : C2CodeStub(), 111 _obj(obj), _mark(mark), _t(t), _thread(thread) {} 112 int max_size() const; 113 void emit(C2_MacroAssembler& masm); 114 Label& push_and_slow_path() { return _push_and_slow_path; } 115 Label& check_successor() { return _check_successor; } 116 Label& unlocked_continuation() { return _unlocked_continuation; } 117 Label& slow_path_continuation() { return continuation(); } 118 }; 119 120 #ifdef _LP64 121 class C2HandleAnonOMOwnerStub : public C2CodeStub { 122 private: 123 Register _monitor; 124 Register _tmp; 125 public: 126 C2HandleAnonOMOwnerStub(Register monitor, Register tmp = noreg) : C2CodeStub(), 127 _monitor(monitor), _tmp(tmp) {} 128 Register monitor() { return _monitor; } 129 Register tmp() { return _tmp; } 130 int max_size() const; 131 void emit(C2_MacroAssembler& masm); 132 }; 133 #endif 134 135 //-----------------------------C2GeneralStub----------------------------------- 136 // A generalized stub that can be used to implement an arbitrary stub in a 137 // type-safe manner. An example: 138 // 139 // Register dst; XMMRegister src; 140 // // The lambda defining how the code is emitted in the stub 141 // auto slowpath = [](C2_MacroAssembler& masm, C2GeneralStub<Register, XMMRegister>& stub) { 142 // // Access the saved data in a type safe manner 143 // Register dst = stub.get<0>(); 144 // XMMRegister src = stub.get<1>(); 145 // masm.bind(stub.entry()); 146 // ... 147 // masm.jump(stub.continuation()); 148 // } 149 // // Create a stub with 2 data fields being dst and src, a max size of 4 bytes 150 // // and predefined emission function 151 // auto stub = C2CodeStub::make<Register, XMMRegister>(dst, src, 4, slowpath); 152 // __ jump_conditional(stub->entry()); 153 // ... 154 // __ bind(stub->continuation()); 155 // 156 template <class... Ts> 157 class C2GeneralStub : public C2CodeStub { 158 private: 159 Tuple<Ts...> _data; 160 int _max_size; 161 void (*_emit)(C2_MacroAssembler&, C2GeneralStub&); 162 163 constexpr C2GeneralStub(const Ts&... data, int max_size, 164 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) 165 : _data(data...), _max_size(max_size), _emit(emit) {} 166 167 friend C2CodeStub; 168 public: 169 template <std::size_t I> 170 constexpr const auto& data() const { return _data.template get<I>(); } 171 172 int max_size() const { return _max_size; } 173 void emit(C2_MacroAssembler& masm) { _emit(masm, *this); } 174 }; 175 176 template <class... Ts> 177 C2GeneralStub<Ts...>* C2CodeStub::make(const Ts&... data, int max_size, 178 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) { 179 auto stub = new (Compile::current()->comp_arena()) C2GeneralStub<Ts...>(data..., max_size, emit); 180 stub->add_to_stub_list(); 181 return stub; 182 } 183 184 #endif // SHARE_OPTO_C2_CODESTUBS_HPP