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* 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 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(bool caller_is_c1); 113 void set_to_megamorphic(CallInfo* call_info, bool caller_is_c1); 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, bool caller_is_c1); 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 // compiled 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 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, bool caller_is_c1); 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