debug_prims.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.49 $ */
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 # include "incls/_debug_prims.cpp.incl"
00026 
00027 TRACE_FUNC(TraceDebugPrims, "debug")
00028 
00029 int debugPrimitives::number_of_calls;
00030 
00031 PRIM_DECL_1(debugPrimitives::boolAt, oop name) {
00032   PROLOGUE_1("boolAt", name)
00033   if (!name->is_byteArray())
00034     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00035   bool result;
00036   if (debugFlags::boolAt(byteArrayOop(name)->chars(),
00037                          byteArrayOop(name)->length(),
00038                          &result))
00039     return result ? trueObj : falseObj;
00040   return markSymbol(vmSymbols::not_found());
00041 }
00042 
00043 PRIM_DECL_2(debugPrimitives::boolAtPut , oop name, oop value) {
00044   PROLOGUE_2("boolAtPut", name, value)
00045   if (!name->is_byteArray())
00046     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00047   bool b;
00048   if      (value == trueObj)  b = true;
00049   else if (value == falseObj) b = false;
00050   else return markSymbol(vmSymbols::first_argument_has_wrong_type());
00051 
00052   if (debugFlags::boolAtPut(byteArrayOop(name)->chars(),
00053                             byteArrayOop(name)->length(),
00054                             &b))
00055     return b ? trueObj : falseObj;
00056   return markSymbol(vmSymbols::not_found());
00057 }
00058 
00059 PRIM_DECL_1(debugPrimitives::smiAt, oop name) {
00060   PROLOGUE_1("smiAt", name)
00061   if (!name->is_byteArray())
00062     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00063   int result;
00064   if (debugFlags::intAt(byteArrayOop(name)->chars(),
00065                         byteArrayOop(name)->length(),
00066                         &result))
00067     return as_smiOop(result);
00068   return markSymbol(vmSymbols::not_found());
00069 }
00070 
00071 PRIM_DECL_2(debugPrimitives::smiAtPut , oop name, oop value) {
00072   PROLOGUE_2("smiAtPut", name, value)
00073   if (!name->is_byteArray())
00074     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00075   if (!value->is_smi())
00076     return markSymbol(vmSymbols::second_argument_has_wrong_type());
00077   int v = smiOop(value)->value();
00078   if (debugFlags::intAtPut(byteArrayOop(name)->chars(),
00079                            byteArrayOop(name)->length(),
00080                            &v))
00081     return as_smiOop(v);
00082   return markSymbol(vmSymbols::not_found());
00083 }
00084 
00085 PRIM_DECL_0(debugPrimitives::clearLookupCache) {
00086   PROLOGUE_0("clearLookupCache")
00087   lookupCache::flush();
00088   return trueObj;
00089 }
00090 
00091 PRIM_DECL_0(debugPrimitives::clearLookupCacheStatistics) {
00092   PROLOGUE_0("clearLookupCacheStatistics")
00093   lookupCache::clear_statistics();
00094   return trueObj;
00095 }
00096 
00097 PRIM_DECL_0(debugPrimitives::printLookupCacheStatistics) {
00098   PRIMITIVE_RETURNS_TRUE_IN_PRODUCT
00099   PROLOGUE_0("printLookupCacheStatistics")
00100   lookupCache::print_statistics();
00101   return trueObj;
00102 }
00103 
00104 PRIM_DECL_0(debugPrimitives::printMemoryLayout) {
00105   PRIMITIVE_RETURNS_TRUE_IN_PRODUCT
00106   PROLOGUE_0("printMemoryLayout")
00107   Universe::print_layout();
00108   return trueObj;
00109 }
00110 
00111 PRIM_DECL_0(debugPrimitives::decodeAllMethods) {
00112   PRIMITIVE_RETURNS_TRUE_IN_PRODUCT
00113   PROLOGUE_0("decodeAllMethods")
00114   Universe::decode_methods();
00115   return trueObj;
00116 }
00117 
00118 PRIM_DECL_2(debugPrimitives::printMethodCodes, oop receiver, oop sel) {
00119   PRIMITIVE_FAILS_IN_PRODUCT
00120   PROLOGUE_2("printMethodCodes", receiver, sel)
00121   if (!sel->is_byteArray())
00122     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00123   symbolOop s = oopFactory::new_symbol(byteArrayOop(sel));
00124   methodOop m = receiver->blueprint()->lookup(s);
00125   if (!m) return markSymbol(vmSymbols::not_found());
00126   { ResourceMark rm;
00127      if (WizardMode) m->print_codes();
00128      prettyPrinter::print(methodOop(m), receiver->klass());
00129   }
00130   return receiver;
00131 }
00132 
00133 PRIM_DECL_2(debugPrimitives::generateIR, oop receiver, oop sel) {
00134   PRIMITIVE_FAILS_IN_PRODUCT
00135   std->print_cr("primitiveGenerateIR called...");
00136   ResourceMark rm;      // needed to avoid memory leaks!
00137   PROLOGUE_2("generateIR", receiver, sel)
00138   if (!sel->is_byteArray())
00139     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00140   symbolOop s = oopFactory::new_symbol(byteArrayOop(sel));
00141   methodOop m = receiver->blueprint()->lookup(s);
00142   if (!m) return markSymbol(vmSymbols::not_found());
00143   LookupKey key(receiver->klass(), s);
00144 # ifdef DELTA_COMPILER
00145   VMProcess::execute(&VM_OptimizeMethod(&key, m));
00146 # endif
00147   return receiver;
00148 }
00149 
00150 PRIM_DECL_2(debugPrimitives::optimizeMethod, oop receiver, oop sel) {
00151   PRIMITIVE_FAILS_IN_PRODUCT
00152   PROLOGUE_2("optimizeMethod", receiver, sel);
00153 
00154   if (!sel->is_byteArray())
00155     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00156   symbolOop s = oopFactory::new_symbol(byteArrayOop(sel));
00157   methodOop m = receiver->blueprint()->lookup(s);
00158   if (!m) return markSymbol(vmSymbols::not_found());
00159 
00160 # ifdef DELTA_COMPILER
00161   LookupKey key(receiver->klass(), s);
00162   VM_OptimizeMethod op(&key, m);
00163   // The operation takes place in the vmProcess
00164   VMProcess::execute(&op);
00165 # endif
00166   return receiver;
00167 }
00168 
00169 PRIM_DECL_2(debugPrimitives::decodeMethod, oop receiver, oop sel) {
00170   PRIMITIVE_FAILS_IN_PRODUCT
00171   PROLOGUE_2("decodeMethod", receiver, sel);
00172   if (!sel->is_symbol())
00173     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00174   LookupResult result = lookupCache::ic_normal_lookup(receiver->klass(), symbolOop(sel));
00175   if (result.is_empty())
00176     return markSymbol(vmSymbols::not_found());
00177   if (result.is_method()) {
00178     // methodOop found => print byte codes
00179    ResourceMark rm;
00180    result.method()->print_codes();
00181   } else {
00182     // nmethod found => print assembly code
00183    result.get_nmethod()->printCode();
00184   }
00185   return receiver;
00186 }
00187 
00188 PRIM_DECL_0(debugPrimitives::timerStart) {
00189   PROLOGUE_0("timerStart");
00190   os::timerStart();
00191   return trueObj;
00192 }
00193 
00194 PRIM_DECL_0(debugPrimitives::timerStop) {
00195   PROLOGUE_0("timerStop");
00196   os::timerStop();
00197   return trueObj;
00198 }
00199 
00200 PRIM_DECL_0(debugPrimitives::timerPrintBuffer) {
00201   PROLOGUE_0("timerPrintBuffer");
00202   os::timerPrintBuffer();
00203   return trueObj;
00204 }
00205 
00206 PRIM_DECL_0(debugPrimitives::interpreterInvocationCounterLimit) {
00207   PROLOGUE_0("interpreterInvocationCounterLimit");
00208   int limit = Interpreter::get_invocation_counter_limit();
00209   if (limit < smi_min) limit = smi_min;
00210   else if (limit > smi_max) limit = smi_max;
00211   return as_smiOop(limit);
00212 }
00213 
00214 PRIM_DECL_1(debugPrimitives::setInterpreterInvocationCounterLimit, oop limit) {
00215   PROLOGUE_1("setInterpreterInvocationCounterLimit", limit);
00216   if (!limit->is_smi())
00217     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00218   int value = smiOop(limit)->value();
00219   if (value < 0 || value > methodOopDesc::_invocation_count_max)
00220     return markSymbol(vmSymbols::out_of_bounds());
00221   Interpreter::set_invocation_counter_limit(value);
00222   Interpreter::set_loop_counter_limit(value);   // for now - probably should have its own primitive
00223   return limit;
00224 }
00225 
00226 class ClearInvocationCounterClosure: public ObjectClosure {
00227   void do_object(memOop obj) {
00228     if (obj->is_method())
00229       methodOop(obj)->set_invocation_count(0);
00230   }
00231 };
00232 
00233 PRIM_DECL_0(debugPrimitives::clearInvocationCounters) {
00234   PROLOGUE_0("clearInvocationCounters");
00235   ClearInvocationCounterClosure blk;
00236   Universe::object_iterate(&blk);
00237   return trueObj;
00238 }
00239 
00240 // Collects all methods with invocation counter >= cutoff
00241 class CollectMethodClosure: public ObjectClosure {
00242   GrowableArray <methodOop>* col;
00243   int                        cutoff;
00244  public:
00245   CollectMethodClosure(GrowableArray <methodOop>* col, int cutoff) {
00246     this->col    = col;
00247     this->cutoff = cutoff;
00248   }
00249   void do_object(memOop obj) {
00250     if (obj->is_method())
00251       if (methodOop(obj)->invocation_count() >= cutoff)
00252         col->push(methodOop(obj));
00253   }
00254 };
00255 
00256 static int compare_method_counters(methodOop* a,  methodOop* b) {
00257   return (*b)->invocation_count() - (*a)->invocation_count();
00258 }
00259 
00260 PRIM_DECL_1(debugPrimitives::printInvocationCounterHistogram, oop size) {
00261   PRIMITIVE_FAILS_IN_PRODUCT
00262   PROLOGUE_1("printInvocationCounterHistogram", size);
00263   if (!size->is_smi())
00264     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00265   ResourceMark rm;
00266   GrowableArray <methodOop>* col = new GrowableArray<methodOop>(1024);
00267   // Collect the methods
00268   CollectMethodClosure blk(col, smiOop(size)->value());
00269   Universe::object_iterate(&blk);
00270   std->print_cr("Collected %d methods", col->length());
00271   // Sort the methods based on the invocation counters.
00272   col->sort(&compare_method_counters);
00273   // Print out the result
00274   for (int index = 0; index < col->length(); index++) {
00275     methodOop m = col->at(index);
00276     std->print("[%d] ", m->invocation_count());
00277     m->pretty_print();
00278   }
00279   return trueObj;
00280 }
00281 
00282 PRIM_DECL_0(debugPrimitives::clearInlineCaches) {
00283   PROLOGUE_0("clearInlineCaches");
00284   Universe::flush_inline_caches_in_methods();
00285   Universe::code->clear_inline_caches();
00286   Universe::code->print();
00287   return trueObj;
00288 }
00289 
00290 #define FOR_ALL_NMETHOD(var) \
00291   for (nmethod *var = Universe::code->first_nm(); var; var = Universe::code->next_nm(var))
00292 
00293 PRIM_DECL_0(debugPrimitives::clearNMethodCounters) {
00294   PROLOGUE_0("clearNMethodCounters");
00295   FOR_ALL_NMETHOD(nm) nm->set_invocation_count(0);
00296   return trueObj;
00297 }
00298 
00299 static int compare_nmethod_counters(nmethod** a, nmethod** b) {
00300   return (*b)->invocation_count() - (*a)->invocation_count();
00301 }
00302 
00303 PRIM_DECL_1(debugPrimitives::printNMethodCounterHistogram, oop size) {
00304   PRIMITIVE_FAILS_IN_PRODUCT
00305   PROLOGUE_1("printNMethodCounterHistogram", size);
00306   if (!size->is_smi())
00307     return markSymbol(vmSymbols::first_argument_has_wrong_type());
00308 
00309   ResourceMark rm;
00310   GrowableArray <nmethod*>* col = new GrowableArray<nmethod*>(1024);
00311   // Collect the nmethods
00312   FOR_ALL_NMETHOD(nm) col->push(nm);
00313 
00314   std->print_cr("Collected %d nmethods", col->length());
00315   // Sort the methods based on the invocation counters.
00316   col->sort(&compare_nmethod_counters);
00317   // Print out the result
00318   int end = (col->length() > smiOop(size)->value()) 
00319             ? smiOop(size)->value() : col->length();
00320   for (int index = 0; index < end; index++) {
00321     nmethod* m = col->at(index);
00322     std->print("[%d] ", m->invocation_count());
00323     m->scopes()->print_partition();
00324     m->method()->pretty_print();
00325   }
00326   return trueObj;
00327 }
00328 
00329 class SumMethodInvocationClosure: public ObjectClosure {
00330   int sum;
00331  public:
00332   SumMethodInvocationClosure() {
00333     sum = 0;
00334   }
00335   void do_object(memOop obj) {
00336     if (obj->is_method())
00337       sum += methodOop(obj)->invocation_count();
00338   }
00339   int result() { return sum; }
00340 };
00341 
00342 PRIM_DECL_0(debugPrimitives::numberOfMethodInvocations) {
00343   PRIMITIVE_RETURNS_ZERO_IN_PRODUCT
00344   PROLOGUE_0("numberOfMethodInvocations");
00345   SumMethodInvocationClosure blk;
00346   Universe::object_iterate(&blk);
00347   return as_smiOop(blk.result());
00348 }
00349 
00350 PRIM_DECL_0(debugPrimitives::numberOfNMethodInvocations) {
00351   PRIMITIVE_RETURNS_ZERO_IN_PRODUCT
00352   PROLOGUE_0("numberOfNMethodInvocations");
00353   int sum = 0;
00354   FOR_ALL_NMETHOD(nm) sum += nm->invocation_count();
00355   return as_smiOop(sum);
00356 }
00357 
00358 PRIM_DECL_0(debugPrimitives::numberOfPrimaryLookupCacheHits) {
00359   PRIMITIVE_RETURNS_ZERO_IN_PRODUCT
00360   PROLOGUE_0("numberOfPrimaryLookupCacheHits");
00361   return as_smiOop(lookupCache::number_of_primary_hits);
00362 }
00363 
00364 PRIM_DECL_0(debugPrimitives::numberOfSecondaryLookupCacheHits) {
00365   PRIMITIVE_RETURNS_ZERO_IN_PRODUCT
00366   PROLOGUE_0("numberOfSecondaryLookupCacheHits");
00367   return as_smiOop(lookupCache::number_of_secondary_hits);
00368 }
00369 
00370 PRIM_DECL_0(debugPrimitives::numberOfLookupCacheMisses) {
00371   PRIMITIVE_RETURNS_ZERO_IN_PRODUCT
00372   PROLOGUE_0("numberOfLookupCacheMisses");
00373   return as_smiOop(lookupCache::number_of_misses);
00374 }
00375 
00376 
00377 PRIM_DECL_0(debugPrimitives::clearPrimitiveCounters){
00378   PRIMITIVE_RETURNS_TRUE_IN_PRODUCT
00379   PROLOGUE_0("clearPrimitiveCounters");
00380   primitives::clear_counters();
00381   return trueObj;
00382 }
00383 
00384 PRIM_DECL_0(debugPrimitives::printPrimitiveCounters){
00385   PRIMITIVE_RETURNS_TRUE_IN_PRODUCT
00386   PROLOGUE_0("printPrimitiveCounters");
00387   primitives::print_counters();
00388   return trueObj;
00389 }
00390 
00391 class Counter : public ResourceObj {
00392  public:
00393    char* title;
00394    int total_size;
00395    int number;
00396    Counter(char* t) {
00397      title = t;
00398      total_size = 0;
00399      number = 0;
00400    }
00401    void update(memOop obj) { 
00402      total_size += obj->size();
00403      number++;
00404    }
00405    void print(char* prefix) {
00406      std->print("%s%s", prefix, title);
00407      std->fill_to(22);
00408      std->print_cr("%6d %8d", number, total_size * oopSize);
00409    }
00410    void add(Counter* i) {
00411      total_size += i->total_size;
00412      number     += i->number;
00413    }
00414 
00415    static int compare(Counter** a,  Counter** b) { 
00416      return (*b)->total_size - (*a)->total_size;
00417    }
00418 };
00419 
00420 class ObjectHistogram : public ObjectClosure {
00421  private:
00422   Counter* doubles;
00423   Counter* blocks;
00424   Counter* objArrays;
00425   Counter* symbols;
00426   Counter* byteArrays;
00427   Counter* doubleByteArrays;
00428   Counter* klasses;
00429   Counter* processes;
00430   Counter* vframes;
00431   Counter* methods;
00432   Counter* proxies;
00433   Counter* mixins;
00434   Counter* associations;
00435   Counter* contexts;
00436   Counter* memOops;
00437   GrowableArray<Counter*>* counters;
00438  public:
00439   ObjectHistogram();
00440 
00441   Counter* counter(memOop obj);
00442   void do_object(memOop obj) { counter(obj)->update(obj); }
00443   void print();
00444 };
00445 
00446 ObjectHistogram::ObjectHistogram() {
00447   counters = new GrowableArray<Counter*>(20);
00448   counters->push(doubles           = new Counter("doubles"));
00449   counters->push(blocks            = new Counter("blocks"));
00450   counters->push(objArrays         = new Counter("arrays"));
00451   counters->push(symbols           = new Counter("symbols"));
00452   counters->push(byteArrays        = new Counter("byte arrays"));
00453   counters->push(doubleByteArrays  = new Counter("double byte arrays"));
00454   counters->push(klasses           = new Counter("class"));
00455   counters->push(processes         = new Counter("processes"));
00456   counters->push(vframes           = new Counter("vframes"));
00457   counters->push(methods           = new Counter("methods"));
00458   counters->push(proxies           = new Counter("proxies"));
00459   counters->push(mixins            = new Counter("mixins"));
00460   counters->push(associations      = new Counter("associations"));
00461   counters->push(contexts          = new Counter("contexts"));
00462   counters->push(memOops           = new Counter("oops"));
00463 }
00464 
00465 Counter* ObjectHistogram::counter(memOop obj) {
00466   if (obj->is_double())           return doubles;
00467   if (obj->is_block())            return blocks;
00468   if (obj->is_objArray())         return objArrays;
00469   if (obj->is_symbol())           return symbols;               // Must be before byteArray
00470   if (obj->is_byteArray())        return byteArrays;
00471   if (obj->is_doubleByteArray())  return doubleByteArrays;
00472   if (obj->is_klass())            return klasses;
00473   if (obj->is_process())          return processes;
00474   if (obj->is_vframe())           return vframes;
00475   if (obj->is_method())           return methods;
00476   if (obj->is_proxy())            return proxies;
00477   if (obj->is_mixin())            return mixins;
00478   if (obj->is_association())      return associations;
00479   if (obj->is_context())          return contexts;
00480   return memOops;
00481 }
00482 
00483 void ObjectHistogram::print() {
00484   std->print("Object Histogram");
00485   std->fill_to(22);
00486   std->print_cr("number    bytes");
00487   Counter* total = new Counter("Total");
00488   counters->sort(&Counter::compare);
00489   for(int index = 0; index < counters->length(); index++) {
00490     Counter* c = counters->at(index);
00491     if (c->number > 0) {
00492       c->print(" - ");
00493       total->add(c);
00494     }
00495   }
00496   total->print(" ");
00497 }
00498 
00499 PRIM_DECL_0(debugPrimitives::printObjectHistogram) {
00500   PROLOGUE_0("printObjectHistogram");
00501   ResourceMark rm;
00502   ObjectHistogram blk;
00503   Universe::object_iterate(&blk);
00504   blk.print();
00505   return trueObj;
00506 }
00507 
00508 PRIM_DECL_0(debugPrimitives::deoptimizeStacks) {
00509   PROLOGUE_0("deoptimizeStacks");
00510   VM_DeoptimizeStacks op;
00511   // The operation takes place in the vmProcess
00512   VMProcess::execute(&op);
00513   return trueObj;
00514 }
00515 
00516 PRIM_DECL_0(debugPrimitives::verify) {
00517   PROLOGUE_0("verify");
00518   Universe::verify();
00519   return trueObj;
00520 }

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