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 public class DataLayout {
  35   public static final int noTag = 0;
  36   public static final int bitDataTag = 1;
  37   public static final int counterDataTag = 2;
  38   public static final int jumpDataTag= 3;
  39   public static final int receiverTypeDataTag = 4;
  40   public static final int virtualCallDataTag = 5;
  41   public static final int retDataTag = 6;
  42   public static final int branchDataTag = 7;
  43   public static final int multiBranchDataTag = 8;
  44 
  45   // The _struct._flags word is formatted as [trapState:4 | flags:4].
  46   // The trap state breaks down further as [recompile:1 | reason:3].
  47   // This further breakdown is defined in deoptimization.cpp.
  48   // See Deoptimization.trapStateReason for an assert that
  49   // trapBits is big enough to hold reasons < reasonRecordedLimit.
  50   //
  51   // The trapState is collected only if ProfileTraps is true.
  52   public static final int trapBits = 1+3;  // 3: enough to distinguish [0..reasonRecordedLimit].
  53   public static final int trapShift = 8 - trapBits;
  54   public static final int trapMask = Bits.rightNBits(trapBits);
  55   public static final int trapMaskInPlace = (trapMask << trapShift);
  56   public static final int flagLimit = trapShift;
  57   public static final int flagMask = Bits.rightNBits(flagLimit);
  58   public static final int firstFlag = 0;
  59 
  60   private Address data;
  61 
  62   private int offset;
  63 
  64   private boolean handlized;
  65 
  66   public DataLayout(MethodData d, int o) {
  67     data = d.getHandle();
  68     offset = o;
  69   }
  70 
  71   public DataLayout(Address d, int o) {
  72     data = d;
  73     offset = o;
  74     handlized = true;
  75   }
  76 
  77   public int dp() { return offset; }
  78 
  79   private int getU11(int at) {
  80     return data.getJByteAt(offset + at) & 0xff;
  81   }
  82 
  83   private int getU22(int at) {
  84     return data.getJShortAt(offset + at) & 0xffff;
  85   }
  86 
  87   int cellAt(int index) {
  88     // Cells are intptr_t sized but only contain ints as raw values
  89     return (int)data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false);
  90   }
  91 
  92   Oop oopAt(int index) {
  93     OopHandle handle;
  94     if (handlized) {
  95       throw new InternalError("unsupported");
  96     }
  97     handle = data.getOopHandleAt(offset + cellOffset(index));
  98     return VM.getVM().getObjectHeap().newOop(handle);
  99   }
 100 
 101   public Address addressAt(int index) {
 102     OopHandle handle;
 103     if (handlized) {
 104       return data.getAddressAt(offset + cellOffset(index));
 105     } else {
 106       return data.getOopHandleAt(offset + cellOffset(index));
 107     }
 108   }
 109 
 110   // Every data layout begins with a header.  This header
 111   // contains a tag, which is used to indicate the size/layout
 112   // of the data, 4 bits of flags, which can be used in any way,
 113   // 4 bits of trap history (none/one reason/many reasons),
 114   // and a bci, which is used to tie this piece of data to a
 115   // specific bci in the bytecodes.
 116   // union {
 117   //   intptrT _bits;
 118   //   struct {
 119   //     u1 _tag;
 120   //     u1 _flags;
 121   //     u2 _bci;
 122   //   } _struct;
 123   // } _header;
 124 
 125   // Some types of data layouts need a length field.
 126   static boolean needsArrayLen(int tag) {
 127     return (tag == multiBranchDataTag);
 128   }
 129 
 130   public static final int counterIncrement = 1;
 131 
 132   // Size computation
 133   static int headerSizeInBytes() {
 134     return MethodData.cellSize;
 135   }
 136   static int headerSizeInCells() {
 137     return 1;
 138   }
 139 
 140   static int computeSizeInBytes(int cellCount) {
 141     return headerSizeInBytes() + cellCount * MethodData.cellSize;
 142   }
 143 
 144   // Initialization
 145   // void initialize(int tag, int bci, int cellCount);
 146 
 147   // Accessors
 148   public int tag() {
 149     return getU11(0);
 150   }
 151 
 152   // Return a few bits of trap state.  Range is [0..trapMask].
 153   // The state tells if traps with zero, one, or many reasons have occurred.
 154   // It also tells whether zero or many recompilations have occurred.
 155   // The associated trap histogram in the MDO itself tells whether
 156   // traps are common or not.  If a BCI shows that a trap X has
 157   // occurred, and the MDO shows N occurrences of X, we make the
 158   // simplifying assumption that all N occurrences can be blamed
 159   // on that BCI.
 160   int trapState() {
 161     return (flags() >> trapShift) & trapMask;
 162   }
 163 
 164   int flags() {
 165     return getU11(1);
 166   }
 167 
 168   int bci() {
 169     return getU22(2);
 170   }
 171 
 172   boolean flagAt(int flagNumber) {
 173     // assert(flagNumber < flagLimit, "oob");
 174     return (flags() & (0x1 << flagNumber)) != 0;
 175   }
 176 
 177   // Low-level support for code generation.
 178   static int headerOffset() {
 179     return 0;
 180   }
 181   static int tagOffset() {
 182     return 0;
 183   }
 184   static int flagsOffset() {
 185     return 1;
 186   }
 187   static int bciOffset() {
 188     return 2;
 189   }
 190   public static int cellOffset(int index) {
 191     return MethodData.cellSize + index * MethodData.cellSize;
 192   }
 193   // // Return a value which, when or-ed as a byte into _flags, sets the flag.
 194   // static int flagNumberToByteConstant(int flagNumber) {
 195   //   assert(0 <= flagNumber && flagNumber < flagLimit, "oob");
 196   //   DataLayout temp; temp.setHeader(0);
 197   //   temp.setFlagAt(flagNumber);
 198   //   return temp._header._struct._flags;
 199   // }
 200   // // Return a value which, when or-ed as a word into _header, sets the flag.
 201   // static intptrT flagMaskToHeaderMask(int byteConstant) {
 202   //   DataLayout temp; temp.setHeader(0);
 203   //   temp._header._struct._flags = byteConstant;
 204   //   return temp._header._bits;
 205   // }
 206 }