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
--- EOF ---