00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.23 $ */ 00002 /* Copyright (c) 2006, Sun Microsystems, Inc. 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 00006 following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 00010 disclaimer in the documentation and/or other materials provided with the distribution. 00011 * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 00012 from this software without specific prior written permission. 00013 00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 00020 00021 00022 */ 00023 00024 #ifdef DELTA_COMPILER 00025 00026 // ICs describe the interface to a send in an nmethod. 00027 // A IC can either describe: 00028 // - an inline cache for a Delta send (isDeltaSend() == true), or 00029 // - a primitive call (isPrimCall() == true). 00030 // 00031 // 00032 // The memory layout of a Delta send (inline cache) is: 00033 // (offsets from return address) 00034 // -5: call { _icLookupStub (if not filled) 00035 // | nmethod address (if filled with compiled method) 00036 // | pic entry point} (if filled with PIC/MIC) 00037 // <--- CompiledIC* pointers point here 00038 // 0: test reg, <--- dummy test instruction used to hold ic info 00039 // 1: ic info 00040 // 5: ... <--- first instruction after move 00041 // 00042 // 00043 // The memory layout of a primitive call is (offsets from return address): 00044 // 00045 // -5: call ... 00046 // <--- PrimitiveIC* pointers point here 00047 // 0: test reg, <--- dummy test instruction used to hold ic info (only if NLR is possible) 00048 // 1: ic info 00049 // 5: ... <--- first instruction after move 00050 // 00051 // 00052 // IC info layout (see als IC_Info for layout constants) 00053 // 00054 // [NLR offset|flags] 32bit immediate of the dummy test instruction 00055 // 31.......8|7...0 00056 // 00057 // The NLR offset is a signed int, the NLR target destination is computed 00058 // from the (call's) return address + NLR offset. 00059 // 00060 // Calling nmethods through a jump table will cost 10% of the total execution speed 00061 // (data provided by Urs 4-21-95) 00062 00063 00064 class AbstractCompiledIC: public NativeCall { 00065 public: 00066 char* NLR_testcode() const { return ic_info_at(next_instruction_address())->NLR_target(); } 00067 00068 // returns the beginning of the inline cache. 00069 char* begin_addr() const { return instruction_address(); } 00070 }; 00071 00072 00073 // Flags 00074 00075 const int dirty_send_bit_no = 0; 00076 const int optimized_bit_no = 1; 00077 const int uninlinable_bit_no = 2; 00078 const int super_send_bit_no = 3; 00079 const int megamorphic_bit_no = 4; 00080 const int receiver_static_bit_no = 5; 00081 00082 00083 // CompiledIC isn't a real object; the 'this' pointer points into the compiled code 00084 // (more precisely, it's the same as the return address of the callee) 00085 00086 class CompiledIC: public AbstractCompiledIC { 00087 protected: 00088 int compiler_info() const { return ic_info_at(next_instruction_address())->flags(); } 00089 void set_compiler_info(int info) { ic_info_at(next_instruction_address())->set_flags(info); } 00090 00091 public: 00092 // lookup routines for empty inline cache 00093 static char* normalLookupRoutine(); 00094 static char* superLookupRoutine(); 00095 00096 // conversion (machine PC to CompiledIC*) 00097 friend CompiledIC* CompiledIC_from_return_addr(char* return_addr); 00098 friend CompiledIC* CompiledIC_from_relocInfo(char* displacement_address); 00099 00100 // Accessors 00101 00102 // isDirty() --> has had misses 00103 bool isDirty() const { return isSet(compiler_info(), dirty_send_bit_no); } 00104 void setDirty() { set_compiler_info(addNth(compiler_info(), dirty_send_bit_no)); } 00105 00106 // isOptimized() --> nmethods called from here should be optimized 00107 bool isOptimized() const { return isSet(compiler_info(), optimized_bit_no); } 00108 void setOptimized() { set_compiler_info(addNth(compiler_info(), optimized_bit_no)); } 00109 void resetOptimized() { set_compiler_info(subNth(compiler_info(), optimized_bit_no)); } 00110 00111 // isUninlinable() --> compiler says don't try to inline this send 00112 bool isUninlinable() const { return isSet(compiler_info(), uninlinable_bit_no); } 00113 00114 // isSuperSend() --> send is a super send 00115 bool isSuperSend() const { return isSet(compiler_info(), super_send_bit_no); } 00116 00117 // isMegamorphic() --> send is megamorphic 00118 bool isMegamorphic() const { return isSet(compiler_info(), megamorphic_bit_no); } 00119 void setMegamorphic() { set_compiler_info(addNth(compiler_info(), megamorphic_bit_no)); } 00120 00121 // isReceiverStatic() --> receiver klass is known statically (connect to verifiedEntryPoint) 00122 bool isReceiverStatic() const { return isSet(compiler_info(), receiver_static_bit_no); } 00123 void setReceiverStatic() { set_compiler_info(addNth(compiler_info(), receiver_static_bit_no)); } 00124 00125 bool wasNeverExecuted() const; 00126 00127 InterpretedIC* inlineCache() const; // corresponding source-level inline cache (NULL if none, e.g. perform) 00128 PIC* pic() const; // NULL if 0 or 1 targets 00129 00130 // returns the first address after this primitive ic 00131 char* end_addr() { return ic_info_at(next_instruction_address())->next_instruction_address(); } 00132 00133 // sets the destination of the call instruction 00134 void set_call_destination(char* entry_point); 00135 00136 // Does a lookup in the receiver and patches the inline cache 00137 char* normalLookup(oop receiver); 00138 char* superLookup (oop receiver); 00139 00140 // Returns the class that holds the current method 00141 klassOop sending_method_holder(); 00142 00143 // replace appropriate target (with key nm->key) by nm 00144 void replace(nmethod* nm); 00145 00146 public: 00147 symbolOop selector() const; 00148 bool is_empty() const; 00149 bool is_monomorphic() const; 00150 bool is_polymorphic() const; 00151 bool is_megamorphic() const; 00152 00153 nmethod* target() const; // directly called nmethod or NULL if none/PIC 00154 klassOop targetKlass() const; // klass of compiled or interpreted target; 00155 // can only call if single target 00156 int ntargets() const; // number of targets in inline cache or PIC 00157 klassOop get_klass(int i) const; // receiver klass of ith target (i=0..ntargets()-1) 00158 00159 // returns the lookup key for PIC index 00160 LookupKey* key(int which, bool is_normal_send) const; 00161 void reset_jump_addr(); 00162 void link(PIC* s); 00163 void clear(); // clear inline cache 00164 void cleanup(); // cleanup inline cache 00165 00166 bool verify(); 00167 void print(); 00168 }; 00169 00170 class PrimitiveIC: public AbstractCompiledIC { 00171 public: 00172 // returns the primitive descriptor (based on the destination of the call). 00173 primitive_desc* primitive(); 00174 00175 // conversion (machine PC to PrimitiveIC*) 00176 friend PrimitiveIC* PrimitiveIC_from_return_addr(char* return_addr); 00177 friend PrimitiveIC* PrimitiveIC_from_relocInfo(char* displacement_address); 00178 00179 // returns the first address after this primitive ic. 00180 char* end_addr(); 00181 00182 void print(); 00183 }; 00184 00185 #endif