compiledIC.hpp

Go to the documentation of this file.
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

Generated on Mon Oct 9 13:37:07 2006 for Strongtalk VM by  doxygen 1.4.7