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 // NOTE: Keep this in sync with PerfData::Units enum in VM code 96 public interface PerfDataUnits { 97 public static final int U_None = 1; 98 public static final int U_Bytes = 2; 99 public static final int U_Ticks = 3; 100 public static final int U_Events = 4; 101 public static final int U_String = 5; 102 public static final int U_Hertz = 6; 103 } 104 105 // returns one of the constants in PerfDataUnits 106 public int dataUnits() { 107 return (int) dataUnitsField.getValue(addr); 108 } 109 110 // NOTE: Keep this in sync with PerfData::Variability enum in VM code 111 public interface PerfDataVariability { 112 public static final int V_Constant = 1; 113 public static final int V_Monotonic = 2; 114 public static final int V_Variable = 3; 115 } 116 117 // returns one of the constants in PerfDataVariability 118 public int dataVariability() { 119 return (int) dataVariabilityField.getValue(addr); 120 } 121 122 public int dataOffset() { 123 return (int) dataOffsetField.getValue(addr); 124 } 125 126 public String name() { 127 int off = nameOffset(); 128 return CStringUtilities.getString(addr.addOffsetTo(off)); 129 } 130 131 public boolean booleanValue() { 132 if (Assert.ASSERTS_ENABLED) { 133 Assert.that(vectorLength() == 0 && 134 dataType() == BasicType.getTBoolean(), "not a boolean"); 135 } 136 return addr.getJBooleanAt(dataOffset()); 137 } 138 139 public char charValue() { 140 if (Assert.ASSERTS_ENABLED) { 141 Assert.that(vectorLength() == 0 && 142 dataType() == BasicType.getTChar(), "not a char"); 143 } 144 return addr.getJCharAt(dataOffset()); 145 } 146 147 public byte byteValue() { 148 if (Assert.ASSERTS_ENABLED) { 149 Assert.that(vectorLength() == 0 && 150 dataType() == BasicType.getTByte(), "not a byte"); 151 } 152 return addr.getJByteAt(dataOffset()); 153 154 } 155 156 public short shortValue() { 157 if (Assert.ASSERTS_ENABLED) { 158 Assert.that(vectorLength() == 0 && 159 dataType() == BasicType.getTShort(), "not a short"); 160 } 161 return addr.getJShortAt(dataOffset()); 162 } 163 164 public int intValue() { 165 if (Assert.ASSERTS_ENABLED) { 166 Assert.that(vectorLength() == 0 && 167 dataType() == BasicType.getTInt(), "not an int"); 168 } 169 return addr.getJIntAt(dataOffset()); 170 } 171 172 public long longValue() { 173 if (Assert.ASSERTS_ENABLED) { 174 Assert.that(vectorLength() == 0 && 175 dataType() == BasicType.getTLong(), "not a long"); 176 } 177 return addr.getJLongAt(dataOffset()); 178 } 179 180 public float floatValue() { 181 if (Assert.ASSERTS_ENABLED) { 182 Assert.that(vectorLength() == 0 && 183 dataType() == BasicType.getTFloat(), "not a float"); 184 } 185 return addr.getJFloatAt(dataOffset()); 186 } 187 188 public double doubleValue() { 189 if (Assert.ASSERTS_ENABLED) { 190 Assert.that(vectorLength() == 0 && 191 dataType() == BasicType.getTDouble(), "not a double"); 192 } 193 return addr.getJDoubleAt(dataOffset()); 194 } 195 196 public boolean[] booleanArrayValue() { 197 int len = vectorLength(); 198 if (Assert.ASSERTS_ENABLED) { 199 Assert.that(len > 0 && 200 dataType() == BasicType.getTBoolean(), "not a boolean vector"); 201 } 202 boolean[] res = new boolean[len]; 203 final int off = dataOffset(); 204 final long size = getHeap().getBooleanSize(); 205 for (int i = 0; i < len; i++) { 206 res[i] = addr.getJBooleanAt(off + i * size); 207 } 208 return res; 209 } 210 211 public char[] charArrayValue() { 212 int len = vectorLength(); 213 if (Assert.ASSERTS_ENABLED) { 214 Assert.that(len > 0 && 215 dataType() == BasicType.getTChar(), "not a char vector"); 216 } 217 char[] res = new char[len]; 218 final int off = dataOffset(); 219 final long size = getHeap().getCharSize(); 220 for (int i = 0; i < len; i++) { 221 res[i] = addr.getJCharAt(off + i * size); 222 } 223 return res; 224 } 225 226 public byte[] byteArrayValue() { 227 int len = vectorLength(); 228 if (Assert.ASSERTS_ENABLED) { 229 Assert.that(len > 0 && 230 dataType() == BasicType.getTByte(), "not a byte vector"); 231 } 232 byte[] res = new byte[len]; 233 final int off = dataOffset(); 234 final long size = getHeap().getByteSize(); 235 for (int i = 0; i < len; i++) { 236 res[i] = addr.getJByteAt(off + i * size); 237 } 238 return res; 239 } 240 241 public short[] shortArrayValue() { 242 int len = vectorLength(); 243 if (Assert.ASSERTS_ENABLED) { 244 Assert.that(len > 0 && 245 dataType() == BasicType.getTShort(), "not a short vector"); 246 } 247 short[] res = new short[len]; 248 final int off = dataOffset(); 249 final long size = getHeap().getShortSize(); 250 for (int i = 0; i < len; i++) { 251 res[i] = addr.getJShortAt(off + i * size); 252 } 253 return res; 254 } 255 256 public int[] intArrayValue() { 257 int len = vectorLength(); 258 if (Assert.ASSERTS_ENABLED) { 259 Assert.that(len > 0 && 260 dataType() == BasicType.getTInt(), "not an int vector"); 261 } 262 int[] res = new int[len]; 263 final int off = dataOffset(); 264 final long size = getHeap().getIntSize(); 265 for (int i = 0; i < len; i++) { 266 res[i] = addr.getJIntAt(off + i * size); 267 } 268 return res; 269 } 270 271 public long[] longArrayValue() { 272 int len = vectorLength(); 273 if (Assert.ASSERTS_ENABLED) { 274 Assert.that(len > 0 && 275 dataType() == BasicType.getTLong(), "not a long vector"); 276 } 277 long[] res = new long[len]; 278 final int off = dataOffset(); 279 final long size = getHeap().getLongSize(); 280 for (int i = 0; i < len; i++) { 281 res[i] = addr.getJLongAt(off + i * size); 282 } 283 return res; 284 } 285 286 public float[] floatArrayValue() { 287 int len = vectorLength(); 288 if (Assert.ASSERTS_ENABLED) { 289 Assert.that(len > 0 && 290 dataType() == BasicType.getTFloat(), "not a float vector"); 291 } 292 float[] res = new float[len]; 293 final int off = dataOffset(); 294 final long size = getHeap().getFloatSize(); 295 for (int i = 0; i < len; i++) { 296 res[i] = addr.getJFloatAt(off + i * size); 297 } 298 return res; 299 } 300 301 public double[] doubleArrayValue() { 302 int len = vectorLength(); 303 if (Assert.ASSERTS_ENABLED) { 304 Assert.that(len > 0 && 305 dataType() == BasicType.getTDouble(), "not a double vector"); 306 } 307 double[] res = new double[len]; 308 final int off = dataOffset(); 309 final long size = getHeap().getDoubleSize(); 310 for (int i = 0; i < len; i++) { 311 res[i] = addr.getJDoubleAt(off + i * size); 312 } 313 return res; 314 } 315 316 // value as String 317 public String valueAsString() { 318 int dataType = dataType(); 319 int len = vectorLength(); 320 String str = null; 321 if (len == 0) { // scalar 322 if (dataType == BasicType.getTBoolean()) { 323 str = Boolean.toString(booleanValue()); 324 } else if (dataType == BasicType.getTChar()) { 325 str = "'" + Character.toString(charValue()) + "'"; 326 } else if (dataType == BasicType.getTByte()) { 327 str = Byte.toString(byteValue()); 328 } else if (dataType == BasicType.getTShort()) { 329 str = Short.toString(shortValue()); 330 } else if (dataType == BasicType.getTInt()) { 331 str = Integer.toString(intValue()); 332 } else if (dataType == BasicType.getTLong()) { 333 str = Long.toString(longValue()); 334 } else if (dataType == BasicType.getTFloat()) { 335 str = Float.toString(floatValue()); 336 } else if (dataType == BasicType.getTDouble()) { 337 str = Double.toString(doubleValue()); 338 } else { 339 str = "<unknown scalar value>"; 340 } 341 } else { // vector 342 if (dataType == BasicType.getTBoolean()) { 343 boolean[] res = booleanArrayValue(); 344 StringBuffer buf = new StringBuffer(); 345 buf.append('['); 346 for (int i = 0; i < res.length; i++) { 347 buf.append(Boolean.toString(res[i])); 348 buf.append(", "); 349 } 350 buf.append(']'); 351 str = buf.toString(); 352 } else if (dataType == BasicType.getTChar()) { 353 // char[] is returned as a String 354 str = new String(charArrayValue()); 355 } else if (dataType == BasicType.getTByte()) { 356 // byte[] is returned as a String 357 try { 358 str = new String(byteArrayValue(), "US-ASCII"); 359 } catch (java.io.UnsupportedEncodingException e) { 360 str = "can't decode string : " + e.getMessage(); 361 } 362 } else if (dataType == BasicType.getTShort()) { 363 short[] res = shortArrayValue(); 364 StringBuffer buf = new StringBuffer(); 365 buf.append('['); 366 for (int i = 0; i < res.length; i++) { 367 buf.append(Short.toString(res[i])); 368 buf.append(", "); 369 } 370 buf.append(']'); 371 str = buf.toString(); 372 } else if (dataType == BasicType.getTInt()) { 373 int[] res = intArrayValue(); 374 StringBuffer buf = new StringBuffer(); 375 buf.append('['); 376 for (int i = 0; i < res.length; i++) { 377 buf.append(Integer.toString(res[i])); 378 buf.append(", "); 379 } 380 buf.append(']'); 381 str = buf.toString(); 382 } else if (dataType == BasicType.getTLong()) { 383 long[] res = longArrayValue(); 384 StringBuffer buf = new StringBuffer(); 385 buf.append('['); 386 for (int i = 0; i < res.length; i++) { 387 buf.append(Long.toString(res[i])); 388 buf.append(", "); 389 } 390 buf.append(']'); 391 str = buf.toString(); 392 } else if (dataType == BasicType.getTFloat()) { 393 float[] res = floatArrayValue(); 394 StringBuffer buf = new StringBuffer(); 395 buf.append('['); 396 for (int i = 0; i < res.length; i++) { 397 buf.append(Float.toString(res[i])); 398 buf.append(", "); 399 } 400 buf.append(']'); 401 str = buf.toString(); 402 } else if (dataType == BasicType.getTDouble()) { 403 double[] res = doubleArrayValue(); 404 StringBuffer buf = new StringBuffer(); 405 buf.append('['); 406 for (int i = 0; i < res.length; i++) { 407 buf.append(Double.toString(res[i])); 408 buf.append(", "); 409 } 410 buf.append(']'); 411 str = buf.toString(); 412 } else { 413 str = "<unknown vector value>"; 414 } 415 } 416 417 // add units 418 switch (dataUnits()) { 419 case PerfDataUnits.U_None: 420 break; 421 case PerfDataUnits.U_Bytes: 422 str += " byte(s)"; 423 break; 424 case PerfDataUnits.U_Ticks: 425 str += " tick(s)"; 426 break; 427 case PerfDataUnits.U_Events: 428 str += " event(s)"; 429 break; 430 case PerfDataUnits.U_String: 431 break; 432 case PerfDataUnits.U_Hertz: 433 str += " Hz"; 434 break; 435 } 436 437 return str; 438 } 439 440 // -- Internals only below this point 441 private ObjectHeap getHeap() { 442 return VM.getVM().getObjectHeap(); 443 } 444 }