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
25package sun.jvm.hotspot.runtime;
26
27import java.util.*;
28import sun.jvm.hotspot.debugger.*;
29import sun.jvm.hotspot.oops.*;
30import sun.jvm.hotspot.types.*;
31import sun.jvm.hotspot.utilities.*;
32
33public 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}
481