1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/prims/perf.cpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,321 @@ 1.4 +/* 1.5 + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "precompiled.hpp" 1.29 +#include "classfile/vmSymbols.hpp" 1.30 +#include "memory/allocation.inline.hpp" 1.31 +#include "memory/resourceArea.hpp" 1.32 +#include "oops/oop.inline.hpp" 1.33 +#include "prims/jni.h" 1.34 +#include "prims/jvm.h" 1.35 +#include "runtime/interfaceSupport.hpp" 1.36 +#include "runtime/perfData.hpp" 1.37 +#include "runtime/perfMemory.hpp" 1.38 + 1.39 +/* 1.40 + * Implementation of class sun.misc.Perf 1.41 + */ 1.42 + 1.43 + 1.44 +#define PERF_ENTRY(result_type, header) \ 1.45 + JVM_ENTRY(result_type, header) 1.46 + 1.47 +#define PERF_END JVM_END 1.48 + 1.49 +#define PerfWrapper(arg) /* Unimplemented at this time */ 1.50 + 1.51 +static char* jstr_to_utf(JNIEnv *env, jstring str, TRAPS) { 1.52 + 1.53 + char* utfstr = NULL; 1.54 + 1.55 + if (str == NULL) { 1.56 + THROW_0(vmSymbols::java_lang_NullPointerException()); 1.57 + //throw_new(env,"NullPointerException"); 1.58 + } 1.59 + 1.60 + int len = env->GetStringUTFLength(str); 1.61 + int unicode_len = env->GetStringLength(str); 1.62 + 1.63 + utfstr = NEW_RESOURCE_ARRAY(char, len + 1); 1.64 + 1.65 + env->GetStringUTFRegion(str, 0, unicode_len, utfstr); 1.66 + 1.67 + return utfstr; 1.68 +} 1.69 + 1.70 +PERF_ENTRY(jobject, Perf_Attach(JNIEnv *env, jobject unused, jstring user, int vmid, int mode)) 1.71 + 1.72 + PerfWrapper("Perf_Attach"); 1.73 + 1.74 + char* address = 0; 1.75 + size_t capacity = 0; 1.76 + const char* user_utf = NULL; 1.77 + 1.78 + ResourceMark rm; 1.79 + 1.80 + { 1.81 + ThreadToNativeFromVM ttnfv(thread); 1.82 + 1.83 + user_utf = user == NULL ? NULL : jstr_to_utf(env, user, CHECK_NULL); 1.84 + } 1.85 + 1.86 + if (mode != PerfMemory::PERF_MODE_RO && 1.87 + mode != PerfMemory::PERF_MODE_RW) { 1.88 + THROW_0(vmSymbols::java_lang_IllegalArgumentException()); 1.89 + } 1.90 + 1.91 + // attach to the PerfData memory region for the specified VM 1.92 + PerfMemory::attach(user_utf, vmid, (PerfMemory::PerfMemoryMode) mode, 1.93 + &address, &capacity, CHECK_NULL); 1.94 + 1.95 + { 1.96 + ThreadToNativeFromVM ttnfv(thread); 1.97 + return env->NewDirectByteBuffer(address, (jlong)capacity); 1.98 + } 1.99 + 1.100 +PERF_END 1.101 + 1.102 +PERF_ENTRY(void, Perf_Detach(JNIEnv *env, jobject unused, jobject buffer)) 1.103 + 1.104 + PerfWrapper("Perf_Detach"); 1.105 + 1.106 + void* address = 0; 1.107 + jlong capacity = 0; 1.108 + 1.109 + // get buffer address and capacity 1.110 + { 1.111 + ThreadToNativeFromVM ttnfv(thread); 1.112 + address = env->GetDirectBufferAddress(buffer); 1.113 + capacity = env->GetDirectBufferCapacity(buffer); 1.114 + } 1.115 + 1.116 + PerfMemory::detach((char*)address, capacity, CHECK); 1.117 + 1.118 +PERF_END 1.119 + 1.120 +PERF_ENTRY(jobject, Perf_CreateLong(JNIEnv *env, jobject perf, jstring name, 1.121 + int variability, int units, jlong value)) 1.122 + 1.123 + PerfWrapper("Perf_CreateLong"); 1.124 + 1.125 + char* name_utf = NULL; 1.126 + 1.127 + if (units <= 0 || units > PerfData::U_Last) { 1.128 + debug_only(warning("unexpected units argument, units = %d", units)); 1.129 + THROW_0(vmSymbols::java_lang_IllegalArgumentException()); 1.130 + } 1.131 + 1.132 + ResourceMark rm; 1.133 + 1.134 + { 1.135 + ThreadToNativeFromVM ttnfv(thread); 1.136 + 1.137 + name_utf = jstr_to_utf(env, name, CHECK_NULL); 1.138 + } 1.139 + 1.140 + PerfLong* pl = NULL; 1.141 + 1.142 + // check that the PerfData name doesn't already exist 1.143 + if (PerfDataManager::exists(name_utf)) { 1.144 + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfLong name already exists"); 1.145 + } 1.146 + 1.147 + switch(variability) { 1.148 + case PerfData::V_Constant: 1.149 + pl = PerfDataManager::create_long_constant(NULL_NS, (char *)name_utf, 1.150 + (PerfData::Units)units, value, 1.151 + CHECK_NULL); 1.152 + break; 1.153 + 1.154 + case PerfData::V_Monotonic: 1.155 + pl = PerfDataManager::create_long_counter(NULL_NS, (char *)name_utf, 1.156 + (PerfData::Units)units, value, 1.157 + CHECK_NULL); 1.158 + break; 1.159 + 1.160 + case PerfData::V_Variable: 1.161 + pl = PerfDataManager::create_long_variable(NULL_NS, (char *)name_utf, 1.162 + (PerfData::Units)units, value, 1.163 + CHECK_NULL); 1.164 + break; 1.165 + 1.166 + default: /* Illegal Argument */ 1.167 + debug_only(warning("unexpected variability value: %d", variability)); 1.168 + THROW_0(vmSymbols::java_lang_IllegalArgumentException()); 1.169 + break; 1.170 + } 1.171 + 1.172 + long* lp = (long*)pl->get_address(); 1.173 + 1.174 + { 1.175 + ThreadToNativeFromVM ttnfv(thread); 1.176 + return env->NewDirectByteBuffer(lp, sizeof(jlong)); 1.177 + } 1.178 + 1.179 +PERF_END 1.180 + 1.181 +PERF_ENTRY(jobject, Perf_CreateByteArray(JNIEnv *env, jobject perf, 1.182 + jstring name, jint variability, 1.183 + jint units, jbyteArray value, 1.184 + jint maxlength)) 1.185 + 1.186 + PerfWrapper("Perf_CreateByteArray"); 1.187 + 1.188 + // check for valid byte array objects 1.189 + if (name == NULL || value == NULL) { 1.190 + THROW_0(vmSymbols::java_lang_NullPointerException()); 1.191 + } 1.192 + 1.193 + // check for valid variability classification 1.194 + if (variability != PerfData::V_Constant && 1.195 + variability != PerfData::V_Variable) { 1.196 + debug_only(warning("unexpected variability value: %d", variability)); 1.197 + THROW_0(vmSymbols::java_lang_IllegalArgumentException()); 1.198 + } 1.199 + 1.200 + // check for valid units 1.201 + if (units != PerfData::U_String) { 1.202 + // only String based ByteArray objects are currently supported 1.203 + debug_only(warning("unexpected units value: %d", variability)); 1.204 + THROW_0(vmSymbols::java_lang_IllegalArgumentException()); 1.205 + } 1.206 + 1.207 + int value_length; 1.208 + char* name_utf = NULL; 1.209 + jbyte* value_local = NULL; 1.210 + 1.211 + ResourceMark rm; 1.212 + 1.213 + { 1.214 + ThreadToNativeFromVM ttnfv(thread); 1.215 + 1.216 + name_utf = jstr_to_utf(env, name, CHECK_NULL); 1.217 + 1.218 + value_length = env->GetArrayLength(value); 1.219 + 1.220 + value_local = NEW_RESOURCE_ARRAY(jbyte, value_length + 1); 1.221 + 1.222 + env->GetByteArrayRegion(value, 0, value_length, value_local); 1.223 + } 1.224 + 1.225 + // check that the counter name doesn't already exist 1.226 + if (PerfDataManager::exists((char*)name_utf)) { 1.227 + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "PerfByteArray name already exists"); 1.228 + } 1.229 + 1.230 + PerfByteArray* pbv = NULL; 1.231 + 1.232 + if (units == PerfData::U_String) { 1.233 + 1.234 + if (variability == PerfData::V_Constant) { 1.235 + // create the string constant 1.236 + pbv = PerfDataManager::create_string_constant(NULL_NS, (char*)name_utf, 1.237 + (char*)value_local, 1.238 + CHECK_NULL); 1.239 + 1.240 + assert(maxlength == value_length, "string constant length should be == maxlength"); 1.241 + maxlength = value_length; 1.242 + } 1.243 + else { 1.244 + 1.245 + // create the string variable 1.246 + pbv = PerfDataManager::create_string_variable(NULL_NS, (char*)name_utf, 1.247 + maxlength, 1.248 + (char*)value_local, 1.249 + CHECK_NULL); 1.250 + 1.251 + assert(maxlength >= value_length,"string variable length should be <= maxlength"); 1.252 + } 1.253 + } 1.254 + 1.255 + char* cp = (char*)pbv->get_address(); 1.256 + 1.257 + { 1.258 + ThreadToNativeFromVM ttnfv(thread); 1.259 + return env->NewDirectByteBuffer(cp, maxlength+1); 1.260 + } 1.261 + 1.262 +PERF_END 1.263 + 1.264 +PERF_ENTRY(jlong, Perf_HighResCounter(JNIEnv *env, jobject perf)) 1.265 + 1.266 + PerfWrapper("Perf_HighResCounter"); 1.267 + 1.268 + // this should be a method in java.lang.System. This value could 1.269 + // be acquired through access to a PerfData performance counter, but 1.270 + // doing so would require that the PerfData monitoring overhead be 1.271 + // incurred by all Java applications, which is unacceptable. 1.272 + 1.273 + return os::elapsed_counter(); 1.274 + 1.275 +PERF_END 1.276 + 1.277 +PERF_ENTRY(jlong, Perf_HighResFrequency(JNIEnv *env, jobject perf)) 1.278 + 1.279 + PerfWrapper("Perf_HighResFrequency"); 1.280 + 1.281 + // this should be a method in java.lang.System. This value could 1.282 + // be acquired through access to a PerfData performance counter, but 1.283 + // doing so would require that the PerfData monitoring overhead be 1.284 + // incurred by all Java applications, which is unacceptable. 1.285 + 1.286 + return os::elapsed_frequency(); 1.287 + 1.288 +PERF_END 1.289 + 1.290 +/// JVM_RegisterPerfMethods 1.291 + 1.292 +#define CC (char*) /*cast a literal from (const char*)*/ 1.293 +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) 1.294 +#define BB "Ljava/nio/ByteBuffer;" 1.295 +#define JLS "Ljava/lang/String;" 1.296 +#define CL_ARGS CC"("JLS"IIJ)"BB 1.297 +#define CBA_ARGS CC"("JLS"II[BI)"BB 1.298 + 1.299 +static JNINativeMethod perfmethods[] = { 1.300 + 1.301 + {CC"attach", CC"("JLS"II)"BB, FN_PTR(Perf_Attach)}, 1.302 + {CC"detach", CC"("BB")V", FN_PTR(Perf_Detach)}, 1.303 + {CC"createLong", CL_ARGS, FN_PTR(Perf_CreateLong)}, 1.304 + {CC"createByteArray", CBA_ARGS, FN_PTR(Perf_CreateByteArray)}, 1.305 + {CC"highResCounter", CC"()J", FN_PTR(Perf_HighResCounter)}, 1.306 + {CC"highResFrequency", CC"()J", FN_PTR(Perf_HighResFrequency)} 1.307 +}; 1.308 + 1.309 +#undef CBA_ARGS 1.310 +#undef CL_ARGS 1.311 +#undef JLS 1.312 +#undef BB 1.313 +#undef FN_PTR 1.314 +#undef CC 1.315 + 1.316 +// This one function is exported, used by NativeLookup. 1.317 +JVM_ENTRY(void, JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass)) 1.318 + PerfWrapper("JVM_RegisterPerfMethods"); 1.319 + { 1.320 + ThreadToNativeFromVM ttnfv(thread); 1.321 + int ok = env->RegisterNatives(perfclass, perfmethods, sizeof(perfmethods)/sizeof(JNINativeMethod)); 1.322 + guarantee(ok == 0, "register perf natives"); 1.323 + } 1.324 +JVM_END