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 #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(CodeBuffer& cb); 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 #ifdef _LP64 101 class C2HandleAnonOMOwnerStub : public C2CodeStub { 102 private: 103 Register _monitor; 104 Register _tmp; 105 public: 106 C2HandleAnonOMOwnerStub(Register monitor, Register tmp = noreg) : C2CodeStub(), 107 _monitor(monitor), _tmp(tmp) {} 108 Register monitor() { return _monitor; } 109 Register tmp() { return _tmp; } 110 int max_size() const; 111 void emit(C2_MacroAssembler& masm); 112 }; 113 #endif 114 115 //-----------------------------C2GeneralStub----------------------------------- 116 // A generalized stub that can be used to implement an arbitrary stub in a 117 // type-safe manner. An example: 118 // 119 // Register dst; XMMRegister src; 120 // // The lambda defining how the code is emitted in the stub 121 // auto slowpath = [](C2_MacroAssembler& masm, C2GeneralStub<Register, XMMRegister>& stub) { 122 // // Access the saved data in a type safe manner 123 // Register dst = stub.get<0>(); 124 // XMMRegister src = stub.get<1>(); 125 // masm.bind(stub.entry()); 126 // ... 127 // masm.jump(stub.continuation()); 128 // } 129 // // Create a stub with 2 data fields being dst and src, a max size of 4 bytes 130 // // and predefined emission function 131 // auto stub = C2CodeStub::make<Register, XMMRegister>(dst, src, 4, slowpath); 132 // __ jump_conditional(stub->entry()); 133 // ... 134 // __ bind(stub->continuation()); 135 // 136 template <class... Ts> 137 class C2GeneralStub : public C2CodeStub { 138 private: 139 Tuple<Ts...> _data; 140 int _max_size; 141 void (*_emit)(C2_MacroAssembler&, C2GeneralStub&); 142 143 constexpr C2GeneralStub(const Ts&... data, int max_size, 144 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) 145 : _data(data...), _max_size(max_size), _emit(emit) {} 146 147 friend C2CodeStub; 148 public: 149 template <std::size_t I> 150 constexpr const auto& data() const { return _data.template get<I>(); } 151 152 int max_size() const { return _max_size; } 153 void emit(C2_MacroAssembler& masm) { _emit(masm, *this); } 154 }; 155 156 template <class... Ts> 157 C2GeneralStub<Ts...>* C2CodeStub::make(const Ts&... data, int max_size, 158 void (*emit)(C2_MacroAssembler&, C2GeneralStub<Ts...>&)) { 159 auto stub = new (Compile::current()->comp_arena()) C2GeneralStub<Ts...>(data..., max_size, emit); 160 stub->add_to_stub_list(); 161 return stub; 162 } 163 164 #endif // SHARE_OPTO_C2_CODESTUBS_HPP