src/share/vm/runtime/perfData.cpp

Fri, 28 Mar 2014 10:13:37 -0700

author
vlivanov
date
Fri, 28 Mar 2014 10:13:37 -0700
changeset 6528
248ff38d2950
parent 5237
f2110083203d
child 6680
78bbf4d43a14
permissions
-rw-r--r--

8035828: Turn on @Stable support in VM
Reviewed-by: jrose, twisti

     1 /*
     2  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "classfile/vmSymbols.hpp"
    27 #include "oops/oop.inline.hpp"
    28 #include "runtime/handles.inline.hpp"
    29 #include "runtime/java.hpp"
    30 #include "runtime/mutex.hpp"
    31 #include "runtime/mutexLocker.hpp"
    32 #include "runtime/os.hpp"
    33 #include "runtime/perfData.hpp"
    34 #include "utilities/exceptions.hpp"
    35 #include "utilities/globalDefinitions.hpp"
    37 PerfDataList*   PerfDataManager::_all = NULL;
    38 PerfDataList*   PerfDataManager::_sampled = NULL;
    39 PerfDataList*   PerfDataManager::_constants = NULL;
    41 /*
    42  * The jvmstat global and subsysem jvmstat counter name spaces. The top
    43  * level name spaces imply the interface stability level of the counter,
    44  * which generally follows the Java package, class, and property naming
    45  * conventions. The CounterNS enumeration values should be used to index
    46  * into this array.
    47  */
    48 const char* PerfDataManager::_name_spaces[] = {
    49   // top level name spaces
    50   "java",                   // stable and supported name space
    51   "com.sun",                // unstable but supported name space
    52   "sun",                    // unstable and unsupported name space
    53   // subsystem name spaces
    54   "java.gc",                // Garbage Collection name spaces
    55   "com.sun.gc",
    56   "sun.gc",
    57   "java.ci",                // Compiler name spaces
    58   "com.sun.ci",
    59   "sun.ci",
    60   "java.cls",               // Class Loader name spaces
    61   "com.sun.cls",
    62   "sun.cls",
    63   "java.rt",                // Runtime name spaces
    64   "com.sun.rt",
    65   "sun.rt",
    66   "java.os",                // Operating System name spaces
    67   "com.sun.os",
    68   "sun.os",
    69   "java.threads",           // Threads System name spaces
    70   "com.sun.threads",
    71   "sun.threads",
    72   "java.property",          // Java Property name spaces
    73   "com.sun.property",
    74   "sun.property",
    75   "",
    76 };
    78 PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v)
    79                   : _name(NULL), _u(u), _v(v), _valuep(NULL),
    80                     _on_c_heap(false) {
    82   const char* prefix = PerfDataManager::ns_to_string(ns);
    84   _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2, mtInternal);
    85   assert(_name != NULL && strlen(name) != 0, "invalid name");
    87   if (ns == NULL_NS) {
    88      // No prefix is added to counters with the NULL_NS namespace.
    89      strcpy(_name, name);
    90      // set the F_Supported flag based on the counter name prefix.
    91      if (PerfDataManager::is_stable_supported(_name) ||
    92          PerfDataManager::is_unstable_supported(_name)) {
    93        _flags = F_Supported;
    94      }
    95      else {
    96        _flags = F_None;
    97      }
    98   }
    99   else {
   100     sprintf(_name, "%s.%s", prefix, name);
   101     // set the F_Supported flag based on the given namespace.
   102     if (PerfDataManager::is_stable_supported(ns) ||
   103         PerfDataManager::is_unstable_supported(ns)) {
   104       _flags = F_Supported;
   105     }
   106     else {
   107       _flags = F_None;
   108     }
   109   }
   110 }
   112 PerfData::~PerfData() {
   113   if (_name != NULL) {
   114     FREE_C_HEAP_ARRAY(char, _name, mtInternal);
   115   }
   116   if (is_on_c_heap()) {
   117     FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep, mtInternal);
   118   }
   119 }
   121 void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
   123   size_t dlen = vlen==0 ? 1 : vlen;
   125   size_t namelen = strlen(name()) + 1;  // include null terminator
   126   size_t size = sizeof(PerfDataEntry) + namelen;
   127   size_t pad_length = ((size % dsize) == 0) ? 0 : dsize - (size % dsize);
   128   size += pad_length;
   129   size_t data_start = size;
   130   size += (dsize * dlen);
   132   // align size to assure allocation in units of 8 bytes
   133   int align = sizeof(jlong) - 1;
   134   size = ((size + align) & ~align);
   135   char* psmp = PerfMemory::alloc(size);
   137   if (psmp == NULL) {
   138     // out of PerfMemory memory resources. allocate on the C heap
   139     // to avoid vm termination.
   140     psmp = NEW_C_HEAP_ARRAY(char, size, mtInternal);
   141     _on_c_heap = true;
   142   }
   144   // compute the addresses for the name and data
   145   char* cname = psmp + sizeof(PerfDataEntry);
   147   // data is in the last dsize*dlen bytes of the entry
   148   void* valuep = (void*) (psmp + data_start);
   150   assert(is_on_c_heap() || PerfMemory::contains(cname), "just checking");
   151   assert(is_on_c_heap() || PerfMemory::contains((char*)valuep), "just checking");
   153   // copy the name, including null terminator, into PerfData memory
   154   strcpy(cname, name());
   157   // set the header values in PerfData memory
   158   PerfDataEntry* pdep = (PerfDataEntry*)psmp;
   159   pdep->entry_length = (jint)size;
   160   pdep->name_offset = (jint) ((uintptr_t) cname - (uintptr_t) psmp);
   161   pdep->vector_length = (jint)vlen;
   162   pdep->data_type = (jbyte) type2char(dtype);
   163   pdep->data_units = units();
   164   pdep->data_variability = variability();
   165   pdep->flags = (jbyte)flags();
   166   pdep->data_offset = (jint) data_start;
   168   if (PerfTraceDataCreation) {
   169     tty->print("name = %s, dtype = %d, variability = %d,"
   170                " units = %d, dsize = %d, vlen = %d,"
   171                " pad_length = %d, size = %d, on_c_heap = %s,"
   172                " address = " INTPTR_FORMAT ","
   173                " data address = " INTPTR_FORMAT "\n",
   174                cname, dtype, variability(),
   175                units(), dsize, vlen,
   176                pad_length, size, is_on_c_heap() ? "TRUE":"FALSE",
   177                psmp, valuep);
   178   }
   180   // record the start of the entry and the location of the data field.
   181   _pdep = pdep;
   182   _valuep = valuep;
   184   // mark the PerfData memory region as having been updated.
   185   PerfMemory::mark_updated();
   186 }
   188 PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
   189                  : PerfData(ns, namep, u, v) {
   191   create_entry(T_LONG, sizeof(jlong));
   192 }
   194 int PerfLong::format(char* buffer, int length) {
   195   return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep);
   196 }
   198 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
   199                                  Variability v, jlong* sampled)
   200                                 : PerfLong(ns, namep, u, v),
   201                                   _sampled(sampled), _sample_helper(NULL) {
   203   sample();
   204 }
   206 PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u,
   207                                  Variability v, PerfLongSampleHelper* helper)
   208                                 : PerfLong(ns, namep, u, v),
   209                                   _sampled(NULL), _sample_helper(helper) {
   211   sample();
   212 }
   214 void PerfLongVariant::sample() {
   216   // JJJ - This should not happen.  Maybe the first sample is taken
   217   // while the _sample_helper is being null'ed out.
   218   // assert(_sample_helper != NULL || _sampled != NULL, "unexpected state");
   219   if (_sample_helper == NULL) return;
   221   if (_sample_helper != NULL) {
   222     *(jlong*)_valuep = _sample_helper->take_sample();
   223   }
   224   else if (_sampled != NULL) {
   225     *(jlong*)_valuep = *_sampled;
   226   }
   227 }
   229 PerfByteArray::PerfByteArray(CounterNS ns, const char* namep, Units u,
   230                              Variability v, jint length)
   231                             : PerfData(ns, namep, u, v), _length(length) {
   233   create_entry(T_BYTE, sizeof(jbyte), (size_t)_length);
   234 }
   236 void PerfString::set_string(const char* s2) {
   238   // copy n bytes of the string, assuring the null string is
   239   // copied if s2 == NULL.
   240   strncpy((char *)_valuep, s2 == NULL ? "" : s2, _length);
   242   // assure the string is null terminated when strlen(s2) >= _length
   243   ((char*)_valuep)[_length-1] = '\0';
   244 }
   246 int PerfString::format(char* buffer, int length) {
   247   return jio_snprintf(buffer, length, "%s", (char*)_valuep);
   248 }
   250 PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep,
   251                                        const char* initial_value)
   252                      : PerfString(ns, namep, V_Constant,
   253                                   initial_value == NULL ? 1 :
   254                                   MIN2((jint)(strlen((char*)initial_value)+1),
   255                                        (jint)(PerfMaxStringConstLength+1)),
   256                                   initial_value) {
   258   if (PrintMiscellaneous && Verbose) {
   259     if (is_valid() && initial_value != NULL &&
   260         ((jint)strlen(initial_value) > (jint)PerfMaxStringConstLength)) {
   262       warning("Truncating PerfStringConstant: name = %s,"
   263               " length = " INT32_FORMAT ","
   264               " PerfMaxStringConstLength = " INT32_FORMAT "\n",
   265               namep,
   266               (jint)strlen(initial_value),
   267               (jint)PerfMaxStringConstLength);
   268     }
   269   }
   270 }
   277 void PerfDataManager::destroy() {
   279   if (_all == NULL)
   280     // destroy already called, or initialization never happened
   281     return;
   283   for (int index = 0; index < _all->length(); index++) {
   284     PerfData* p = _all->at(index);
   285     delete p;
   286   }
   288   delete(_all);
   289   delete(_sampled);
   290   delete(_constants);
   292   _all = NULL;
   293   _sampled = NULL;
   294   _constants = NULL;
   295 }
   297 void PerfDataManager::add_item(PerfData* p, bool sampled) {
   299   MutexLocker ml(PerfDataManager_lock);
   301   if (_all == NULL) {
   302     _all = new PerfDataList(100);
   303   }
   305   assert(!_all->contains(p->name()), "duplicate name added");
   307   // add to the list of all perf data items
   308   _all->append(p);
   310   if (p->variability() == PerfData::V_Constant) {
   311     if (_constants == NULL) {
   312       _constants = new PerfDataList(25);
   313     }
   314     _constants->append(p);
   315     return;
   316   }
   318   if (sampled) {
   319     if (_sampled == NULL) {
   320       _sampled = new PerfDataList(25);
   321     }
   322     _sampled->append(p);
   323   }
   324 }
   326 PerfData* PerfDataManager::find_by_name(const char* name) {
   327   return _all->find_by_name(name);
   328 }
   330 PerfDataList* PerfDataManager::all() {
   332   MutexLocker ml(PerfDataManager_lock);
   334   if (_all == NULL)
   335     return NULL;
   337   PerfDataList* clone = _all->clone();
   338   return clone;
   339 }
   341 PerfDataList* PerfDataManager::sampled() {
   343   MutexLocker ml(PerfDataManager_lock);
   345   if (_sampled == NULL)
   346     return NULL;
   348   PerfDataList* clone = _sampled->clone();
   349   return clone;
   350 }
   352 PerfDataList* PerfDataManager::constants() {
   354   MutexLocker ml(PerfDataManager_lock);
   356   if (_constants == NULL)
   357     return NULL;
   359   PerfDataList* clone = _constants->clone();
   360   return clone;
   361 }
   363 char* PerfDataManager::counter_name(const char* ns, const char* name) {
   364    assert(ns != NULL, "ns string required");
   365    assert(name != NULL, "name string required");
   367    size_t len = strlen(ns) + strlen(name) + 2;
   368    char* result = NEW_RESOURCE_ARRAY(char, len);
   369    sprintf(result, "%s.%s", ns, name);
   370    return result;
   371 }
   373 char* PerfDataManager::name_space(const char* ns, const char* sub,
   374                                   int instance) {
   375    char intbuf[40];
   376    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
   377    return name_space(ns, name_space(sub, intbuf));
   378 }
   380 char *PerfDataManager::name_space(const char* ns, int instance) {
   381    char intbuf[40];
   382    jio_snprintf(intbuf, 40, UINT32_FORMAT, instance);
   383    return name_space(ns, intbuf);
   384 }
   386 PerfStringConstant* PerfDataManager::create_string_constant(CounterNS ns,
   387                                                             const char* name,
   388                                                             const char* s,
   389                                                             TRAPS) {
   391   PerfStringConstant* p = new PerfStringConstant(ns, name, s);
   393   if (!p->is_valid()) {
   394     // allocation of native resources failed.
   395     delete p;
   396     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   397   }
   399   add_item(p, false);
   401   return p;
   402 }
   404 PerfLongConstant* PerfDataManager::create_long_constant(CounterNS ns,
   405                                                         const char* name,
   406                                                         PerfData::Units u,
   407                                                         jlong val, TRAPS) {
   409   PerfLongConstant* p = new PerfLongConstant(ns, name, u, val);
   411   if (!p->is_valid()) {
   412     // allocation of native resources failed.
   413     delete p;
   414     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   415   }
   417   add_item(p, false);
   419   return p;
   420 }
   422 PerfStringVariable* PerfDataManager::create_string_variable(CounterNS ns,
   423                                                             const char* name,
   424                                                             jint max_length,
   425                                                             const char* s,
   426                                                             TRAPS) {
   428   if (max_length == 0 && s != NULL) max_length = (jint)strlen(s);
   430   assert(max_length != 0, "PerfStringVariable with length 0");
   432   PerfStringVariable* p = new PerfStringVariable(ns, name, max_length, s);
   434   if (!p->is_valid()) {
   435     // allocation of native resources failed.
   436     delete p;
   437     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   438   }
   440   add_item(p, false);
   442   return p;
   443 }
   445 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
   446                                                         const char* name,
   447                                                         PerfData::Units u,
   448                                                         jlong ival, TRAPS) {
   450   PerfLongVariable* p = new PerfLongVariable(ns, name, u, ival);
   452   if (!p->is_valid()) {
   453     // allocation of native resources failed.
   454     delete p;
   455     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   456   }
   458   add_item(p, false);
   460   return p;
   461 }
   463 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
   464                                                         const char* name,
   465                                                         PerfData::Units u,
   466                                                         jlong* sp, TRAPS) {
   468   // Sampled counters not supported if UsePerfData is false
   469   if (!UsePerfData) return NULL;
   471   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp);
   473   if (!p->is_valid()) {
   474     // allocation of native resources failed.
   475     delete p;
   476     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   477   }
   479   add_item(p, true);
   481   return p;
   482 }
   484 PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns,
   485                                                         const char* name,
   486                                                         PerfData::Units u,
   487                                                         PerfSampleHelper* sh,
   488                                                         TRAPS) {
   490   // Sampled counters not supported if UsePerfData is false
   491   if (!UsePerfData) return NULL;
   493   PerfLongVariable* p = new PerfLongVariable(ns, name, u, sh);
   495   if (!p->is_valid()) {
   496     // allocation of native resources failed.
   497     delete p;
   498     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   499   }
   501   add_item(p, true);
   503   return p;
   504 }
   506 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
   507                                                       const char* name,
   508                                                       PerfData::Units u,
   509                                                       jlong ival, TRAPS) {
   511   PerfLongCounter* p = new PerfLongCounter(ns, name, u, ival);
   513   if (!p->is_valid()) {
   514     // allocation of native resources failed.
   515     delete p;
   516     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   517   }
   519   add_item(p, false);
   521   return p;
   522 }
   524 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
   525                                                       const char* name,
   526                                                       PerfData::Units u,
   527                                                       jlong* sp, TRAPS) {
   529   // Sampled counters not supported if UsePerfData is false
   530   if (!UsePerfData) return NULL;
   532   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp);
   534   if (!p->is_valid()) {
   535     // allocation of native resources failed.
   536     delete p;
   537     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   538   }
   540   add_item(p, true);
   542   return p;
   543 }
   545 PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns,
   546                                                       const char* name,
   547                                                       PerfData::Units u,
   548                                                       PerfSampleHelper* sh,
   549                                                       TRAPS) {
   551   // Sampled counters not supported if UsePerfData is false
   552   if (!UsePerfData) return NULL;
   554   PerfLongCounter* p = new PerfLongCounter(ns, name, u, sh);
   556   if (!p->is_valid()) {
   557     // allocation of native resources failed.
   558     delete p;
   559     THROW_0(vmSymbols::java_lang_OutOfMemoryError());
   560   }
   562   add_item(p, true);
   564   return p;
   565 }
   567 PerfDataList::PerfDataList(int length) {
   569   _set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(length, true);
   570 }
   572 PerfDataList::PerfDataList(PerfDataList* p) {
   574   _set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(p->length(), true);
   576   _set->appendAll(p->get_impl());
   577 }
   579 PerfDataList::~PerfDataList() {
   581   delete _set;
   583 }
   585 bool PerfDataList::by_name(void* name, PerfData* pd) {
   587   if (pd == NULL)
   588     return false;
   590   return strcmp((const char*)name, pd->name()) == 0;
   591 }
   593 PerfData* PerfDataList::find_by_name(const char* name) {
   595   // if add_item hasn't been called the list won't be initialized
   596   if (this == NULL)
   597     return NULL;
   599   int i = _set->find((void*)name, PerfDataList::by_name);
   601   if (i >= 0 && i <= _set->length())
   602     return _set->at(i);
   603   else
   604     return NULL;
   605 }
   607 PerfDataList* PerfDataList::clone() {
   609   PerfDataList* copy = new PerfDataList(this);
   611   assert(copy != NULL, "just checking");
   613   return copy;
   614 }

mercurial