gt:         byte elementSignature = getElementType();
context: /*
   * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this
   * particular file as subject to the "Classpath" exception as provided
   * by Oracle in the LICENSE file that accompanied this code.
   *
   * This code is distributed in the hope that it will be useful, but WITHOUT
   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   * version 2 for more details (a copy is included in the LICENSE file that
   * accompanied this code).
   *
   * You should have received a copy of the GNU General Public License version
   * 2 along with this work; if not, write to the Free Software Foundation,
   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   *
   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   * or visit www.oracle.com if you need additional information or have any
   * questions.
   */
  
  
  /*
   * The Original Code is HAT. The Initial Developer of the
   * Original Code is Bill Foote, with contributions from others
   * at JavaSoft/Sun.
   */
  
  package jdk.test.lib.hprof.model;
  
  import jdk.test.lib.hprof.parser.ReadBuffer;
  import java.io.IOException;
  
  /**
   * 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);
          }
      }
  
      /*
       * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks
       * as below:
       *
       *    object ID
       *    stack trace serial number (int)
       *    number of elements (int)
       *    element type (byte)
       *    array data
       */
      @Override
      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;
      }
  
  
      @Override
      protected final JavaThing[] readValue() throws IOException {
          int len = getLength();
          long offset = dataStartOffset();
  
          JavaThing[] res = new JavaThing[len];
          synchronized (buf()) {
              switch (getElementType()) {
                  case 'Z': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaBoolean(booleanAt(offset));
                                    offset += 1;
                                }
                                return res;
                  }
                  case 'B': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaByte(byteAt(offset));
                                    offset += 1;
                                }
                                return res;
                  }
                  case 'C': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaChar(charAt(offset));
                                    offset += 2;
                                }
                                return res;
                  }
                  case 'S': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaShort(shortAt(offset));
                                    offset += 2;
                                }
                                return res;
                  }
                  case 'I': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaInt(intAt(offset));
                                    offset += 4;
                                }
                                return res;
                  }
                  case 'J': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaLong(longAt(offset));
                                    offset += 8;
                                }
                                return res;
                  }
                  case 'F': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaFloat(floatAt(offset));
                                    offset += 4;
                                }
                                return res;
                  }
                  case 'D': {
                                for (int i = 0; i < len; i++) {
                                    res[i] = new JavaDouble(doubleAt(offset));
                                    offset += 8;
                                }
                                return res;
                  }
                  default: {
                               throw new RuntimeException("unknown primitive type?");
                  }
              }
          }
      }
  
      // JavaClass set only after resolve.
      private JavaClass clazz;
  
      // 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;
  
      // First 8 bits of data is used for element signature
      private static final int SIGNATURE_MASK = 0x0FF;
  
      // Next 8 bits of data is used for length divider
      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() {
          int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT;
          if (divider == 0) {
              byte elementSignature = getElementType();
              switch (elementSignature) {
              case 'B':
              case 'Z':
                  divider = 1;
                  break;
              case 'C':
              case 'S':
                  divider = 2;
                  break;
              case 'I':
              case 'F':
                  divider = 4;
                  break;
              case 'J':
              case 'D':
                  divider = 8;
                  break;
              default:
                  throw new RuntimeException("unknown primitive type: " +
                                  elementSignature);
              }
              data |= (divider << LENGTH_DIVIDER_SHIFT);
          }
          return (int)(getValueLength() / divider);
      }
  
      public JavaThing[] getElements() {
          return getValue();
      }
  
      public byte getElementType() {
          return (byte) (data & SIGNATURE_MASK);
      }
  
      private void checkIndex(int index) {
          if (index < 0 || index >= getLength()) {
              throw new ArrayIndexOutOfBoundsException(index);
          }
      }
  
      private void requireType(char type) {
          if (getElementType() != type) {
              throw new RuntimeException("not of type : " + type);
          }
      }
  
      public String valueString() {
          return valueString(true);
      }
  
      public String valueString(boolean bigLimit) {
          // Char arrays deserve special treatment
          StringBuilder result;
          JavaThing[] things = getValue();
  