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