1 /*
2 * Copyright (c) 1997, 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 #ifndef SHARE_CODE_COMPILEDIC_HPP
26 #define SHARE_CODE_COMPILEDIC_HPP
27
28 #include "code/nativeInst.hpp"
29 #include "interpreter/linkResolver.hpp"
30 #include "runtime/safepointVerifiers.hpp"
31
32 //-----------------------------------------------------------------------------
33 // The CompiledIC represents a compiled inline cache.
34 //
35 // It's safe to transition from any state to any state. Typically an inline cache starts
36 // in the clean state, meaning it will resolve the call when called. Then it typically
37 // transitions to monomorphic, assuming the first dynamic receiver will be the only one
38 // observed. If that speculation fails, we transition to megamorphic.
39 //
40 class CompiledIC;
41 class CompiledICProtectionBehaviour;
42 class nmethod;
43
44 class CompiledICLocker: public StackObj {
45 nmethod* _method;
46 CompiledICProtectionBehaviour* _behaviour;
47 bool _locked;
48 NoSafepointVerifier _nsv;
49
50 public:
51 CompiledICLocker(nmethod* method);
52 ~CompiledICLocker();
53 static bool is_safe(nmethod* nm);
54 static bool is_safe(address code);
55 };
56
57 // A CompiledICData is a helper object for the inline cache implementation.
58 // It comprises:
59 // (1) The first receiver klass and its selected method
60 // (2) Itable call metadata
61
62 class CompiledICData : public CHeapObj<mtCode> {
63 friend class VMStructs;
64 friend class JVMCIVMStructs;
65
66 Method* volatile _speculated_method;
67 uintptr_t volatile _speculated_klass;
68 Klass* _itable_defc_klass;
69 Klass* _itable_refc_klass;
70 bool _is_initialized;
71
72 bool is_speculated_klass_unloaded() const;
73
74 public:
75 // Constructor
76 CompiledICData();
77
78 // accessors
79 Klass* speculated_klass() const;
80 Method* speculated_method() const { return _speculated_method; }
81 Klass* itable_defc_klass() const { return _itable_defc_klass; }
82 Klass* itable_refc_klass() const { return _itable_refc_klass; }
83
84 static ByteSize speculated_method_offset() { return byte_offset_of(CompiledICData, _speculated_method); }
85 static ByteSize speculated_klass_offset() { return byte_offset_of(CompiledICData, _speculated_klass); }
86
87 static ByteSize itable_defc_klass_offset() { return byte_offset_of(CompiledICData, _itable_defc_klass); }
88 static ByteSize itable_refc_klass_offset() { return byte_offset_of(CompiledICData, _itable_refc_klass); }
89
90 void initialize(CallInfo* call_info, Klass* receiver_klass);
91
92 bool is_initialized() const { return _is_initialized; }
93
94 // GC Support
95 void clean_metadata();
96 void metadata_do(MetadataClosure* cl);
97 };
98
99 class CompiledIC: public ResourceObj {
100 private:
101 nmethod* _method;
102 CompiledICData* _data;
103 NativeCall* _call;
104
105 CompiledIC(RelocIterator* iter);
106
107 // CompiledICData wrappers
108 void ensure_initialized(CallInfo* call_info, Klass* receiver_klass);
109 bool is_speculated_klass(Klass* receiver_klass);
110
111 // Inline cache states
112 void set_to_monomorphic();
113 void set_to_megamorphic(CallInfo* call_info);
114
115 public:
116 // conversion (machine PC to CompiledIC*)
117 friend CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
118 friend CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
119 friend CompiledIC* CompiledIC_at(Relocation* call_site);
120 friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
121
122 CompiledICData* data() const;
123
124 // State
125 bool is_clean() const;
126 bool is_monomorphic() const;
127 bool is_megamorphic() const;
128
129 address end_of_call() const { return _call->return_address(); }
130
131 // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledICLocker
132 // so you are guaranteed that no patching takes place. The same goes for verify.
133 void set_to_clean();
134 void update(CallInfo* call_info, Klass* receiver_klass);
135
136 // GC support
137 void clean_metadata();
138 void metadata_do(MetadataClosure* cl);
139
140 // Location
141 address instruction_address() const { return _call->instruction_address(); }
142 address destination() const { return _call->destination(); }
143
144 // Misc
145 void print() PRODUCT_RETURN;
146 void verify() PRODUCT_RETURN;
147 };
148
149 CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
150 CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
151 CompiledIC* CompiledIC_at(Relocation* call_site);
152 CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
153
154 //-----------------------------------------------------------------------------
155 // The CompiledDirectCall represents a call to a method in the compiled code
156 //
157 //
158 // -----<----- Clean ----->-----
159 // / \
160 // / \
161 // compilled code <------------> interpreted code
162 //
163 // Clean: Calls directly to runtime method for fixup
164 // Compiled code: Calls directly to compiled code
165 // Interpreted code: Calls to stub that set Method* reference
166 //
167 //
168
169 class CompiledDirectCall : public ResourceObj {
170 private:
171 friend class CompiledIC;
172 friend class DirectNativeCallWrapper;
173
174 // Also used by CompiledIC
175 void set_to_interpreted(const methodHandle& callee, address entry);
176 void verify_mt_safe(const methodHandle& callee, address entry,
177 NativeMovConstReg* method_holder,
178 NativeJump* jump) PRODUCT_RETURN;
179 address instruction_address() const { return _call->instruction_address(); }
180 void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
181
182 NativeCall* _call;
183
184 CompiledDirectCall(NativeCall* call) : _call(call) {}
185
186 public:
187 // Returns null if CodeBuffer::expand fails
188 static address emit_to_interp_stub(MacroAssembler *masm, address mark = nullptr);
189 static int to_interp_stub_size();
190 static int to_trampoline_stub_size();
191 static int reloc_to_interp_stub();
192
193 static inline CompiledDirectCall* before(address return_addr) {
194 CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr));
195 if (VerifyInlineCaches) st->verify();
196 return st;
197 }
198
199 static inline CompiledDirectCall* at(address native_call) {
200 CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call));
201 if (VerifyInlineCaches) st->verify();
202 return st;
203 }
204
205 static inline CompiledDirectCall* at(Relocation* call_site) {
206 return at(call_site->addr());
207 }
208
209 // Delegation
210 address destination() const { return _call->destination(); }
211 address end_of_call() const { return _call->return_address(); }
212
213 // Clean static call (will force resolving on next use)
214 void set_to_clean();
215
216 void set(const methodHandle& callee_method);
217
218 // State
219 bool is_clean() const;
220 bool is_call_to_interpreted() const;
221 bool is_call_to_compiled() const;
222
223 // Stub support
224 static address find_stub_for(address instruction);
225 address find_stub();
226 static void set_stub_to_clean(static_stub_Relocation* static_stub);
227
228 // Misc.
229 void print() PRODUCT_RETURN;
230 void verify() PRODUCT_RETURN;
231 };
232
233 #endif // SHARE_CODE_COMPILEDIC_HPP