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