1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/code/compiledIC.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,241 @@ 1.4 +/* 1.5 + * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +//----------------------------------------------------------------------------- 1.29 +// The CompiledIC represents a compiled inline cache. 1.30 +// 1.31 +// In order to make patching of the inline cache MT-safe, we only allow the following 1.32 +// transitions (when not at a safepoint): 1.33 +// 1.34 +// 1.35 +// [1] --<-- Clean -->--- [1] 1.36 +// / (null) \ 1.37 +// / \ /-<-\ 1.38 +// / [2] \ / \ 1.39 +// Interpreted ---------> Monomorphic | [3] 1.40 +// (compiledICHolderOop) (klassOop) | 1.41 +// \ / \ / 1.42 +// [4] \ / [4] \->-/ 1.43 +// \->- Megamorphic -<-/ 1.44 +// (methodOop) 1.45 +// 1.46 +// The text in paranteses () refere to the value of the inline cache receiver (mov instruction) 1.47 +// 1.48 +// The numbers in square brackets refere to the kind of transition: 1.49 +// [1]: Initial fixup. Receiver it found from debug information 1.50 +// [2]: Compilation of a method 1.51 +// [3]: Recompilation of a method (note: only entry is changed. The klassOop must stay the same) 1.52 +// [4]: Inline cache miss. We go directly to megamorphic call. 1.53 +// 1.54 +// The class automatically inserts transition stubs (using the InlineCacheBuffer) when an MT-unsafe 1.55 +// transition is made to a stub. 1.56 +// 1.57 +class CompiledIC; 1.58 + 1.59 +class CompiledICInfo { 1.60 + friend class CompiledIC; 1.61 + private: 1.62 + address _entry; // entry point for call 1.63 + Handle _cached_oop; // Value of cached_oop (either in stub or inline cache) 1.64 + bool _is_optimized; // it is an optimized virtual call (i.e., can be statically bound) 1.65 + bool _to_interpreter; // Call it to interpreter 1.66 + public: 1.67 + address entry() const { return _entry; } 1.68 + Handle cached_oop() const { return _cached_oop; } 1.69 + bool is_optimized() const { return _is_optimized; } 1.70 +}; 1.71 + 1.72 +class CompiledIC: public ResourceObj { 1.73 + friend class InlineCacheBuffer; 1.74 + friend class ICStub; 1.75 + 1.76 + 1.77 + private: 1.78 + NativeCall* _ic_call; // the call instruction 1.79 + oop* _oop_addr; // patchable oop cell for this IC 1.80 + RelocIterator _oops; // iteration over any and all set-oop instructions 1.81 + bool _is_optimized; // an optimized virtual call (i.e., no compiled IC) 1.82 + 1.83 + CompiledIC(NativeCall* ic_call); 1.84 + CompiledIC(Relocation* ic_reloc); // Must be of virtual_call_type/opt_virtual_call_type 1.85 + 1.86 + // low-level inline-cache manipulation. Cannot be accessed directly, since it might not be MT-safe 1.87 + // to change an inline-cache. These changes the underlying inline-cache directly. They *newer* make 1.88 + // changes to a transition stub. 1.89 + void set_ic_destination(address entry_point); 1.90 + void set_cached_oop(oop cache); 1.91 + 1.92 + // Reads the location of the transition stub. This will fail with an assertion, if no transition stub is 1.93 + // associated with the inline cache. 1.94 + address stub_address() const; 1.95 + bool is_in_transition_state() const; // Use InlineCacheBuffer 1.96 + 1.97 + public: 1.98 + // conversion (machine PC to CompiledIC*) 1.99 + friend CompiledIC* CompiledIC_before(address return_addr); 1.100 + friend CompiledIC* CompiledIC_at(address call_site); 1.101 + friend CompiledIC* CompiledIC_at(Relocation* call_site); 1.102 + 1.103 + // Return the cached_oop/destination associated with this inline cache. If the cache currently points 1.104 + // to a transition stub, it will read the values from the transition stub. 1.105 + oop cached_oop() const; 1.106 + address ic_destination() const; 1.107 + 1.108 + bool is_optimized() const { return _is_optimized; } 1.109 + 1.110 + // State 1.111 + bool is_clean() const; 1.112 + bool is_megamorphic() const; 1.113 + bool is_call_to_compiled() const; 1.114 + bool is_call_to_interpreted() const; 1.115 + 1.116 + address end_of_call() { return _ic_call->return_address(); } 1.117 + 1.118 + // MT-safe patching of inline caches. Note: Only safe to call is_xxx when holding the CompiledIC_ock 1.119 + // so you are guaranteed that no patching takes place. The same goes for verify. 1.120 + // 1.121 + // Note: We do not provide any direct access to the stub code, to prevent parts of the code 1.122 + // to manipulate the inline cache in MT-unsafe ways. 1.123 + // 1.124 + // They all takes a TRAP argument, since they can cause a GC if the inline-cache buffer is full. 1.125 + // 1.126 + void set_to_clean(); // Can only be called during a safepoint operation 1.127 + void set_to_monomorphic(const CompiledICInfo& info); 1.128 + void set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); 1.129 + 1.130 + static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass, 1.131 + bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS); 1.132 + 1.133 + // Location 1.134 + address instruction_address() const { return _ic_call->instruction_address(); } 1.135 + 1.136 + // Misc 1.137 + void print() PRODUCT_RETURN; 1.138 + void print_compiled_ic() PRODUCT_RETURN; 1.139 + void verify() PRODUCT_RETURN; 1.140 +}; 1.141 + 1.142 +inline CompiledIC* CompiledIC_before(address return_addr) { 1.143 + CompiledIC* c_ic = new CompiledIC(nativeCall_before(return_addr)); 1.144 + c_ic->verify(); 1.145 + return c_ic; 1.146 +} 1.147 + 1.148 +inline CompiledIC* CompiledIC_at(address call_site) { 1.149 + CompiledIC* c_ic = new CompiledIC(nativeCall_at(call_site)); 1.150 + c_ic->verify(); 1.151 + return c_ic; 1.152 +} 1.153 + 1.154 +inline CompiledIC* CompiledIC_at(Relocation* call_site) { 1.155 + CompiledIC* c_ic = new CompiledIC(call_site); 1.156 + c_ic->verify(); 1.157 + return c_ic; 1.158 +} 1.159 + 1.160 + 1.161 +//----------------------------------------------------------------------------- 1.162 +// The CompiledStaticCall represents a call to a static method in the compiled 1.163 +// 1.164 +// Transition diagram of a static call site is somewhat simpler than for an inlined cache: 1.165 +// 1.166 +// 1.167 +// -----<----- Clean ----->----- 1.168 +// / \ 1.169 +// / \ 1.170 +// compilled code <------------> interpreted code 1.171 +// 1.172 +// Clean: Calls directly to runtime method for fixup 1.173 +// Compiled code: Calls directly to compiled code 1.174 +// Interpreted code: Calls to stub that set methodOop reference 1.175 +// 1.176 +// 1.177 +class CompiledStaticCall; 1.178 + 1.179 +class StaticCallInfo { 1.180 + private: 1.181 + address _entry; // Entrypoint 1.182 + methodHandle _callee; // Callee (used when calling interpreter) 1.183 + bool _to_interpreter; // call to interpreted method (otherwise compiled) 1.184 + 1.185 + friend class CompiledStaticCall; 1.186 + public: 1.187 + address entry() const { return _entry; } 1.188 + methodHandle callee() const { return _callee; } 1.189 +}; 1.190 + 1.191 + 1.192 +class CompiledStaticCall: public NativeCall { 1.193 + friend class CompiledIC; 1.194 + 1.195 + // Also used by CompiledIC 1.196 + void set_to_interpreted(methodHandle callee, address entry); 1.197 + bool is_optimized_virtual(); 1.198 + 1.199 + public: 1.200 + friend CompiledStaticCall* compiledStaticCall_before(address return_addr); 1.201 + friend CompiledStaticCall* compiledStaticCall_at(address native_call); 1.202 + friend CompiledStaticCall* compiledStaticCall_at(Relocation* call_site); 1.203 + 1.204 + // State 1.205 + bool is_clean() const; 1.206 + bool is_call_to_compiled() const; 1.207 + bool is_call_to_interpreted() const; 1.208 + 1.209 + // Clean static call (will force resolving on next use) 1.210 + void set_to_clean(); 1.211 + 1.212 + // Set state. The entry must be the same, as computed by compute_entry. 1.213 + // Computation and setting is split up, since the actions are separate during 1.214 + // a OptoRuntime::resolve_xxx. 1.215 + void set(const StaticCallInfo& info); 1.216 + 1.217 + // Compute entry point given a method 1.218 + static void compute_entry(methodHandle m, StaticCallInfo& info); 1.219 + 1.220 + // Stub support 1.221 + address find_stub(); 1.222 + static void set_stub_to_clean(static_stub_Relocation* static_stub); 1.223 + 1.224 + // Misc. 1.225 + void print() PRODUCT_RETURN; 1.226 + void verify() PRODUCT_RETURN; 1.227 +}; 1.228 + 1.229 + 1.230 +inline CompiledStaticCall* compiledStaticCall_before(address return_addr) { 1.231 + CompiledStaticCall* st = (CompiledStaticCall*)nativeCall_before(return_addr); 1.232 + st->verify(); 1.233 + return st; 1.234 +} 1.235 + 1.236 +inline CompiledStaticCall* compiledStaticCall_at(address native_call) { 1.237 + CompiledStaticCall* st = (CompiledStaticCall*)native_call; 1.238 + st->verify(); 1.239 + return st; 1.240 +} 1.241 + 1.242 +inline CompiledStaticCall* compiledStaticCall_at(Relocation* call_site) { 1.243 + return compiledStaticCall_at(call_site->addr()); 1.244 +}