scopeDesc.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.59 $ */
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/_scopeDesc.cpp.incl"
00029 
00030 char* ScopeDesc::invalid_pc = (char*) -1;
00031 
00032 int compareBCI(int bci1, int bci2) {
00033   assert(bci1 != IllegalBCI && bci2 != IllegalBCI, "can't compare");
00034   return bci1 - bci2;
00035 }
00036 
00037 ScopeDesc::ScopeDesc(const nmethodScopes* scopes, int offset, char* pc) {
00038   _scopes     = scopes;
00039   _offset     = offset;
00040   _pc         = pc;
00041 
00042   _name_desc_offset = offset;
00043 
00044   scopeDescHeaderByte b;
00045   b.unpack(_scopes->get_next_char(_name_desc_offset));
00046 
00047   _lite              = b.is_lite();
00048   _has_temps         = b.has_temps();
00049   _has_context_temps = b.has_context_temps();
00050   _has_expr_stack    = b.has_expr_stack();
00051 
00052   assert(offset != 0 || !is_lite(), "Root scopeDesc cannot be lite");
00053 
00054   if (b.has_nameDescs()) {
00055     _next = _scopes->unpackValueAt(_name_desc_offset) + _offset;  
00056   } else {
00057     _next = -1;
00058   }
00059 
00060   if (_offset == 0) {
00061     _senderScopeOffset   = 0;
00062     _senderByteCodeIndex = IllegalBCI;
00063   } else {
00064     _senderScopeOffset   = _scopes->unpackValueAt(_name_desc_offset);  
00065     _senderByteCodeIndex = _scopes->unpackValueAt(_name_desc_offset);
00066   }
00067   _method  = methodOop(_scopes->unpackOopAt(_name_desc_offset));
00068   assert(_method->is_method(), "expecting a method");
00069   _allocates_compiled_context = b.has_compiled_context();
00070   _scopeID = _scopes->unpackValueAt(_name_desc_offset);  
00071 }
00072 
00073 
00074 ScopeDesc* ScopeDesc::home(bool cross_nmethod_boundary ) const {
00075   ScopeDesc* p = (ScopeDesc*)this;
00076   for ( ; p && !p->isMethodScope(); p = p->parent(cross_nmethod_boundary)) ;
00077   return p;
00078 }
00079 
00080 
00081 NameDesc* ScopeDesc::temporary(int index, bool canFail) {
00082   int pos = _name_desc_offset;
00083   NameDesc* result = NULL;
00084   if (_has_temps) {
00085     NameDesc* current = nameDescAt(pos);
00086     int i = 0;
00087     while (current != NULL) {
00088       if (i == index) { result = current; break; }
00089       current = nameDescAt(pos);
00090       i++;
00091     }
00092   }
00093   if (!result && !canFail) fatal1("couldn't find temporary %d", index);
00094   return result;
00095 }
00096 
00097 
00098 NameDesc* ScopeDesc::contextTemporary(int index, bool canFail) {
00099   int pos = _name_desc_offset;
00100   NameDesc* result = NULL;
00101   if (_has_temps) {
00102     NameDesc* current = nameDescAt(pos);
00103     while(current) {
00104       current = nameDescAt(pos);
00105     }
00106   }
00107   if (_has_context_temps) {
00108     NameDesc* current = nameDescAt(pos);
00109     int i = 0;
00110     while(current) {
00111       if (i == index) { result = current; break; }
00112       current = nameDescAt(pos);
00113       i++;
00114     }
00115   }
00116   if (!result && !canFail) fatal1("couldn't find context temporary %d", index);
00117   return result;
00118 }
00119 
00120 
00121 NameDesc* ScopeDesc::exprStackElem(int bci, bool includeTrivial) {
00122   int pos = _name_desc_offset;
00123   if (_has_temps) {
00124     NameDesc* current = nameDescAt(pos);
00125     while(current) {
00126       current = nameDescAt(pos);
00127     }
00128   }
00129   if (_has_context_temps) {
00130     NameDesc* current = nameDescAt(pos);
00131     while(current) {
00132       current = nameDescAt(pos);
00133     }
00134   }
00135   if (_has_expr_stack) {
00136     NameDesc* current = nameDescAt(pos);
00137     while(current) {
00138       int the_bci = valueAt(pos);
00139       if (bci == the_bci) return current;
00140       current = nameDescAt(pos);
00141     }
00142   }
00143   return NULL;
00144 }
00145 
00146 
00147 void ScopeDesc::iterate(NameDescClosure* blk) {
00148   int pos = _name_desc_offset;
00149   if (_has_temps) {
00150     NameDesc* current = nameDescAt(pos);
00151     int       number  = 0;
00152     while(current) {
00153       blk->temp(number++, current, pc());
00154       current = nameDescAt(pos);
00155     }
00156   }
00157   if (_has_context_temps) {
00158     NameDesc* current = nameDescAt(pos);
00159     int       number  = 0;
00160     while(current) {
00161       blk->context_temp(number++, current, pc());
00162       current = nameDescAt(pos);
00163     }
00164   }
00165   if (_has_expr_stack) {
00166     NameDesc* current = nameDescAt(pos);
00167     while(current) {
00168       blk->stack_expr(valueAt(pos), current, pc());
00169       current = nameDescAt(pos);
00170     }
00171   }
00172 }
00173 
00174 
00175 // Wrapper class for NameDescClosure, allows iteration over
00176 // string of NameDescs with different pc information.
00177 
00178 class IterationHelper: public UnpackClosure {
00179  protected:
00180   int              _no;
00181   NameDescClosure* _blk;
00182   bool             _is_used;
00183 
00184   void use()       { _is_used = true; }
00185 
00186  public:
00187   void init(int no, NameDescClosure* blk) {
00188     _no      = no;
00189     _blk     = blk;
00190     _is_used = false;
00191   }
00192 
00193   bool is_used() const { return _is_used; }
00194 };
00195 
00196 class IH_arg         : public IterationHelper { void nameDescAt(NameDesc* nd, char* pc) { use(); _blk->arg         (_no, nd, pc); } };
00197 class IH_temp        : public IterationHelper { void nameDescAt(NameDesc* nd, char* pc) { use(); _blk->temp        (_no, nd, pc); } };
00198 class IH_context_temp: public IterationHelper { void nameDescAt(NameDesc* nd, char* pc) { use(); _blk->context_temp(_no, nd, pc); } };
00199 class IH_stack_expr  : public IterationHelper { void nameDescAt(NameDesc* nd, char* pc) { use(); _blk->stack_expr  (_no, nd, pc); } };
00200 
00201 
00202 
00203 void ScopeDesc::iterate_all(NameDescClosure* blk) {
00204   int pos = _name_desc_offset;
00205   if (_has_temps) {
00206     int no = 0;
00207     IH_temp helper;
00208     do {
00209       helper.init(no++, blk);
00210       _scopes->iterate(pos, &helper);
00211     } while (helper.is_used());
00212   }
00213   if (_has_context_temps) {
00214     int no = 0;
00215     IH_context_temp helper;
00216     do {
00217       helper.init(no++, blk);
00218       _scopes->iterate(pos, &helper);
00219     } while (helper.is_used());
00220   }
00221   if (_has_expr_stack) {
00222     int no = 0;
00223     IH_stack_expr helper;
00224     do {
00225       helper.init(no++, blk);
00226       _scopes->iterate(pos, &helper);
00227       if (helper.is_used()) valueAt(pos); // get bci (i.e., print-out is showing expr. index and not bci)
00228     } while (helper.is_used());
00229   }
00230 }
00231 
00232 
00233 bool ScopeDesc::allocates_interpreted_context() const {
00234   return method()->allocatesInterpretedContext();
00235 }
00236 
00237 
00238 NameDesc* ScopeDesc::compiled_context() {
00239   assert(allocates_compiled_context(), "must allocate a context");
00240   const int temporary_index_for_context = 0;
00241   return temporary(temporary_index_for_context);
00242 }
00243 
00244 
00245 bool ScopeDesc::s_equivalent(ScopeDesc* s) const {
00246   return method() == s->method()
00247      && (_senderByteCodeIndex == s->_senderByteCodeIndex ||
00248          _senderByteCodeIndex < 0 || s->_senderByteCodeIndex < 0);
00249          // don't check senderByteCodeIndex for pseudo BCIs
00250 }
00251 
00252 
00253 bool ScopeDesc::l_equivalent(LookupKey* l) const {
00254   return selector() == l->selector();
00255 }
00256 
00257 
00258 ScopeDesc* ScopeDesc::sender() const {
00259   return _senderScopeOffset ? _scopes->at(_offset - _senderScopeOffset, pc()) : NULL; 
00260 }
00261 
00262 
00263 NameDesc* ScopeDesc::nameDescAt(int& offset) const {
00264   return _scopes->unpackNameDescAt(offset, pc());
00265 }
00266 
00267 
00268 int ScopeDesc::valueAt(int& offset) const {
00269   return _scopes->unpackValueAt(offset);
00270 }
00271 
00272 
00273 bool ScopeDesc::verify() {
00274   // verifies mostly structure, not contents
00275   bool ok = true;
00276 
00277   // don't do a full verify of parent/sender -- too many redundant verifies
00278   ScopeDesc* s = sender();
00279   if (s && !s->shallow_verify()) {
00280     std->print("invalid sender %#lx of ScopeDesc %#lx", s, this);
00281     ok = false;
00282   }
00283   ScopeDesc* p = parent();
00284   if (p && !p->shallow_verify()) {
00285     std->print("invalid parent %#lx of ScopeDesc %#lx", p, this);
00286     ok = false;
00287   }
00288   return ok;
00289 }
00290 
00291 
00292 // verify expression stack at a call or primitive call
00293 void ScopeDesc::verify_expression_stack(int bci) {
00294   GrowableArray<int>* mapping = method()->expression_stack_mapping(bci);
00295   for (int index = 0; index < mapping->length(); index++) {
00296     NameDesc* nd    = exprStackElem(mapping->at(index));
00297     if (nd == NULL) { warning("expression not found in nmethod"); continue; }
00298     // Fix this Lars (add parameter for checking registers
00299     // if (nd->hasLocation() && nd->location().isRegisterLocation()) {
00300     //   print(); nd->print(); method()->print_codes();
00301     //   error("expr stack element is in register at call at bci %d", bci);
00302     // }
00303   }
00304 }
00305 
00306 
00307 class PrintNameDescClosure: public NameDescClosure {
00308  private:
00309   int   _indent;
00310   char* _pc0;
00311 
00312   void print(char* title, int no, NameDesc* nd, char* pc) {
00313     std->fill_to(_indent);
00314     if (UseNewBackend) {
00315       std->print("%5d: ", pc - _pc0);
00316     }
00317     std->print("%s[%d]\t", title, no); nd->print(); std->cr();
00318   }
00319 
00320  public:
00321   PrintNameDescClosure(int indent, char* pc0)      { _indent = indent; _pc0 = pc0; }
00322 
00323   void arg         (int no, NameDesc* a, char* pc) { print("arg   ", no, a, pc); }
00324   void temp        (int no, NameDesc* t, char* pc) { print("temp  ", no, t, pc); }
00325   void context_temp(int no, NameDesc* c, char* pc) { print("c_temp", no, c, pc); }
00326   void stack_expr  (int no, NameDesc* e, char* pc) { print("expr  ", no, e, pc); }
00327 };
00328 
00329 
00330 void ScopeDesc::print(int indent, bool all_pcs) {
00331   std->fill_to(indent);
00332   printName();
00333   std->print("ScopeDesc @%d%s: ", offset(), is_lite() ? ", lite" : "");
00334   std->print(" (ID %ld) ", scopeID());
00335   method()->selector()->print_symbol_on();
00336   std->print(" %#x", method());
00337   std->cr();
00338   ScopeDesc* s = sender();
00339   if (s != NULL) {
00340     std->fill_to(indent);
00341     std->print("sender: (%d) @ %ld", s->offset(), long(senderBCI()));
00342   }
00343   ScopeDesc* p = parent();
00344   if (p != NULL) {
00345     if (s != NULL) {
00346       std->print("; ");
00347     } else {
00348       std->fill_to(indent);
00349     }
00350     std->print("parent: (%d)", p->offset());
00351   }
00352   if (s != NULL || p != NULL) {
00353     std->cr();
00354   }
00355   std->fill_to(indent);
00356   printSelf();
00357   PrintNameDescClosure blk(indent+2, _scopes->my_nmethod()->insts());
00358   if (all_pcs) {
00359     iterate_all(&blk);
00360   } else {
00361     iterate(&blk);
00362   }
00363 }
00364 
00365 
00366 void ScopeDesc::print_value_on(outputStream* st) const {
00367   // print offset
00368   if (WizardMode) 
00369     st->print(" [%d]", offset());
00370 }
00371 
00372 
00373 bool MethodScopeDesc::s_equivalent(ScopeDesc* s) const {
00374   return s->isMethodScope() 
00375       && ScopeDesc::s_equivalent(s)
00376       && key()->equal(((MethodScopeDesc*)s)->key());
00377 }
00378 
00379 
00380 bool MethodScopeDesc::l_equivalent(LookupKey* l) const {
00381   return ScopeDesc::l_equivalent(l) && selfKlass() == l->klass();
00382 }
00383 
00384 
00385 MethodScopeDesc::MethodScopeDesc(const nmethodScopes* scopes, int offset, char* pc)
00386   : ScopeDesc(scopes, offset, pc), _key() {
00387   oop k = _scopes->unpackOopAt(_name_desc_offset);
00388   oop s = _scopes->unpackOopAt(_name_desc_offset);
00389   _key.initialize((klassOop) k, s);
00390   _self_name = _scopes->unpackNameDescAt(_name_desc_offset, pc);
00391   if (_next == -1) _next = _name_desc_offset;
00392 }
00393 
00394 
00395 void MethodScopeDesc::printName() {
00396   std->print("Method");
00397 }
00398 
00399 
00400 void MethodScopeDesc::printSelf() {
00401   printIndent();
00402   std->print("self: ");
00403   self()->print();
00404   std->cr();
00405 }
00406 
00407 
00408 void MethodScopeDesc::print_value_on(outputStream* st) const {
00409   key()->print_on(st);
00410   ScopeDesc::print_value_on(st);
00411 }
00412 
00413 
00414 void BlockScopeDesc::printSelf() {
00415   ScopeDesc::printSelf();
00416   std->cr();
00417 }
00418 
00419 
00420 BlockScopeDesc::BlockScopeDesc(const nmethodScopes* scopes, int offset, char* pc)
00421   : ScopeDesc(scopes, offset, pc) {
00422   _parentScopeOffset = _scopes->unpackValueAt(_name_desc_offset);
00423   if (_next == -1) _next = _name_desc_offset;
00424 }
00425 
00426 
00427 bool BlockScopeDesc::s_equivalent(ScopeDesc* s) const {
00428   return s->isBlockScope() && ScopeDesc::s_equivalent(s);
00429 }
00430 
00431 
00432 void BlockScopeDesc::printName() {
00433   std->print("Block");
00434 }
00435 
00436 
00437 klassOop BlockScopeDesc::selfKlass() const {
00438   ScopeDesc* p = parent();
00439   return p ? p->selfKlass() : NULL;
00440 }
00441 
00442 
00443 NameDesc* BlockScopeDesc::self() const {
00444   ScopeDesc* p = parent();
00445   return p ? p->self() : NULL;
00446 }
00447 
00448 
00449 ScopeDesc* BlockScopeDesc::parent(bool cross_nmethod_boundary) const {
00450   return _parentScopeOffset ? _scopes->at(_offset - _parentScopeOffset, pc()) : NULL; 
00451 }
00452 
00453 
00454 void BlockScopeDesc::print_value_on(outputStream* st) const {
00455   st->print("block {parent %d}", _offset - _parentScopeOffset);
00456   ScopeDesc::print_value_on(st);
00457 }
00458 
00459 
00460 LookupKey* BlockScopeDesc::key() const {
00461   return LookupKey::allocate(selfKlass(), method());
00462 }
00463 
00464 
00465 LookupKey* TopLevelBlockScopeDesc::key() const {
00466   return LookupKey::allocate(selfKlass(), method());
00467 }
00468 
00469 
00470 NonInlinedBlockScopeDesc::NonInlinedBlockScopeDesc(const nmethodScopes* scopes, int offset) {
00471   _offset            = offset;
00472   _scopes            = scopes;
00473 
00474   scopeDescHeaderByte b;
00475   b.unpack(_scopes->get_next_char(offset));
00476   _method            = methodOop(scopes->unpackOopAt(offset));
00477   _parentScopeOffset = scopes->unpackValueAt(offset);
00478 }
00479 
00480 
00481 void NonInlinedBlockScopeDesc::print() {
00482   std->print("NonInlinedBlockScopeDesc\n");
00483   std->print(" - method: "); 
00484   method()->print_value();
00485   std->cr();
00486   std->print(" - parent offset: %d\n", _parentScopeOffset);
00487 }
00488 
00489 
00490 ScopeDesc* NonInlinedBlockScopeDesc::parent() const { 
00491   return _parentScopeOffset ? _scopes->at(_offset - _parentScopeOffset, ScopeDesc::invalid_pc) : NULL;
00492 }
00493 
00494 
00495 TopLevelBlockScopeDesc::TopLevelBlockScopeDesc(const nmethodScopes* scopes, int offset, char* pc)
00496   : ScopeDesc(scopes, offset, pc) {
00497   _self_name  = _scopes->unpackNameDescAt(_name_desc_offset, pc);
00498   _self_klass = klassOop(scopes->unpackOopAt(_name_desc_offset));
00499   if (_next == -1) _next = _name_desc_offset;
00500 }
00501 
00502 
00503 void TopLevelBlockScopeDesc::printSelf() {
00504   ScopeDesc::printSelf(); 
00505   std->print("self: ");
00506   self()->print();
00507   std->cr();
00508 }
00509 
00510 
00511 ScopeDesc* TopLevelBlockScopeDesc::parent(bool cross_nmethod_boundary) const {
00512   if (!cross_nmethod_boundary) return NULL;
00513   nmethod* nm = _scopes->my_nmethod();
00514   int index;
00515   nmethod* parent = nm->jump_table_entry()->parent_nmethod(index); 
00516   NonInlinedBlockScopeDesc* scope = parent->noninlined_block_scope_at(index);
00517   return scope->parent();
00518 }
00519 
00520 
00521 bool TopLevelBlockScopeDesc::s_equivalent(ScopeDesc* s) const {
00522   // programming can tranform a nested block to a top-level block
00523   return s->isBlockScope() && ScopeDesc::s_equivalent(s);
00524 }
00525 
00526 
00527 void TopLevelBlockScopeDesc::printName() {
00528   std->print("TopLevelBlock");
00529 }
00530 
00531 
00532 void TopLevelBlockScopeDesc::print_value_on(outputStream* st) const {
00533   st->print("top block");
00534   ScopeDesc::print_value_on(st);
00535 }
00536 
00537 
00538 Expr* ScopeDesc::selfExpr(PReg* p) const {
00539   klassOop self_klass = selfKlass();
00540   if (self_klass == trueObj->klass())  return new ConstantExpr(trueObj,  p, NULL);
00541   if (self_klass == falseObj->klass()) return new ConstantExpr(falseObj, p, NULL);
00542   if (self_klass == nilObj->klass())   return new ConstantExpr(nilObj,   p, NULL);
00543   return new KlassExpr(self_klass, p, NULL);
00544 }
00545 
00546 
00547 #endif
00548 

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