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