1 /*
  2  * Copyright (c) 1997, 2023, 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 CompiledMethod;
 43 
 44 class CompiledICLocker: public StackObj {
 45   CompiledMethod* _method;
 46   CompiledICProtectionBehaviour* _behaviour;
 47   bool _locked;
 48   NoSafepointVerifier _nsv;
 49 
 50 public:
 51   CompiledICLocker(CompiledMethod* method);
 52   ~CompiledICLocker();
 53   static bool is_safe(CompiledMethod* method);
 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   CompiledMethod* _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(CompiledMethod* nm, address return_addr);
118   friend CompiledIC* CompiledIC_at(CompiledMethod* 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(CompiledMethod* nm, address return_addr);
150 CompiledIC* CompiledIC_at(CompiledMethod* 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(CodeBuffer &cbuf, 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     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     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