1 /* 2 * Copyright (c) 2004, 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.tBoolean, "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.tChar, "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.tByte, "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.tShort, "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.tInt, "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.tLong, "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.tFloat, "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.tDouble, "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.tBoolean, "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.tChar, "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.tByte, "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.tShort, "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.tInt, "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.tLong, "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.tFloat, "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.tDouble, "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 switch (dataType) { 323 case BasicType.tBoolean: 324 str = Boolean.toString(booleanValue()); 325 break; 326 case BasicType.tChar: 327 str = "'" + Character.toString(charValue()) + "'"; 328 break; 329 case BasicType.tByte: 330 str = Byte.toString(byteValue()); 331 break; 332 case BasicType.tShort: 333 str = Short.toString(shortValue()); 334 break; 335 case BasicType.tInt: 336 str = Integer.toString(intValue()); 337 break; 338 case BasicType.tLong: 339 str = Long.toString(longValue()); 340 break; 341 case BasicType.tFloat: 342 str = Float.toString(floatValue()); 343 break; 344 case BasicType.tDouble: 345 str = Double.toString(doubleValue()); 346 break; 347 default: 348 str = "<unknown scalar value>"; 349 break; 350 } 351 } else { // vector 352 switch (dataType) { 353 case BasicType.tBoolean: { 354 boolean[] res = booleanArrayValue(); 355 StringBuffer buf = new StringBuffer(); 356 buf.append('['); 357 for (int i = 0; i < res.length; i++) { 358 buf.append(Boolean.toString(res[i])); 359 buf.append(", "); 360 } 361 buf.append(']'); 362 str = buf.toString(); 363 break; 364 } 365 366 case BasicType.tChar: { 367 // char[] is returned as a String 368 str = new String(charArrayValue()); 369 break; 370 } 371 372 case BasicType.tByte: { 373 // byte[] is returned as a String 374 try { 375 str = new String(byteArrayValue(), "US-ASCII"); 376 } catch (java.io.UnsupportedEncodingException e) { 377 str = "can't decode string : " + e.getMessage(); 378 } 379 break; 380 } 381 382 case BasicType.tShort: { 383 short[] res = shortArrayValue(); 384 StringBuffer buf = new StringBuffer(); 385 buf.append('['); 386 for (int i = 0; i < res.length; i++) { 387 buf.append(Short.toString(res[i])); 388 buf.append(", "); 389 } 390 buf.append(']'); 391 str = buf.toString(); 392 break; 393 } 394 395 case BasicType.tInt: { 396 int[] res = intArrayValue(); 397 StringBuffer buf = new StringBuffer(); 398 buf.append('['); 399 for (int i = 0; i < res.length; i++) { 400 buf.append(Integer.toString(res[i])); 401 buf.append(", "); 402 } 403 buf.append(']'); 404 str = buf.toString(); 405 break; 406 } 407 408 case BasicType.tLong: { 409 long[] res = longArrayValue(); 410 StringBuffer buf = new StringBuffer(); 411 buf.append('['); 412 for (int i = 0; i < res.length; i++) { 413 buf.append(Long.toString(res[i])); 414 buf.append(", "); 415 } 416 buf.append(']'); 417 str = buf.toString(); 418 break; 419 } 420 421 case BasicType.tFloat: { 422 float[] res = floatArrayValue(); 423 StringBuffer buf = new StringBuffer(); 424 buf.append('['); 425 for (int i = 0; i < res.length; i++) { 426 buf.append(Float.toString(res[i])); 427 buf.append(", "); 428 } 429 buf.append(']'); 430 str = buf.toString(); 431 break; 432 } 433 434 case BasicType.tDouble: { 435 double[] res = doubleArrayValue(); 436 StringBuffer buf = new StringBuffer(); 437 buf.append('['); 438 for (int i = 0; i < res.length; i++) { 439 buf.append(Double.toString(res[i])); 440 buf.append(", "); 441 } 442 buf.append(']'); 443 str = buf.toString(); 444 break; 445 } 446 447 default: 448 str = "<unknown vector value>"; 449 break; 450 } 451 } 452 453 // add units 454 switch (dataUnits()) { 455 case PerfDataUnits.U_None: 456 break; 457 case PerfDataUnits.U_Bytes: 458 str += " byte(s)"; 459 break; 460 case PerfDataUnits.U_Ticks: 461 str += " tick(s)"; 462 break; 463 case PerfDataUnits.U_Events: 464 str += " event(s)"; 465 break; 466 case PerfDataUnits.U_String: 467 break; 468 case PerfDataUnits.U_Hertz: 469 str += " Hz"; 470 break; 471 } 472 473 return str; 474 } 475 476 // -- Internals only below this point 477 private ObjectHeap getHeap() { 478 return VM.getVM().getObjectHeap(); 479 } 480 }