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