< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java

Print this page




   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 }
< prev index next >