rframe.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.33 $ */
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 # include "incls/_precompiled.incl"
00026 
00027 #ifdef DELTA_COMPILER
00028 
00029 #include "incls/_rframe.cpp.incl"
00030 
00031 const RFrame* noCaller    = (RFrame*) 0x1;              // no caller (i.e., initial frame)
00032 const RFrame* noCallerYet = (RFrame*) 0x0;              // caller not yet computed
00033 
00034 RFrame::RFrame(frame fr, const RFrame* callee) : _fr(fr) {
00035   _caller = (RFrame*)noCallerYet;
00036   _callee = (RFrame*)callee;
00037   _invocations = _sends = _cumulSends = _loopDepth = 0;
00038   _num = callee ? callee->num() + 1 : 0;
00039   _distance = -1;
00040 }
00041 
00042 void RFrame::set_distance(int d) { 
00043   _distance = d; 
00044 }
00045 
00046 InterpretedRFrame::InterpretedRFrame(frame fr, const RFrame* callee) : RFrame(fr, callee) {
00047   vframe* vf1 = vframe::new_vframe(&_fr);
00048   assert(vf1->is_interpreted_frame(), "must be interpreted");
00049   interpretedVFrame* vf = (interpretedVFrame*)vf1;
00050   _method = vf->method();
00051   assert(_method->codes() <= _fr.hp() && _fr.hp() < _method->codes_end(),
00052          "frame doesn't match method");
00053   _bci = vf->bci();
00054   _receiverKlass = theRecompilation->receiverOf(vf)->klass();
00055   _vf = vf;
00056 }
00057 
00058 InterpretedRFrame::InterpretedRFrame(frame fr, methodOop m, klassOop rcvrKlass) : RFrame(fr, NULL) {
00059   _method = m;
00060   assert(_method->codes() <= _fr.hp() && _fr.hp() < _method->codes_end(),
00061          "frame doesn't match method");
00062   _bci = PrologueBCI;
00063   _receiverKlass = rcvrKlass;
00064   vframe* vf1 = vframe::new_vframe(&_fr);
00065   assert(vf1->is_interpreted_frame(), "must be interpreted");
00066   interpretedVFrame* vf = (interpretedVFrame*)vf1;
00067   _vf = vf;
00068   init();
00069 }
00070 
00071 CompiledRFrame::CompiledRFrame(frame fr, const RFrame* callee) : RFrame(fr, callee) {
00072 }
00073 
00074 CompiledRFrame::CompiledRFrame(frame fr) : RFrame(fr, NULL) { init(); }
00075 
00076 
00077 RFrame* RFrame::new_RFrame(frame fr, const RFrame* callee) {
00078   RFrame* rf;
00079   int dist = callee ? callee->distance() : -1;
00080   if (fr.is_interpreted_frame()) {
00081     rf = new InterpretedRFrame(fr, callee);
00082     dist++;
00083   } else if (fr.is_compiled_frame()) { 
00084     rf = new CompiledRFrame(fr, callee);
00085   } else {
00086     fatal("not a Delta frame");
00087   }
00088   rf->init();
00089   rf->set_distance(dist);
00090   return rf;
00091 }
00092 
00093 bool RFrame::is_blockMethod() const { return top_method()->is_blockMethod(); }
00094 
00095 RFrame* RFrame::caller() {
00096   if (_caller != noCallerYet) return (_caller == noCaller) ? NULL : _caller;    // already computed caller
00097   
00098   // caller not yet computed; do it now
00099   if (_fr.is_first_delta_frame()) {
00100     _caller = (RFrame*)noCaller;
00101     return NULL;
00102   } else {
00103     _caller = new_RFrame(_fr.delta_sender(), this);
00104     return _caller;
00105   }
00106 }
00107 
00108 methodOop CompiledRFrame::top_method() const {
00109   return _nm->method();
00110 }
00111 
00112 bool RFrame::is_super() const {
00113   if (is_blockMethod()) return false;
00114   IC_Iterator* it = _fr.sender_ic_iterator();
00115   return it ? it->is_super_send() : false;
00116 }
00117 
00118 bool RFrame::hasBlockArgs() const {
00119   deltaVFrame* vf = top_vframe();
00120   if (!vf) return false;
00121   int nargs = vf->method()->number_of_arguments();
00122   for (int i = 0; i < nargs; i++) {
00123     oop b = vf->argument_at(i);
00124     if (b->is_block()) return true;
00125   }
00126   return false;
00127 }
00128 
00129 GrowableArray<blockClosureOop>* RFrame::blockArgs() const {
00130   deltaVFrame* vf = top_vframe();
00131   int nargs = top_method()->number_of_arguments();
00132   GrowableArray<blockClosureOop>* blocks = new GrowableArray<blockClosureOop>(nargs);
00133   if (!vf) return blocks;
00134   for (int i = 0; i < nargs; i++) {
00135     oop b = vf->argument_at(i);
00136     if (b->is_block()) blocks->append(blockClosureOop(b));
00137   }
00138   return blocks;
00139 }
00140 
00141 LookupKey* CompiledRFrame::key() const {
00142   return &_nm->key;
00143 }
00144 
00145 LookupKey* InterpretedRFrame::key() const {
00146   if (_key) return _key;                        // cached result
00147   if (_method->is_blockMethod()) return NULL;   // has no lookup key
00148   symbolOop sel = _method->selector();
00149   ((InterpretedRFrame*)this)->_key = LookupKey::allocate(_receiverKlass, sel);
00150   // Note: this code should really be factored out somewhere; it's duplicated (at least) in lookupCache
00151   if (is_super()) {
00152     deltaVFrame* senderVF = _vf ? _vf->sender_delta_frame() : DeltaProcess::active()->last_delta_vframe();
00153     methodOop sendingMethod = senderVF->method()->home();
00154     klassOop sendingMethodHolder =_receiverKlass->klass_part()->lookup_method_holder_for(sendingMethod);
00155     if (sendingMethodHolder) {
00156       klassOop superKlass = sendingMethodHolder->klass_part()->superKlass();
00157       assert(_method == lookupCache::method_lookup(superKlass, sel),
00158              "inconsistent lookup result");
00159       _key->initialize(superKlass, sel);
00160     } else {
00161       if (WizardMode) warning("sending method holder not found??");
00162       ((InterpretedRFrame*)this)->_key = NULL;
00163     }
00164   } else {
00165     assert(_method == lookupCache::compile_time_normal_lookup(_receiverKlass, sel),
00166            "inconsistent lookup result");
00167   }
00168   return _key;
00169 }
00170 
00171 int InterpretedRFrame::cost() const {
00172   return _method->estimated_inline_cost(_receiverKlass);
00173 }
00174 
00175 int CompiledRFrame::cost() const {
00176   return _nm->instsLen();
00177 }
00178 
00179 void CompiledRFrame::cleanupStaleInlineCaches() { _nm->cleanup_inline_caches(); }
00180 void InterpretedRFrame::cleanupStaleInlineCaches() { _method->cleanup_inline_caches(); }
00181 
00182 int RFrame::computeSends(methodOop m) {
00183   // how many sends did m cause?  (rough approximation)
00184   // add up invocation counts of all methods called by m
00185   int sends = 0;
00186   CodeIterator iter(m);
00187   do {
00188     switch (iter.send()) {
00189       case Bytecodes::interpreted_send:
00190       case Bytecodes::compiled_send   :
00191       case Bytecodes::polymorphic_send:
00192       case Bytecodes::predicted_send  :
00193       case Bytecodes::accessor_send   :
00194         { InterpretedIC* ic = iter.ic();
00195           InterpretedIC_Iterator it(ic);
00196           while (!it.at_end()) {
00197             int count;
00198             if (it.is_compiled()) {
00199               sends += (count = it.compiled_method()->invocation_count());
00200             } else {
00201               sends += (count = it.interpreted_method()->invocation_count());
00202             }
00203             assert(count >= 0 && count <= 100 * 1000 * 1000, "bad invocation count");
00204             it.advance();
00205           }
00206         }
00207         break;
00208       case Bytecodes::megamorphic_send:
00209         // don't know how to count megamorphic sends; for now, just ignore them
00210         // because compiler can't eliminate them anyway
00211         break;
00212       case Bytecodes::primitive_send  : // send to method containing predicted primitive
00213       case Bytecodes::no_send         :
00214         break;
00215       default:
00216         fatal1("unexpected send type %d", iter.send());
00217     }
00218   } while (iter.advance());
00219   return sends;
00220 }
00221 
00222 static CompiledRFrame* this_rframe = NULL;
00223 static int sum_ics_result = 0;
00224 static void sum_ics(CompiledIC* ic) {
00225   // estimate ic's # of sends and add to sum_ics_result
00226   // This code is here and not in CompiledIC_Iterator because it contains policy decisions,
00227   // e.g. how to attribute sends for nmethods w/multiple callers or w/o counters.
00228   if (ic->is_empty()) return;     // no sends
00229   CompiledIC_Iterator it(ic);
00230   while (!it.at_end()) {
00231     if (it.is_compiled()) {
00232       sum_ics_result += it.compiled_method()->invocation_count();
00233     } else {
00234       sum_ics_result += it.interpreted_method()->invocation_count();
00235     }
00236     it.advance();
00237   }
00238 }
00239 
00240 void CompiledRFrame::init() {
00241   vframe* vf = vframe::new_vframe(&_fr);
00242   assert(vf->is_compiled_frame(), "must be compiled");
00243   _nm = ((compiledVFrame*)vf)->code();
00244   vf = vf->top();
00245   assert(vf->is_compiled_frame(), "must be compiled");
00246   _vf = (deltaVFrame*)vf;  
00247   _invocations = _nm->invocation_count();
00248   _ncallers = _nm->number_of_links();
00249   this_rframe = this;
00250   sum_ics_result = 0;
00251   _nm->CompiledICs_do(sum_ics);
00252   _sends += sum_ics_result;
00253 }
00254 
00255 void InterpretedRFrame::init() {
00256   // find the InlineCache
00257   if (_bci != PrologueBCI) {
00258     CodeIterator iter(_method);
00259     while (bciLT(iter.bci(), _bci)) {
00260       switch (iter.loopType()) {
00261         case Bytecodes::loop_start:     _loopDepth++; break;
00262         case Bytecodes::loop_end  :     _loopDepth--; break;
00263         case Bytecodes::no_loop   :     break;
00264         default:                        fatal1("unexpected loop type %d", iter.loopType());
00265       }
00266       if (!iter.advance()) break;
00267     }
00268     assert(iter.bci() == _bci, "should have found exact bci");
00269   }
00270   _invocations = _method->invocation_count();
00271   _ncallers = _method->sharing_count();
00272   _sends = computeSends(_method);
00273   _cumulSends = computeCumulSends(_method) + _sends;
00274   _key = NULL;
00275 }
00276 
00277 
00278 // a helper class for computing cumulCost
00279 class CumulCounter: public SpecializedMethodClosure {
00280  public:
00281   methodOop method;                     // the method currently being scanned for uplevel-accesses
00282   int cumulSends;
00283   bool top;
00284 
00285   CumulCounter(methodOop m) { cumulSends = 0; method = m; top = true;}
00286 
00287   void count() {
00288     if (!top) cumulSends += RFrame::computeSends(method);
00289     top = false;
00290     MethodIterator iter(method, this);
00291   }
00292 
00293   void allocate_closure(AllocationType type, int nofArgs, methodOop meth) { // recursively search nested blocks
00294     methodOop savedMethod = method;
00295     method = meth;
00296     count();
00297     method = savedMethod;
00298   }
00299 };
00300 
00301 
00302 int RFrame::computeCumulSends(methodOop m) {
00303   CumulCounter c(m);
00304   c.count();
00305   return c.cumulSends;
00306 }
00307 
00308 void RFrame::print(const char* kind) {
00309   lprintf("%3d %s %-15.15s: inv=%5d/%3d snd=%6d cum=%6d loop=%2d cst=%4d\n", 
00310           _num, is_interpreted() ? "I" : "C", top_method()->selector()->as_string(),  
00311           _invocations, _ncallers, _sends, _cumulSends, _loopDepth, cost());
00312 }
00313 
00314 void CompiledRFrame::print() {
00315   RFrame::print("comp");
00316 }
00317 
00318 void InterpretedRFrame::print() {
00319   RFrame::print("int.");
00320 }
00321 
00322 #endif

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