1 /*
   2  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
   3  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
   4  *
   5  *
   6  *
   7  *
   8  *
   9  *
  10  *
  11  *
  12  *
  13  *
  14  *
  15  *
  16  *
  17  *
  18  *
  19  *
  20  *
  21  *
  22  *
  23  */
  24 
  25 package sun.jvm.hotspot.oops;
  26 
  27 import java.io.*;
  28 import java.util.*;
  29 import sun.jvm.hotspot.debugger.*;
  30 import sun.jvm.hotspot.runtime.*;
  31 import sun.jvm.hotspot.types.*;
  32 import sun.jvm.hotspot.utilities.*;
  33 
  34 // ReceiverTypeData
  35 //
  36 // A ReceiverTypeData is used to access profiling information about a
  37 // dynamic type check.  It consists of a counter which counts the total times
  38 // that the check is reached, and a series of (Klass, count) pairs
  39 // which are used to store a type profile for the receiver of the check.
  40 public class ReceiverTypeData extends CounterData {
  41   static final int   receiver0Offset = counterCellCount;
  42   static final int     count0Offset = receiver0Offset + 1;
  43   static final int     receiverTypeRowCellCount = (count0Offset + 1) - receiver0Offset;
  44 
  45   public ReceiverTypeData(DataLayout layout) {
  46     super(layout);
  47     //assert(layout.tag() == DataLayout.receiverTypeDataTag ||
  48     //       layout.tag() == DataLayout.virtualCallDataTag, "wrong type");
  49   }
  50 
  51   boolean isReceivertypedata() { return true; }
  52 
  53   static int staticCellCount() {
  54     return counterCellCount + MethodData.TypeProfileWidth * receiverTypeRowCellCount;
  55   }
  56 
  57   public int cellCount() {
  58     return staticCellCount();
  59   }
  60 
  61   // Direct accessors
  62   public static int rowLimit() {
  63     return MethodData.TypeProfileWidth;
  64   }
  65   public static int receiverCellIndex(int row) {
  66     return receiver0Offset + row * receiverTypeRowCellCount;
  67   }
  68   public static int receiverCountCellIndex(int row) {
  69     return count0Offset + row * receiverTypeRowCellCount;
  70   }
  71 
  72   // Get the receiver at row.  The 'unchecked' version is needed by parallel old
  73   // gc; it does not assert the receiver is a klass.  During compaction of the
  74   // perm gen, the klass may already have moved, so the isKlass() predicate
  75   // would fail.  The 'normal' version should be used whenever possible.
  76   Klass receiverUnchecked(int row) {
  77     //assert(row < rowLimit(), "oob");
  78     Oop recv = oopAt(receiverCellIndex(row));
  79     return (Klass)recv;
  80   }
  81 
  82   public Klass receiver(int row) {
  83     Klass recv = receiverUnchecked(row);
  84     //assert(recv == NULL || ((oop)recv).isKlass(), "wrong type");
  85     return recv;
  86   }
  87 
  88   public int receiverCount(int row) {
  89     //assert(row < rowLimit(), "oob");
  90     return uintAt(receiverCountCellIndex(row));
  91   }
  92 
  93   // Code generation support
  94   static int receiverOffset(int row) {
  95     return cellOffset(receiverCellIndex(row));
  96   }
  97   static int receiverCountOffset(int row) {
  98     return cellOffset(receiverCountCellIndex(row));
  99   }
 100   static int receiverTypeDataSize() {
 101     return cellOffset(staticCellCount());
 102   }
 103 
 104   void printReceiverDataOn(PrintStream st) {
 105     int row;
 106     int entries = 0;
 107     for (row = 0; row < rowLimit(); row++) {
 108       if (receiver(row) != null)  entries++;
 109     }
 110     st.println("count(" + count() + ") entries(" + entries + ")");
 111     for (row = 0; row < rowLimit(); row++) {
 112       if (receiver(row) != null) {
 113         tab(st);
 114         receiver(row).printValueOn(st);
 115         st.println("(" + receiverCount(row) + ")");
 116       }
 117     }
 118   }
 119   public void printDataOn(PrintStream st) {
 120     printShared(st, "ReceiverTypeData");
 121     printReceiverDataOn(st);
 122   }
 123 }