1 /*
  2  * Copyright (c) 1997, 2026, 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 
 65   Method*   volatile _speculated_method;
 66   uintptr_t volatile _speculated_klass;
 67   Klass*             _itable_defc_klass;
 68   Klass*             _itable_refc_klass;
 69   bool               _is_initialized;
 70 
 71   bool is_speculated_klass_unloaded() const;
 72 
 73  public:
 74   // Constructor
 75   CompiledICData();
 76 
 77   // accessors
 78   Klass*    speculated_klass()  const;
 79   Method*   speculated_method() const { return _speculated_method; }
 80   Klass*    itable_defc_klass() const { return _itable_defc_klass; }
 81   Klass*    itable_refc_klass() const { return _itable_refc_klass; }
 82 
 83   static ByteSize speculated_method_offset() { return byte_offset_of(CompiledICData, _speculated_method); }
 84   static ByteSize speculated_klass_offset()  { return byte_offset_of(CompiledICData, _speculated_klass); }
 85 
 86   static ByteSize itable_defc_klass_offset() { return byte_offset_of(CompiledICData, _itable_defc_klass); }
 87   static ByteSize itable_refc_klass_offset() { return byte_offset_of(CompiledICData, _itable_refc_klass); }
 88 
 89   void initialize(CallInfo* call_info, Klass* receiver_klass);
 90 
 91   bool is_initialized()       const { return _is_initialized; }
 92 
 93   // GC Support
 94   void clean_metadata();
 95   void metadata_do(MetadataClosure* cl);
 96 };
 97 
 98 class CompiledIC: public ResourceObj {
 99 private:
100   nmethod* _method;
101   CompiledICData* _data;
102   NativeCall* _call;
103 
104   CompiledIC(RelocIterator* iter);
105 
106   // CompiledICData wrappers
107   void ensure_initialized(CallInfo* call_info, Klass* receiver_klass);
108   bool is_speculated_klass(Klass* receiver_klass);
109 
110   // Inline cache states
111   void set_to_monomorphic(bool caller_is_c1);
112   void set_to_megamorphic(CallInfo* call_info, bool caller_is_c1);
113 
114 public:
115   // conversion (machine PC to CompiledIC*)
116   friend CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
117   friend CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
118   friend CompiledIC* CompiledIC_at(Relocation* call_site);
119   friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
120 
121   CompiledICData* data() const;
122 
123   // State
124   bool is_clean()       const;
125   bool is_monomorphic() const;
126   bool is_megamorphic() const;
127 
128   address end_of_call() const { return _call->return_address(); }
129 
130   // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledICLocker
131   // so you are guaranteed that no patching takes place. The same goes for verify.
132   void set_to_clean();
133   void update(CallInfo* call_info, Klass* receiver_klass, bool caller_is_c1);
134 
135   // GC support
136   void clean_metadata();
137   void metadata_do(MetadataClosure* cl);
138 
139   // Location
140   address instruction_address() const { return _call->instruction_address(); }
141   address destination() const         { return _call->destination(); }
142 
143   // Misc
144   void print()             PRODUCT_RETURN;
145   void verify()            PRODUCT_RETURN;
146 };
147 
148 CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
149 CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
150 CompiledIC* CompiledIC_at(Relocation* call_site);
151 CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
152 
153 //-----------------------------------------------------------------------------
154 // The CompiledDirectCall represents a call to a method in the compiled code
155 //
156 //
157 //           -----<----- Clean ----->-----
158 //          /                             \
159 //         /                               \
160 //    compiled code <------------> interpreted code
161 //
162 //  Clean:            Calls directly to runtime method for fixup
163 //  Compiled code:    Calls directly to compiled code
164 //  Interpreted code: Calls to stub that set Method* reference
165 //
166 //
167 
168 class CompiledDirectCall : public ResourceObj {
169 private:
170   friend class CompiledIC;
171   friend class DirectNativeCallWrapper;
172 
173   // Also used by CompiledIC
174   void set_to_interpreted(const methodHandle& callee, address entry);
175   void verify_mt_safe(const methodHandle& callee, address entry,
176                       NativeMovConstReg* method_holder,
177                       NativeJump*        jump) PRODUCT_RETURN;
178   address instruction_address() const { return _call->instruction_address(); }
179   void set_destination_mt_safe(address dest) { _call->set_destination_mt_safe(dest); }
180 
181   NativeCall* _call;
182 
183   CompiledDirectCall(NativeCall* call) : _call(call) {}
184 
185  public:
186   // Returns null if CodeBuffer::expand fails
187   static address emit_to_interp_stub(MacroAssembler *masm, address mark = nullptr);
188   static int to_interp_stub_size();
189   static int to_trampoline_stub_size();
190   static int reloc_to_interp_stub();
191 
192   static inline CompiledDirectCall* before(address return_addr) {
193     CompiledDirectCall* st = new CompiledDirectCall(nativeCall_before(return_addr));
194     if (VerifyInlineCaches) st->verify();
195     return st;
196   }
197 
198   static inline CompiledDirectCall* at(address native_call) {
199     CompiledDirectCall* st = new CompiledDirectCall(nativeCall_at(native_call));
200     if (VerifyInlineCaches) st->verify();
201     return st;
202   }
203 
204   static inline CompiledDirectCall* at(Relocation* call_site) {
205     return at(call_site->addr());
206   }
207 
208   // Delegation
209   address destination() const { return _call->destination(); }
210   address end_of_call() const { return _call->return_address(); }
211 
212   // Clean static call (will force resolving on next use)
213   void set_to_clean();
214 
215   void set(const methodHandle& callee_method, bool caller_is_c1);
216 
217   // State
218   bool is_clean() const;
219   bool is_call_to_interpreted() const;
220   bool is_call_to_compiled() const;
221 
222   // Stub support
223   static address find_stub_for(address instruction);
224   address find_stub();
225   static void set_stub_to_clean(static_stub_Relocation* static_stub);
226 
227   // Misc.
228   void print()  PRODUCT_RETURN;
229   void verify() PRODUCT_RETURN;
230 };
231 
232 #endif // SHARE_CODE_COMPILEDIC_HPP