rscope.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996, LongView Technologies L.L.C. $Revision: 1.57 $ */
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/_rscope.cpp.incl"
00029 
00030 RScope::RScope(RNonDummyScope* s, int bci) : _senderBCI(bci) {
00031   _sender = s; 
00032   if (s) {
00033     s->addScope(bci, this);
00034     nsends = s->nsends;
00035   } else {
00036     nsends = -1;
00037   }
00038 }
00039 
00040 GrowableArray<RScope*>* RNullScope::subScopes(int bci) const {
00041   return new GrowableArray<RScope*>(1);
00042 }
00043 
00044 static int compare_pcDescs(PcDesc** a, PcDesc** b) {
00045   // to sort by descending scope and ascending bci
00046   int diff = (*b)->scope - (*a)->scope;
00047   return diff ? diff : (*a)->byteCode - (*b)->byteCode;
00048 }
00049   
00050 int RNonDummyScope::compare(RNonDummyScope** a,  RNonDummyScope** b) {
00051   return (*b)->scopeID() - (*a)->scopeID();
00052 }
00053   
00054 RNonDummyScope::RNonDummyScope(RNonDummyScope* s, int bci, methodOop m, int level)
00055 : RScope(s, bci),  
00056   _level(level), 
00057   uncommon(1),
00058   ncodes(m == NULL ? 1 : m->size_of_codes() * oopSize) {
00059   _subScopes = NEW_RESOURCE_ARRAY(GrowableArray<RScope*>*, ncodes + 1);
00060   for (int i = 0; i <= ncodes; i++) _subScopes[i] = NULL;
00061 }
00062 
00063 RInlinedScope::RInlinedScope(RNonDummyScope* s, int bci, const nmethod* n, ScopeDesc* d, int level)
00064 : RNonDummyScope(s, bci, d->method(), level), desc(d), nm(n) {}
00065 
00066 
00067 RPICScope::RPICScope(const nmethod* c, PcDesc* pc, CompiledIC* s, klassOop k,
00068                      ScopeDesc* dsc, nmethod* n, methodOop m, int ns, int lev, bool tr)
00069   : RNonDummyScope(NULL, pc->byteCode, m, lev), 
00070     caller(c), _sd(s), pcDesc(pc), klass(k), nm(n), _method(m), trusted(tr), desc(dsc) {
00071   nsends = ns; 
00072   extended = false;
00073 }
00074 
00075 RDatabaseScope::RDatabaseScope(RNonDummyScope* sender, int bci, klassOop receiver_klass, methodOop method, int level)
00076 : RNonDummyScope(sender, bci, method, level) {
00077   _receiver_klass = receiver_klass;
00078   _method         = method;
00079   _key            = LookupKey::allocate(receiver_klass, method->is_blockMethod() ? oop(method) : oop(_method->selector()));
00080   _uncommon       = new GrowableArray<bool>(ncodes);
00081   for (int i = 0; i <= ncodes; i++) _uncommon->append(false);
00082 }
00083 
00084 RUntakenScope::RUntakenScope(RNonDummyScope* sender, PcDesc* p, bool u)
00085   : RNonDummyScope(sender, p->byteCode, NULL, 0), isUncommon(u), pc(p) { 
00086   int i = 0;    // to allow setting breakpoints
00087 }
00088 
00089 RUninlinableScope::RUninlinableScope(RNonDummyScope* sender, int bci) : RNullScope(sender, bci) { 
00090   int i = 0;    // to allow setting breakpoints
00091 }
00092 
00093 RInterpretedScope::RInterpretedScope(RNonDummyScope* sender, int bci, LookupKey* key, 
00094                                      methodOop m, int level, bool trusted) 
00095   : RNonDummyScope(sender, bci, m, level) {
00096   _key = key; _method = m; this->nsends = m->invocation_count(); this->trusted = trusted;
00097   extended = false;
00098 }
00099 
00100 LookupKey* RInlinedScope::key() const {
00101   return desc->key();
00102 }
00103 
00104 LookupKey* RPICScope::key() const {
00105   // If we have a nmethod, return the key of the nmethod
00106   if (nm)
00107     return (LookupKey*) &nm->key;
00108 
00109   // If we have a scope desc, return the key of the scope desc
00110   if (desc)
00111     return desc->key();
00112 
00113   // If we have a send desc, return an allocated lookup key
00114   if (sd()) {
00115     return sd()->isSuperSend()
00116          ? LookupKey::allocate(klass, _method)
00117          : LookupKey::allocate(klass, _method->selector());
00118   }
00119   ShouldNotReachHere();
00120   // return nm ? (LookupKey*)&nm->key : LookupKey::allocate(klass, _method->selector()); 
00121   //                    // potential bug -- is key correct?  (super sends) -- fix this
00122   return NULL;
00123 }
00124 
00125 methodOop RInlinedScope::method() const { return desc->method(); }
00126 
00127 bool RScope::wasNeverExecuted() const {
00128   methodOop m = method();
00129   symbolOop sel = m->selector();
00130   if (InliningPolicy::isInterpreterPredictedSmiSelector(sel) ||
00131       InliningPolicy::isInterpreterPredictedBoolSelector(sel)) {
00132     // predicted methods aren't called by interpreter if prediction succeeds
00133     return false;
00134   } else {
00135     return m->was_never_executed();
00136   }
00137 }
00138 
00139 
00140 // equivalent: test whether receiver scope and argument (a InlinedScope or a LookupKey) denote the same source-level scope
00141 
00142 bool RInterpretedScope::equivalent(LookupKey* l) const {
00143   return _key->equal(l);
00144 }
00145   
00146 bool RInterpretedScope::equivalent(InlinedScope* s) const {
00147   return _key->equal(s->key());
00148 }
00149   
00150 bool RInlinedScope::equivalent(LookupKey* l) const {
00151   return desc->l_equivalent(l);
00152 }
00153   
00154 bool RInlinedScope::equivalent(InlinedScope* s) const {
00155   if (!s->isInlinedScope()) return false;
00156   InlinedScope* ss = (InlinedScope*)s;
00157   // don't use ss->rscope because it may not be set yet; but ss's sender
00158   // must have an rscope if ss is equivalent to this.
00159   return ss->senderBCI() == desc->senderBCI() &&
00160          ss->sender()->rscope == sender();
00161 }
00162   
00163 bool RPICScope::equivalent(InlinedScope* s) const {
00164   Unused(s);
00165   // an RPICScope represents a non-inlined scope, so it can't be equivalent
00166   // to any InlinedScope
00167   return false;
00168 }
00169 
00170 bool RPICScope::equivalent(LookupKey* l) const {
00171   if (desc != NULL) return desc->l_equivalent(l);   // compiled case
00172   assert(!_sd->isSuperSend(), "this code probably doesn't work for super sends");
00173   return klass == l->klass() && _method->selector() == l->selector();
00174 }
00175   
00176 RScope* RNonDummyScope::subScope(int bci, LookupKey* k) const {
00177   // return the subscope matching the lookup
00178   assert(bci >= 0 && bci < ncodes, "bci out of range");
00179   GrowableArray<RScope*>* list = _subScopes[bci];
00180   if (list == NULL) return new RNullScope;
00181   for (int i = 0; i < list->length(); i++) {
00182     RScope* rs = list->at(i);
00183     if (rs->equivalent(k))
00184       return rs;
00185   }
00186   return new RNullScope;
00187 }
00188 
00189 GrowableArray<RScope*>* RNonDummyScope::subScopes(int bci) const {
00190   // return all subscopes at bci
00191   assert(bci >= 0 && bci < ncodes, "bci out of range");
00192   GrowableArray<RScope*>* list = _subScopes[bci];
00193   if (list == NULL) return new GrowableArray<RScope*>(1);
00194   return list;
00195 }
00196 
00197 bool RNonDummyScope::hasSubScopes(int bci) const {
00198   assert(bci >= 0 && bci < ncodes, "bci out of range");
00199   return _subScopes[bci] != NULL;
00200 }
00201 
00202 void RNonDummyScope::addScope(int bci, RScope* s) {
00203   assert(bci >= 0 && bci < ncodes, "bci out of range");
00204   if (_subScopes[bci] == NULL) _subScopes[bci] = new GrowableArray<RScope*>(5);
00205   assert(!_subScopes[bci]->contains(s), "already there");
00206   // remove uninlineble markers if real scopes are added
00207   if (_subScopes[bci]->length() == 1 && _subScopes[bci]->first()->isUninlinableScope()) {
00208     _subScopes[bci]->pop();
00209   }
00210   _subScopes[bci]->append(s);
00211 }
00212 
00213 bool RInterpretedScope::isUncommonAt(int bci) const { return DeferUncommonBranches; }
00214 
00215 bool RNonDummyScope::isUncommonAt(int bci) const {
00216   if (_subScopes[bci]) {
00217     RScope* s = _subScopes[bci]->first();
00218     if (s && s->isUntakenScope()) {
00219       // send was never executed - make it uncommon
00220       return true;
00221     }
00222   }
00223   return false;
00224 }
00225 
00226 bool RNonDummyScope::isNotUncommonAt(int bci) const {
00227   assert(bci >= 0 && bci < ncodes, "bci out of range");
00228 
00229   // check if program got uncommon trap in the past
00230   for (int i = 0; i < uncommon.length(); i++) {
00231     if (uncommon.at(i)->bci() == bci) return true;
00232   }
00233 
00234   if (_subScopes[bci]) {
00235     RScope* s = _subScopes[bci]->first();
00236     if (s && !s->isUntakenScope()) {
00237       // send was executed at least once - don't make it uncommon
00238       return true;
00239     }
00240   }
00241   return false;
00242 }
00243 
00244 Expr* RScope::receiverExpr(PReg* p) const {
00245   // guess that true/false map really means true/false object
00246   // (gives more efficient testing code)
00247   klassOop k = receiverKlass();
00248   if (k == trueObj->klass()) {
00249     return new ConstantExpr(trueObj, p, NULL);
00250   } else if (k == falseObj->klass()) {
00251     return new ConstantExpr(falseObj, p, NULL);
00252   } else {
00253     return new KlassExpr(k, p, NULL);
00254   }
00255 }
00256 
00257 Expr* RUntakenScope::receiverExpr(PReg* p) const {
00258   return new UnknownExpr(p, NULL, true);
00259 }
00260 
00261 bool RInlinedScope::isLite() const      { return desc->is_lite(); }
00262 bool RPICScope::isLite() const  { return desc && desc->is_lite(); }
00263 klassOop RInterpretedScope::receiverKlass() const { return _key->klass(); }
00264 klassOop RInlinedScope::receiverKlass() const { return desc->selfKlass(); }
00265 
00266 void RNonDummyScope::unify(RNonDummyScope* s) {
00267   assert(ncodes == s->ncodes, "should be the same");
00268   for (int i = 0; i < ncodes; i++) {
00269     _subScopes[i] = s->_subScopes[i];
00270     if (_subScopes[i]) {
00271       for (int j = _subScopes[i]->length() - 1; j >= 0; j--) {
00272         _subScopes[i]->at(j)->_sender = this;
00273       }
00274     }
00275   }
00276 }
00277 
00278 void RPICScope::unify(RNonDummyScope* s) {
00279   RNonDummyScope::unify(s);
00280   if (s->isPICScope()) {
00281     uncommon.appendAll(&((RPICScope*)s)->uncommon);
00282   }
00283 
00284 }
00285 
00286 const int UntrustedPICLimit = 2;
00287 const int PICTrustLimit = 2;
00288   
00289 static void getCallees(const nmethod* nm, 
00290                        GrowableArray<PcDesc*>*&   taken_uncommon,
00291                        GrowableArray<PcDesc*>*& untaken_uncommon,
00292                        GrowableArray<PcDesc*>*& uninlinable,
00293                        GrowableArray<RNonDummyScope*>*& sends, 
00294                        bool trusted, 
00295                        int level) {
00296   // return a list of all uncommon branches of nm, plus a list
00297   // of all nmethods called by nm (in the form of PICScopes)
00298   // all lists are sorted by scope (biggest offset first)
00299   if (theCompiler && CompilerDebug) {
00300     cout(PrintRScopes)->print("%*s*searching nm %#lx \"%s\" (%strusted; %ld callers)\n", 2 * level, "",
00301                               nm, nm->key.selector()->as_string(), trusted ? "" : "not ", nm->ncallers());
00302   }
00303   taken_uncommon = new GrowableArray<PcDesc*>(1);
00304   untaken_uncommon = new GrowableArray<PcDesc*>(16);
00305   uninlinable = new GrowableArray<PcDesc*>(16);
00306   sends = new GrowableArray<RNonDummyScope*>(10);
00307   relocIterator iter(nm);
00308   while (iter.next()) {
00309     if (iter.type() == relocInfo::uncommon_type) {
00310       GrowableArray<PcDesc*>* l = iter.wasUncommonTrapExecuted() ? taken_uncommon : untaken_uncommon;
00311       l->append(nm->containingPcDesc((char*)iter.word_addr()));
00312     }
00313   }
00314 
00315   taken_uncommon->sort(&compare_pcDescs);
00316   untaken_uncommon->sort(&compare_pcDescs);
00317 
00318   if (TypeFeedback) {
00319     relocIterator iter(nm);
00320     while (iter.next()) {
00321       if (iter.type() != relocInfo::ic_type)  continue;
00322       CompiledIC* sd = iter.ic();
00323       PcDesc* p = nm->containingPcDesc((char*)sd);
00324       if (sd->wasNeverExecuted()) {
00325         // this send was never taken
00326         sends->append(new RUntakenScope(NULL, p, false));
00327       } else if (sd->isUninlinable() || sd->isMegamorphic()) {
00328         // don't inline this send
00329         uninlinable->append(p);
00330       } else {
00331         bool useInfo  = trusted || sd->ntargets() <= UntrustedPICLimit;
00332         if (useInfo) {
00333           CompiledIC_Iterator it(sd);
00334           while (!it.at_end()) {
00335             nmethod* callee = it.compiled_method();
00336             methodOop m = it.interpreted_method();
00337             ScopeDesc* desc;
00338             int count;
00339             if (callee != NULL) {
00340               // compiled target
00341               desc = callee->scopes()->root();
00342               count = callee->invocation_count() / max(1, callee->ncallers());
00343             } else {
00344               // interpreted target
00345               desc = NULL;
00346               count = m->invocation_count();
00347             }
00348             sends->append(new RPICScope(nm, p, sd, it.klass(), desc, callee, m, count, level, trusted));
00349             it.advance();
00350           }
00351         } else if (theCompiler && CompilerDebug) {
00352           cout(PrintRScopes)->print("%*s*not trusting PICs in sd %#lx \"%s\" (%ld cases)\n",
00353                                     2*level, "", sd, sd->selector()->as_string(), sd->ntargets());
00354         }
00355       }
00356     }
00357     sends->sort(&RPICScope::compare);
00358     uninlinable->sort(&compare_pcDescs);
00359   }
00360 }
00361 
00362 RNonDummyScope* RNonDummyScope::constructRScopes(const nmethod* nm, bool trusted, int level) {
00363   // construct nm's RScope tree and return the root
00364   // level > 0 means recursive invocation through a RPICScope (level
00365   // is the recursion depth); trusted means PICs info is considered accurate
00366   RNonDummyScope* current = NULL;
00367   RNonDummyScope* root = NULL;
00368   GrowableArray<PcDesc*>* taken_uncommon;
00369   GrowableArray<PcDesc*>* untaken_uncommon;
00370   GrowableArray<PcDesc*>* uninlinable;
00371   GrowableArray<RNonDummyScope*>* sends;
00372   getCallees(nm, taken_uncommon, untaken_uncommon, uninlinable, sends, trusted, level);
00373 
00374   // visit each scope in the debug info and enter it into the tree
00375   FOR_EACH_SCOPE(nm->scopes(), s) {
00376     // search s' sender RScope
00377     ScopeDesc* sender = s->sender();
00378     for (RNonDummyScope* rsender = current; rsender; rsender = rsender->sender()) {
00379       if (rsender->isInlinedScope() &&
00380           ((RInlinedScope*)rsender)->desc->is_equal(sender))
00381         break;
00382     }
00383     int bci = sender ? s->senderBCI() : IllegalBCI;
00384     current = new RInlinedScope((RInlinedScope*)rsender, bci, nm, s, level);
00385     if (!root) {
00386       root = current;
00387       root->nsends = nm->invocation_count();
00388     }
00389 
00390     // enter bcis with taken uncommon branches
00391     while (taken_uncommon->nonEmpty() && taken_uncommon->top()->scope == s->offset()) {
00392       current->uncommon.push(new RUncommonBranch(current, taken_uncommon->pop()));
00393     }
00394     // enter info from PICs
00395     while (sends->nonEmpty() && sends->top()->scopeID() == s->offset()) {
00396       RNonDummyScope* s = sends->pop();
00397       s->_sender = current; 
00398       current->addScope(s->senderBCI(), s);
00399     }
00400     // enter untaken uncommon branches
00401     PcDesc* u;
00402     while (untaken_uncommon->nonEmpty() && (u = untaken_uncommon->top())->scope == s->offset()) {
00403       new RUntakenScope(current, u, true);    // will add it as subscope of current
00404       untaken_uncommon->pop();
00405     }
00406     // enter uninlinable sends
00407     while (uninlinable->nonEmpty() && (u = uninlinable->top())->scope == s->offset()) {
00408       // only add uninlinable markers for sends that have no inlined cases
00409       int bci = u->byteCode;
00410       if (!current->hasSubScopes(bci)) {
00411         new RUninlinableScope(current, bci);    // will add it as subscope of current
00412       }
00413       uninlinable->pop();
00414     }
00415   }
00416   assert(sends           ->isEmpty(), "sends should have been connected to rscopes");
00417   assert(  taken_uncommon->isEmpty(), "taken uncommon branches should have been connected to rscopes");
00418   assert(untaken_uncommon->isEmpty(), "untaken uncommon branches should have been connected to rscopes");
00419   assert(uninlinable     ->isEmpty(), "uninlinable sends should have been connected to rscopes");
00420   return root;
00421 }
00422 
00423 void RNonDummyScope::constructSubScopes(bool trusted) {
00424   // construct all our (immediate) subscopes
00425   methodOop m = method();
00426   if (m->is_accessMethod()) return;
00427   CodeIterator iter(m);
00428   do {
00429     RNonDummyScope* s = NULL;
00430     InterpretedIC* ic = iter.ic();
00431     switch (iter.send()) {
00432       case Bytecodes::interpreted_send:
00433       case Bytecodes::compiled_send   :
00434       case Bytecodes::predicted_send  :
00435       case Bytecodes::accessor_send   :
00436       case Bytecodes::polymorphic_send:
00437       case Bytecodes::primitive_send  :
00438         { for (InterpretedIC_Iterator it(ic); !it.at_end(); it.advance()) {
00439             if (it.is_compiled()) {
00440               nmethod* nm = it.compiled_method();
00441               RNonDummyScope* s = constructRScopes(nm, trusted && trustPICs(m), _level + 1);
00442               addScope(iter.bci(), s);
00443             } else {
00444               methodOop m = it.interpreted_method();
00445               LookupKey* k = LookupKey::allocate(it.klass(), it.selector());
00446               new RInterpretedScope(this, iter.bci(), k, m, _level + 1, trusted && trustPICs(m)); 
00447               // NB: constructor adds callee to our subScope list
00448             }
00449           }
00450         }
00451         break;
00452       case Bytecodes::megamorphic_send:
00453         new RUninlinableScope(this, iter.bci());  // constructor adds callee to our subScope list
00454         break;
00455       case Bytecodes::no_send         :
00456         break;
00457       default:
00458         fatal1("unexpected send type %d", iter.send());
00459     }
00460   } while (iter.advance());
00461 }
00462 
00463 
00464 bool RNonDummyScope::trustPICs(methodOop m) {
00465   // should the PICs in m be trusted?
00466   symbolOop sel = m->selector();
00467   if (sel == vmSymbols::plus() || sel == vmSymbols::minus() ||
00468       sel == vmSymbols::multiply() || sel == vmSymbols::divide()) {
00469     // code space optimization: try to avoid unnecessary mixed-type arithmetic
00470     return false;
00471   } else {
00472     return true;        // can't easily determine number of callers
00473   }
00474 }
00475 
00476 bool RPICScope::trustPICs(const nmethod* nm) {
00477   // should the PICs in nm be trusted?
00478   int invoc = nm->invocation_count();
00479   if (invoc < MinInvocationsBeforeTrust) return false;
00480   int ncallers = nm->ncallers();
00481   symbolOop sel = nm->key.selector();
00482   if (sel == vmSymbols::plus() || sel == vmSymbols::minus() ||
00483       sel == vmSymbols::multiply() || sel == vmSymbols::divide()) {
00484     // code space optimization: try to avoid unnecessary mixed-type arithmetic
00485     return ncallers <= 1;
00486   } else {
00487     return ncallers <= PICTrustLimit;
00488   }
00489 }
00490 
00491 void RPICScope::extend() {
00492   // try to follow PIC info one level deeper (i.e. extend rscope tree)
00493   if (extended) return;
00494   if (nm && !nm->isZombie()) {
00495     // search the callee for type info
00496     RNonDummyScope* s = constructRScopes(nm, trusted && trustPICs(nm), _level + 1);
00497     // s and receiver represent the same scope - unify them
00498     unify(s);
00499   } else {
00500     constructSubScopes(false);    // search interpreted inline caches but don't trust their info
00501   }
00502   extended = true;
00503 }
00504 
00505 void RInterpretedScope::extend() {
00506   // try to follow PIC info one level deeper (i.e. extend rscope tree)
00507   if (!extended) {
00508     // search the inline caches for type info
00509     constructSubScopes(trusted);
00510     if (PrintRScopes) printTree(_senderBCI, _level);
00511   }
00512   extended = true;
00513 }
00514 
00515 void RScope::print() { 
00516   std->print("; sender: %#lx@%ld; count %ld\n", PrintHexAddresses ? _sender : 0, _senderBCI, nsends);
00517 }
00518 
00519 void RNonDummyScope::printSubScopes() const {
00520   for (int i = 0; i < ncodes && _subScopes[i] == NULL; i++) ;
00521   if (i < ncodes) {
00522     std->print("{ ");
00523     for (i = 0; i < ncodes; i++) {
00524       std->print("%#lx ", PrintHexAddresses ? _subScopes[i] : 0);
00525     }
00526     std->print("}");
00527   } else {
00528     std->print("none");
00529   }
00530 }
00531   
00532 void RInterpretedScope::print_short() {
00533   std->print("((RInterpretedScope*)%#lx) \"%s\" #%ld", PrintHexAddresses ? this : 0, _key->print_string(), nsends);
00534 }
00535   
00536 void RInlinedScope::print_short() {
00537   std->print("((RInlinedScope*)%#lx) \"%s\" #%ld", PrintHexAddresses ? this : 0, desc->selector()->as_string(), nsends);
00538 }
00539   
00540 void RInlinedScope::print() {
00541   print_short();
00542   std->print(": scope %#lx; subScopes: ", PrintHexAddresses ? desc : 0);
00543   printSubScopes();
00544   if (uncommon.nonEmpty()) { std->print("; uncommon "); uncommon.print(); }
00545   RScope::print();
00546 }
00547 
00548 void RPICScope::print_short() {
00549   std->print("((RPICScope*)%#lx) \"%s\" #%ld", PrintHexAddresses ? this : 0, method()->selector()->as_string(), nsends);
00550 }
00551   
00552 void RPICScope::print() {
00553   print_short();
00554   std->print(": IC %#lx; subScopes: ", PrintHexAddresses ? _sd : 0);
00555   printSubScopes();
00556   if (uncommon.nonEmpty()) { std->print("; uncommon "); uncommon.print(); }
00557 }
00558 
00559 void RUntakenScope::print_short() {
00560   std->print("((RUntakenScope*)%#lx) \"%s\"", PrintHexAddresses ? this : 0);
00561 }
00562 
00563 void RUntakenScope::print() {
00564   print_short();
00565   assert(!*_subScopes, "should have no subscopes");
00566   assert(uncommon.isEmpty(), "should have no uncommon branches");
00567 }
00568 
00569 void RUncommonBranch::print() {
00570   std->print("((RUncommonScope*)%#lx) : %#lx@%ld\n", PrintHexAddresses ? this : 0, PrintHexAddresses ? scope : 0, bci());
00571 }
00572 
00573 void RUninlinableScope::print_short()   { std->print("((RUninlinableScope*)%#lx)", PrintHexAddresses ? this : 0); }
00574 void RNullScope::print_short()          { std->print("((RNullScope*)%#lx)", PrintHexAddresses ? this : 0); }
00575 
00576 void RNullScope::printTree(int bci, int level) const { }
00577 
00578 void RScope::printTree(int bci, int level) const {
00579   std->print("%*s%3ld: ", level * 2, "", bci); ((RScope*)this)->print_short(); std->print("\n");
00580 }
00581 
00582 void RNonDummyScope::printTree(int senderBCI, int level) const {
00583   RScope::printTree(senderBCI, level);
00584   int u = 0;          // current position in uncommon
00585   for (int bci = 0; bci < ncodes; bci++) {
00586     if (_subScopes[bci]) {
00587       for (int j = 0; j < _subScopes[bci]->length(); j++) {
00588         _subScopes[bci]->at(j)->printTree(bci, level + 1);
00589       }
00590     }
00591     for (int j = u; j < uncommon.length() && uncommon.at(j)->bci() < bci; u++, j++) ;
00592     if (j < uncommon.length() && uncommon.at(j)->bci() == bci) {
00593       std->print("  %*s%3ld: uncommon\n", level * 2, "", bci);
00594     }
00595   }
00596 }
00597 
00598 void RDatabaseScope::print() {
00599   print_short();
00600   printSubScopes();
00601 }
00602 
00603 void RDatabaseScope::print_short() {
00604   std->print("((RDatabaseScope*)%#lx)  \"%s\"", PrintHexAddresses ? this : 0, _key->print_string());
00605 }
00606 
00607 bool RDatabaseScope::equivalent(InlinedScope* s) const {
00608   Unimplemented();
00609   return false;
00610 }
00611 
00612 bool RDatabaseScope::equivalent(LookupKey* l) const {
00613   return _key->equal(l);
00614 }
00615 
00616 bool RDatabaseScope::isUncommonAt(int bci) const {
00617   // if the DB has an uncommon branch at bci, treat it as untaken
00618   return _uncommon->at(bci);  
00619 }
00620 
00621 bool RDatabaseScope::isNotUncommonAt(int bci) const {
00622   // if there's no uncommon branch in the DB, don't use it here either
00623   return !_uncommon->at(bci);  
00624 }
00625 
00626 int  RInlinedScope::inlining_database_size() {
00627   int result = 1; // Count this node
00628 
00629   for (int i = 0; i < ncodes; i++) {
00630     if (_subScopes[i]) {
00631       for (int j = 0; j < _subScopes[i]->length(); j++) {
00632         result += _subScopes[i]->at(j)->inlining_database_size();
00633       }
00634     }
00635   }
00636   return result;
00637 }
00638 
00639 
00640 
00641 // don't file out PIC scopes in the output since they're not inlined into the current nmethod;
00642 // same for interpreted scopes 
00643 
00644 inline PcDesc* next_uncommon(int scope, int u, GrowableArray<PcDesc*>* uncommon) {
00645   if (uncommon == NULL || u >= uncommon->length()) return NULL;   // none left
00646   PcDesc* pc = uncommon->at(u);
00647   return (pc->scope == scope) ? pc : NULL;
00648 }
00649 
00650 void RUninlinableScope::print_inlining_database_on(outputStream* st, GrowableArray<PcDesc*>* uncommon, int bci, int level) {
00651   // not necessary to actually write out this info since DB-driven compilation won't inline anything not inlined in DB
00652   // st->print_cr("%*s%d uninlinable", level * 2, "", bci);
00653 }
00654 
00655 void RInlinedScope::print_inlining_database_on(outputStream* st, GrowableArray<PcDesc*>* uncommon, int bci, int level) {
00656   // File out level and bci
00657   if (bci != -1) {
00658     st->print("%*s%d ", level * 2, "", bci);
00659   }
00660 
00661   LookupKey* k = key();
00662   k->print_inlining_database_on(st);
00663   st->cr();
00664 
00665   // find scope in uncommon list
00666   int scope = desc->offset();
00667   for (int u = 0; uncommon && u < uncommon->length() - 1 && uncommon->at(u)->scope < scope; u++) ;
00668   PcDesc* current_uncommon = next_uncommon(scope, u, uncommon);
00669 
00670   // File out subscopes
00671   for (int i = 0; i < ncodes; i++) {
00672     if (_subScopes[i]) {
00673       for (int j = 0; j < _subScopes[i]->length(); j++) {
00674         _subScopes[i]->at(j)->print_inlining_database_on(st, uncommon, i, level + 1);
00675       }
00676     }
00677     if (current_uncommon && current_uncommon->byteCode == i) {
00678       // nmethod has an uncommon branch at this bci
00679       st->print_cr("%*s%d uncommon", (level + 1) * 2, "", i);
00680       // advance to next uncommon branch
00681       u++;
00682       current_uncommon = next_uncommon(scope, u, uncommon);
00683     }
00684   }
00685 }
00686 
00687 # endif

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