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 _slow_path; 107 Label _push_and_slow_path; 108 Label _check_successor; 109 Label _unlocked_continuation; 110 public: 111 C2FastUnlockLightweightStub(Register obj, Register mark, Register t, Register thread) : C2CodeStub(), 112 _obj(obj), _mark(mark), _t(t), _thread(thread) {} 113 int max_size() const; 114 void emit(C2_MacroAssembler& masm); 115 Label& slow_path() { return _slow_path; } 116 Label& push_and_slow_path() { return _push_and_slow_path; } 117 Label& check_successor() { return _check_successor; } 118 Label& unlocked_continuation() { return _unlocked_continuation; } 119 Label& slow_path_continuation() { return continuation(); } 120 }; 121 122 #ifdef _LP64 123 class C2HandleAnonOMOwnerStub : public C2CodeStub { 124 private: 125 Register _monitor; 126 Register _tmp; 127 public: 128 C2HandleAnonOMOwnerStub(Register monitor, Register tmp = noreg) : C2CodeStub(), 129 _monitor(monitor), _tmp(tmp) {} 130 Register monitor() { return _monitor; } 131 Register tmp() { return _tmp; } 132 int max_size() const; 133 void emit(C2_MacroAssembler& masm); 134 }; 135 #endif // _LP64 136 137 //-----------------------------C2GeneralStub----------------------------------- 138 // A generalized stub that can be used to implement an arbitrary stub in a 139 // type-safe manner. An example: 140 // 141 // Register dst; XMMRegister src; 142 // // The lambda defining how the code is emitted in the stub 143 // auto slowpath = [](C2_MacroAssembler& masm, C2GeneralStub<Register, XMMRegister>& stub) { 144 // // Access the saved data in a type safe manner 145 // Register dst = stub.get<0>(); 146 // XMMRegister src = stub.get<1>(); 147 // masm.bind(stub.entry()); 148 // ... 149 // masm.jump(stub.continuation()); 150 // } 151 // // Create a stub with 2 data fields being dst and src, a max size of 4 bytes 152 // // and predefined emission function 153 // auto stub = C2CodeStub::make<Register, XMMRegister>(dst, src, 4, slowpath); 154 // __ jump_conditional(stub->entry()); 155 // ... 156 // __ bind(stub->continuation()); 157 // 158 template <class... Ts> 159 class C2GeneralStub : public C2CodeStub { 160 private: 161 Tuple<Ts...> _data; 162 int _max_size; 163 void (*_emit)(C2_MacroAssembler&, C2GeneralStub&); 164 165 constexpr C2GeneralStub(const Ts&... data, int max_size, 166 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) 167 : _data(data...), _max_size(max_size), _emit(emit) {} 168 169 friend C2CodeStub; 170 public: 171 template <std::size_t I> 172 constexpr const auto& data() const { return _data.template get<I>(); } 173 174 int max_size() const { return _max_size; } 175 void emit(C2_MacroAssembler& masm) { _emit(masm, *this); } 176 }; 177 178 template <class... Ts> 179 C2GeneralStub<Ts...>* C2CodeStub::make(const Ts&... data, int max_size, 180 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) { 181 auto stub = new (Compile::current()->comp_arena()) C2GeneralStub<Ts...>(data..., max_size, emit); 182 stub->add_to_stub_list(); 183 return stub; 184 } 185 186 #endif // SHARE_OPTO_C2_CODESTUBS_HPP