methodOop.hpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.89 $ */
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 methodOop is a method with byte codes.
00025 
00026 const int method_size_mask_bitno  =  2;
00027 const int method_size_mask_size   = 18;
00028 
00029 const int method_args_mask_bitno  =  method_size_mask_bitno + method_size_mask_size;
00030 const int method_args_mask_size   =  4;
00031 
00032 const int method_flags_mask_bitno =  method_args_mask_bitno + method_args_mask_size;
00033 const int method_flags_mask_size  =  8;
00034 
00035 
00036 class methodOopDesc : public memOopDesc {
00037  private:
00038   objArrayOop _debugInfo;
00039   oop         _selector_or_method;      // selector for normal methods, enclosing method for blocks
00040   int         _counters;                // invocation counter and sharing counter
00041   smiOop      _size_and_flags;
00042   // [flags (8 bits),  nofArgs (4 bits), size in oops (18 bits), tag (2 bits)]
00043   methodOopDesc* addr() const           { return (methodOopDesc*)memOopDesc::addr(); }
00044 
00045   // returns the header size of a methodOop
00046   static int header_size()              { return sizeof(methodOopDesc)/oopSize; }
00047 
00048  public:
00049   // offsets for code generation
00050   static int selector_or_method_byte_offset()   { return int(&(((methodOopDesc*)NULL)->_selector_or_method)) - Mem_Tag; }
00051   static int counters_byte_offset()             { return int(&(((methodOopDesc*)NULL)->_counters)) - Mem_Tag; }
00052   static int codes_byte_offset()                { return sizeof(methodOopDesc) - Mem_Tag; }
00053 
00054   smiOop size_and_flags() const { return addr()->_size_and_flags; }     
00055   void set_size_and_flags(int size, int nofArgs, int flags) {
00056     addr()->_size_and_flags = (smiOop)
00057       ((flags << method_flags_mask_bitno) + (nofArgs << method_args_mask_bitno) + (size << method_size_mask_bitno));
00058   }
00059 
00060   int flags() const { 
00061     return get_unsigned_bitfield((int)size_and_flags(), method_flags_mask_bitno, method_flags_mask_size);
00062   }
00063 
00064   void set_flags(int flags) {
00065     set_size_and_flags(size_of_codes(), nofArgs(), flags);
00066   }
00067 
00068   int nofArgs() const {                  // number of arguments (excluding receiver)
00069     return get_unsigned_bitfield((int)size_and_flags(), method_args_mask_bitno, method_args_mask_size); }
00070 
00071  public:
00072   friend methodOop as_methodOop(void* p) { return methodOop(as_memOop(p)); }
00073 
00074   void bootstrap_object(bootstrap* st);
00075 
00076   // Tester
00077   bool is_blockMethod() const           { return !selector_or_method()->is_symbol(); }
00078 
00079   objArrayOop debugInfo() const         { return addr()->_debugInfo; }
00080   void set_debugInfo(objArrayOop d)     { addr()->_debugInfo = d; }
00081 
00082   symbolOop selector() const;
00083   methodOop parent() const;             // returns the enclosing block or method (for blocks), or NULL
00084   methodOop home() const;               // returns the enclosing method (for blocks), or itself
00085 
00086   oop  selector_or_method() const       { return addr()->_selector_or_method; }
00087   void set_selector_or_method(oop value){ addr()->_selector_or_method = value; }
00088 
00089   // returns the enclosing method's selector (block methods only)
00090   symbolOop enclosing_method_selector() const;
00091 
00092   // returns the source if the debugInfo is present, otherwise NULL.
00093   byteArrayOop source();
00094 
00095   // returns the tempInfo if the debugInfo is present, otherwise NULL.
00096   objArrayOop tempInfo();
00097 
00098   // Generates an array with fileout information.
00099   // The array contains pair of information:
00100   // (true,  SmallInteger) means character
00101   // (false, oop)          means oop
00102   objArrayOop fileout_body();
00103 
00104   // Accessor operaions on counters.
00105   //   invocation counter - tells how many times this methodOop has been executed (may decay over time)
00106   //   sharing counter    - tells how many callers this methodOop has.
00107 
00108   enum {
00109     _short_size              = 16,
00110     _invocation_count_offset = _short_size,
00111     _invocation_count_width  = _short_size,
00112     _invocation_count_max    = (1 << _short_size) - 1,
00113 
00114     _sharing_count_offset    = 0,
00115     _sharing_count_width     = _short_size,
00116     _sharing_count_max       = (1 << _short_size) - 1
00117   };
00118 
00119   int  counters() const                 { return addr()->_counters; }
00120   void set_counters(int inv, int share) { addr()->_counters = (inv << _invocation_count_offset) | share; }
00121 
00122   // Invocation counter
00123   int invocation_count() const          { return get_unsigned_bitfield(counters(), _invocation_count_offset, _invocation_count_width); }
00124   void set_invocation_count(int value)  { set_counters(value, sharing_count()); }
00125 
00126   void decay_invocation_count(double decay_factor);
00127   
00128   // Sharing counter (number of callers)
00129   int sharing_count() const             { return get_unsigned_bitfield(counters(), _sharing_count_offset, _sharing_count_width); }
00130   void set_sharing_count(int value)     { set_counters(invocation_count(), value); }
00131   void inc_sharing_count();
00132   void dec_sharing_count();
00133 
00134   bool was_never_executed();            // was method never executed? (count = 0, empty inline caches)
00135 
00136   int size_of_codes() const {           // size of byte codes in words
00137     return get_unsigned_bitfield((int) size_and_flags(), method_size_mask_bitno, method_size_mask_size); 
00138   }
00139 
00140   void set_size_of_code(int size) {
00141     set_size_and_flags(size, nofArgs(), flags());
00142   }
00143 
00144   // Returns a pointer to the hybrid code at 'offset'
00145   u_char* codes(int offset = 1) const {
00146      return (u_char*) addr() + sizeof(methodOopDesc) + offset - 1;
00147   }
00148 
00149   u_char* codes_end() const {
00150      return codes() + size_of_codes() * oopSize;
00151   }
00152 
00153   // find methodOop given an hcode pointer 
00154   static methodOop methodOop_from_hcode(u_char* hp);
00155 
00156   u_char byte_at(int offset) const              { return *codes(offset); }
00157   void byte_at_put(int offset,u_char c)         { *codes(offset) = c; }
00158 
00159   long word_at(int offset) const                { return * (long*) codes(offset); }
00160   void word_at_put(int offset,unsigned long w)  { * (long*) codes(offset) = w; }
00161 
00162   oop  oop_at(int offset) const                 { return * (oop*) codes(offset); }
00163   void oop_at_put(int offset,oop obj)           { * (oop*) codes(offset) = obj; }
00164 
00165   // Returns the next byte code index based on hp.
00166   int  next_bci_from(u_char* hp) const;
00167 
00168   // Returns the current byte code index based on hp (points to the next byte code)
00169   int  bci_from(u_char* hp) const;
00170 
00171   int  number_of_arguments() const;
00172 
00173   // Returns the number of temporaries allocated by the interpreter
00174   // (excluding receiver & float temporaries, which may come afterwards).
00175   int number_of_stack_temporaries() const;
00176 
00177   // Method with hardwired floating-point operations
00178   bool has_float_temporaries() const            { return *codes(1) == Bytecodes::float_allocate; }
00179   int  number_of_float_temporaries() const      { return has_float_temporaries() ? *codes(3) : 0; }
00180   int  float_expression_stack_size() const      { return has_float_temporaries() ? *codes(4) : 0; }
00181   int  total_number_of_floats() const           { return number_of_float_temporaries() + float_expression_stack_size(); }
00182 
00183   // Stack frame layout if there's a float section (offset & size in oops relative to ebp)
00184   int  float_offset(int float_no) const;
00185   int  float_section_start_offset() const       { return frame_temp_offset - number_of_stack_temporaries(); }
00186   int  float_section_size() const               { return total_number_of_floats()*floatSize/oopSize; }
00187 
00188   // Testers
00189   bool is_accessMethod() const                  { return *codes() == Bytecodes::return_instVar; }
00190   bool is_primitiveMethod() const;
00191 
00192   // For predicted sends (smi +, -, *, etc.)
00193   bool is_special_primitiveMethod() const       { return *codes(1) == Bytecodes::special_primitive_send_1_hint; }
00194   Bytecodes::Code special_primitive_code() const;
00195 
00196 
00197   // Information needed by the optimizing compiler
00198   //
00199   // Incoming_Info describes the possible oop kinds that a methodOop gets 'from' the
00200   // outside (via the closure) when invoked. Currently, the incoming oop is stored in
00201   // the recv and temp0 stack location for blocks, and in the recv location only for
00202   // methods (ordinary send). This should change at some point and the incoming oop
00203   // should be stored in the recv location only (allows better stack usage).
00204   //
00205   // Temporaries_Info is used to compute the number of stack-allocated temporaries. If
00206   // more than two temporaries are needed, the very first bytecode is an allocate temp
00207   // byte code (bytecode invariant).
00208 
00209   enum Flags {
00210     // general flags
00211     containsNLRFlag     = 0,
00212     allocatesContextFlag= 1,
00213     mustBeCustomizedFlag= 2,
00214     isCustomizedFlag    = 3,
00215 
00216     // method specific flags (overlapping with block specific flags)
00217     methodInfoFlags     = isCustomizedFlag + 1,
00218     methodInfoSize      = 2,
00219 
00220     // block specific flags (overlapping with method specific flags)
00221     blockInfoFlags      = methodInfoFlags,
00222     blockInfoSize       = methodInfoSize
00223   };
00224 
00225   // Flags for inlining
00226   enum Method_Inlining_Info {
00227     never_inline  = 0,
00228     normal_inline = 1,
00229     always_inline = 2,
00230   } method_inlining_info() const;
00231 
00232   void set_method_inlining_info(Method_Inlining_Info info);
00233 
00234   enum Block_Info {
00235     expects_nil         = 0,                    // 'clean' block
00236     expects_self        = 1,                    // 'copying' block
00237     expects_parameter   = 2,                    // 'copying' block
00238     expects_context     = 3                     // 'full' block
00239   } block_info() const;
00240 
00241   // Tells if an activation of this method has a context stored as temp 0.
00242   bool activation_has_context() const { 
00243     return allocatesInterpretedContext()
00244         || (is_blockMethod() && expectsContext());
00245   }
00246 
00247   // Tells if bci is a context allocation
00248   bool in_context_allocation(int bci) const;
00249 
00250   bool containsNLR() const                      { return isSet(flags(), containsNLRFlag); }
00251   bool allocatesInterpretedContext() const      { return isSet(flags(), allocatesContextFlag); }
00252   bool mustBeCustomizedToClass() const          { return isSet(flags(), mustBeCustomizedFlag); }
00253   bool expectsContext() const                   { return block_info() == expects_context; }
00254   bool hasNestedBlocks() const;
00255   bool is_clean_block() const                   { return block_info() == expects_nil; }
00256   bool is_copying_block() const                 { return block_info() == expects_self || block_info() == expects_parameter; }
00257   bool is_full_block() const                    { return block_info() == expects_context; }
00258 
00259   // Method customization
00260   bool has_instVar_access() const               { return true; } // for now - conservative - FIX THIS
00261   bool has_classVar_access() const              { return true; } // for now - conservative - FIX THIS
00262   bool has_inlineCache() const                  { return true; } // for now - conservative - FIX THIS
00263   bool is_customized() const                    { return isSet(flags(), isCustomizedFlag); }                    
00264   bool should_be_customized() const             { return has_instVar_access() || has_classVar_access() || has_inlineCache(); }
00265 
00266   // Returns a deep copy of the methodOop
00267   methodOop copy_for_customization() const;
00268 
00269   // Customize method to klass
00270   void customize_for(klassOop klass, mixinOop mixin);
00271   void uncustomize_for(mixinOop mixin);
00272 
00273   // Uplevel accesses via contexts
00274   int lexicalDistance(int contextNo);   // for uplevel accesses; see comment in .c file
00275   int contextNo(int lexicalDistance);   // inverse of lexicalDistance()
00276 
00277   // Computes the number of interpreter contexts from here up to the home method
00278   int context_chain_length() const;
00279 
00280   // Clears all the inline caches in the method.
00281   void clear_inline_caches();
00282 
00283   // Cleanup all inline caches
00284   void cleanup_inline_caches();
00285 
00286   // Computes the estimated cost of a method by summing 
00287   // cost of all byte codes (see code_cost in methodOop.cpp).
00288   int estimated_inline_cost(klassOop receiverKlass);
00289 
00290   // Finds the bci based on the next bci
00291   // Returns -1 if the search failed.
00292   int find_bci_from(int nbci) const;
00293 
00294   // Returns the next bci
00295   int next_bci(int bci) const;
00296 
00297   // Returns the end bci (excluding the padding)
00298   int end_bci() const;
00299 
00300   // Returns the inline cache associated with the send at bci.
00301   InterpretedIC* ic_at(int bci) const;
00302 
00303   // Returns an array of byte code indecies contributing to the expression stack
00304   GrowableArray<int>* expression_stack_mapping(int bci);
00305 
00306   // For debugging only
00307   void print_codes();
00308   void pretty_print();
00309 
00310   // Printing support
00311   void print_value_for(klassOop receiver_klass, outputStream* st = NULL);
00312 
00313   // Inlining database support
00314   void print_inlining_database_on(outputStream* st);
00315   int  bci_for_block_method(methodOop inner);
00316   methodOop block_method_at(int bci);
00317 
00318   // Returns the numbers of temporaries allocated in a context.
00319   // self_in_context tells if self is copied into context.
00320   // Note: This function is extremely slow, so please use it for
00321   //       verify and debug code only.
00322   int number_of_context_temporaries(bool* self_in_context = NULL);
00323 
00324   // Checks if the context matches this method
00325   void verify_context(contextOop con);
00326 
00327   // Query primitives
00328   objArrayOop referenced_instance_variable_names(mixinOop mixin) const;
00329   objArrayOop referenced_class_variable_names() const;
00330   objArrayOop referenced_global_names() const;
00331   objArrayOop senders() const;
00332 
00333   friend methodKlass;
00334 };

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