src/share/vm/prims/perf.cpp

Tue, 08 Aug 2017 15:57:29 +0800

author
aoqi
date
Tue, 08 Aug 2017 15:57:29 +0800
changeset 6876
710a3c8b516e
parent 6198
55fb97c4c58d
parent 0
f90c822e73f8
child 9448
73d689add964
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation.
aoqi@0 8 *
aoqi@0 9 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 12 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 13 * accompanied this code).
aoqi@0 14 *
aoqi@0 15 * You should have received a copy of the GNU General Public License version
aoqi@0 16 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 18 *
aoqi@0 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 20 * or visit www.oracle.com if you need additional information or have any
aoqi@0 21 * questions.
aoqi@0 22 *
aoqi@0 23 */
aoqi@0 24
aoqi@0 25 #include "precompiled.hpp"
aoqi@0 26 #include "classfile/vmSymbols.hpp"
aoqi@0 27 #include "memory/allocation.inline.hpp"
aoqi@0 28 #include "memory/resourceArea.hpp"
aoqi@0 29 #include "oops/oop.inline.hpp"
aoqi@0 30 #include "prims/jni.h"
aoqi@0 31 #include "prims/jvm.h"
aoqi@0 32 #include "runtime/interfaceSupport.hpp"
aoqi@0 33 #include "runtime/perfData.hpp"
aoqi@0 34 #include "runtime/perfMemory.hpp"
aoqi@0 35
aoqi@0 36 /*
aoqi@0 37 * Implementation of class sun.misc.Perf
aoqi@0 38 */
aoqi@0 39
aoqi@0 40
aoqi@0 41 #define PERF_ENTRY(result_type, header) \
aoqi@0 42 JVM_ENTRY(result_type, header)
aoqi@0 43
aoqi@0 44 #define PERF_END JVM_END
aoqi@0 45
aoqi@0 46 #define PerfWrapper(arg) /* Unimplemented at this time */
aoqi@0 47
aoqi@0 48 static char* jstr_to_utf(JNIEnv *env, jstring str, TRAPS) {
aoqi@0 49
aoqi@0 50 char* utfstr = NULL;
aoqi@0 51
aoqi@0 52 if (str == NULL) {
aoqi@0 53 THROW_0(vmSymbols::java_lang_NullPointerException());
aoqi@0 54 //throw_new(env,"NullPointerException");
aoqi@0 55 }
aoqi@0 56
aoqi@0 57 int len = env->GetStringUTFLength(str);
aoqi@0 58 int unicode_len = env->GetStringLength(str);
aoqi@0 59
aoqi@0 60 utfstr = NEW_RESOURCE_ARRAY(char, len + 1);
aoqi@0 61
aoqi@0 62 env->GetStringUTFRegion(str, 0, unicode_len, utfstr);
aoqi@0 63
aoqi@0 64 return utfstr;
aoqi@0 65 }
aoqi@0 66
aoqi@0 67 PERF_ENTRY(jobject, Perf_Attach(JNIEnv *env, jobject unused, jstring user, int vmid, int mode))
aoqi@0 68
aoqi@0 69 PerfWrapper("Perf_Attach");
aoqi@0 70
aoqi@0 71 char* address = 0;
aoqi@0 72 size_t capacity = 0;
aoqi@0 73 const char* user_utf = NULL;
aoqi@0 74
aoqi@0 75 ResourceMark rm;
aoqi@0 76
aoqi@0 77 {
aoqi@0 78 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 79
aoqi@0 80 user_utf = user == NULL ? NULL : jstr_to_utf(env, user, CHECK_NULL);
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 if (mode != PerfMemory::PERF_MODE_RO &&
aoqi@0 84 mode != PerfMemory::PERF_MODE_RW) {
aoqi@0 85 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
aoqi@0 86 }
aoqi@0 87
aoqi@0 88 // attach to the PerfData memory region for the specified VM
aoqi@0 89 PerfMemory::attach(user_utf, vmid, (PerfMemory::PerfMemoryMode) mode,
aoqi@0 90 &address, &capacity, CHECK_NULL);
aoqi@0 91
aoqi@0 92 {
aoqi@0 93 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 94 return env->NewDirectByteBuffer(address, (jlong)capacity);
aoqi@0 95 }
aoqi@0 96
aoqi@0 97 PERF_END
aoqi@0 98
aoqi@0 99 PERF_ENTRY(void, Perf_Detach(JNIEnv *env, jobject unused, jobject buffer))
aoqi@0 100
aoqi@0 101 PerfWrapper("Perf_Detach");
aoqi@0 102
aoqi@0 103 void* address = 0;
aoqi@0 104 jlong capacity = 0;
aoqi@0 105
aoqi@0 106 // get buffer address and capacity
aoqi@0 107 {
aoqi@0 108 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 109 address = env->GetDirectBufferAddress(buffer);
aoqi@0 110 capacity = env->GetDirectBufferCapacity(buffer);
aoqi@0 111 }
aoqi@0 112
aoqi@0 113 PerfMemory::detach((char*)address, capacity, CHECK);
aoqi@0 114
aoqi@0 115 PERF_END
aoqi@0 116
aoqi@0 117 PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name,
aoqi@0 118 int variability, int units, jlong value))
aoqi@0 119
aoqi@0 120 PerfWrapper("Perf_CreateLong");
aoqi@0 121
aoqi@0 122 char* name_utf = NULL;
aoqi@0 123
aoqi@0 124 if (units <= 0 || units > PerfData::U_Last) {
aoqi@0 125 debug_only(warning("unexpected units argument, units = %d", units));
aoqi@0 126 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
aoqi@0 127 }
aoqi@0 128
aoqi@0 129 ResourceMark rm;
aoqi@0 130
aoqi@0 131 {
aoqi@0 132 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 133
aoqi@0 134 name_utf = jstr_to_utf(env, name, CHECK_NULL);
aoqi@0 135 }
aoqi@0 136
aoqi@0 137 PerfLong* pl = NULL;
aoqi@0 138
aoqi@0 139 // check that the PerfData name doesn't already exist
aoqi@0 140 if (PerfDataManager::exists(name_utf)) {
aoqi@0 141 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfLong name already exists");
aoqi@0 142 }
aoqi@0 143
aoqi@0 144 switch(variability) {
aoqi@0 145 case PerfData::V_Constant:
aoqi@0 146 pl = PerfDataManager::create_long_constant(NULL_NS, (char *)name_utf,
aoqi@0 147 (PerfData::Units)units, value,
aoqi@0 148 CHECK_NULL);
aoqi@0 149 break;
aoqi@0 150
aoqi@0 151 case PerfData::V_Monotonic:
aoqi@0 152 pl = PerfDataManager::create_long_counter(NULL_NS, (char *)name_utf,
aoqi@0 153 (PerfData::Units)units, value,
aoqi@0 154 CHECK_NULL);
aoqi@0 155 break;
aoqi@0 156
aoqi@0 157 case PerfData::V_Variable:
aoqi@0 158 pl = PerfDataManager::create_long_variable(NULL_NS, (char *)name_utf,
aoqi@0 159 (PerfData::Units)units, value,
aoqi@0 160 CHECK_NULL);
aoqi@0 161 break;
aoqi@0 162
aoqi@0 163 default: /* Illegal Argument */
aoqi@0 164 debug_only(warning("unexpected variability value: %d", variability));
aoqi@0 165 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
aoqi@0 166 break;
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 long* lp = (long*)pl->get_address();
aoqi@0 170
aoqi@0 171 {
aoqi@0 172 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 173 return env->NewDirectByteBuffer(lp, sizeof(jlong));
aoqi@0 174 }
aoqi@0 175
aoqi@0 176 PERF_END
aoqi@0 177
aoqi@0 178 PERF_ENTRY(jobject, Perf_CreateByteArray(JNIEnv *env, jobject perf,
aoqi@0 179 jstring name, jint variability,
aoqi@0 180 jint units, jbyteArray value,
aoqi@0 181 jint maxlength))
aoqi@0 182
aoqi@0 183 PerfWrapper("Perf_CreateByteArray");
aoqi@0 184
aoqi@0 185 // check for valid byte array objects
aoqi@0 186 if (name == NULL || value == NULL) {
aoqi@0 187 THROW_0(vmSymbols::java_lang_NullPointerException());
aoqi@0 188 }
aoqi@0 189
aoqi@0 190 // check for valid variability classification
aoqi@0 191 if (variability != PerfData::V_Constant &&
aoqi@0 192 variability != PerfData::V_Variable) {
aoqi@0 193 debug_only(warning("unexpected variability value: %d", variability));
aoqi@0 194 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
aoqi@0 195 }
aoqi@0 196
aoqi@0 197 // check for valid units
aoqi@0 198 if (units != PerfData::U_String) {
aoqi@0 199 // only String based ByteArray objects are currently supported
aoqi@0 200 debug_only(warning("unexpected units value: %d", variability));
aoqi@0 201 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
aoqi@0 202 }
aoqi@0 203
aoqi@0 204 int value_length;
aoqi@0 205 char* name_utf = NULL;
aoqi@0 206 jbyte* value_local = NULL;
aoqi@0 207
aoqi@0 208 ResourceMark rm;
aoqi@0 209
aoqi@0 210 {
aoqi@0 211 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 212
aoqi@0 213 name_utf = jstr_to_utf(env, name, CHECK_NULL);
aoqi@0 214
aoqi@0 215 value_length = env->GetArrayLength(value);
aoqi@0 216
aoqi@0 217 value_local = NEW_RESOURCE_ARRAY(jbyte, value_length + 1);
aoqi@0 218
aoqi@0 219 env->GetByteArrayRegion(value, 0, value_length, value_local);
aoqi@0 220 }
aoqi@0 221
aoqi@0 222 // check that the counter name doesn't already exist
aoqi@0 223 if (PerfDataManager::exists((char*)name_utf)) {
aoqi@0 224 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfByteArray name already exists");
aoqi@0 225 }
aoqi@0 226
aoqi@0 227 PerfByteArray* pbv = NULL;
aoqi@0 228
aoqi@0 229 if (units == PerfData::U_String) {
aoqi@0 230
aoqi@0 231 if (variability == PerfData::V_Constant) {
aoqi@0 232 // create the string constant
aoqi@0 233 pbv = PerfDataManager::create_string_constant(NULL_NS, (char*)name_utf,
aoqi@0 234 (char*)value_local,
aoqi@0 235 CHECK_NULL);
aoqi@0 236
aoqi@0 237 assert(maxlength == value_length, "string constant length should be == maxlength");
aoqi@0 238 maxlength = value_length;
aoqi@0 239 }
aoqi@0 240 else {
aoqi@0 241
aoqi@0 242 // create the string variable
aoqi@0 243 pbv = PerfDataManager::create_string_variable(NULL_NS, (char*)name_utf,
aoqi@0 244 maxlength,
aoqi@0 245 (char*)value_local,
aoqi@0 246 CHECK_NULL);
aoqi@0 247
aoqi@0 248 assert(maxlength >= value_length,"string variable length should be <= maxlength");
aoqi@0 249 }
aoqi@0 250 }
aoqi@0 251
aoqi@0 252 char* cp = (char*)pbv->get_address();
aoqi@0 253
aoqi@0 254 {
aoqi@0 255 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 256 return env->NewDirectByteBuffer(cp, maxlength+1);
aoqi@0 257 }
aoqi@0 258
aoqi@0 259 PERF_END
aoqi@0 260
aoqi@0 261 PERF_ENTRY(jlong, Perf_HighResCounter(JNIEnv *env, jobject perf))
aoqi@0 262
aoqi@0 263 PerfWrapper("Perf_HighResCounter");
aoqi@0 264
aoqi@0 265 // this should be a method in java.lang.System. This value could
aoqi@0 266 // be acquired through access to a PerfData performance counter, but
aoqi@0 267 // doing so would require that the PerfData monitoring overhead be
aoqi@0 268 // incurred by all Java applications, which is unacceptable.
aoqi@0 269
aoqi@0 270 return os::elapsed_counter();
aoqi@0 271
aoqi@0 272 PERF_END
aoqi@0 273
aoqi@0 274 PERF_ENTRY(jlong, Perf_HighResFrequency(JNIEnv *env, jobject perf))
aoqi@0 275
aoqi@0 276 PerfWrapper("Perf_HighResFrequency");
aoqi@0 277
aoqi@0 278 // this should be a method in java.lang.System. This value could
aoqi@0 279 // be acquired through access to a PerfData performance counter, but
aoqi@0 280 // doing so would require that the PerfData monitoring overhead be
aoqi@0 281 // incurred by all Java applications, which is unacceptable.
aoqi@0 282
aoqi@0 283 return os::elapsed_frequency();
aoqi@0 284
aoqi@0 285 PERF_END
aoqi@0 286
aoqi@0 287 /// JVM_RegisterPerfMethods
aoqi@0 288
aoqi@0 289 #define CC (char*) /*cast a literal from (const char*)*/
aoqi@0 290 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
aoqi@0 291 #define BB "Ljava/nio/ByteBuffer;"
aoqi@0 292 #define JLS "Ljava/lang/String;"
aoqi@0 293 #define CL_ARGS CC"("JLS"IIJ)"BB
aoqi@0 294 #define CBA_ARGS CC"("JLS"II[BI)"BB
aoqi@0 295
aoqi@0 296 static JNINativeMethod perfmethods[] = {
aoqi@0 297
aoqi@0 298 {CC"attach", CC"("JLS"II)"BB, FN_PTR(Perf_Attach)},
aoqi@0 299 {CC"detach", CC"("BB")V", FN_PTR(Perf_Detach)},
aoqi@0 300 {CC"createLong", CL_ARGS, FN_PTR(Perf_CreateLong)},
aoqi@0 301 {CC"createByteArray", CBA_ARGS, FN_PTR(Perf_CreateByteArray)},
aoqi@0 302 {CC"highResCounter", CC"()J", FN_PTR(Perf_HighResCounter)},
aoqi@0 303 {CC"highResFrequency", CC"()J", FN_PTR(Perf_HighResFrequency)}
aoqi@0 304 };
aoqi@0 305
aoqi@0 306 #undef CBA_ARGS
aoqi@0 307 #undef CL_ARGS
aoqi@0 308 #undef JLS
aoqi@0 309 #undef BB
aoqi@0 310 #undef FN_PTR
aoqi@0 311 #undef CC
aoqi@0 312
aoqi@0 313 // This one function is exported, used by NativeLookup.
aoqi@0 314 JVM_ENTRY(void, JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass))
aoqi@0 315 PerfWrapper("JVM_RegisterPerfMethods");
aoqi@0 316 {
aoqi@0 317 ThreadToNativeFromVM ttnfv(thread);
aoqi@0 318 int ok = env->RegisterNatives(perfclass, perfmethods, sizeof(perfmethods)/sizeof(JNINativeMethod));
aoqi@0 319 guarantee(ok == 0, "register perf natives");
aoqi@0 320 }
aoqi@0 321 JVM_END

mercurial