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 package jdk.vm.ci.hotspot;
24
25 import static java.lang.String.*;
26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.*;
27 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
28
29 import java.util.*;
30
31 import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.*;
32 import jdk.vm.ci.meta.*;
33 import jdk.vm.ci.meta.JavaMethodProfile.*;
34 import jdk.vm.ci.meta.JavaTypeProfile.*;
35 import sun.misc.*;
36
37 /**
38 * Access to a HotSpot MethodData structure (defined in methodData.hpp).
39 */
40 public final class HotSpotMethodData {
41
42 private static final HotSpotVMConfig config = runtime().getConfig();
43 private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE);
44 private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN);
45
46 // sorted by tag
47 // @formatter:off
48 private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
49 null,
50 new BitData(),
51 new CounterData(),
52 new JumpData(),
53 new TypeCheckData(),
54 new VirtualCallData(),
55 new RetData(),
56 new BranchData(),
57 new MultiBranchData(),
58 new ArgInfoData(),
59 null, // call_type_data_tag
60 null, // virtual_call_type_data_tag
61 null, // parameters_type_data_tag
62 null, // speculative_trap_data_tag
63 };
64 // @formatter:on
65
66 /**
67 * Reference to the C++ MethodData object.
68 */
69 private final long metaspaceMethodData;
70 @SuppressWarnings("unused") private final HotSpotResolvedJavaMethodImpl method;
71
72 public HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
73 this.metaspaceMethodData = metaspaceMethodData;
74 this.method = method;
75 }
76
77 /**
78 * @return value of the MethodData::_data_size field
79 */
80 private int normalDataSize() {
81 return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
82 }
110 }
111
112 public int getDeoptimizationCount(DeoptimizationReason reason) {
113 HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
114 int reasonIndex = metaAccess.convertDeoptReason(reason);
115 return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
116 }
117
118 public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
119 HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
120 int reasonIndex = metaAccess.convertDeoptReason(reason);
121 return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
122 }
123
124 public HotSpotMethodDataAccessor getNormalData(int position) {
125 if (position >= normalDataSize()) {
126 return null;
127 }
128
129 HotSpotMethodDataAccessor result = getData(position);
130 assert result != null : "NO_DATA tag is not allowed";
131 return result;
132 }
133
134 public HotSpotMethodDataAccessor getExtraData(int position) {
135 if (position >= normalDataSize() + extraDataSize()) {
136 return null;
137 }
138 HotSpotMethodDataAccessor data = getData(position);
139 if (data != null) {
140 return data;
141 }
142 return data;
143 }
144
145 public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
146 if (exceptionPossiblyNotRecorded) {
147 return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
148 } else {
149 return NO_DATA_NO_EXCEPTION_ACCESSOR;
150 }
176 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
177 return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
178 }
179
180 private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
181 long value = readUnsignedInt(position, offsetInBytes);
182 return truncateLongToInt(value);
183 }
184
185 /**
186 * Since the values are stored in cells (platform words) this method uses
187 * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
188 */
189 private int readInt(int position, int offsetInBytes) {
190 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
191 return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
192 }
193
194 private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
195 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
196 return runtime().compilerToVm.getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
197 }
198
199 private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
200 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
201 return runtime().compilerToVm.getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
202 }
203
204 private static int truncateLongToInt(long value) {
205 return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
206 }
207
208 private static int computeFullOffset(int position, int offsetInBytes) {
209 return config.methodDataOopDataOffset + position + offsetInBytes;
210 }
211
212 private static int cellIndexToOffset(int cells) {
213 return config.dataLayoutHeaderSize + cellsToBytes(cells);
214 }
215
216 private static int cellsToBytes(int cells) {
217 return cells * config.dataLayoutCellSize;
218 }
219
220 /**
221 * Returns whether profiling ran long enough that the profile information is mature. Other
249 HotSpotMethodDataAccessor data;
250 while ((data = getExtraData(pos)) != null) {
251 if (pos == getExtraDataBeginOffset()) {
252 sb.append(nl).append("--- Extra data:");
253 }
254 int bci = data.getBCI(this, pos);
255 sb.append(String.format("%n%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
256 sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
257 pos = pos + data.getSize(this, pos);
258 }
259
260 }
261 return sb.toString();
262 }
263
264 private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor {
265
266 /**
267 * Corresponds to {@code exception_seen_flag}.
268 */
269 private static final int EXCEPTIONS_MASK = 0x2;
270
271 private final Tag tag;
272 private final int staticSize;
273
274 protected AbstractMethodData(Tag tag, int staticSize) {
275 this.tag = tag;
276 this.staticSize = staticSize;
277 }
278
279 public Tag getTag() {
280 return tag;
281 }
282
283 public static Tag readTag(HotSpotMethodData data, int position) {
284 final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
285 return Tag.getEnum(tag);
286 }
287
288 @Override
289 public int getBCI(HotSpotMethodData data, int position) {
290 return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
291 }
292
293 @Override
294 public int getSize(HotSpotMethodData data, int position) {
295 return staticSize + getDynamicSize(data, position);
296 }
297
298 @Override
299 public TriState getExceptionSeen(HotSpotMethodData data, int position) {
300 return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
301 }
302
303 @Override
304 public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
305 return null;
306 }
307
308 @Override
309 public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
310 return null;
311 }
312
313 @Override
314 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
315 return -1;
358
359 @Override
360 public int getBCI(HotSpotMethodData data, int position) {
361 return -1;
362 }
363
364 @Override
365 public TriState getExceptionSeen(HotSpotMethodData data, int position) {
366 return exceptionSeen;
367 }
368
369 @Override
370 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
371 return sb;
372 }
373 }
374
375 private static class BitData extends AbstractMethodData {
376
377 private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
378 private static final int BIT_DATA_NULL_SEEN_FLAG = 0x01;
379
380 private BitData() {
381 super(Tag.BitData, BIT_DATA_SIZE);
382 }
383
384 protected BitData(Tag tag, int staticSize) {
385 super(tag, staticSize);
386 }
387
388 @Override
389 public TriState getNullSeen(HotSpotMethodData data, int position) {
390 return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
391 }
392
393 @Override
394 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
395 return sb.append(format("exception_seen(%s)", getExceptionSeen(data, pos)));
396 }
397 }
398
399 private static class CounterData extends BitData {
400
401 private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
402 private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(0);
403
404 public CounterData() {
405 super(Tag.CounterData, COUNTER_DATA_SIZE);
406 }
407
408 protected CounterData(Tag tag, int staticSize) {
409 super(tag, staticSize);
410 }
411
412 @Override
413 public int getExecutionCount(HotSpotMethodData data, int position) {
414 return getCounterValue(data, position);
415 }
416
417 protected int getCounterValue(HotSpotMethodData data, int position) {
418 return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
419 }
420
421 @Override
422 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
423 return sb.append(format("count(%d) null_seen(%s) exception_seen(%s)", getCounterValue(data, pos), getNullSeen(data, pos), getExceptionSeen(data, pos)));
424 }
425 }
426
427 private static class JumpData extends AbstractMethodData {
428
429 private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
430 protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(0);
431 protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(1);
432
433 public JumpData() {
434 super(Tag.JumpData, JUMP_DATA_SIZE);
435 }
436
437 protected JumpData(Tag tag, int staticSize) {
438 super(tag, staticSize);
439 }
440
441 @Override
442 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
443 return getExecutionCount(data, position) != 0 ? 1 : 0;
444 }
445
446 @Override
447 public int getExecutionCount(HotSpotMethodData data, int position) {
448 return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
449 }
450
451 public int getTakenDisplacement(HotSpotMethodData data, int position) {
457 return sb.append(format("taken(%d) displacement(%d)", getExecutionCount(data, pos), getTakenDisplacement(data, pos)));
458 }
459 }
460
461 static class RawItemProfile<T> {
462 final int entries;
463 final T[] items;
464 final long[] counts;
465 final long totalCount;
466
467 public RawItemProfile(int entries, T[] items, long[] counts, long totalCount) {
468 this.entries = entries;
469 this.items = items;
470 this.counts = counts;
471 this.totalCount = totalCount;
472 }
473 }
474
475 private abstract static class AbstractTypeData extends CounterData {
476
477 protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(2);
478
479 protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(1);
480 protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(2);
481 protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(3);
482
483 protected AbstractTypeData(Tag tag, int staticSize) {
484 super(tag, staticSize);
485 }
486
487 @Override
488 public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
489 return createTypeProfile(getNullSeen(data, position), getRawTypeProfile(data, position));
490 }
491
492 private RawItemProfile<ResolvedJavaType> getRawTypeProfile(HotSpotMethodData data, int position) {
493 int typeProfileWidth = config.typeProfileWidth;
494
495 ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth];
496 long[] counts = new long[typeProfileWidth];
497 long totalCount = 0;
498 int entries = 0;
499
500 outer: for (int i = 0; i < typeProfileWidth; i++) {
501 HotSpotResolvedObjectTypeImpl receiverKlass = data.readKlass(position, getTypeOffset(i));
554
555 protected static int getTypeCountOffset(int row) {
556 return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
557 }
558
559 @Override
560 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
561 RawItemProfile<ResolvedJavaType> profile = getRawTypeProfile(data, pos);
562 TriState nullSeen = getNullSeen(data, pos);
563 TriState exceptionSeen = getExceptionSeen(data, pos);
564 sb.append(format("count(%d) null_seen(%s) exception_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, exceptionSeen,
565 getTypesNotRecordedExecutionCount(data, pos), profile.entries));
566 for (int i = 0; i < profile.entries; i++) {
567 long count = profile.counts[i];
568 sb.append(format("%n %s (%d, %4.2f)", profile.items[i].toJavaName(), count, (double) count / profile.totalCount));
569 }
570 return sb;
571 }
572 }
573
574 private static class TypeCheckData extends AbstractTypeData {
575
576 private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
577
578 public TypeCheckData() {
579 super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
580 }
581
582 @Override
583 public int getExecutionCount(HotSpotMethodData data, int position) {
584 return -1;
585 }
586
587 @Override
588 protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
589 return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
590 }
591 }
592
593 private static class VirtualCallData extends AbstractTypeData {
594
595 private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
596 private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
597 private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
598
599 public VirtualCallData() {
600 super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
601 }
602
603 @Override
604 public int getExecutionCount(HotSpotMethodData data, int position) {
605 final int typeProfileWidth = config.typeProfileWidth;
606
607 long total = 0;
608 for (int i = 0; i < typeProfileWidth; i++) {
609 total += data.readUnsignedInt(position, getTypeCountOffset(i));
610 }
611
612 total += getCounterValue(data, position);
613 return truncateLongToInt(total);
614 }
615
616 @Override
617 protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
618 return getCounterValue(data, position);
619 }
620
621 private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
622 return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
675 private static int getMethodOffset(int row) {
676 return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
677 }
678
679 private static int getMethodCountOffset(int row) {
680 return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
681 }
682
683 @Override
684 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
685 RawItemProfile<ResolvedJavaMethod> profile = getRawMethodProfile(data, pos);
686 super.appendTo(sb.append(format("exception_seen(%s) ", getExceptionSeen(data, pos))), data, pos).append(format("%nmethod_entries(%d)", profile.entries));
687 for (int i = 0; i < profile.entries; i++) {
688 long count = profile.counts[i];
689 sb.append(format("%n %s (%d, %4.2f)", profile.items[i].format("%H.%n(%p)"), count, (double) count / profile.totalCount));
690 }
691 return sb;
692 }
693 }
694
695 private static class RetData extends CounterData {
696
697 private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
698 private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
699
700 public RetData() {
701 super(Tag.RetData, RET_DATA_SIZE);
702 }
703 }
704
705 private static class BranchData extends JumpData {
706
707 private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
708 private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(2);
709
710 public BranchData() {
711 super(Tag.BranchData, BRANCH_DATA_SIZE);
712 }
713
714 @Override
715 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
716 long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
717 long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
718 long total = takenCount + notTakenCount;
719
720 return total <= 0 ? -1 : takenCount / (double) total;
721 }
722
723 @Override
724 public int getExecutionCount(HotSpotMethodData data, int position) {
725 long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
726 return truncateLongToInt(count);
727 }
728
729 @Override
730 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
731 long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
732 long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
733 double takenProbability = getBranchTakenProbability(data, pos);
734 return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
735 }
736 }
737
738 private static class ArrayData extends AbstractMethodData {
739
740 private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(0);
741 protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(1);
742
743 public ArrayData(Tag tag, int staticSize) {
744 super(tag, staticSize);
745 }
746
747 @Override
748 protected int getDynamicSize(HotSpotMethodData data, int position) {
749 return cellsToBytes(getLength(data, position));
750 }
751
752 protected static int getLength(HotSpotMethodData data, int position) {
753 return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
754 }
755
756 @Override
757 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
758 return sb.append(format("length(%d)", getLength(data, pos)));
759 }
760 }
761
762 private static class MultiBranchData extends ArrayData {
763
764 private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
765 private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = 2;
766 private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
767 private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
768 private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
769
770 public MultiBranchData() {
771 super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
772 }
773
774 @Override
775 public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
776 int arrayLength = getLength(data, position);
777 assert arrayLength > 0 : "switch must have at least the default case";
778 assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
779
780 int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
781 long totalCount = 0;
782 double[] result = new double[length];
783
784 // default case is first in HotSpot but last for the compiler
785 long count = readCount(data, position, 0);
837 @Override
838 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
839 int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
840 sb.append(format("entries(%d)", entries));
841 for (int i = 0; i < entries; i++) {
842 sb.append(format("%n %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
843 }
844 return sb;
845 }
846 }
847
848 private static class ArgInfoData extends ArrayData {
849
850 private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
851
852 public ArgInfoData() {
853 super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
854 }
855 }
856
857 public void setCompiledIRSize(int size) {
858 UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
859 }
860
861 public int getCompiledIRSize() {
862 return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
863 }
864 }
|
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 package jdk.vm.ci.hotspot;
24
25 import static java.lang.String.format;
26 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
27 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
28 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
29 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
30
31 import java.util.Arrays;
32
33 import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.Tag;
34 import jdk.vm.ci.meta.DeoptimizationReason;
35 import jdk.vm.ci.meta.JavaMethodProfile;
36 import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
37 import jdk.vm.ci.meta.JavaTypeProfile;
38 import jdk.vm.ci.meta.JavaTypeProfile.ProfiledType;
39 import jdk.vm.ci.meta.ResolvedJavaMethod;
40 import jdk.vm.ci.meta.ResolvedJavaType;
41 import jdk.vm.ci.meta.TriState;
42 import sun.misc.Unsafe;
43
44 /**
45 * Access to a HotSpot MethodData structure (defined in methodData.hpp).
46 */
47 public final class HotSpotMethodData {
48
49 private static final HotSpotVMConfig config = config();
50 private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE);
51 private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN);
52
53 // sorted by tag
54 // @formatter:off
55 private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
56 null,
57 new BitData(),
58 new CounterData(),
59 new JumpData(),
60 new ReceiverTypeData(),
61 new VirtualCallData(),
62 new RetData(),
63 new BranchData(),
64 new MultiBranchData(),
65 new ArgInfoData(),
66 new UnknownProfileData(Tag.CallTypeData),
67 new VirtualCallTypeData(),
68 new UnknownProfileData(Tag.ParametersTypeData),
69 new UnknownProfileData(Tag.SpeculativeTrapData),
70 };
71 // @formatter:on
72
73 /**
74 * Reference to the C++ MethodData object.
75 */
76 private final long metaspaceMethodData;
77 @SuppressWarnings("unused") private final HotSpotResolvedJavaMethodImpl method;
78
79 public HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
80 this.metaspaceMethodData = metaspaceMethodData;
81 this.method = method;
82 }
83
84 /**
85 * @return value of the MethodData::_data_size field
86 */
87 private int normalDataSize() {
88 return UNSAFE.getInt(metaspaceMethodData + config.methodDataDataSize);
89 }
117 }
118
119 public int getDeoptimizationCount(DeoptimizationReason reason) {
120 HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
121 int reasonIndex = metaAccess.convertDeoptReason(reason);
122 return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF;
123 }
124
125 public int getOSRDeoptimizationCount(DeoptimizationReason reason) {
126 HotSpotMetaAccessProvider metaAccess = (HotSpotMetaAccessProvider) runtime().getHostJVMCIBackend().getMetaAccess();
127 int reasonIndex = metaAccess.convertDeoptReason(reason);
128 return UNSAFE.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + config.deoptReasonOSROffset + reasonIndex) & 0xFF;
129 }
130
131 public HotSpotMethodDataAccessor getNormalData(int position) {
132 if (position >= normalDataSize()) {
133 return null;
134 }
135
136 HotSpotMethodDataAccessor result = getData(position);
137 final Tag tag = AbstractMethodData.readTag(this, position);
138 assert result != null : "NO_DATA tag is not allowed " + tag;
139 return result;
140 }
141
142 public HotSpotMethodDataAccessor getExtraData(int position) {
143 if (position >= normalDataSize() + extraDataSize()) {
144 return null;
145 }
146 HotSpotMethodDataAccessor data = getData(position);
147 if (data != null) {
148 return data;
149 }
150 return data;
151 }
152
153 public static HotSpotMethodDataAccessor getNoDataAccessor(boolean exceptionPossiblyNotRecorded) {
154 if (exceptionPossiblyNotRecorded) {
155 return NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR;
156 } else {
157 return NO_DATA_NO_EXCEPTION_ACCESSOR;
158 }
184 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
185 return UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes) & 0xFFFFFFFFL;
186 }
187
188 private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) {
189 long value = readUnsignedInt(position, offsetInBytes);
190 return truncateLongToInt(value);
191 }
192
193 /**
194 * Since the values are stored in cells (platform words) this method uses
195 * {@link Unsafe#getAddress} to read the right value on both little and big endian machines.
196 */
197 private int readInt(int position, int offsetInBytes) {
198 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
199 return (int) UNSAFE.getAddress(metaspaceMethodData + fullOffsetInBytes);
200 }
201
202 private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {
203 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
204 return compilerToVM().getResolvedJavaMethod(null, metaspaceMethodData + fullOffsetInBytes);
205 }
206
207 private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
208 long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
209 return compilerToVM().getResolvedJavaType(null, metaspaceMethodData + fullOffsetInBytes, false);
210 }
211
212 private static int truncateLongToInt(long value) {
213 return value > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) value;
214 }
215
216 private static int computeFullOffset(int position, int offsetInBytes) {
217 return config.methodDataOopDataOffset + position + offsetInBytes;
218 }
219
220 private static int cellIndexToOffset(int cells) {
221 return config.dataLayoutHeaderSize + cellsToBytes(cells);
222 }
223
224 private static int cellsToBytes(int cells) {
225 return cells * config.dataLayoutCellSize;
226 }
227
228 /**
229 * Returns whether profiling ran long enough that the profile information is mature. Other
257 HotSpotMethodDataAccessor data;
258 while ((data = getExtraData(pos)) != null) {
259 if (pos == getExtraDataBeginOffset()) {
260 sb.append(nl).append("--- Extra data:");
261 }
262 int bci = data.getBCI(this, pos);
263 sb.append(String.format("%n%-6d bci: %-6d%-20s", pos, bci, data.getClass().getSimpleName()));
264 sb.append(data.appendTo(new StringBuilder(), this, pos).toString().replace(nl, nlIndent));
265 pos = pos + data.getSize(this, pos);
266 }
267
268 }
269 return sb.toString();
270 }
271
272 private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor {
273
274 /**
275 * Corresponds to {@code exception_seen_flag}.
276 */
277 private static final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
278
279 private final Tag tag;
280 protected final int staticSize;
281
282 protected AbstractMethodData(Tag tag, int staticSize) {
283 this.tag = tag;
284 this.staticSize = staticSize;
285 }
286
287 public Tag getTag() {
288 return tag;
289 }
290
291 public static Tag readTag(HotSpotMethodData data, int position) {
292 final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
293 return Tag.getEnum(tag);
294 }
295
296 @Override
297 public int getBCI(HotSpotMethodData data, int position) {
298 return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
299 }
300
301 @Override
302 public final int getSize(HotSpotMethodData data, int position) {
303 int size = staticSize + getDynamicSize(data, position);
304 // Sanity check against VM
305 int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
306 assert size == vmSize : size + " != " + vmSize;
307 return size;
308 }
309
310 @Override
311 public TriState getExceptionSeen(HotSpotMethodData data, int position) {
312 return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
313 }
314
315 @Override
316 public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
317 return null;
318 }
319
320 @Override
321 public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
322 return null;
323 }
324
325 @Override
326 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
327 return -1;
370
371 @Override
372 public int getBCI(HotSpotMethodData data, int position) {
373 return -1;
374 }
375
376 @Override
377 public TriState getExceptionSeen(HotSpotMethodData data, int position) {
378 return exceptionSeen;
379 }
380
381 @Override
382 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
383 return sb;
384 }
385 }
386
387 private static class BitData extends AbstractMethodData {
388
389 private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
390 private static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
391
392 private BitData() {
393 super(Tag.BitData, BIT_DATA_SIZE);
394 }
395
396 protected BitData(Tag tag, int staticSize) {
397 super(tag, staticSize);
398 }
399
400 @Override
401 public TriState getNullSeen(HotSpotMethodData data, int position) {
402 return TriState.get((getFlags(data, position) & BIT_DATA_NULL_SEEN_FLAG) != 0);
403 }
404
405 @Override
406 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
407 return sb.append(format("exception_seen(%s)", getExceptionSeen(data, pos)));
408 }
409 }
410
411 private static class CounterData extends BitData {
412
413 private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
414 private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
415
416 public CounterData() {
417 super(Tag.CounterData, COUNTER_DATA_SIZE);
418 }
419
420 protected CounterData(Tag tag, int staticSize) {
421 super(tag, staticSize);
422 }
423
424 @Override
425 public int getExecutionCount(HotSpotMethodData data, int position) {
426 return getCounterValue(data, position);
427 }
428
429 protected int getCounterValue(HotSpotMethodData data, int position) {
430 return data.readUnsignedIntAsSignedInt(position, COUNTER_DATA_COUNT_OFFSET);
431 }
432
433 @Override
434 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
435 return sb.append(format("count(%d) null_seen(%s) exception_seen(%s)", getCounterValue(data, pos), getNullSeen(data, pos), getExceptionSeen(data, pos)));
436 }
437 }
438
439 private static class JumpData extends AbstractMethodData {
440
441 private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
442 protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
443 protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
444
445 public JumpData() {
446 super(Tag.JumpData, JUMP_DATA_SIZE);
447 }
448
449 protected JumpData(Tag tag, int staticSize) {
450 super(tag, staticSize);
451 }
452
453 @Override
454 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
455 return getExecutionCount(data, position) != 0 ? 1 : 0;
456 }
457
458 @Override
459 public int getExecutionCount(HotSpotMethodData data, int position) {
460 return data.readUnsignedIntAsSignedInt(position, TAKEN_COUNT_OFFSET);
461 }
462
463 public int getTakenDisplacement(HotSpotMethodData data, int position) {
469 return sb.append(format("taken(%d) displacement(%d)", getExecutionCount(data, pos), getTakenDisplacement(data, pos)));
470 }
471 }
472
473 static class RawItemProfile<T> {
474 final int entries;
475 final T[] items;
476 final long[] counts;
477 final long totalCount;
478
479 public RawItemProfile(int entries, T[] items, long[] counts, long totalCount) {
480 this.entries = entries;
481 this.items = items;
482 this.counts = counts;
483 this.totalCount = totalCount;
484 }
485 }
486
487 private abstract static class AbstractTypeData extends CounterData {
488
489 protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
490
491 protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
492 protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
493 protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
494
495 protected AbstractTypeData(Tag tag, int staticSize) {
496 super(tag, staticSize);
497 }
498
499 @Override
500 public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
501 return createTypeProfile(getNullSeen(data, position), getRawTypeProfile(data, position));
502 }
503
504 private RawItemProfile<ResolvedJavaType> getRawTypeProfile(HotSpotMethodData data, int position) {
505 int typeProfileWidth = config.typeProfileWidth;
506
507 ResolvedJavaType[] types = new ResolvedJavaType[typeProfileWidth];
508 long[] counts = new long[typeProfileWidth];
509 long totalCount = 0;
510 int entries = 0;
511
512 outer: for (int i = 0; i < typeProfileWidth; i++) {
513 HotSpotResolvedObjectTypeImpl receiverKlass = data.readKlass(position, getTypeOffset(i));
566
567 protected static int getTypeCountOffset(int row) {
568 return TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
569 }
570
571 @Override
572 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
573 RawItemProfile<ResolvedJavaType> profile = getRawTypeProfile(data, pos);
574 TriState nullSeen = getNullSeen(data, pos);
575 TriState exceptionSeen = getExceptionSeen(data, pos);
576 sb.append(format("count(%d) null_seen(%s) exception_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, exceptionSeen,
577 getTypesNotRecordedExecutionCount(data, pos), profile.entries));
578 for (int i = 0; i < profile.entries; i++) {
579 long count = profile.counts[i];
580 sb.append(format("%n %s (%d, %4.2f)", profile.items[i].toJavaName(), count, (double) count / profile.totalCount));
581 }
582 return sb;
583 }
584 }
585
586 private static class ReceiverTypeData extends AbstractTypeData {
587
588 private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
589
590 public ReceiverTypeData() {
591 super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
592 }
593
594 protected ReceiverTypeData(Tag tag, int staticSize) {
595 super(tag, staticSize);
596 }
597
598 @Override
599 public int getExecutionCount(HotSpotMethodData data, int position) {
600 return -1;
601 }
602
603 @Override
604 protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
605 return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
606 }
607 }
608
609 private static class VirtualCallData extends ReceiverTypeData {
610
611 private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
612 private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
613 private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
614
615 public VirtualCallData() {
616 super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
617 }
618
619 protected VirtualCallData(Tag tag, int staticSize) {
620 super(tag, staticSize);
621 }
622
623 @Override
624 public int getExecutionCount(HotSpotMethodData data, int position) {
625 final int typeProfileWidth = config.typeProfileWidth;
626
627 long total = 0;
628 for (int i = 0; i < typeProfileWidth; i++) {
629 total += data.readUnsignedInt(position, getTypeCountOffset(i));
630 }
631
632 total += getCounterValue(data, position);
633 return truncateLongToInt(total);
634 }
635
636 @Override
637 protected long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position) {
638 return getCounterValue(data, position);
639 }
640
641 private static long getMethodsNotRecordedExecutionCount(HotSpotMethodData data, int position) {
642 return data.readUnsignedIntAsSignedInt(position, NONPROFILED_COUNT_OFFSET);
695 private static int getMethodOffset(int row) {
696 return VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET + row * TYPE_DATA_ROW_SIZE;
697 }
698
699 private static int getMethodCountOffset(int row) {
700 return VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET + row * TYPE_DATA_ROW_SIZE;
701 }
702
703 @Override
704 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
705 RawItemProfile<ResolvedJavaMethod> profile = getRawMethodProfile(data, pos);
706 super.appendTo(sb.append(format("exception_seen(%s) ", getExceptionSeen(data, pos))), data, pos).append(format("%nmethod_entries(%d)", profile.entries));
707 for (int i = 0; i < profile.entries; i++) {
708 long count = profile.counts[i];
709 sb.append(format("%n %s (%d, %4.2f)", profile.items[i].format("%H.%n(%p)"), count, (double) count / profile.totalCount));
710 }
711 return sb;
712 }
713 }
714
715 private static class VirtualCallTypeData extends VirtualCallData {
716
717 public VirtualCallTypeData() {
718 super(Tag.VirtualCallTypeData, 0);
719 }
720
721 @Override
722 protected int getDynamicSize(HotSpotMethodData data, int position) {
723 assert staticSize == 0;
724 return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
725 }
726 }
727
728 private static class RetData extends CounterData {
729
730 private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
731 private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
732
733 public RetData() {
734 super(Tag.RetData, RET_DATA_SIZE);
735 }
736 }
737
738 private static class BranchData extends JumpData {
739
740 private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
741 private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
742
743 public BranchData() {
744 super(Tag.BranchData, BRANCH_DATA_SIZE);
745 }
746
747 @Override
748 public double getBranchTakenProbability(HotSpotMethodData data, int position) {
749 long takenCount = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET);
750 long notTakenCount = data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
751 long total = takenCount + notTakenCount;
752
753 return total <= 0 ? -1 : takenCount / (double) total;
754 }
755
756 @Override
757 public int getExecutionCount(HotSpotMethodData data, int position) {
758 long count = data.readUnsignedInt(position, TAKEN_COUNT_OFFSET) + data.readUnsignedInt(position, NOT_TAKEN_COUNT_OFFSET);
759 return truncateLongToInt(count);
760 }
761
762 @Override
763 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
764 long taken = data.readUnsignedInt(pos, TAKEN_COUNT_OFFSET);
765 long notTaken = data.readUnsignedInt(pos, NOT_TAKEN_COUNT_OFFSET);
766 double takenProbability = getBranchTakenProbability(data, pos);
767 return sb.append(format("taken(%d, %4.2f) not_taken(%d, %4.2f) displacement(%d)", taken, takenProbability, notTaken, 1.0D - takenProbability, getTakenDisplacement(data, pos)));
768 }
769 }
770
771 private static class ArrayData extends AbstractMethodData {
772
773 private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
774 protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
775
776 public ArrayData(Tag tag, int staticSize) {
777 super(tag, staticSize);
778 }
779
780 @Override
781 protected int getDynamicSize(HotSpotMethodData data, int position) {
782 return cellsToBytes(getLength(data, position));
783 }
784
785 protected static int getLength(HotSpotMethodData data, int position) {
786 return data.readInt(position, ARRAY_DATA_LENGTH_OFFSET);
787 }
788
789 @Override
790 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
791 return sb.append(format("length(%d)", getLength(data, pos)));
792 }
793 }
794
795 private static class MultiBranchData extends ArrayData {
796
797 private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
798 private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
799 private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
800 private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
801 private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
802
803 public MultiBranchData() {
804 super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
805 }
806
807 @Override
808 public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
809 int arrayLength = getLength(data, position);
810 assert arrayLength > 0 : "switch must have at least the default case";
811 assert arrayLength % MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS == 0 : "array must have full rows";
812
813 int length = arrayLength / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
814 long totalCount = 0;
815 double[] result = new double[length];
816
817 // default case is first in HotSpot but last for the compiler
818 long count = readCount(data, position, 0);
870 @Override
871 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
872 int entries = getLength(data, pos) / MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS;
873 sb.append(format("entries(%d)", entries));
874 for (int i = 0; i < entries; i++) {
875 sb.append(format("%n %d: count(%d) displacement(%d)", i, data.readUnsignedInt(pos, getCountOffset(i)), data.readUnsignedInt(pos, getDisplacementOffset(i))));
876 }
877 return sb;
878 }
879 }
880
881 private static class ArgInfoData extends ArrayData {
882
883 private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
884
885 public ArgInfoData() {
886 super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
887 }
888 }
889
890 private static class UnknownProfileData extends AbstractMethodData {
891 public UnknownProfileData(Tag tag) {
892 super(tag, 0);
893 }
894
895 @Override
896 protected int getDynamicSize(HotSpotMethodData data, int position) {
897 assert staticSize == 0;
898 return HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
899 }
900
901 @Override
902 public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
903 // TODO Auto-generated method stub
904 return null;
905 }
906 }
907
908 public void setCompiledIRSize(int size) {
909 UNSAFE.putInt(metaspaceMethodData + config.methodDataIRSizeOffset, size);
910 }
911
912 public int getCompiledIRSize() {
913 return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
914 }
915 }
|