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