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