frame.hpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.50 $ */
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 // A frame represents a physical stack frame (an activation).  Frames can be
00025 // C or Delta frames, and the Delta frames can be interpreted or compiled.
00026 // In contrast, vframes represent source-level activations, so that one (Delta) frame 
00027 // can correspond to multiple deltaVFrames because of inlining.
00028 
00029 // Layout of interpreter frame:
00030 //    [locals + expr         ] * <- sp
00031 //    [old frame pointer     ]   <- fp
00032 //    [return pc             ]
00033 //    [previous locals + expr]   <- sender sp
00034 
00035 // Layout of deoptimized frame:
00036 //    [&unpack_unoptimized_frame ]              // patched return address
00037 //    [scrap area                ] * <- sp
00038 //    [sender sp                 ]
00039 //    [frame array               ]              // objArrayOop holding the deoptimized frames
00040 //    [old frame                 ]   <- fp      // old frame may skip real frames deoptimized away.
00041 //    [return pc                 ]
00042 
00043 const int frame_temp_offset          = -3; // For interpreter frames only
00044 const int frame_hp_offset            = -2; // For interpreter frames only
00045 const int frame_receiver_offset      = -1; // For interpreter frames only
00046 const int frame_next_Delta_fp_offset = -1; // For entry frames only; see call_delta in interpreter_asm.asm
00047 const int frame_next_Delta_sp_offset = -2; // For entry frames only; see call_delta in interpreter_asm.asm
00048 const int frame_link_offset          =  0;
00049 const int frame_return_addr_offset   =  1;
00050 const int frame_arg_offset           =  2;
00051 const int frame_sender_sp_offset     =  2;
00052 
00053 const int frame_real_sender_sp_offset   = -2; // For deoptimized frames only
00054 const int frame_frame_array_offset      = -1; // For deoptimized frames only
00055 
00056 const int interpreted_frame_float_magic_offset = frame_temp_offset - 1;
00057 const int compiled_frame_magic_oop_offset      = -1;
00058 const int minimum_size_for_deoptimized_frame   = 4;
00059     
00060 class frame : ValueObj {
00061  private:
00062   oop*  _sp; // stack pointer
00063   int*  _fp; // frame pointer
00064   char* _pc; // program counter
00065 
00066  public:
00067   // Constructors
00068   frame() {}
00069   frame(oop* sp, int* fp, char* pc) { 
00070     _sp = sp; _fp = fp; _pc = pc;
00071   }
00072 
00073   frame(oop* sp, int* fp) { 
00074     _sp = sp;
00075     _fp = fp;
00076     _pc = (char*) sp[-1];
00077   }
00078 
00079   // accessors for the instance variables
00080   oop*  sp() const                      { return _sp; }
00081   int*  fp() const                      { return _fp; }
00082   char* pc() const                      { return _pc; }
00083 
00084   // patching operations
00085   void patch_pc(char* pc); // patch the return address of the frame below.
00086   void patch_fp(int*  fp); // patch the link of the frame below.
00087 
00088   int*   addr_at(int index) const       { return &fp()[index];    }
00089   int    at(int index) const            { return *addr_at(index); }
00090 
00091  private:
00092   int**  link_addr() const              { return (int**) addr_at(frame_link_offset); }
00093   char** return_addr_addr() const       { return (char**) addr_at(frame_return_addr_offset); }
00094 
00095   // support for interpreter frames
00096   oop*   receiver_addr() const          { return (oop*) addr_at(frame_receiver_offset); }
00097   u_char** hp_addr() const              { return (u_char**) addr_at(frame_hp_offset); }
00098   oop*   arg_addr(int off) const        { return (oop*) addr_at(frame_arg_offset + off); }
00099 
00100  public:
00101   // returns the stack pointer of the calling frame
00102   oop* sender_sp() const                { return (oop*)  addr_at(frame_sender_sp_offset); }
00103 
00104   // Link
00105   int*     link() const                 { return *link_addr(); }
00106   void set_link(int* addr)              { *link_addr() = addr; }
00107 
00108   // Return address
00109   char*    return_addr() const          { return *return_addr_addr(); }
00110   void set_return_addr(char* addr)      { *return_addr_addr() = addr; }
00111 
00112   // Receiver
00113   oop      receiver() const             { return *receiver_addr(); }
00114   void set_receiver(oop recv)           { *receiver_addr() = recv; }
00115 
00116   // Temporaries
00117   oop       temp(int offset) const      { return *temp_addr(offset); }
00118   void  set_temp(int offset, oop obj)   { *temp_addr(offset) = obj; }
00119   oop* temp_addr(int offset) const      { return (oop*) addr_at(frame_temp_offset - offset); }
00120 
00121   // Arguments
00122   oop      arg(int offset) const        { return *arg_addr(offset); }
00123   void set_arg(int offset, oop obj)     { *arg_addr(offset) = obj; }
00124 
00125   // Expressions
00126   oop      expr(int index) const        { return ((oop*)sp())[index]; }
00127 
00128   // Hybrid Code Pointer (interpreted frames only); corresponds to "current PC", not return address
00129   u_char*   hp() const;
00130   void  set_hp(u_char* hp);
00131 
00132   // Returns the method for a valid hp() or NULL if frame not set up yet (interpreted frames only) 
00133   // Used by the profiler which means we must check for
00134   // valid frame before using the hp value.
00135   methodOop method() const;
00136 
00137   // compiled code (compiled frames only)
00138   nmethod* code() const;
00139 
00140  private:
00141   // Float support
00142   inline bool has_interpreted_float_marker() const;
00143   bool oop_iterate_interpreted_float_frame(OopClosure* blk);
00144   bool follow_roots_interpreted_float_frame();
00145 
00146   inline bool has_compiled_float_marker() const;
00147   bool oop_iterate_compiled_float_frame(OopClosure* blk);
00148   bool follow_roots_compiled_float_frame();
00149  public:
00150 
00151   // Accessors for (deoptimized frames only)
00152   objArrayOop* frame_array_addr() const;  
00153   oop**        real_sender_sp_addr() const;
00154  
00155   objArrayOop frame_array() const;
00156   void  set_frame_array(objArrayOop a) { *frame_array_addr() = a; }
00157 
00158   oop*  real_sender_sp() const         { return *real_sender_sp_addr(); }
00159   void  set_real_sender_sp(oop* addr)  { *real_sender_sp_addr() = addr;   }
00160 
00161   // returns the frame size in oops
00162   int frame_size() const                { return sender_sp() - sp(); }
00163 
00164   // returns the the sending frame
00165   frame sender() const;
00166   // returns the the sending Delta frame, skipping any intermediate C frames 
00167   // NB: receiver must not be first frame
00168   frame delta_sender() const;
00169 
00170   // tells whether there is another chunk of Delta stack above (entry frames only)
00171   bool has_next_Delta_fp() const;
00172   // returns the next C entry frame (entry frames only)
00173   int* next_Delta_fp()     const;
00174   oop* next_Delta_sp()     const;
00175 
00176   bool is_first_frame() const;                  // oldest frame? (has no sender)
00177   bool is_first_delta_frame() const;            // same for Delta frame
00178 
00179   // testers
00180   bool is_interpreted_frame() const;
00181   bool is_compiled_frame()    const;
00182   bool is_delta_frame()       const     { return is_interpreted_frame() || is_compiled_frame(); }
00183 
00184   bool should_be_deoptimized() const;
00185   bool is_entry_frame()        const;           // Delta frame called from C?
00186   bool is_deoptimized_frame()  const;
00187 
00188   // inline caches
00189   IC_Iterator* sender_ic_iterator() const;      // sending IC (NULL if entry frame or if a perform rather than a send)
00190   IC_Iterator* current_ic_iterator() const;     // current IC (will break if not at a send or perform)
00191   InterpretedIC* current_interpretedIC() const; // current IC in this frame; NULL if !is_interpreted_frame 
00192   CompiledIC* current_compiledIC() const;       // current IC in this frame; NULL if !is_compiled_frame
00193 
00194   // Iterators
00195   void oop_iterate(OopClosure* blk);
00196   void layout_iterate(FrameLayoutClosure* blk);
00197 
00198   // For debugging
00199  private:
00200   char* print_name() const;
00201 
00202  public:
00203   void verify() const;
00204   void print() const;
00205 
00206   // Prints the frame in a format useful when debugging deoptimization.
00207   void print_for_deoptimization(outputStream* st);
00208 
00209   // Garbage collection operations
00210   void follow_roots();
00211   void convert_hcode_pointer();
00212   void restore_hcode_pointer();
00213 
00214   // Returns the size of a number of interpreter frames in words.
00215   // This is used during deoptimization.
00216   static int interpreter_stack_size(int number_of_frames, int number_of_temporaries_and_locals) {
00217     return number_of_frames * interpreter_frame_size(0) 
00218          + number_of_temporaries_and_locals;
00219   }
00220 
00221   // Returns the word size of an interpreter frame
00222   static int interpreter_frame_size(int locals) {
00223     return frame_return_addr_offset - frame_temp_offset + locals;
00224   }
00225 };

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