< prev index next >

test/lib/jdk/test/lib/hprof/model/JavaValueArray.java

Print this page
*** 34,53 ***
  
  import java.io.IOException;
  import java.util.Objects;
  
  /**
!  * An array of values, that is, an array of ints, boolean, floats or the like.
   *
   * @author      Bill Foote
   */
  public class JavaValueArray extends JavaLazyReadObject
                  /*imports*/ implements ArrayTypeCodes {
  
!     private static String arrayTypeName(byte sig) {
!         switch (sig) {
              case 'B':
-                 return "byte[]";
              case 'Z':
!                 return "boolean[]";
              case 'C':
-                 return "char[]";
              case 'S':
!                 return "short[]";
              case 'I':
-                 return "int[]";
              case 'F':
!                 return "float[]";
              case 'J':
-                 return "long[]";
              case 'D':
-                 return "double[]";
-             default:
-                 throw new RuntimeException("invalid array element sig: " + sig);
-         }
-     }
- 
-     private static int elementSize(byte type) {
-         switch (type) {
-             case T_BYTE:
-             case T_BOOLEAN:
-                 return 1;
-             case T_CHAR:
-             case T_SHORT:
-                 return 2;
-             case T_INT:
-             case T_FLOAT:
-                 return 4;
-             case T_LONG:
-             case T_DOUBLE:
                  return 8;
              default:
                  throw new RuntimeException("invalid array element type: " + type);
          }
      }
--- 34,31 ---
  
  import java.io.IOException;
  import java.util.Objects;
  
  /**
!  * An array of values, that is, an array of ints, boolean, floats, etc.
+  * or flat array of primitive objects.
   *
   * @author      Bill Foote
   */
  public class JavaValueArray extends JavaLazyReadObject
                  /*imports*/ implements ArrayTypeCodes {
  
!     private static int elementSize(byte type) {
!         switch (type) {
              case 'B':
              case 'Z':
!                 return 1;
              case 'C':
              case 'S':
!                 return 2;
              case 'I':
              case 'F':
!                 return 4;
              case 'J':
              case 'D':
                  return 8;
              default:
                  throw new RuntimeException("invalid array element type: " + type);
          }
      }

*** 99,11 ***
      protected final long readValueLength() throws IOException {
          long offset = getOffset() + idSize() + 4;
          // length of the array in elements
          long len = buf().getInt(offset);
          // byte length of array
!         return len * elementSize(getElementType());
      }
  
      private long dataStartOffset() {
          return getOffset() + idSize() + 4 + 4 + 1;
      }
--- 77,11 ---
      protected final long readValueLength() throws IOException {
          long offset = getOffset() + idSize() + 4;
          // length of the array in elements
          long len = buf().getInt(offset);
          // byte length of array
!         return len * elementSize(getRealElementType());
      }
  
      private long dataStartOffset() {
          return getOffset() + idSize() + 4 + 4 + 1;
      }

*** 171,20 ***
--- 149,29 ---
                                    res[i] = new JavaDouble(doubleAt(offset));
                                    offset += 8;
                                }
                                return res;
                  }
+                 case 'Q': {
+                     for (int i = 0; i < len; i++) {
+                         res[i] = new InlinedJavaObject(flatArrayElementClass, offset);
+                         offset += flatArrayElementClass.getInlinedInstanceSize();
+                     }
+                     return res;
+                 }
                  default: {
                               throw new RuntimeException("unknown primitive type?");
                  }
              }
          }
      }
  
      // JavaClass set only after resolve.
      private JavaClass clazz;
  
+     private long objID;
+ 
      // This field contains elementSignature byte and
      // divider to be used to calculate length. Note that
      // length of content byte[] is not same as array length.
      // Actual array length is (byte[].length / divider)
      private int data;

*** 196,32 ***
      private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
  
      // Number of bits to shift to get length divider
      private static final int LENGTH_DIVIDER_SHIFT = 8;
  
!     public JavaValueArray(byte elementSignature, long offset) {
          super(offset);
          this.data = (elementSignature & SIGNATURE_MASK);
      }
  
      public JavaClass getClazz() {
          return clazz;
      }
  
      public void visitReferencedObjects(JavaHeapObjectVisitor v) {
          super.visitReferencedObjects(v);
      }
  
      public void resolve(Snapshot snapshot) {
          if (clazz instanceof JavaClass) {
              return;
          }
!         byte elementSig = getElementType();
!         clazz = snapshot.findClass(arrayTypeName(elementSig));
!         if (clazz == null) {
!             clazz = snapshot.getArrayClass("" + ((char) elementSig));
          }
          getClazz().addInstance(this);
          super.resolve(snapshot);
      }
  
      public int getLength() {
--- 183,58 ---
      private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
  
      // Number of bits to shift to get length divider
      private static final int LENGTH_DIVIDER_SHIFT = 8;
  
!     // Flat array support.
+     private JavaClass flatArrayElementClass;
+ 
+     public JavaValueArray(long id, byte elementSignature, long offset) {
          super(offset);
+         this.objID = id;
          this.data = (elementSignature & SIGNATURE_MASK);
      }
  
      public JavaClass getClazz() {
          return clazz;
      }
  
+     public boolean isFlatArray() {
+         return flatArrayElementClass != null;
+     }
+ 
+     public JavaClass getFlatElementClazz() {
+         return flatArrayElementClass;
+     }
+ 
      public void visitReferencedObjects(JavaHeapObjectVisitor v) {
          super.visitReferencedObjects(v);
      }
  
      public void resolve(Snapshot snapshot) {
          if (clazz instanceof JavaClass) {
              return;
          }
! 
!         byte elementType = getElementType();
!         String elementSig = "" + (char)elementType;
!         // Check if this is a flat array of primitive objects.
+         Number elementClassID = snapshot.findFlatArrayElementType(objID);
+         if (elementClassID != null) {
+             // This is flat array.
+             JavaHeapObject elementClazz = snapshot.findThing(getIdValue(elementClassID));
+             if (elementClazz instanceof JavaClass elementJavaClazz) {
+                 flatArrayElementClass = elementJavaClazz;
+                 // need to resolve the element class
+                 flatArrayElementClass.resolve(snapshot);
+                 elementSig = "Q" + flatArrayElementClass.getName() + ";";
+             } else {
+                 // The class not found.
+                 System.out.println("WARNING: flat array element class not found");
+             }
          }
+         clazz = snapshot.getArrayClass(elementSig);
          getClazz().addInstance(this);
          super.resolve(snapshot);
      }
  
      public int getLength() {

*** 243,10 ***
--- 256,13 ---
                  break;
              case 'J':
              case 'D':
                  divider = 8;
                  break;
+             case 'Q':
+                 divider = flatArrayElementClass.getInlinedInstanceSize();
+                 break;
              default:
                  throw new RuntimeException("unknown primitive type: " +
                                  elementSignature);
              }
              data |= (divider << LENGTH_DIVIDER_SHIFT);

*** 257,10 ***
--- 273,14 ---
      public JavaThing[] getElements() {
          return getValue();
      }
  
      public byte getElementType() {
+         return isFlatArray() ? (byte)'Q' : getRealElementType();
+     }
+ 
+     private byte getRealElementType() {
          return (byte) (data & SIGNATURE_MASK);
      }
  
      private void checkIndex(int index) {
          Objects.checkIndex(index, getLength());

*** 279,11 ***
      public String valueString(boolean bigLimit) {
          // Char arrays deserve special treatment
          StringBuilder result;
          JavaThing[] things = getValue();
          byte elementSignature = getElementType();
!         if (elementSignature == 'C')  {
              result = new StringBuilder();
              for (int i = 0; i < things.length; i++) {
                  result.append(things[i]);
              }
          } else {
--- 299,11 ---
      public String valueString(boolean bigLimit) {
          // Char arrays deserve special treatment
          StringBuilder result;
          JavaThing[] things = getValue();
          byte elementSignature = getElementType();
!         if (elementSignature == 'C' && !isFlatArray())  {
              result = new StringBuilder();
              for (int i = 0; i < things.length; i++) {
                  result.append(things[i]);
              }
          } else {

*** 338,10 ***
--- 358,14 ---
                      case 'D': {         // double
                          double val = ((JavaDouble)things[i]).value;
                          result.append(val);
                          break;
                      }
+                     case 'Q': {
+                         InlinedJavaObject obj = (InlinedJavaObject)things[i];
+                         result.append(obj);
+                     }
                      default: {
                          throw new RuntimeException("unknown primitive type?");
                      }
                  }
              }
< prev index next >