00001 /* Copyright 1994 - 1996, LongView Technologies, L.L.C. $Revision: 1.12 $ */ 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 00025 // The InterpretedIC describes the contents of an inline cache in the 00026 // byte codes of a method. The inline cache holds a combination of 00027 // selector/method and 0/class oops and is read and modified during 00028 // execution. 00029 // 00030 // 00031 // An InterpretedIC can have four different states: 00032 // 00033 // 1) empty {selector, 0} 00034 // 2) filled with a call to interpreted code {method, klass} 00035 // 3) filled with an interpreter PIC {selector, objArrayObj} 00036 // 4) filled with a call to compiled code {jump table entry, klass} 00037 // 00038 // 00039 // Layout: 00040 // 00041 // send byte code <----- send_code_addr() 00042 // ... 00043 // halt byte codes for alignment 00044 // ... 00045 // 0: selector/method/jump table entry <----- first_word_addr() 00046 // 4: 0/klass/objArray <----- second_word_addr() 00047 // 8: ... 00048 00049 class InterpretedIC: ValueObj { 00050 public: 00051 enum { 00052 size = 8, // inline cache size in words 00053 first_word_offset = 0, // layout info: first word 00054 second_word_offset = 4, // layout info: second word 00055 } InterpretedICConstants; 00056 00057 // Conversion (Bytecode* -> InterpretedIC*) 00058 friend InterpretedIC* as_InterpretedIC(char* address_of_next_instr); 00059 00060 // find send bytecode, given address of selector; return NULL/IllegalBCI if not in a send 00061 static u_char* findStartOfSend(u_char* selector_addr); 00062 static int findStartOfSend(methodOop m, int bci); 00063 00064 private: 00065 // field access 00066 char* addr_at(int offset) const { return (char*)this + offset; } 00067 oop* first_word_addr() const { return (oop*)addr_at(first_word_offset); } 00068 oop* second_word_addr() const { return (oop*)addr_at(second_word_offset); } 00069 void set(Bytecodes::Code send_code, oop first_word, oop second_word); 00070 00071 public: 00072 // Raw inline cache access 00073 u_char* send_code_addr() const { return findStartOfSend((u_char*)this); } 00074 Bytecodes::Code send_code() const { return Bytecodes::Code(*send_code_addr()); } 00075 oop first_word() const { return *first_word_addr(); } 00076 oop second_word() const { return *second_word_addr(); } 00077 00078 // Returns the polymorphic inline cache array. Assert fails if no pic is present. 00079 objArrayOop pic_array(); 00080 00081 // Inline cache information 00082 bool is_empty() const { return second_word() == NULL; } 00083 symbolOop selector() const; // the selector 00084 jumpTableEntry* jump_table_entry() const; // only legal to call if compiled send 00085 00086 int nof_arguments() const; // the number of arguments 00087 Bytecodes::SendType send_type() const; // the send type 00088 Bytecodes::ArgumentSpec argument_spec() const;// the argument spec 00089 00090 // Manipulation 00091 void clear(); // clears the inline cache 00092 void cleanup(); // cleanup the inline cache 00093 void clear_without_deallocation_pic(); // clears the inline cache without deallocating the pic 00094 void replace(nmethod* nm); // replaces the appropriate target with a nm 00095 void replace(LookupResult result, klassOop receiver_klass); // replaces the inline cache with a lookup result 00096 00097 // Debugging 00098 void print(); 00099 00100 // Cache miss 00101 static void inline_cache_miss(); // the inline cache miss handler 00102 00103 private: 00104 // helpers for inline_cache_miss 00105 static void update_inline_cache(InterpretedIC* ic, frame* f, Bytecodes::Code send_code, klassOop klass, LookupResult result); 00106 static void does_not_understand(oop receiver, InterpretedIC* ic, frame* f); 00107 static void trace_inline_cache_miss(InterpretedIC* ic, klassOop klass, LookupResult result); 00108 }; 00109 00110 00111 // Interpreter_PICs handles the allocation and deallocation of interpreter PICs. 00112 00113 static const int size_of_smallest_interpreterPIC = 2; 00114 static const int size_of_largest_interpreterPIC = 5; 00115 static const int number_of_interpreterPIC_sizes = size_of_largest_interpreterPIC - size_of_smallest_interpreterPIC + 1; 00116 00117 00118 // An InterpretedIC_Iterator is used to iterate through the entries of 00119 // an inline cache in a methodOop. Whenever possible, one should use this 00120 // abstraction instead of the (raw) InterpretedIC. 00121 00122 class InterpretedIC_Iterator: public IC_Iterator { 00123 private: 00124 InterpretedIC* _ic; // the inline cache 00125 objArrayOop _pic; // the PIC if there is one 00126 00127 // state machine 00128 int _number_of_targets; // the no. of IC entries 00129 IC_Shape _info; // send site information 00130 int _index; // the current entry no. 00131 klassOop _klass; // the current klass 00132 methodOop _method; // the current method 00133 nmethod* _nm; // current nmethod (NULL if none) 00134 00135 void set_method(oop m); // set _method and _nmethod 00136 void set_klass(oop k); // don't assign to _klass directly 00137 00138 public: 00139 InterpretedIC_Iterator(InterpretedIC* ic); 00140 00141 // IC information 00142 int number_of_targets() const { return _number_of_targets; } 00143 IC_Shape shape() const { return _info; } 00144 symbolOop selector() const { return _ic->selector(); } 00145 bool is_interpreted_ic() const { return true; } 00146 bool is_super_send() const; 00147 InterpretedIC* interpreted_ic() const { return _ic; } 00148 00149 00150 // Iterating through entries 00151 void init_iteration(); 00152 void advance(); 00153 bool at_end() const { return _index >= number_of_targets(); } 00154 00155 // Accessing entries 00156 klassOop klass() const { return _klass; } 00157 00158 // answer whether current target method is compiled or interpreted 00159 bool is_interpreted() const { return _nm == NULL; } 00160 bool is_compiled() const { return _nm != NULL; } 00161 00162 methodOop interpreted_method() const; 00163 nmethod* compiled_method() const; 00164 00165 // Debugging 00166 void print(); 00167 };