src/share/vm/prims/perf.cpp

Wed, 27 Aug 2014 08:19:12 -0400

author
zgu
date
Wed, 27 Aug 2014 08:19:12 -0400
changeset 7074
833b0f92429a
parent 6198
55fb97c4c58d
child 6876
710a3c8b516e
child 9327
f96fcd9e1e1b
permissions
-rw-r--r--

8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill

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

mercurial