nmethodScopes.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.32 $ */
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 # include "incls/_precompiled.incl"
00025 
00026 #ifdef DELTA_COMPILER
00027 
00028 # include "incls/_nmethodScopes.cpp.incl"
00029 
00030 ScopeDesc* nmethodScopes::at(int offset, char* pc) const {
00031   // Read the first byte and decode the ScopeDesc type at the location.
00032   assert(offset >= 0, "illegal desc offset");
00033   scopeDescHeaderByte b;
00034   b.unpack(peek_next_char(offset));
00035   switch (b.code()) {
00036     case METHOD_CODE          : return new MethodScopeDesc(       (nmethodScopes*) this, offset, pc);
00037     case TOPLEVELBLOCK_CODE   : return new TopLevelBlockScopeDesc((nmethodScopes*) this, offset, pc);
00038     case BLOCK_CODE           : return new BlockScopeDesc(        (nmethodScopes*) this, offset, pc);
00039     case NONINLINED_BLOCK_CODE: return NULL;
00040   }
00041   fatal("Unknown ScopeDesc code in nmethodScopes");
00042   return NULL;
00043 }
00044 
00045 
00046 NonInlinedBlockScopeDesc* nmethodScopes::noninlined_block_scope_at(int offset) const {
00047   // Read the first byte and decode the ScopeDesc type at the location.
00048   assert(offset > 0, "illegal desc offset");
00049   scopeDescHeaderByte b;
00050   b.unpack(peek_next_char(offset));
00051   if ( b.code() != NONINLINED_BLOCK_CODE) {
00052     fatal("Not an noninlined scope desc as expected");
00053   }
00054   return new NonInlinedBlockScopeDesc((nmethodScopes*)this, offset);
00055 }
00056 
00057 
00058 int16 nmethodScopes::get_next_half(int& offset) const {
00059   int16 v;
00060   v = get_next_char(offset) << BYTE_WIDTH;
00061   v = addBits(v, get_next_char(offset));
00062   return v;
00063 }
00064 
00065 
00066 inline u_char nmethodScopes::getIndexAt(int& offset) const { 
00067   return get_next_char(offset);
00068 }
00069 
00070 
00071 inline oop nmethodScopes::unpackOopFromIndex(u_char index, int& offset) const {
00072   if (index == 0)  return 0;
00073   if (index < EXTENDED_INDEX) return oop_at(index-1);
00074   return oop_at(get_next_half(offset)-1); 
00075 }
00076 
00077 
00078 inline int nmethodScopes::unpackValueFromIndex(u_char index, int& offset) const {
00079   if (index <= MAX_INLINE_VALUE) return index;
00080   if (index < EXTENDED_INDEX) return value_at(index-(MAX_INLINE_VALUE+1));
00081   return value_at(get_next_half(offset)-(MAX_INLINE_VALUE+1)); 
00082 }
00083 
00084 
00085 oop nmethodScopes::unpackOopAt(int& offset) const {
00086   u_char index = getIndexAt(offset);
00087   return unpackOopFromIndex(index, offset);
00088 }
00089 
00090 
00091 int nmethodScopes::unpackValueAt(int& offset) const {
00092   u_char index = getIndexAt(offset);
00093   return unpackValueFromIndex(index, offset);
00094 }
00095 
00096 
00097 NameDesc* nmethodScopes::unpackNameDescAt(int& offset, bool& is_last, char* pc) const {
00098   int startOffset = offset;
00099   nameDescHeaderByte b;
00100   b.unpack(get_next_char(offset));
00101   is_last = b.is_last();
00102   NameDesc* nd;
00103   if (b.is_illegal()) {
00104     nd = new IllegalNameDesc;
00105   } else if (b.is_termination()) {
00106     return NULL;
00107   } else {
00108     u_char index;
00109     index = b.has_index() ? b.index() : getIndexAt(offset);
00110 
00111     switch(b.code()) {
00112      case LOCATION_CODE: {
00113        Location l = Location(unpackValueFromIndex(index, offset));
00114        nd = new LocationNameDesc(l);
00115        break;
00116      }
00117      case VALUE_CODE: {
00118        oop v = unpackOopFromIndex(index, offset);
00119        nd = new ValueNameDesc(v);
00120        break;
00121      }
00122      case BLOCKVALUE_CODE: {
00123        oop blkMethod    = unpackOopFromIndex(index, offset);
00124        assert(blkMethod->is_method(), "must be a method");
00125        int parent_scope_offset = unpackValueAt(offset);
00126        ScopeDesc* parent_scope = at(parent_scope_offset, pc);
00127        nd = new BlockValueNameDesc(methodOop(blkMethod), parent_scope);
00128        break;
00129      }
00130      case MEMOIZEDBLOCK_CODE: {
00131        Location l   = Location(unpackValueFromIndex(index, offset));
00132        oop      blkMethod = unpackOopAt(offset);
00133        assert(blkMethod->is_method(), "must be a method");
00134        int parent_scope_offset = unpackValueAt(offset);
00135        ScopeDesc* parent_scope = at(parent_scope_offset, pc);
00136        nd = new MemoizedBlockNameDesc(l, methodOop(blkMethod), parent_scope);
00137        break;
00138      }
00139      default:
00140       fatal1("no such name desc (code %d)", b.code());
00141     }
00142   }
00143   nd->offset = startOffset;
00144   return nd;
00145 }
00146 
00147 
00148 void nmethodScopes::iterate(int& offset, UnpackClosure* closure) const {
00149   char* pc = my_nmethod()->insts();
00150   bool is_last;
00151   NameDesc* nd = unpackNameDescAt(offset, is_last, ScopeDesc::invalid_pc);
00152   if (nd == NULL) return;               // if at termination byte
00153   closure->nameDescAt(nd, pc);
00154   while (!is_last) {
00155     nd  = unpackNameDescAt(offset, is_last, ScopeDesc::invalid_pc);
00156     pc += unpackValueAt(offset);
00157     closure->nameDescAt(nd, pc);
00158   }
00159 }
00160 
00161 
00162 NameDesc* nmethodScopes::unpackNameDescAt(int& offset, char* pc) const {
00163   int pc_offset = pc - my_nmethod()->insts();
00164   int current_pc_offset = 0;
00165   bool is_last;
00166   NameDesc* result = unpackNameDescAt(offset, is_last, pc);
00167   if (result == NULL) return NULL;      // if at termination byte
00168   while (!is_last) {
00169     NameDesc* current  = unpackNameDescAt(offset, is_last, pc);
00170     current_pc_offset += unpackValueAt(offset);
00171     if (current_pc_offset <= pc_offset) {
00172       result = current;
00173     }
00174   }
00175   return result;
00176 }
00177 
00178 
00179 # define FOR_EACH_OOPADDR(VAR)                                                \
00180     for (oop* VAR = oops(), *CONC(VAR, _end) = oops() + oops_size();          \
00181          VAR < CONC(VAR, _end); VAR++)
00182 
00183 
00184 void nmethodScopes::verify() {
00185   // Verify all oops
00186   FOR_EACH_OOPADDR(addr) {
00187     VERIFY_TEMPLATE(addr)
00188   }
00189 
00190   // Verify all scopedesc
00191   FOR_EACH_SCOPE(this, s) {
00192     if (!s->verify())
00193       lprintf("\t\tin nmethod at %#lx (scopes)\n", my_nmethod()); 
00194   }
00195 }
00196 
00197 
00198 void nmethodScopes::scavenge_contents() {
00199   FOR_EACH_OOPADDR(addr) {
00200     SCAVENGE_TEMPLATE(addr);
00201   }
00202 }
00203 
00204 
00205 void nmethodScopes::switch_pointers(oop from, oop to,
00206                                     GrowableArray<nmethod*> *nmethods_to_invalidate) {
00207   Unused(to);
00208 /*
00209   This is tricky!
00210   First, since some inlined methods are not included in scopes
00211   (those that generate no code such as asSmallInteger),
00212   you might think that this would
00213   not be needed, since memory is swept and dependencies flushed
00214   (see space::switch_pointers_in_region).
00215 
00216   But, when nmethods are converted on the stack, zombie nmethods are
00217   produced. These are obsolete nmethods that carry on the execution of
00218   active but no longer referenced methods on the stack.
00219   Since they have no dependencies, they are not found from the heap.
00220   That is why this code is needed anyway.
00221 
00222   Now, since this info describes the code, you cannot change it,
00223   instead, you invalidate the nmethod if it has a ref to from in its scopes.
00224   For example the method oops in the scope determine the activations
00225   that might be on the stack, and you can't change these, because
00226   activations are clones of methods. This may be the last reference to
00227   a currently executing method, must keep it around.
00228 
00229   However, you may be confused by the fact that locs (embedded literals)
00230   in the code in the method are changed. But, those are just object literals,
00231   maps of inlined stuff, and are different than the scope oops.
00232 
00233   Although they could possibly be the same, by invalidating any
00234   match (beyond just the method holder and method) we are safe.
00235 */
00236 
00237 # ifdef NOT_IMPLEMENTED
00238   if (my_nmethod()->isInvalid()) return;
00239   
00240   FOR_EACH_OOPADDR(addr) {
00241     if (*addr == from) {
00242       nmethods_to_invalidate->append(my_nmethod());
00243         return;
00244       }
00245   }
00246 # endif
00247 }
00248 
00249 
00250 void nmethodScopes::oops_do(void f(oop*)) {
00251   oop* end = oops() + oops_size();
00252   for (oop* p = oops(); p < end; p++) {
00253     f(p);
00254   }
00255 }
00256 
00257 
00258 void nmethodScopes::relocate() {
00259   FOR_EACH_OOPADDR(addr) {
00260     RELOCATE_TEMPLATE(addr);
00261   }
00262 }
00263 
00264 
00265 bool nmethodScopes::is_new() const {
00266   bool result = false;
00267   FOR_EACH_OOPADDR(addr) {
00268     if ((*addr)->is_new()) return true;
00269   }
00270   return false;
00271 }
00272 
00273 
00274 void nmethodScopes::print() {
00275   ResourceMark m;       // in case methods get printed via debugger
00276   printIndent();
00277   lprintf("scopes:\n");
00278   Indent ++;
00279   FOR_EACH_SCOPE(this, d)
00280     d->print();
00281   Indent --;
00282 }
00283 
00284 
00285 void nmethodScopes::print_partition() {
00286   int d_size = dependent_length() * sizeof(oop);
00287   int o_size = oops_size() * sizeof(oop) - d_size;
00288   int p_size = (int) pcsEnd() - (int) pcs();
00289   int v_size = value_size() * sizeof(int);
00290   int total  = v_size + p_size + o_size + d_size;
00291  
00292   std->print_cr("{deps %d%%, oops %d%%, bytes %d%%, pcs %d%%}",
00293                 d_size * 100/ total,
00294                 o_size * 100/ total,
00295                 v_size * 100/ total,
00296                 p_size * 100/ total);
00297 }
00298 
00299 #endif

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