1 /* 2 * Copyright (c) 2004, 2017, 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 package sun.jvm.hotspot.runtime; 26 27 import java.util.*; 28 import sun.jvm.hotspot.debugger.*; 29 import sun.jvm.hotspot.oops.*; 30 import sun.jvm.hotspot.types.*; 31 import sun.jvm.hotspot.utilities.*; 32 33 public class PerfDataEntry extends VMObject { 34 private static JIntField entryLengthField; 35 private static JIntField nameOffsetField; 36 private static JIntField vectorLengthField; 37 private static JByteField dataTypeField; 38 private static JByteField flagsField; 39 private static JByteField dataUnitsField; 40 private static JByteField dataVariabilityField; 41 private static JIntField dataOffsetField; 42 43 static { 44 VM.registerVMInitializedObserver(new Observer() { 45 public void update(Observable o, Object data) { 46 initialize(VM.getVM().getTypeDataBase()); 47 } 48 }); 49 } 50 51 private static synchronized void initialize(TypeDataBase db) { 52 Type type = db.lookupType("PerfDataEntry"); 53 entryLengthField = type.getJIntField("entry_length"); 54 nameOffsetField = type.getJIntField("name_offset"); 55 vectorLengthField = type.getJIntField("vector_length"); 56 dataTypeField = type.getJByteField("data_type"); 57 flagsField = type.getJByteField("flags"); 58 dataUnitsField = type.getJByteField("data_units"); 59 dataVariabilityField = type.getJByteField("data_variability"); 60 dataOffsetField = type.getJIntField("data_offset"); 61 } 62 63 public PerfDataEntry(Address addr) { 64 super(addr); 65 } 66 67 // Accessors 68 69 public int entryLength() { 70 return (int) entryLengthField.getValue(addr); 71 } 72 73 public int nameOffset() { 74 return (int) nameOffsetField.getValue(addr); 75 } 76 77 public int vectorLength() { 78 return (int) vectorLengthField.getValue(addr); 79 } 80 81 // returns one of the constants in BasicType class 82 public int dataType() { 83 char ch = (char) (byte) dataTypeField.getValue(addr); 84 return BasicType.charToType(ch); 85 } 86 87 public byte flags() { 88 return (byte) flagsField.getValue(addr); 89 } 90 91 public boolean supported() { 92 return (flags() & 0x1) != 0; 93 } 94 95 private static class PerfDataUnits { 96 public static int U_None; 97 public static int U_Bytes; 98 public static int U_Ticks; 99 public static int U_Events; 100 public static int U_String; 101 public static int U_Hertz; 102 103 static { 104 VM.registerVMInitializedObserver(new Observer() { 105 public void update(Observable o, Object data) { 106 initialize(VM.getVM().getTypeDataBase()); 107 } 108 }); 109 } 110 private static synchronized void initialize(TypeDataBase db) { 111 U_None = db.lookupIntConstant("PerfData::U_None"); 112 U_Bytes = db.lookupIntConstant("PerfData::U_Bytes"); 113 U_Ticks = db.lookupIntConstant("PerfData::U_Ticks"); 114 U_Events = db.lookupIntConstant("PerfData::U_Events"); 115 U_String = db.lookupIntConstant("PerfData::U_String"); 116 U_Hertz = db.lookupIntConstant("PerfData::U_Hertz"); 117 } 118 } 119 120 // returns one of the constants in PerfDataUnits 121 public int dataUnits() { 122 return (int) dataUnitsField.getValue(addr); 123 } 124 125 // returns one of the constants in PerfDataVariability 126 public int dataVariability() { 127 return (int) dataVariabilityField.getValue(addr); 128 } 129 130 public int dataOffset() { 131 return (int) dataOffsetField.getValue(addr); 132 } 133 134 public String name() { 135 int off = nameOffset(); 136 return CStringUtilities.getString(addr.addOffsetTo(off)); 137 } 138 139 public boolean booleanValue() { 140 if (Assert.ASSERTS_ENABLED) { 141 Assert.that(vectorLength() == 0 && 142 dataType() == BasicType.getTBoolean(), "not a boolean"); 143 } 144 return addr.getJBooleanAt(dataOffset()); 145 } 146 147 public char charValue() { 148 if (Assert.ASSERTS_ENABLED) { 149 Assert.that(vectorLength() == 0 && 150 dataType() == BasicType.getTChar(), "not a char"); 151 } 152 return addr.getJCharAt(dataOffset()); 153 } 154 155 public byte byteValue() { 156 if (Assert.ASSERTS_ENABLED) { 157 Assert.that(vectorLength() == 0 && 158 dataType() == BasicType.getTByte(), "not a byte"); 159 } 160 return addr.getJByteAt(dataOffset()); 161 162 } 163 164 public short shortValue() { 165 if (Assert.ASSERTS_ENABLED) { 166 Assert.that(vectorLength() == 0 && 167 dataType() == BasicType.getTShort(), "not a short"); 168 } 169 return addr.getJShortAt(dataOffset()); 170 } 171 172 public int intValue() { 173 if (Assert.ASSERTS_ENABLED) { 174 Assert.that(vectorLength() == 0 && 175 dataType() == BasicType.getTInt(), "not an int"); 176 } 177 return addr.getJIntAt(dataOffset()); 178 } 179 180 public long longValue() { 181 if (Assert.ASSERTS_ENABLED) { 182 Assert.that(vectorLength() == 0 && 183 dataType() == BasicType.getTLong(), "not a long"); 184 } 185 return addr.getJLongAt(dataOffset()); 186 } 187 188 public float floatValue() { 189 if (Assert.ASSERTS_ENABLED) { 190 Assert.that(vectorLength() == 0 && 191 dataType() == BasicType.getTFloat(), "not a float"); 192 } 193 return addr.getJFloatAt(dataOffset()); 194 } 195 196 public double doubleValue() { 197 if (Assert.ASSERTS_ENABLED) { 198 Assert.that(vectorLength() == 0 && 199 dataType() == BasicType.getTDouble(), "not a double"); 200 } 201 return addr.getJDoubleAt(dataOffset()); 202 } 203 204 public boolean[] booleanArrayValue() { 205 int len = vectorLength(); 206 if (Assert.ASSERTS_ENABLED) { 207 Assert.that(len > 0 && 208 dataType() == BasicType.getTBoolean(), "not a boolean vector"); 209 } 210 boolean[] res = new boolean[len]; 211 final int off = dataOffset(); 212 final long size = getHeap().getBooleanSize(); 213 for (int i = 0; i < len; i++) { 214 res[i] = addr.getJBooleanAt(off + i * size); 215 } 216 return res; 217 } 218 219 public char[] charArrayValue() { 220 int len = vectorLength(); 221 if (Assert.ASSERTS_ENABLED) { 222 Assert.that(len > 0 && 223 dataType() == BasicType.getTChar(), "not a char vector"); 224 } 225 char[] res = new char[len]; 226 final int off = dataOffset(); 227 final long size = getHeap().getCharSize(); 228 for (int i = 0; i < len; i++) { 229 res[i] = addr.getJCharAt(off + i * size); 230 } 231 return res; 232 } 233 234 public byte[] byteArrayValue() { 235 int len = vectorLength(); 236 if (Assert.ASSERTS_ENABLED) { 237 Assert.that(len > 0 && 238 dataType() == BasicType.getTByte(), "not a byte vector"); 239 } 240 byte[] res = new byte[len]; 241 final int off = dataOffset(); 242 final long size = getHeap().getByteSize(); 243 for (int i = 0; i < len; i++) { 244 res[i] = addr.getJByteAt(off + i * size); 245 } 246 return res; 247 } 248 249 public short[] shortArrayValue() { 250 int len = vectorLength(); 251 if (Assert.ASSERTS_ENABLED) { 252 Assert.that(len > 0 && 253 dataType() == BasicType.getTShort(), "not a short vector"); 254 } 255 short[] res = new short[len]; 256 final int off = dataOffset(); 257 final long size = getHeap().getShortSize(); 258 for (int i = 0; i < len; i++) { 259 res[i] = addr.getJShortAt(off + i * size); 260 } 261 return res; 262 } 263 264 public int[] intArrayValue() { 265 int len = vectorLength(); 266 if (Assert.ASSERTS_ENABLED) { 267 Assert.that(len > 0 && 268 dataType() == BasicType.getTInt(), "not an int vector"); 269 } 270 int[] res = new int[len]; 271 final int off = dataOffset(); 272 final long size = getHeap().getIntSize(); 273 for (int i = 0; i < len; i++) { 274 res[i] = addr.getJIntAt(off + i * size); 275 } 276 return res; 277 } 278 279 public long[] longArrayValue() { 280 int len = vectorLength(); 281 if (Assert.ASSERTS_ENABLED) { 282 Assert.that(len > 0 && 283 dataType() == BasicType.getTLong(), "not a long vector"); 284 } 285 long[] res = new long[len]; 286 final int off = dataOffset(); 287 final long size = getHeap().getLongSize(); 288 for (int i = 0; i < len; i++) { 289 res[i] = addr.getJLongAt(off + i * size); 290 } 291 return res; 292 } 293 294 public float[] floatArrayValue() { 295 int len = vectorLength(); 296 if (Assert.ASSERTS_ENABLED) { 297 Assert.that(len > 0 && 298 dataType() == BasicType.getTFloat(), "not a float vector"); 299 } 300 float[] res = new float[len]; 301 final int off = dataOffset(); 302 final long size = getHeap().getFloatSize(); 303 for (int i = 0; i < len; i++) { 304 res[i] = addr.getJFloatAt(off + i * size); 305 } 306 return res; 307 } 308 309 public double[] doubleArrayValue() { 310 int len = vectorLength(); 311 if (Assert.ASSERTS_ENABLED) { 312 Assert.that(len > 0 && 313 dataType() == BasicType.getTDouble(), "not a double vector"); 314 } 315 double[] res = new double[len]; 316 final int off = dataOffset(); 317 final long size = getHeap().getDoubleSize(); 318 for (int i = 0; i < len; i++) { 319 res[i] = addr.getJDoubleAt(off + i * size); 320 } 321 return res; 322 } 323 324 // value as String 325 public String valueAsString() { 326 int dataType = dataType(); 327 int len = vectorLength(); 328 String str = null; 329 if (len == 0) { // scalar 330 if (dataType == BasicType.getTBoolean()) { 331 str = Boolean.toString(booleanValue()); 332 } else if (dataType == BasicType.getTChar()) { 333 str = "'" + Character.toString(charValue()) + "'"; 334 } else if (dataType == BasicType.getTByte()) { 335 str = Byte.toString(byteValue()); 336 } else if (dataType == BasicType.getTShort()) { 337 str = Short.toString(shortValue()); 338 } else if (dataType == BasicType.getTInt()) { 339 str = Integer.toString(intValue()); 340 } else if (dataType == BasicType.getTLong()) { 341 str = Long.toString(longValue()); 342 } else if (dataType == BasicType.getTFloat()) { 343 str = Float.toString(floatValue()); 344 } else if (dataType == BasicType.getTDouble()) { 345 str = Double.toString(doubleValue()); 346 } else { 347 str = "<unknown scalar value>"; 348 } 349 } else { // vector 350 if (dataType == BasicType.getTBoolean()) { 351 boolean[] res = booleanArrayValue(); 352 StringBuffer buf = new StringBuffer(); 353 buf.append('['); 354 for (int i = 0; i < res.length; i++) { 355 buf.append(Boolean.toString(res[i])); 356 buf.append(", "); 357 } 358 buf.append(']'); 359 str = buf.toString(); 360 } else if (dataType == BasicType.getTChar()) { 361 // char[] is returned as a String 362 str = new String(charArrayValue()); 363 } else if (dataType == BasicType.getTByte()) { 364 // byte[] is returned as a String 365 try { 366 str = new String(byteArrayValue(), "US-ASCII"); 367 } catch (java.io.UnsupportedEncodingException e) { 368 str = "can't decode string : " + e.getMessage(); 369 } 370 } else if (dataType == BasicType.getTShort()) { 371 short[] res = shortArrayValue(); 372 StringBuffer buf = new StringBuffer(); 373 buf.append('['); 374 for (int i = 0; i < res.length; i++) { 375 buf.append(Short.toString(res[i])); 376 buf.append(", "); 377 } 378 buf.append(']'); 379 str = buf.toString(); 380 } else if (dataType == BasicType.getTInt()) { 381 int[] res = intArrayValue(); 382 StringBuffer buf = new StringBuffer(); 383 buf.append('['); 384 for (int i = 0; i < res.length; i++) { 385 buf.append(Integer.toString(res[i])); 386 buf.append(", "); 387 } 388 buf.append(']'); 389 str = buf.toString(); 390 } else if (dataType == BasicType.getTLong()) { 391 long[] res = longArrayValue(); 392 StringBuffer buf = new StringBuffer(); 393 buf.append('['); 394 for (int i = 0; i < res.length; i++) { 395 buf.append(Long.toString(res[i])); 396 buf.append(", "); 397 } 398 buf.append(']'); 399 str = buf.toString(); 400 } else if (dataType == BasicType.getTFloat()) { 401 float[] res = floatArrayValue(); 402 StringBuffer buf = new StringBuffer(); 403 buf.append('['); 404 for (int i = 0; i < res.length; i++) { 405 buf.append(Float.toString(res[i])); 406 buf.append(", "); 407 } 408 buf.append(']'); 409 str = buf.toString(); 410 } else if (dataType == BasicType.getTDouble()) { 411 double[] res = doubleArrayValue(); 412 StringBuffer buf = new StringBuffer(); 413 buf.append('['); 414 for (int i = 0; i < res.length; i++) { 415 buf.append(Double.toString(res[i])); 416 buf.append(", "); 417 } 418 buf.append(']'); 419 str = buf.toString(); 420 } else { 421 str = "<unknown vector value>"; 422 } 423 } 424 425 // add units 426 int dataUnitsValue = dataUnits(); 427 428 if (dataUnitsValue == PerfDataUnits.U_Bytes) { 429 str += " byte(s)"; 430 } else if (dataUnitsValue == PerfDataUnits.U_Ticks) { 431 str += " tick(s)"; 432 } else if (dataUnitsValue == PerfDataUnits.U_Events) { 433 str += " event(s)"; 434 } else if (dataUnitsValue == PerfDataUnits.U_Hertz) { 435 str += " Hz"; 436 } 437 438 return str; 439 } 440 441 // -- Internals only below this point 442 private ObjectHeap getHeap() { 443 return VM.getVM().getObjectHeap(); 444 } 445 }