1 /* 2 * Copyright (c) 1997, 2005, 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 //----------------------------------------------------------------------------- 26 // The CompiledIC represents a compiled inline cache. 27 // 28 // In order to make patching of the inline cache MT-safe, we only allow the following 29 // transitions (when not at a safepoint): 30 // 31 // 32 // [1] --<-- Clean -->--- [1] 33 // / (null) \ 34 // / \ /-<-\ 35 // / [2] \ / \ 36 // Interpreted ---------> Monomorphic | [3] 37 // (compiledICHolderOop) (klassOop) | 38 // \ / \ / 39 // [4] \ / [4] \->-/ 40 // \->- Megamorphic -<-/ 41 // (methodOop) 42 // 43 // The text in paranteses () refere to the value of the inline cache receiver (mov instruction) 44 // 45 // The numbers in square brackets refere to the kind of transition: 46 // [1]: Initial fixup. Receiver it found from debug information 47 // [2]: Compilation of a method 48 // [3]: Recompilation of a method (note: only entry is changed. The klassOop must stay the same) 49 // [4]: Inline cache miss. We go directly to megamorphic call. 50 // 51 // The class automatically inserts transition stubs (using the InlineCacheBuffer) when an MT-unsafe 52 // transition is made to a stub. 53 // 54 class CompiledIC; 55 56 class CompiledICInfo { 57 friend class CompiledIC; 58 private: 59 address _entry; // entry point for call 60 Handle _cached_oop; // Value of cached_oop (either in stub or inline cache) 61 bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound) 62 bool _to_interpreter; // Call it to interpreter 63 public: 64 address entry() const { return _entry; } 65 Handle cached_oop() const { return _cached_oop; } 66 bool is_optimized() const { return _is_optimized; } 67 }; 68 69 class CompiledIC: public ResourceObj { 70 friend class InlineCacheBuffer; 71 friend class ICStub; 72 73 74 private: 75 NativeCall* _ic_call; // the call instruction 76 oop* _oop_addr; // patchable oop cell for this IC 77 RelocIterator _oops; // iteration over any and all set-oop instructions 78 bool _is_optimized; // an optimized virtual call (i.e., no compiled IC) 79 80 CompiledIC(NativeCall* ic_call); 81 CompiledIC(Relocation* ic_reloc); // Must be of virtual_call_type/opt_virtual_call_type 82 83 // low-level inline-cache manipulation. Cannot be accessed directly, since it might not be MT-safe 84 // to change an inline-cache. These changes the underlying inline-cache directly. They *newer* make 85 // changes to a transition stub. 86 void set_ic_destination(address entry_point); 87 void set_cached_oop(oop cache); 88 89 // Reads the location of the transition stub. This will fail with an assertion, if no transition stub is 90 // associated with the inline cache. 91 address stub_address() const; 92 bool is_in_transition_state() const; // Use InlineCacheBuffer 93 94 public: 95 // conversion (machine PC to CompiledIC*) 96 friend CompiledIC* CompiledIC_before(address return_addr); 97 friend CompiledIC* CompiledIC_at(address call_site); 98 friend CompiledIC* CompiledIC_at(Relocation* call_site); 99 100 // Return the cached_oop/destination associated with this inline cache. If the cache currently points 101 // to a transition stub, it will read the values from the transition stub. 102 oop cached_oop() const; 103 address ic_destination() const; 104 105 bool is_optimized() const { return _is_optimized; } 106 107 // State 108 bool is_clean() const; 109 bool is_megamorphic() const; 110 bool is_call_to_compiled() const; 111 bool is_call_to_interpreted() const; 112 113 address end_of_call() { return _ic_call->return_address(); } 114 115 // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledIC_ock 116 // so you are guaranteed that no patching takes place. The same goes for verify. 117 // 118 // Note: We do not provide any direct access to the stub code, to prevent parts of the code 119 // to manipulate the inline cache in MT-unsafe ways. 120 // 121 // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full. 122 // 123 void set_to_clean(); // Can only be called during a safepoint operation 124 void set_to_monomorphic(const CompiledICInfo& info); 125 void set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); 126 127 static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass, 128 bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS); 129 130 // Location 131 address instruction_address() const { return _ic_call->instruction_address(); } 132 133 // Misc 134 void print() PRODUCT_RETURN; 135 void print_compiled_ic() PRODUCT_RETURN; 136 void verify() PRODUCT_RETURN; 137 }; 138 139 inline CompiledIC* CompiledIC_before(address return_addr) { 140 CompiledIC* c_ic = new CompiledIC(nativeCall_before(return_addr)); 141 c_ic->verify(); 142 return c_ic; 143 } 144 145 inline CompiledIC* CompiledIC_at(address call_site) { 146 CompiledIC* c_ic = new CompiledIC(nativeCall_at(call_site)); 147 c_ic->verify(); 148 return c_ic; 149 } 150 151 inline CompiledIC* CompiledIC_at(Relocation* call_site) { 152 CompiledIC* c_ic = new CompiledIC(call_site); 153 c_ic->verify(); 154 return c_ic; 155 } 156 157 158 //----------------------------------------------------------------------------- 159 // The CompiledStaticCall represents a call to a static method in the compiled 160 // 161 // Transition diagram of a static call site is somewhat simpler than for an inlined cache: 162 // 163 // 164 // -----<----- Clean ----->----- 165 // / \ 166 // / \ 167 // compilled code <------------> interpreted code 168 // 169 // Clean: Calls directly to runtime method for fixup 170 // Compiled code: Calls directly to compiled code 171 // Interpreted code: Calls to stub that set methodOop reference 172 // 173 // 174 class CompiledStaticCall; 175 176 class StaticCallInfo { 177 private: 178 address _entry; // Entrypoint 179 methodHandle _callee; // Callee (used when calling interpreter) 180 bool _to_interpreter; // call to interpreted method (otherwise compiled) 181 182 friend class CompiledStaticCall; 183 public: 184 address entry() const { return _entry; } 185 methodHandle callee() const { return _callee; } 186 }; 187 188 189 class CompiledStaticCall: public NativeCall { 190 friend class CompiledIC; 191 192 // Also used by CompiledIC 193 void set_to_interpreted(methodHandle callee, address entry); 194 bool is_optimized_virtual(); 195 196 public: 197 friend CompiledStaticCall* compiledStaticCall_before(address return_addr); 198 friend CompiledStaticCall* compiledStaticCall_at(address native_call); 199 friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site); 200 201 // State 202 bool is_clean() const; 203 bool is_call_to_compiled() const; 204 bool is_call_to_interpreted() const; 205 206 // Clean static call (will force resolving on next use) 207 void set_to_clean(); 208 209 // Set state. The entry must be the same, as computed by compute_entry. 210 // Computation and setting is split up, since the actions are separate during 211 // a OptoRuntime::resolve_xxx. 212 void set(const StaticCallInfo& info); 213 214 // Compute entry point given a method 215 static void compute_entry(methodHandle m, StaticCallInfo& info); 216 217 // Stub support 218 address find_stub(); 219 static void set_stub_to_clean(static_stub_Relocation* static_stub); 220 221 // Misc. 222 void print() PRODUCT_RETURN; 223 void verify() PRODUCT_RETURN; 224 }; 225 226 227 inline CompiledStaticCall* compiledStaticCall_before(address return_addr) { 228 CompiledStaticCall* st = (CompiledStaticCall*)nativeCall_before(return_addr); 229 st->verify(); 230 return st; 231 } 232 233 inline CompiledStaticCall* compiledStaticCall_at(address native_call) { 234 CompiledStaticCall* st = (CompiledStaticCall*)native_call; 235 st->verify(); 236 return st; 237 } 238 239 inline CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) { 240 return compiledStaticCall_at(call_site->addr()); 241 }