8159613: [Findbugs] various warnings reported for JVMCI sources
authordnsimon
Thu, 23 Jun 2016 05:13:55 +0000
changeset 39443 ca6dfb34e46c
parent 39442 ca66cfb4e62b
child 39444 2eae9b74c1f3
child 39445 0ff6e5517504
8159613: [Findbugs] various warnings reported for JVMCI sources Reviewed-by: kvn, twisti
hotspot/.mx.jvmci/mx_jvmci.py
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterArray.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SuppressFBWarnings.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractJavaProfile.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractProfiledItem.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTable.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Local.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTable.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SuppressFBWarnings.java
hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java
hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java
hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java
hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/sparc/SPARCTestAssembler.java
--- a/hotspot/.mx.jvmci/mx_jvmci.py	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/.mx.jvmci/mx_jvmci.py	Thu Jun 23 05:13:55 2016 +0000
@@ -186,7 +186,8 @@
             # Might be building with JDK8 which has cacerts under jre/
             srcCerts = join(mx.get_jdk(tag='default').home, 'jre', 'lib', 'security', 'cacerts')
         dstCerts = join(jdkImageDir, 'lib', 'security', 'cacerts')
-        shutil.copyfile(srcCerts, dstCerts)
+        if srcCerts != dstCerts:
+            shutil.copyfile(srcCerts, dstCerts)
 
         _create_jdk_bundle(jdkBuildDir, _vm.debugLevel, jdkImageDir)
 
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.aarch64/src/jdk/vm/ci/aarch64/AArch64.java	Thu Jun 23 05:13:55 2016 +0000
@@ -28,6 +28,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.PlatformKind;
 
@@ -84,13 +85,13 @@
     public static final Register lr = r30;
 
     // @formatter:off
-    public static final Register[] cpuRegisters = {
+    public static final RegisterArray cpuRegisters = new RegisterArray(
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
         r24, r25, r26, r27, r28, r29, r30, r31,
         zr,  sp
-    };
+    );
     // @formatter:on
 
     public static final RegisterCategory SIMD = new RegisterCategory("SIMD");
@@ -130,16 +131,16 @@
     public static final Register v31 = new Register(65, 31, "v31", SIMD);
 
     // @formatter:off
-    public static final Register[] simdRegisters = {
+    public static final RegisterArray simdRegisters = new RegisterArray(
         v0,  v1,  v2,  v3,  v4,  v5,  v6,  v7,
         v8,  v9,  v10, v11, v12, v13, v14, v15,
         v16, v17, v18, v19, v20, v21, v22, v23,
         v24, v25, v26, v27, v28, v29, v30, v31
-    };
+    );
     // @formatter:on
 
     // @formatter:off
-    public static final Register[] allRegisters = {
+    public static final RegisterArray allRegisters = new RegisterArray(
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
@@ -150,7 +151,7 @@
         v8,  v9,  v10, v11, v12, v13, v14, v15,
         v16, v17, v18, v19, v20, v21, v22, v23,
         v24, v25, v26, v27, v28, v29, v30, v31
-    };
+    );
     // @formatter:on
 
     /**
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java	Thu Jun 23 05:13:55 2016 +0000
@@ -33,6 +33,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.PlatformKind;
 
@@ -131,14 +132,14 @@
     public static final Register k6 = new Register(54, 6, "k6", MASK);
     public static final Register k7 = new Register(55, 7, "k7", MASK);
 
-    public static final Register[] valueRegistersSSE = {
+    public static final RegisterArray valueRegistersSSE = new RegisterArray(
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
         xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
-    };
+    );
 
-    public static final Register[] valueRegistersAVX512 = {
+    public static final RegisterArray valueRegistersAVX512 = new RegisterArray(
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
@@ -146,14 +147,14 @@
         xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
         xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
         k0, k1, k2, k3, k4, k5, k6, k7
-    };
+    );
 
     /**
      * Register used to construct an instruction-relative address.
      */
     public static final Register rip = new Register(56, -1, "rip", SPECIAL);
 
-    public static final Register[] allRegisters = {
+    public static final RegisterArray allRegisters = new RegisterArray(
         rax,  rcx,  rdx,   rbx,   rsp,   rbp,   rsi,   rdi,
         r8,   r9,   r10,   r11,   r12,   r13,   r14,   r15,
         xmm0, xmm1, xmm2,  xmm3,  xmm4,  xmm5,  xmm6,  xmm7,
@@ -162,7 +163,7 @@
         xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
         k0, k1, k2, k3, k4, k5, k6, k7,
         rip
-    };
+    );
 
     // @formatter:on
 
@@ -245,7 +246,7 @@
     }
 
     @Override
-    public Register[] getAvailableValueRegisters() {
+    public RegisterArray getAvailableValueRegisters() {
         if (features.contains(CPUFeature.AVX512F)) {
             return valueRegistersAVX512;
         } else {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/Architecture.java	Thu Jun 23 05:13:55 2016 +0000
@@ -23,7 +23,6 @@
 package jdk.vm.ci.code;
 
 import java.nio.ByteOrder;
-import java.util.Arrays;
 
 import jdk.vm.ci.code.Register.RegisterCategory;
 import jdk.vm.ci.meta.JavaKind;
@@ -46,10 +45,10 @@
     private final String name;
 
     /**
-     * Array of all available registers on this architecture. The index of each register in this
-     * array is equal to its {@linkplain Register#number number}.
+     * List of all available registers on this architecture. The index of each register in this list
+     * is equal to its {@linkplain Register#number number}.
      */
-    private final Register[] registers;
+    private final RegisterArray registers;
 
     /**
      * The byte ordering can be either little or big endian.
@@ -78,7 +77,8 @@
      */
     private final int returnAddressSize;
 
-    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
+    protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, RegisterArray registers, int implicitMemoryBarriers,
+                    int nativeCallDisplacementOffset,
                     int returnAddressSize) {
         this.name = name;
         this.registers = registers;
@@ -120,20 +120,20 @@
     }
 
     /**
-     * Gets an array of all registers that exist on this architecture. This contains all registers
+     * Gets the list of all registers that exist on this architecture. This contains all registers
      * that exist in the specification of this architecture. Not all of them may be available on
-     * this particular architecture instance. The index of each register in this array is equal to
+     * this particular architecture instance. The index of each register in this list is equal to
      * its {@linkplain Register#number number}.
      */
-    public Register[] getRegisters() {
-        return registers.clone();
+    public RegisterArray getRegisters() {
+        return registers;
     }
 
     /**
-     * Gets an array of all registers available for storing values on this architecture. This may be
-     * a subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
+     * Gets a list of all registers available for storing values on this architecture. This may be a
+     * subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
      */
-    public Register[] getAvailableValueRegisters() {
+    public RegisterArray getAvailableValueRegisters() {
         return getRegisters();
     }
 
@@ -206,7 +206,7 @@
                 assert this.byteOrder.equals(that.byteOrder);
                 assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
                 assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
-                assert Arrays.equals(this.registers, that.registers);
+                assert this.registers.equals(that.registers);
                 assert this.returnAddressSize == that.returnAddressSize;
                 assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
                 assert this.wordKind == that.wordKind;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/BytecodeFrame.java	Thu Jun 23 05:13:55 2016 +0000
@@ -34,7 +34,7 @@
  * where to find the local variables, operand stack values and locked objects of the bytecode
  * frame(s).
  */
-public class BytecodeFrame extends BytecodePosition {
+public final class BytecodeFrame extends BytecodePosition {
 
     /**
      * An array of values representing how to reconstruct the state of the Java frame. This is array
@@ -65,14 +65,18 @@
      * <p>
      * Note that the number of locals and the number of stack slots may be smaller than the maximum
      * number of locals and stack slots as specified in the compiled method.
+     *
+     * This field is intentionally exposed as a mutable array that a compiler may modify (e.g.
+     * during register allocation).
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "field is intentionally mutable")//
     public final JavaValue[] values;
 
     /**
-     * An array describing the Java kind of the {@link #values}. It records a kind for the locals
-     * and the operand stack.
+     * An array describing the Java kinds in {@link #values}. It records a kind for the locals and
+     * the operand stack.
      */
-    public final JavaKind[] slotKinds;
+    private final JavaKind[] slotKinds;
 
     /**
      * The number of locals in the values array.
@@ -99,8 +103,8 @@
     public final boolean rethrowException;
 
     /**
-     * Specifies if this object represents a frame state in the middle of executing a call. If
-     * true, the arguments to the call have been popped from the stack and the return value (for a
+     * Specifies if this object represents a frame state in the middle of executing a call. If true,
+     * the arguments to the call have been popped from the stack and the return value (for a
      * non-void call) has not yet been pushed.
      */
     public final boolean duringCall;
@@ -178,11 +182,14 @@
      * @param bci a BCI within the method
      * @param rethrowException specifies if the VM should re-throw the pending exception when
      *            deopt'ing using this frame
-     * @param values the frame state {@link #values}
+     * @param values the frame state {@link #values}.
+     * @param slotKinds the kinds in {@code values}. This array is now owned by this object and must
+     *            not be mutated by the caller.
      * @param numLocals the number of local variables
      * @param numStack the depth of the stack
      * @param numLocks the number of locked objects
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
     public BytecodeFrame(BytecodeFrame caller, ResolvedJavaMethod method, int bci, boolean rethrowException, boolean duringCall, JavaValue[] values, JavaKind[] slotKinds, int numLocals, int numStack,
                     int numLocks) {
         super(caller, method, bci);
@@ -219,12 +226,44 @@
     }
 
     /**
+     * Gets the kind of a local variable.
+     *
+     * @param i the local variable to query
+     * @return the kind of local variable {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
+     */
+    public JavaKind getLocalValueKind(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i];
+    }
+
+    /**
+     * Gets the kind of a stack slot.
+     *
+     * @param i the local variable to query
+     * @return the kind of stack slot {@code i}
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
+     */
+    public JavaKind getStackValueKind(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
+        return slotKinds[i + numLocals];
+    }
+
+    /**
      * Gets the value representing the specified local variable.
      *
      * @param i the local variable index
      * @return the value that can be used to reconstruct the local's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocals}
      */
     public JavaValue getLocalValue(int i) {
+        if (i < 0 || i >= numLocals) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i];
     }
 
@@ -233,8 +272,12 @@
      *
      * @param i the stack index
      * @return the value that can be used to reconstruct the stack slot's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numStack}
      */
     public JavaValue getStackValue(int i) {
+        if (i < 0 || i >= numStack) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i + numLocals];
     }
 
@@ -243,8 +286,12 @@
      *
      * @param i the lock index
      * @return the value that can be used to reconstruct the lock's current value
+     * @throw {@link IndexOutOfBoundsException} if {@code i < 0 || i >= this.numLocks}
      */
     public JavaValue getLockValue(int i) {
+        if (i < 0 || i >= numLocks) {
+            throw new IndexOutOfBoundsException();
+        }
         return values[i + numLocals + numStack];
     }
 
@@ -258,6 +305,11 @@
     }
 
     @Override
+    public int hashCode() {
+        return (numLocals + 1) ^ (numStack + 11) ^ (numLocks + 7);
+    }
+
+    @Override
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/CallingConvention.java	Thu Jun 23 05:13:55 2016 +0000
@@ -100,6 +100,7 @@
     /**
      * Gets the locations required for the arguments.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "FB false positive")
     public AllocatableValue[] getArguments() {
         if (argumentLocations.length == 0) {
             return argumentLocations;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DebugInfo.java	Thu Jun 23 05:13:55 2016 +0000
@@ -48,8 +48,10 @@
      *
      * @param codePos the {@linkplain BytecodePosition code position} or {@linkplain BytecodeFrame
      *            frame} info
-     * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values
+     * @param virtualObjectMapping the mapping of {@link VirtualObject}s to their real values. This
+     *            array is now owned by this object and must not be mutated by the caller.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `virtualObjectMapping`")
     public DebugInfo(BytecodePosition codePos, VirtualObject[] virtualObjectMapping) {
         this.bytecodePosition = codePos;
         this.virtualObjectMapping = virtualObjectMapping;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterArray.java	Thu Jun 23 05:13:55 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+package jdk.vm.ci.code;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * An immutable ordered list of registers. Only required because Java lacks immutable arrays.
+ */
+public final class RegisterArray implements Iterable<Register> {
+
+    private final Register[] registers;
+    private int hash;
+
+    public RegisterArray(Register... registers) {
+        this.registers = registers;
+    }
+
+    public RegisterArray(Collection<Register> registers) {
+        this.registers = registers.toArray(new Register[registers.size()]);
+    }
+
+    /**
+     * Gets the number of registers.
+     */
+    public int size() {
+        return registers.length;
+    }
+
+    /**
+     * Gets the register at a given index.
+     *
+     * @param index the index of the register to retrieve
+     */
+    public Register get(int index) {
+        return registers[index];
+    }
+
+    public void addTo(Collection<Register> collection) {
+        collection.addAll(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets an immutable view of the registers as a list.
+     */
+    public List<Register> asList() {
+        return Collections.unmodifiableList(Arrays.asList(registers));
+    }
+
+    /**
+     * Gets a copy of the registers as an array.
+     */
+    public Register[] toArray() {
+        return registers.clone();
+    }
+
+    public Iterator<Register> iterator() {
+        return Arrays.asList(registers).iterator();
+    }
+
+    @Override
+    public int hashCode() {
+        if (hash == 0 && registers.length > 0) {
+            hash = Arrays.hashCode(registers);
+        }
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RegisterArray) {
+            return Arrays.equals(registers, ((RegisterArray) obj).registers);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(registers);
+    }
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterAttributes.java	Thu Jun 23 05:13:55 2016 +0000
@@ -23,6 +23,8 @@
 package jdk.vm.ci.code;
 
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A collection of register attributes. The specific attribute values for a register may be local to
@@ -53,13 +55,14 @@
      * @return an array whose length is the max register number in {@code registers} plus 1. An
      *         element at index i holds the attributes of the register whose number is i.
      */
-    public static RegisterAttributes[] createMap(RegisterConfig registerConfig, Register[] registers) {
-        RegisterAttributes[] map = new RegisterAttributes[registers.length];
+    public static RegisterAttributes[] createMap(RegisterConfig registerConfig, RegisterArray registers) {
+        RegisterAttributes[] map = new RegisterAttributes[registers.size()];
+        List<Register> callerSaveRegisters = registerConfig.getCallerSaveRegisters().asList();
+        List<Register> calleeSaveRegisters = registerConfig.getCalleeSaveRegisters() == null ? Collections.emptyList() : registerConfig.getCalleeSaveRegisters().asList();
+        List<Register> allocatableRegisters = registerConfig.getAllocatableRegisters().asList();
         for (Register reg : registers) {
             if (reg != null) {
-                Register[] csr = registerConfig.getCalleeSaveRegisters();
-                RegisterAttributes attr = new RegisterAttributes(Arrays.asList(registerConfig.getCallerSaveRegisters()).contains(reg), csr == null ? false : Arrays.asList(csr).contains(reg),
-                                Arrays.asList(registerConfig.getAllocatableRegisters()).contains(reg));
+                RegisterAttributes attr = new RegisterAttributes(callerSaveRegisters.contains(reg), calleeSaveRegisters.contains(reg), allocatableRegisters.contains(reg));
                 if (map.length <= reg.number) {
                     map = Arrays.copyOf(map, reg.number + 1);
                 }
@@ -75,23 +78,24 @@
     }
 
     /**
-     * @return Denotes a register that is available for use by a register allocator.
+     * @return {@code true} if a register is available for use by a register allocator otherwise
+     *         {@code false}
      */
     public boolean isAllocatable() {
         return allocatable;
     }
 
     /**
-     * @return Denotes a register whose value preservation (if required) across a call is the
-     *         responsibility of the callee.
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the callee otherwise {@code false}
      */
     public boolean isCalleeSave() {
         return calleeSave;
     }
 
     /**
-     * @return Denotes a register whose value preservation (if required) across a call is the
-     *         responsibility of the caller.
+     * @return {@code true} if a register whose value preservation (if required) across a call is
+     *         the responsibility of the caller otherwise {@code false}
      */
     public boolean isCallerSave() {
         return callerSave;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -71,7 +71,7 @@
      * @return the ordered set of registers that may be used to pass parameters in a call conforming
      *         to {@code type}
      */
-    Register[] getCallingConventionRegisters(Type type, JavaKind kind);
+    RegisterArray getCallingConventionRegisters(Type type, JavaKind kind);
 
     /**
      * Gets the set of all registers that might be used by the register allocator.
@@ -80,23 +80,23 @@
      * {@link RegisterAllocationConfig#getAllocatableRegisters()}
      */
     @SuppressWarnings("javadoc")
-    Register[] getAllocatableRegisters();
+    RegisterArray getAllocatableRegisters();
 
     /**
      * Filters a set of registers and returns only those that can be used by the register allocator
      * for a value of a particular kind.
      */
-    Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers);
+    RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers);
 
     /**
      * Gets the registers whose values must be preserved by a method across any call it makes.
      */
-    Register[] getCallerSaveRegisters();
+    RegisterArray getCallerSaveRegisters();
 
     /**
      * Gets the registers whose values must be preserved by the callee.
      */
-    Register[] getCalleeSaveRegisters();
+    RegisterArray getCalleeSaveRegisters();
 
     /**
      * Gets a map from register {@linkplain Register#number numbers} to register
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/RegisterSaveLayout.java	Thu Jun 23 05:13:55 2016 +0000
@@ -50,6 +50,7 @@
      * @param registers the keys in the map
      * @param slots frame slot index for each register in {@code registers}
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `registers` and `slots`")
     public RegisterSaveLayout(Register[] registers, int[] slots) {
         assert registers.length == slots.length;
         this.registers = registers;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/SuppressFBWarnings.java	Thu Jun 23 05:13:55 2016 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+package jdk.vm.ci.code;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/VirtualObject.java	Thu Jun 23 05:13:55 2016 +0000
@@ -119,17 +119,20 @@
     }
 
     /**
-     * Returns an array containing all the values to be stored into the object when it is recreated.
+     * Returns the array containing all the values to be stored into the object when it is
+     * recreated. This field is intentional exposed as a mutable array that a compiler may modify
+     * (e.g. during register allocation).
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "`values` is intentional mutable")//
     public JavaValue[] getValues() {
         return values;
     }
 
     /**
-     * Returns an array containing the Java kind of all values in the object.
+     * Returns the kind of the value at {@code index}.
      */
-    public JavaKind[] getSlotKinds() {
-        return slotKinds;
+    public JavaKind getSlotKind(int index) {
+        return slotKinds[index];
     }
 
     /**
@@ -145,9 +148,13 @@
      *
      * @param values an array containing all the values to be stored into the object when it is
      *            recreated.
-     * @param slotKinds an array containing the Java kinds of the values.
+     * @param slotKinds an array containing the Java kinds of the values. This must have the same
+     *            length as {@code values}. This array is now owned by this object and must not be
+     *            mutated by the caller.
      */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `slotKinds`")
     public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
+        assert values.length == slotKinds.length;
         this.values = values;
         this.slotKinds = slotKinds;
     }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.common/src/jdk/vm/ci/common/InitTimer.java	Thu Jun 23 05:13:55 2016 +0000
@@ -30,8 +30,8 @@
  * {@code "jvmci.inittimer"} system property to {@code "true"}.
  */
 public final class InitTimer implements AutoCloseable {
-    final String name;
-    final long start;
+    private final String name;
+    private final long start;
 
     private InitTimer(String name) {
         int n = nesting.getAndIncrement();
@@ -76,5 +76,5 @@
     /**
      * Used to assert the invariant that all related initialization happens on the same thread.
      */
-    public static Thread initializingThread;
+    static Thread initializingThread;
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotRegisterConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -49,8 +49,6 @@
 import static jdk.vm.ci.aarch64.AArch64.zr;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -60,6 +58,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -78,24 +77,24 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
+    private final RegisterArray allocatable;
 
     /**
      * The caller saved registers always include all parameter registers.
      */
-    private final Register[] callerSaved;
+    private final RegisterArray callerSaved;
 
     private final boolean allAllocatableAreCallerSaved;
 
     private final RegisterAttributes[] attributesMap;
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
@@ -103,8 +102,7 @@
             }
         }
 
-        Register[] ret = list.toArray(new Register[list.size()]);
-        return ret;
+        return new RegisterArray(list);
     }
 
     @Override
@@ -112,9 +110,9 @@
         return attributesMap.clone();
     }
 
-    private final Register[] javaGeneralParameterRegisters = {r1, r2, r3, r4, r5, r6, r7, r0};
-    private final Register[] nativeGeneralParameterRegisters = {r0, r1, r2, r3, r4, r5, r6, r7};
-    private final Register[] simdParameterRegisters = {v0, v1, v2, v3, v4, v5, v6, v7};
+    private final RegisterArray javaGeneralParameterRegisters = new RegisterArray(r1, r2, r3, r4, r5, r6, r7, r0);
+    private final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(r0, r1, r2, r3, r4, r5, r6, r7);
+    private final RegisterArray simdParameterRegisters = new RegisterArray(v0, v1, v2, v3, v4, v5, v6, v7);
 
     public static final Register inlineCacheRegister = r9;
 
@@ -127,12 +125,12 @@
     public static final Register threadRegister = r28;
     public static final Register fp = r29;
 
-    private static final Register[] reservedRegisters = {threadRegister, fp, lr, r31, zr, sp};
+    private static final RegisterArray reservedRegisters = new RegisterArray(threadRegister, fp, lr, r31, zr, sp);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -150,35 +148,35 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
     public AArch64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
         this(target, initAllocatable(target.arch, useCompressedOops));
-        assert callerSaved.length >= allocatable.length;
+        assert callerSaved.size() >= allocatable.size();
     }
 
-    public AArch64HotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
+    public AArch64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
         this.target = target;
 
-        this.allocatable = allocatable.clone();
+        this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, allocatable);
-        Collections.addAll(callerSaveSet, simdParameterRegisters);
-        Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
-        Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
-        callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        allocatable.addTo(callerSaveSet);
+        simdParameterRegisters.addTo(callerSaveSet);
+        javaGeneralParameterRegisters.addTo(callerSaveSet);
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
 
         allAllocatableAreCallerSaved = true;
         attributesMap = RegisterAttributes.createMap(this, AArch64.allRegisters);
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaved;
     }
 
-    public Register[] getCalleeSaveRegisters() {
+    public RegisterArray getCalleeSaveRegisters() {
         return null;
     }
 
@@ -199,7 +197,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -218,7 +216,7 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
@@ -237,15 +235,15 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentSIMD < simdParameterRegisters.length) {
-                        Register register = simdParameterRegisters[currentSIMD++];
+                    if (currentSIMD < simdParameterRegisters.size()) {
+                        Register register = simdParameterRegisters.get(currentSIMD++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -294,6 +292,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.aarch64/src/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotVMConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -36,11 +36,6 @@
         super(config);
     }
 
-    /**
-     * Maximum allowed size of allocated area for a frame.
-     */
-    final int maxFrameSize = 16 * 1024;
-
     final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
 
     final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -42,8 +42,6 @@
 import static jdk.vm.ci.amd64.AMD64.xmm7;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -52,6 +50,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -70,24 +69,24 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
+    private final RegisterArray allocatable;
 
     /**
      * The caller saved registers always include all parameter registers.
      */
-    private final Register[] callerSaved;
+    private final RegisterArray callerSaved;
 
     private final boolean allAllocatableAreCallerSaved;
 
     private final RegisterAttributes[] attributesMap;
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
@@ -95,7 +94,7 @@
             }
         }
 
-        Register[] ret = list.toArray(new Register[list.size()]);
+        RegisterArray ret = new RegisterArray(list);
         return ret;
     }
 
@@ -104,9 +103,9 @@
         return attributesMap.clone();
     }
 
-    private final Register[] javaGeneralParameterRegisters;
-    private final Register[] nativeGeneralParameterRegisters;
-    private final Register[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7};
+    private final RegisterArray javaGeneralParameterRegisters;
+    private final RegisterArray nativeGeneralParameterRegisters;
+    private final RegisterArray xmmParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
 
     /*
      * Some ABIs (e.g. Windows) require a so-called "home space", that is a save area on the stack
@@ -114,12 +113,12 @@
      */
     private final boolean needsNativeStackHomeSpace;
 
-    private static final Register[] reservedRegisters = {rsp, r15};
+    private static final RegisterArray reservedRegisters = new RegisterArray(rsp, r15);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -136,46 +135,46 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
     public AMD64HotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops, boolean windowsOs) {
         this(target, initAllocatable(target.arch, useCompressedOops), windowsOs);
-        assert callerSaved.length >= allocatable.length;
+        assert callerSaved.size() >= allocatable.size();
     }
 
-    public AMD64HotSpotRegisterConfig(TargetDescription target, Register[] allocatable, boolean windowsOs) {
+    public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable, boolean windowsOs) {
         this.target = target;
 
         if (windowsOs) {
-            javaGeneralParameterRegisters = new Register[]{rdx, r8, r9, rdi, rsi, rcx};
-            nativeGeneralParameterRegisters = new Register[]{rcx, rdx, r8, r9};
+            javaGeneralParameterRegisters = new RegisterArray(rdx, r8, r9, rdi, rsi, rcx);
+            nativeGeneralParameterRegisters = new RegisterArray(rcx, rdx, r8, r9);
             this.needsNativeStackHomeSpace = true;
         } else {
-            javaGeneralParameterRegisters = new Register[]{rsi, rdx, rcx, r8, r9, rdi};
-            nativeGeneralParameterRegisters = new Register[]{rdi, rsi, rdx, rcx, r8, r9};
+            javaGeneralParameterRegisters = new RegisterArray(rsi, rdx, rcx, r8, r9, rdi);
+            nativeGeneralParameterRegisters = new RegisterArray(rdi, rsi, rdx, rcx, r8, r9);
             this.needsNativeStackHomeSpace = false;
         }
 
         this.allocatable = allocatable;
         Set<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, allocatable);
-        Collections.addAll(callerSaveSet, xmmParameterRegisters);
-        Collections.addAll(callerSaveSet, javaGeneralParameterRegisters);
-        Collections.addAll(callerSaveSet, nativeGeneralParameterRegisters);
-        callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        allocatable.addTo(callerSaveSet);
+        xmmParameterRegisters.addTo(callerSaveSet);
+        callerSaveSet.addAll(javaGeneralParameterRegisters.asList());
+        nativeGeneralParameterRegisters.addTo(callerSaveSet);
+        callerSaved = new RegisterArray(callerSaveSet);
 
         allAllocatableAreCallerSaved = true;
         attributesMap = RegisterAttributes.createMap(this, target.arch.getRegisters());
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaved;
     }
 
     @Override
-    public Register[] getCalleeSaveRegisters() {
+    public RegisterArray getCalleeSaveRegisters() {
         return null;
     }
 
@@ -196,7 +195,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -215,13 +214,13 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
         int currentGeneral = 0;
         int currentXMM = 0;
-        int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.length * target.wordSize : 0;
+        int currentStackOffset = type == HotSpotCallingConventionType.NativeCall && needsNativeStackHomeSpace ? generalParameterRegisters.size() * target.wordSize : 0;
 
         for (int i = 0; i < parameterTypes.length; i++) {
             final JavaKind kind = parameterTypes[i].getJavaKind().getStackKind();
@@ -234,15 +233,15 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
                 case Double:
-                    if (currentXMM < xmmParameterRegisters.length) {
-                        Register register = xmmParameterRegisters[currentXMM++];
+                    if (currentXMM < xmmParameterRegisters.size()) {
+                        Register register = xmmParameterRegisters.get(currentXMM++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -291,6 +290,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -31,11 +31,6 @@
         super(config);
     }
 
-    /**
-     * Maximum allowed size of allocated area for a frame.
-     */
-    final int maxFrameSize = 16 * 1024;
-
     final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
 
     final boolean useCountLeadingZerosInstruction = getFlag("UseCountLeadingZerosInstruction", Boolean.class);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotRegisterConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -65,8 +65,6 @@
 import static jdk.vm.ci.sparc.SPARC.sp;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
@@ -74,6 +72,7 @@
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.RegisterAttributes;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
@@ -92,7 +91,7 @@
 
     private final TargetDescription target;
 
-    private final Register[] allocatable;
+    private final RegisterArray allocatable;
 
     private final RegisterAttributes[] attributesMap;
 
@@ -102,20 +101,19 @@
     private final boolean addNativeRegisterArgumentSlots;
 
     @Override
-    public Register[] getAllocatableRegisters() {
-        return allocatable.clone();
+    public RegisterArray getAllocatableRegisters() {
+        return allocatable;
     }
 
     @Override
-    public Register[] filterAllocatableRegisters(PlatformKind kind, Register[] registers) {
+    public RegisterArray filterAllocatableRegisters(PlatformKind kind, RegisterArray registers) {
         ArrayList<Register> list = new ArrayList<>();
         for (Register reg : registers) {
             if (target.arch.canStoreValue(reg.getRegisterCategory(), kind)) {
                 list.add(reg);
             }
         }
-        Register[] ret = list.toArray(new Register[list.size()]);
-        return ret;
+        return new RegisterArray(list);
     }
 
     @Override
@@ -123,29 +121,29 @@
         return attributesMap.clone();
     }
 
-    private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
-    private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
+    private final RegisterArray cpuCallerParameterRegisters = new RegisterArray(o0, o1, o2, o3, o4, o5);
+    private final RegisterArray cpuCalleeParameterRegisters = new RegisterArray(i0, i1, i2, i3, i4, i5);
 
-    private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
-    private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
+    private final RegisterArray fpuFloatParameterRegisters = new RegisterArray(f0, f1, f2, f3, f4, f5, f6, f7);
+    private final RegisterArray fpuDoubleParameterRegisters = new RegisterArray(d0, null, d2, null, d4, null, d6, null);
 
     // @formatter:off
-    private final Register[] callerSaveRegisters;
+    private final RegisterArray callerSaveRegisters;
 
     /**
      * This lists all L and I registers which are saved in the register window.
      */
-    private final Register[] windowSaveRegisters = {
+    private final RegisterArray windowSaveRegisters = new RegisterArray(
                     l0, l1, l2, l3, l4, l5, l6, l7,
-                    i0, i1, i2, i3, i4, i5, i6, i7};
+                    i0, i1, i2, i3, i4, i5, i6, i7);
     // @formatter:on
 
-    private static final Register[] reservedRegisters = {sp, g0, g2};
+    private static final RegisterArray reservedRegisters = new RegisterArray(sp, g0, g2);
 
-    private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
-        Register[] allRegisters = arch.getAvailableValueRegisters();
-        Register[] registers = new Register[allRegisters.length - reservedRegisters.length - (reserveForHeapBase ? 1 : 0)];
-        List<Register> reservedRegistersList = Arrays.asList(reservedRegisters);
+    private static RegisterArray initAllocatable(Architecture arch, boolean reserveForHeapBase) {
+        RegisterArray allRegisters = arch.getAvailableValueRegisters();
+        Register[] registers = new Register[allRegisters.size() - reservedRegisters.size() - (reserveForHeapBase ? 1 : 0)];
+        List<Register> reservedRegistersList = reservedRegisters.asList();
 
         int idx = 0;
         for (Register reg : allRegisters) {
@@ -162,33 +160,32 @@
         }
 
         assert idx == registers.length;
-        return registers;
+        return new RegisterArray(registers);
     }
 
     public SPARCHotSpotRegisterConfig(TargetDescription target, boolean useCompressedOops) {
         this(target, initAllocatable(target.arch, useCompressedOops));
     }
 
-    public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
+    public SPARCHotSpotRegisterConfig(TargetDescription target, RegisterArray allocatable) {
         this.target = target;
-        this.allocatable = allocatable.clone();
+        this.allocatable = allocatable;
         this.addNativeRegisterArgumentSlots = false;
-        HashSet<Register> callerSaveSet = new HashSet<>();
-        Collections.addAll(callerSaveSet, target.arch.getAvailableValueRegisters());
+        HashSet<Register> callerSaveSet = new HashSet<>(target.arch.getAvailableValueRegisters().asList());
         for (Register cs : windowSaveRegisters) {
             callerSaveSet.remove(cs);
         }
-        this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
+        this.callerSaveRegisters = new RegisterArray(callerSaveSet);
         attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
     }
 
     @Override
-    public Register[] getCallerSaveRegisters() {
+    public RegisterArray getCallerSaveRegisters() {
         return callerSaveRegisters;
     }
 
     @Override
-    public Register[] getCalleeSaveRegisters() {
+    public RegisterArray getCalleeSaveRegisters() {
         return null;
     }
 
@@ -210,7 +207,7 @@
     }
 
     @Override
-    public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
+    public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) {
         HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type;
         switch (kind) {
             case Boolean:
@@ -229,7 +226,7 @@
         }
     }
 
-    private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
+    private CallingConvention callingConvention(RegisterArray generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, HotSpotCallingConventionType type,
                     ValueKindFactory<?> valueKindFactory) {
         AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
 
@@ -248,25 +245,25 @@
                 case Int:
                 case Long:
                 case Object:
-                    if (currentGeneral < generalParameterRegisters.length) {
-                        Register register = generalParameterRegisters[currentGeneral++];
+                    if (currentGeneral < generalParameterRegisters.size()) {
+                        Register register = generalParameterRegisters.get(currentGeneral++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Double:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
+                    if (currentFloating < fpuFloatParameterRegisters.size()) {
                         if (currentFloating % 2 != 0) {
                             // Make register number even to be a double reg
                             currentFloating++;
                         }
-                        Register register = fpuDoubleParameterRegisters[currentFloating];
+                        Register register = fpuDoubleParameterRegisters.get(currentFloating);
                         currentFloating += 2; // Only every second is a double register
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
                 case Float:
-                    if (currentFloating < fpuFloatParameterRegisters.length) {
-                        Register register = fpuFloatParameterRegisters[currentFloating++];
+                    if (currentFloating < fpuFloatParameterRegisters.size()) {
+                        Register register = fpuFloatParameterRegisters.get(currentFloating++);
                         locations[i] = register.asValue(valueKindFactory.getValueKind(kind));
                     }
                     break;
@@ -291,7 +288,7 @@
         int outArgSpillArea;
         if (type == HotSpotCallingConventionType.NativeCall && addNativeRegisterArgumentSlots) {
             // Space for native callee which may spill our outgoing arguments
-            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
+            outArgSpillArea = Math.min(locations.length, generalParameterRegisters.size()) * target.wordSize;
         } else {
             outArgSpillArea = 0;
         }
@@ -336,6 +333,6 @@
 
     @Override
     public String toString() {
-        return String.format("Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave:  " + Arrays.toString(getCallerSaveRegisters()) + "%n");
+        return String.format("Allocatable: " + getAllocatableRegisters() + "%n" + "CallerSave:  " + getCallerSaveRegisters() + "%n");
     }
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java	Thu Jun 23 05:13:55 2016 +0000
@@ -80,12 +80,13 @@
         for (Field f : fields) {
             if (f.getName().endsWith("Stub")) {
                 f.setAccessible(true);
+                Object address;
                 try {
-                    Object address = f.get(runtime.getConfig());
+                    address = f.get(runtime.getConfig());
                     if (address.equals(call.target)) {
                         return f.getName() + ":0x" + Long.toHexString((Long) address);
                     }
-                } catch (Exception e) {
+                } catch (IllegalArgumentException | IllegalAccessException e) {
                 }
             }
         }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java	Thu Jun 23 05:13:55 2016 +0000
@@ -115,6 +115,7 @@
         }
     }
 
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `sites`, `targetCode`, `comments`, `methods`, `dataSection`, `dataSectionPatches` and `assumptions`")
     public HotSpotCompiledCode(String name, byte[] targetCode, int targetCodeSize, Site[] sites, Assumption[] assumptions, ResolvedJavaMethod[] methods, Comment[] comments, byte[] dataSection,
                     int dataSectionAlignment, DataPatch[] dataSectionPatches, boolean isImmutablePIC, int totalFrameSize, StackSlot deoptRescueSlot) {
         this.name = name;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Thu Jun 23 05:13:55 2016 +0000
@@ -300,7 +300,8 @@
      */
     private long getEntryAt(int index) {
         assertBounds(index);
-        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -311,7 +312,8 @@
      */
     private int getIntAt(int index) {
         assertTag(index, JVM_CONSTANT.Integer);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -322,7 +324,8 @@
      */
     private long getLongAt(int index) {
         assertTag(index, JVM_CONSTANT.Long);
-        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getLong(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -333,7 +336,8 @@
      */
     private float getFloatAt(int index) {
         assertTag(index, JVM_CONSTANT.Float);
-        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getFloat(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -344,7 +348,8 @@
      */
     private double getDoubleAt(int index) {
         assertTag(index, JVM_CONSTANT.Double);
-        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getDouble(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -355,7 +360,8 @@
      */
     private int getNameAndTypeAt(int index) {
         assertTag(index, JVM_CONSTANT.NameAndType);
-        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        return UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
     }
 
     /**
@@ -436,7 +442,8 @@
      */
     private int getUncachedKlassRefIndexAt(int index) {
         assertTagIsFieldOrMethod(index);
-        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + index * runtime().getHostJVMCIBackend().getTarget().wordSize);
+        int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
+        final int refIndex = UNSAFE.getInt(getMetaspaceConstantPool() + config().constantPoolSize + offset);
         // klass ref index is in the low 16-bits.
         return refIndex & 0xFFFF;
     }
@@ -682,15 +689,15 @@
                 if (!klass.isPrimitive() && !klass.isArray()) {
                     UNSAFE.ensureClassInitialized(klass);
                 }
-                switch (tag) {
-                    case MethodRef:
-                        if (Bytecodes.isInvokeHandleAlias(opcode)) {
-                            final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
-                            if (isInvokeHandle(methodRefCacheIndex, type)) {
-                                compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
-                            }
+                if (tag == JVM_CONSTANT.MethodRef) {
+                    if (Bytecodes.isInvokeHandleAlias(opcode)) {
+                        final int methodRefCacheIndex = rawIndexToConstantPoolIndex(cpi, opcode);
+                        if (isInvokeHandle(methodRefCacheIndex, type)) {
+                            compilerToVM().resolveInvokeHandleInPool(this, methodRefCacheIndex);
                         }
+                    }
                 }
+
                 break;
             case InvokeDynamic:
                 if (isInvokedynamicIndex(cpi)) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotForeignCallTarget.java	Thu Jun 23 05:13:55 2016 +0000
@@ -29,6 +29,7 @@
     /**
      * The entry point address of this call's target.
      */
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD", justification = "accessed by subclasses")//
     protected long address;
 
     public HotSpotForeignCallTarget(long address) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Thu Jun 23 05:13:55 2016 +0000
@@ -27,10 +27,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -48,8 +44,8 @@
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.JVMCIError;
 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;
+import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener;
-import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaType;
@@ -95,9 +91,10 @@
      */
     public enum Option {
         Compiler(String.class, null, "Selects the system compiler."),
-        // Note: The following one is not used (see InitTimer.ENABLED).
+        // Note: The following one is not used (see InitTimer.ENABLED). It is added here
+        // so that -Djvmci.PrintFlags=true shows the option.
         InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
-        PrintConfig(boolean.class, false, "Prints all HotSpotVMConfig fields."),
+        PrintConfig(boolean.class, false, "Prints VM configuration available via JVMCI and exits."),
         PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
         ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
         TraceMethodDataFilter(String.class, null, "");
@@ -242,6 +239,7 @@
     @SuppressWarnings("unused") private final String[] trivialPrefixes;
 
     @SuppressWarnings("try")
+    @SuppressFBWarnings(value = "DM_EXIT", justification = "PrintFlags is meant to exit the VM")
     private HotSpotJVMCIRuntime() {
         compilerToVm = new CompilerToVM();
 
@@ -273,7 +271,8 @@
         }
 
         if (Option.PrintConfig.getBoolean()) {
-            printConfig(config, compilerToVm);
+            printConfig(configStore, compilerToVm);
+            System.exit(0);
         }
 
         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
@@ -464,71 +463,40 @@
         }
     }
 
-    private static void printConfig(HotSpotVMConfig config, CompilerToVM vm) {
-        Field[] fields = config.getClass().getDeclaredFields();
-        Map<String, Field> sortedFields = new TreeMap<>();
-        for (Field f : fields) {
-            if (!f.isSynthetic() && !Modifier.isStatic(f.getModifiers())) {
-                f.setAccessible(true);
-                sortedFields.put(f.getName(), f);
-            }
-        }
-        for (Field f : sortedFields.values()) {
-            try {
-                String line = String.format("%9s %-40s = %s%n", f.getType().getSimpleName(), f.getName(), pretty(f.get(config)));
-                byte[] lineBytes = line.getBytes();
-                vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
-                vm.flushDebugOutput();
-            } catch (Exception e) {
-            }
-        }
+    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
+    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
+        String line = String.format(format, args);
+        byte[] lineBytes = line.getBytes();
+        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
+        vm.flushDebugOutput();
     }
 
-    private static String pretty(Object value) {
-        if (value == null) {
-            return "null";
-        }
-
-        Class<?> klass = value.getClass();
-        if (value instanceof String) {
-            return "\"" + value + "\"";
-        } else if (value instanceof Method) {
-            return "method \"" + ((Method) value).getName() + "\"";
-        } else if (value instanceof Class<?>) {
-            return "class \"" + ((Class<?>) value).getSimpleName() + "\"";
-        } else if (value instanceof Integer) {
-            if ((Integer) value < 10) {
-                return value.toString();
-            }
-            return value + " (0x" + Integer.toHexString((Integer) value) + ")";
-        } else if (value instanceof Long) {
-            if ((Long) value < 10 && (Long) value > -10) {
-                return value + "l";
+    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
+        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
+        for (VMField field : fields.values()) {
+            if (!field.isStatic()) {
+                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
+            } else {
+                String value = field.value == null ? "null" : String.format("%d[0x%x]", field.value, field.value);
+                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
             }
-            return value + "l (0x" + Long.toHexString((Long) value) + "l)";
-        } else if (klass.isArray()) {
-            StringBuilder str = new StringBuilder();
-            int dimensions = 0;
-            while (klass.isArray()) {
-                dimensions++;
-                klass = klass.getComponentType();
-            }
-            int length = Array.getLength(value);
-            str.append(klass.getSimpleName()).append('[').append(length).append(']');
-            for (int i = 1; i < dimensions; i++) {
-                str.append("[]");
-            }
-            str.append(" {");
-            for (int i = 0; i < length; i++) {
-                str.append(pretty(Array.get(value, i)));
-                if (i < length - 1) {
-                    str.append(", ");
-                }
-            }
-            str.append('}');
-            return str.toString();
+        }
+        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
+        for (VMFlag flag : flags.values()) {
+            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
+        }
+        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
+        for (Map.Entry<String, Long> e : addresses.entrySet()) {
+            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
         }
-        return value.toString();
+        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
+        for (Map.Entry<String, Long> e : constants.entrySet()) {
+            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
+        }
+        TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
+        for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
+            printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
+        }
     }
 
     public OutputStream getLogStream() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodData.java	Thu Jun 23 05:13:55 2016 +0000
@@ -30,7 +30,7 @@
 
 import java.util.Arrays;
 
-import jdk.vm.ci.hotspot.HotSpotMethodDataAccessor.Tag;
+import jdk.internal.misc.Unsafe;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.JavaMethodProfile;
 import jdk.vm.ci.meta.JavaMethodProfile.ProfiledMethod;
@@ -39,41 +39,20 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaType;
 import jdk.vm.ci.meta.TriState;
-import jdk.internal.misc.Unsafe;
 
 /**
- * Access to a HotSpot MethodData structure (defined in methodData.hpp).
+ * Access to a HotSpot {@code MethodData} structure (defined in methodData.hpp).
  */
-public final class HotSpotMethodData {
-
-    private static final HotSpotVMConfig config = config();
-    private static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(TriState.FALSE);
-    private static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(TriState.UNKNOWN);
+final class HotSpotMethodData {
 
-    // sorted by tag
-    // @formatter:off
-    private static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
-        null,
-        new BitData(),
-        new CounterData(),
-        new JumpData(),
-        new ReceiverTypeData(),
-        new VirtualCallData(),
-        new RetData(),
-        new BranchData(),
-        new MultiBranchData(),
-        new ArgInfoData(),
-        new UnknownProfileData(Tag.CallTypeData),
-        new VirtualCallTypeData(),
-        new UnknownProfileData(Tag.ParametersTypeData),
-        new UnknownProfileData(Tag.SpeculativeTrapData),
-    };
-    // @formatter:on
+    static final HotSpotVMConfig config = config();
+    static final HotSpotMethodDataAccessor NO_DATA_NO_EXCEPTION_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.FALSE);
+    static final HotSpotMethodDataAccessor NO_DATA_EXCEPTION_POSSIBLY_NOT_RECORDED_ACCESSOR = new NoMethodData(config, config.dataLayoutNoTag, TriState.UNKNOWN);
 
     /**
      * Reference to the C++ MethodData object.
      */
-    private final long metaspaceMethodData;
+    final long metaspaceMethodData;
     @SuppressWarnings("unused") private final HotSpotResolvedJavaMethodImpl method;
 
     public HotSpotMethodData(long metaspaceMethodData, HotSpotResolvedJavaMethodImpl method) {
@@ -133,10 +112,7 @@
             return null;
         }
 
-        HotSpotMethodDataAccessor result = getData(position);
-        final Tag tag = AbstractMethodData.readTag(this, position);
-        assert result != null : "NO_DATA tag is not allowed " + tag;
-        return result;
+        return getData(position);
     }
 
     public HotSpotMethodDataAccessor getExtraData(int position) {
@@ -160,18 +136,18 @@
 
     private HotSpotMethodDataAccessor getData(int position) {
         assert position >= 0 : "out of bounds";
-        final Tag tag = AbstractMethodData.readTag(this, position);
-        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag.getValue()];
+        final int tag = HotSpotMethodDataAccessor.readTag(config, this, position);
+        HotSpotMethodDataAccessor accessor = PROFILE_DATA_ACCESSORS[tag];
         assert accessor == null || accessor.getTag() == tag : "wrong data accessor " + accessor + " for tag " + tag;
         return accessor;
     }
 
-    private int readUnsignedByte(int position, int offsetInBytes) {
+    int readUnsignedByte(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
         return UNSAFE.getByte(metaspaceMethodData + fullOffsetInBytes) & 0xFF;
     }
 
-    private int readUnsignedShort(int position, int offsetInBytes) {
+    int readUnsignedShort(int position, int offsetInBytes) {
         long fullOffsetInBytes = computeFullOffset(position, offsetInBytes);
         return UNSAFE.getShort(metaspaceMethodData + fullOffsetInBytes) & 0xFFFF;
     }
@@ -269,102 +245,14 @@
         return sb.toString();
     }
 
-    private abstract static class AbstractMethodData implements HotSpotMethodDataAccessor {
-
-        /**
-         * Corresponds to {@code exception_seen_flag}.
-         */
-        private static final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
-
-        private final Tag tag;
-        protected final int staticSize;
-
-        protected AbstractMethodData(Tag tag, int staticSize) {
-            this.tag = tag;
-            this.staticSize = staticSize;
-        }
-
-        public Tag getTag() {
-            return tag;
-        }
-
-        public static Tag readTag(HotSpotMethodData data, int position) {
-            final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
-            return Tag.getEnum(tag);
-        }
-
-        @Override
-        public int getBCI(HotSpotMethodData data, int position) {
-            return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
-        }
-
-        @Override
-        public final int getSize(HotSpotMethodData data, int position) {
-            int size = staticSize + getDynamicSize(data, position);
-            // Sanity check against VM
-            int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
-            assert size == vmSize : size + " != " + vmSize;
-            return size;
-        }
-
-        @Override
-        public TriState getExceptionSeen(HotSpotMethodData data, int position) {
-            return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
-        }
+    static final int NO_DATA_SIZE = cellIndexToOffset(0);
 
-        @Override
-        public JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public double getBranchTakenProbability(HotSpotMethodData data, int position) {
-            return -1;
-        }
-
-        @Override
-        public double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
-            return null;
-        }
-
-        @Override
-        public int getExecutionCount(HotSpotMethodData data, int position) {
-            return -1;
-        }
-
-        @Override
-        public TriState getNullSeen(HotSpotMethodData data, int position) {
-            return TriState.UNKNOWN;
-        }
-
-        protected int getFlags(HotSpotMethodData data, int position) {
-            return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
-        }
-
-        /**
-         * @param data
-         * @param position
-         */
-        protected int getDynamicSize(HotSpotMethodData data, int position) {
-            return 0;
-        }
-
-        public abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
-    }
-
-    private static class NoMethodData extends AbstractMethodData {
-
-        private static final int NO_DATA_SIZE = cellIndexToOffset(0);
+    static class NoMethodData extends HotSpotMethodDataAccessor {
 
         private final TriState exceptionSeen;
 
-        protected NoMethodData(TriState exceptionSeen) {
-            super(Tag.No, NO_DATA_SIZE);
+        protected NoMethodData(HotSpotVMConfig config, int tag, TriState exceptionSeen) {
+            super(config, tag, NO_DATA_SIZE);
             this.exceptionSeen = exceptionSeen;
         }
 
@@ -384,17 +272,17 @@
         }
     }
 
-    private static class BitData extends AbstractMethodData {
+    static final int BIT_DATA_SIZE = cellIndexToOffset(0);
+    static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
 
-        private static final int BIT_DATA_SIZE = cellIndexToOffset(0);
-        private static final int BIT_DATA_NULL_SEEN_FLAG = 1 << config.bitDataNullSeenFlag;
+    static class BitData extends HotSpotMethodDataAccessor {
 
-        private BitData() {
-            super(Tag.BitData, BIT_DATA_SIZE);
+        private BitData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BIT_DATA_SIZE);
         }
 
-        protected BitData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected BitData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -408,17 +296,17 @@
         }
     }
 
-    private static class CounterData extends BitData {
+    static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
+    static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
 
-        private static final int COUNTER_DATA_SIZE = cellIndexToOffset(1);
-        private static final int COUNTER_DATA_COUNT_OFFSET = cellIndexToOffset(config.methodDataCountOffset);
+    static class CounterData extends BitData {
 
-        CounterData() {
-            super(Tag.CounterData, COUNTER_DATA_SIZE);
+        CounterData(HotSpotVMConfig config, int tag) {
+            super(config, tag, COUNTER_DATA_SIZE);
         }
 
-        protected CounterData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected CounterData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -436,18 +324,18 @@
         }
     }
 
-    private static class JumpData extends AbstractMethodData {
+    static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
+    static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
+    static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
 
-        private static final int JUMP_DATA_SIZE = cellIndexToOffset(2);
-        protected static final int TAKEN_COUNT_OFFSET = cellIndexToOffset(config.jumpDataTakenOffset);
-        protected static final int TAKEN_DISPLACEMENT_OFFSET = cellIndexToOffset(config.jumpDataDisplacementOffset);
+    static class JumpData extends HotSpotMethodDataAccessor {
 
-        JumpData() {
-            super(Tag.JumpData, JUMP_DATA_SIZE);
+        JumpData(HotSpotVMConfig config, int tag) {
+            super(config, tag, JUMP_DATA_SIZE);
         }
 
-        protected JumpData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected JumpData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -484,16 +372,16 @@
         }
     }
 
-    private abstract static class AbstractTypeData extends CounterData {
-
-        protected static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
+    static final int TYPE_DATA_ROW_SIZE = cellsToBytes(config.receiverTypeDataReceiverTypeRowCellCount);
 
-        protected static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
-        protected static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
-        protected static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
+    static final int NONPROFILED_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataNonprofiledCountOffset);
+    static final int TYPE_DATA_FIRST_TYPE_OFFSET = cellIndexToOffset(config.receiverTypeDataReceiver0Offset);
+    static final int TYPE_DATA_FIRST_TYPE_COUNT_OFFSET = cellIndexToOffset(config.receiverTypeDataCount0Offset);
 
-        protected AbstractTypeData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+    abstract static class AbstractTypeData extends CounterData {
+
+        protected AbstractTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -539,7 +427,7 @@
 
         protected abstract long getTypesNotRecordedExecutionCount(HotSpotMethodData data, int position);
 
-        private static JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
+        private JavaTypeProfile createTypeProfile(TriState nullSeen, RawItemProfile<ResolvedJavaType> profile) {
             if (profile.entries <= 0 || profile.totalCount <= 0) {
                 return null;
             }
@@ -583,16 +471,16 @@
         }
     }
 
-    private static class ReceiverTypeData extends AbstractTypeData {
+    static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
-        private static final int TYPE_CHECK_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static class ReceiverTypeData extends AbstractTypeData {
 
-        ReceiverTypeData() {
-            super(Tag.ReceiverTypeData, TYPE_CHECK_DATA_SIZE);
+        ReceiverTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, TYPE_CHECK_DATA_SIZE);
         }
 
-        protected ReceiverTypeData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected ReceiverTypeData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -606,18 +494,18 @@
         }
     }
 
-    private static class VirtualCallData extends ReceiverTypeData {
+    static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
 
-        private static final int VIRTUAL_CALL_DATA_SIZE = cellIndexToOffset(2) + TYPE_DATA_ROW_SIZE * (config.typeProfileWidth + config.methodProfileWidth);
-        private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_OFFSET = TYPE_DATA_FIRST_TYPE_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
-        private static final int VIRTUAL_CALL_DATA_FIRST_METHOD_COUNT_OFFSET = TYPE_DATA_FIRST_TYPE_COUNT_OFFSET + TYPE_DATA_ROW_SIZE * config.typeProfileWidth;
+    static class VirtualCallData extends ReceiverTypeData {
 
-        VirtualCallData() {
-            super(Tag.VirtualCallData, VIRTUAL_CALL_DATA_SIZE);
+        VirtualCallData(HotSpotVMConfig config, int tag) {
+            super(config, tag, VIRTUAL_CALL_DATA_SIZE);
         }
 
-        protected VirtualCallData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        protected VirtualCallData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -647,7 +535,7 @@
             return createMethodProfile(getRawMethodProfile(data, position));
         }
 
-        private static RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
+        private RawItemProfile<ResolvedJavaMethod> getRawMethodProfile(HotSpotMethodData data, int position) {
             int profileWidth = config.methodProfileWidth;
 
             ResolvedJavaMethod[] methods = new ResolvedJavaMethod[profileWidth];
@@ -671,7 +559,7 @@
             return new RawItemProfile<>(entries, methods, counts, totalCount);
         }
 
-        private static JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
+        private JavaMethodProfile createMethodProfile(RawItemProfile<ResolvedJavaMethod> profile) {
             if (profile.entries <= 0 || profile.totalCount <= 0) {
                 return null;
             }
@@ -712,10 +600,10 @@
         }
     }
 
-    private static class VirtualCallTypeData extends VirtualCallData {
+    static class VirtualCallTypeData extends VirtualCallData {
 
-        VirtualCallTypeData() {
-            super(Tag.VirtualCallTypeData, 0);
+        VirtualCallTypeData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
         }
 
         @Override
@@ -725,23 +613,23 @@
         }
     }
 
-    private static class RetData extends CounterData {
+    static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
+    static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
 
-        private static final int RET_DATA_ROW_SIZE = cellsToBytes(3);
-        private static final int RET_DATA_SIZE = cellIndexToOffset(1) + RET_DATA_ROW_SIZE * config.bciProfileWidth;
+    static class RetData extends CounterData {
 
-        RetData() {
-            super(Tag.RetData, RET_DATA_SIZE);
+        RetData(HotSpotVMConfig config, int tag) {
+            super(config, tag, RET_DATA_SIZE);
         }
     }
 
-    private static class BranchData extends JumpData {
+    static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
+    static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
 
-        private static final int BRANCH_DATA_SIZE = cellIndexToOffset(3);
-        private static final int NOT_TAKEN_COUNT_OFFSET = cellIndexToOffset(config.branchDataNotTakenOffset);
+    static class BranchData extends JumpData {
 
-        BranchData() {
-            super(Tag.BranchData, BRANCH_DATA_SIZE);
+        BranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -768,13 +656,13 @@
         }
     }
 
-    private static class ArrayData extends AbstractMethodData {
+    static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
+    static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
 
-        private static final int ARRAY_DATA_LENGTH_OFFSET = cellIndexToOffset(config.arrayDataArrayLenOffset);
-        protected static final int ARRAY_DATA_START_OFFSET = cellIndexToOffset(config.arrayDataArrayStartOffset);
+    static class ArrayData extends HotSpotMethodDataAccessor {
 
-        ArrayData(Tag tag, int staticSize) {
-            super(tag, staticSize);
+        ArrayData(HotSpotVMConfig config, int tag, int staticSize) {
+            super(config, tag, staticSize);
         }
 
         @Override
@@ -792,16 +680,16 @@
         }
     }
 
-    private static class MultiBranchData extends ArrayData {
+    static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
+    static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
+    static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
+    static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
+    static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
 
-        private static final int MULTI_BRANCH_DATA_SIZE = cellIndexToOffset(1);
-        private static final int MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS = config.multiBranchDataPerCaseCellCount;
-        private static final int MULTI_BRANCH_DATA_ROW_SIZE = cellsToBytes(MULTI_BRANCH_DATA_ROW_SIZE_IN_CELLS);
-        private static final int MULTI_BRANCH_DATA_FIRST_COUNT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(0);
-        private static final int MULTI_BRANCH_DATA_FIRST_DISPLACEMENT_OFFSET = ARRAY_DATA_START_OFFSET + cellsToBytes(1);
+    static class MultiBranchData extends ArrayData {
 
-        MultiBranchData() {
-            super(Tag.MultiBranchData, MULTI_BRANCH_DATA_SIZE);
+        MultiBranchData(HotSpotVMConfig config, int tag) {
+            super(config, tag, MULTI_BRANCH_DATA_SIZE);
         }
 
         @Override
@@ -878,18 +766,18 @@
         }
     }
 
-    private static class ArgInfoData extends ArrayData {
+    static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
 
-        private static final int ARG_INFO_DATA_SIZE = cellIndexToOffset(1);
+    static class ArgInfoData extends ArrayData {
 
-        ArgInfoData() {
-            super(Tag.ArgInfoData, ARG_INFO_DATA_SIZE);
+        ArgInfoData(HotSpotVMConfig config, int tag) {
+            super(config, tag, ARG_INFO_DATA_SIZE);
         }
     }
 
-    private static class UnknownProfileData extends AbstractMethodData {
-        UnknownProfileData(Tag tag) {
-            super(tag, 0);
+    static class UnknownProfileData extends HotSpotMethodDataAccessor {
+        UnknownProfileData(HotSpotVMConfig config, int tag) {
+            super(config, tag, 0);
         }
 
         @Override
@@ -900,7 +788,6 @@
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            // TODO Auto-generated method stub
             return null;
         }
     }
@@ -912,4 +799,41 @@
     public int getCompiledIRSize() {
         return UNSAFE.getInt(metaspaceMethodData + config.methodDataIRSizeOffset);
     }
+
+    // sorted by tag
+    // @formatter:off
+    static final HotSpotMethodDataAccessor[] PROFILE_DATA_ACCESSORS = {
+        null,
+        new BitData(config, config.dataLayoutBitDataTag),
+        new CounterData(config, config.dataLayoutCounterDataTag),
+        new JumpData(config, config.dataLayoutJumpDataTag),
+        new ReceiverTypeData(config, config.dataLayoutReceiverTypeDataTag),
+        new VirtualCallData(config, config.dataLayoutVirtualCallDataTag),
+        new RetData(config, config.dataLayoutRetDataTag),
+        new BranchData(config, config.dataLayoutBranchDataTag),
+        new MultiBranchData(config, config.dataLayoutMultiBranchDataTag),
+        new ArgInfoData(config, config.dataLayoutArgInfoDataTag),
+        new UnknownProfileData(config, config.dataLayoutCallTypeDataTag),
+        new VirtualCallTypeData(config, config.dataLayoutVirtualCallTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutParametersTypeDataTag),
+        new UnknownProfileData(config, config.dataLayoutSpeculativeTrapDataTag),
+    };
+
+    private static boolean checkAccessorTags() {
+        int expectedTag = 0;
+        for (HotSpotMethodDataAccessor accessor : PROFILE_DATA_ACCESSORS) {
+            if (expectedTag ==0 ) {
+                assert accessor == null;
+            } else {
+                assert accessor.tag == expectedTag: expectedTag + " != " + accessor.tag + " " + accessor;
+            }
+            expectedTag++;
+        }
+        return true;
+    }
+
+    static {
+        assert checkAccessorTags();
+    }
+    // @formatter:on
 }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodDataAccessor.java	Thu Jun 23 05:13:55 2016 +0000
@@ -1,110 +1,129 @@
-/*
- * Copyright (c) 2011, 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.
- *
- * 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.
- */
 package jdk.vm.ci.hotspot;
 
-import static jdk.vm.ci.hotspot.HotSpotVMConfig.config;
 import jdk.vm.ci.meta.JavaMethodProfile;
 import jdk.vm.ci.meta.JavaTypeProfile;
 import jdk.vm.ci.meta.ProfilingInfo;
 import jdk.vm.ci.meta.TriState;
 
 /**
- * Interface for accessor objects that encapsulate the logic for accessing the different kinds of
- * data in a HotSpot methodDataOop. This interface is similar to the interface {@link ProfilingInfo}
- * , but most methods require a MethodDataObject and the exact position within the methodData.
+ * Base class for accessing the different kinds of data in a HotSpot {@code MethodData}. This is
+ * similar to {@link ProfilingInfo}, but most methods require a {@link HotSpotMethodData} and the
+ * exact position within the method data.
  */
-public interface HotSpotMethodDataAccessor {
+abstract class HotSpotMethodDataAccessor {
 
-    /**
-     * {@code DataLayout} tag values.
-     */
-    enum Tag {
-        No(config().dataLayoutNoTag),
-        BitData(config().dataLayoutBitDataTag),
-        CounterData(config().dataLayoutCounterDataTag),
-        JumpData(config().dataLayoutJumpDataTag),
-        ReceiverTypeData(config().dataLayoutReceiverTypeDataTag),
-        VirtualCallData(config().dataLayoutVirtualCallDataTag),
-        RetData(config().dataLayoutRetDataTag),
-        BranchData(config().dataLayoutBranchDataTag),
-        MultiBranchData(config().dataLayoutMultiBranchDataTag),
-        ArgInfoData(config().dataLayoutArgInfoDataTag),
-        CallTypeData(config().dataLayoutCallTypeDataTag),
-        VirtualCallTypeData(config().dataLayoutVirtualCallTypeDataTag),
-        ParametersTypeData(config().dataLayoutParametersTypeDataTag),
-        SpeculativeTrapData(config().dataLayoutSpeculativeTrapDataTag);
+    final int tag;
+    final int staticSize;
+    final HotSpotVMConfig config;
 
-        private final int value;
-
-        Tag(int value) {
-            this.value = value;
-        }
-
-        public int getValue() {
-            return value;
-        }
-
-        public static Tag getEnum(int value) {
-            Tag result = values()[value];
-            assert value == result.value;
-            return result;
-        }
+    protected HotSpotMethodDataAccessor(HotSpotVMConfig config, int tag, int staticSize) {
+        this.config = config;
+        this.tag = tag;
+        this.staticSize = staticSize;
     }
 
     /**
-     * Returns the {@link Tag} stored in the LayoutData header.
+     * Returns the tag stored in the LayoutData header.
      *
      * @return tag stored in the LayoutData header
      */
-    Tag getTag();
+    int getTag() {
+        return tag;
+    }
+
+    static int readTag(HotSpotVMConfig config, HotSpotMethodData data, int position) {
+        final int tag = data.readUnsignedByte(position, config.dataLayoutTagOffset);
+        assert tag >= config.dataLayoutNoTag && tag <= config.dataLayoutSpeculativeTrapDataTag : "profile data tag out of bounds: " + tag;
+        return tag;
+    }
 
     /**
      * Returns the BCI stored in the LayoutData header.
      *
-     * @return An integer &ge; 0 and &le; Short.MAX_VALUE, or -1 if not supported.
+     * @return an integer between 0 and {@link Short#MAX_VALUE} inclusive, or -1 if not supported
      */
-    int getBCI(HotSpotMethodData data, int position);
+    int getBCI(HotSpotMethodData data, int position) {
+        return data.readUnsignedShort(position, config.dataLayoutBCIOffset);
+    }
 
     /**
      * Computes the size for the specific data at the given position.
      *
-     * @return An integer &gt; 0.
+     * @return a value greater than 0
      */
-    int getSize(HotSpotMethodData data, int position);
+    final int getSize(HotSpotMethodData data, int position) {
+        int size = staticSize + getDynamicSize(data, position);
+        // Sanity check against VM
+        int vmSize = HotSpotJVMCIRuntime.runtime().compilerToVm.methodDataProfileDataSize(data.metaspaceMethodData, position);
+        assert size == vmSize : size + " != " + vmSize;
+        return size;
+    }
+
+    TriState getExceptionSeen(HotSpotMethodData data, int position) {
+        final int EXCEPTIONS_MASK = 1 << config.bitDataExceptionSeenFlag;
+        return TriState.get((getFlags(data, position) & EXCEPTIONS_MASK) != 0);
+    }
 
-    JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    JavaTypeProfile getTypeProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    JavaMethodProfile getMethodProfile(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    double getBranchTakenProbability(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    double getBranchTakenProbability(HotSpotMethodData data, int position) {
+        return -1;
+    }
 
-    double[] getSwitchProbabilities(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    double[] getSwitchProbabilities(HotSpotMethodData data, int position) {
+        return null;
+    }
 
-    TriState getExceptionSeen(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    int getExecutionCount(HotSpotMethodData data, int position) {
+        return -1;
+    }
 
-    TriState getNullSeen(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    TriState getNullSeen(HotSpotMethodData data, int position) {
+        return TriState.UNKNOWN;
+    }
+
+    protected int getFlags(HotSpotMethodData data, int position) {
+        return data.readUnsignedByte(position, config.dataLayoutFlagsOffset);
+    }
 
-    int getExecutionCount(HotSpotMethodData data, int position);
+    /**
+     * @param data
+     * @param position
+     */
+    protected int getDynamicSize(HotSpotMethodData data, int position) {
+        return 0;
+    }
 
-    StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
-}
+    abstract StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos);
+
+}
\ No newline at end of file
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotReferenceMap.java	Thu Jun 23 05:13:55 2016 +0000
@@ -27,13 +27,25 @@
 import jdk.vm.ci.code.Location;
 import jdk.vm.ci.code.ReferenceMap;
 
+/**
+ * Describes where the object references are in machine state, compliant with what HotSpot expects.
+ */
 public final class HotSpotReferenceMap extends ReferenceMap {
 
-    final Location[] objects;
-    final Location[] derivedBase;
-    final int[] sizeInBytes;
-    final int maxRegisterSize;
+    private final Location[] objects;
+    private final Location[] derivedBase;
+    private final int[] sizeInBytes;
+    private final int maxRegisterSize;
 
+    /**
+     *
+     * @param objects This array is now owned by this object and must not be mutated by the caller.
+     * @param derivedBase This array is now owned by this object and must not be mutated by the
+     *            caller.
+     * @param sizeInBytes This array is now owned by this object and must not be mutated by the
+     *            caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `objects`, `derivedBase` and `sizeInBytes`")
     public HotSpotReferenceMap(Location[] objects, Location[] derivedBase, int[] sizeInBytes, int maxRegisterSize) {
         this.objects = objects;
         this.derivedBase = derivedBase;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Jun 23 05:13:55 2016 +0000
@@ -591,7 +591,8 @@
             // Get Klass::_fields
             final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
             assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code";
-            metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index;
+            int offset = config.fieldInfoFieldSlots * Short.BYTES * index;
+            metaspaceData = metaspaceFields + config.arrayU2DataOffset + offset;
         }
 
         private int getAccessFlags() {
@@ -619,7 +620,8 @@
          * on top an array of Java shorts.
          */
         private int readFieldSlot(int index) {
-            return UNSAFE.getChar(metaspaceData + Short.BYTES * index);
+            int offset = Short.BYTES * index;
+            return UNSAFE.getChar(metaspaceData + offset);
         }
 
         /**
@@ -628,7 +630,7 @@
          */
         public String getName() {
             final int nameIndex = getNameIndex();
-            return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
+            return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex);
         }
 
         /**
@@ -637,7 +639,7 @@
          */
         public String getSignature() {
             final int signatureIndex = getSignatureIndex();
-            return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
+            return isInternal() ? config().symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex);
         }
 
         public JavaType getType() {
@@ -658,6 +660,7 @@
         }
     }
 
+    @SuppressFBWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", justification = "comparator is only used transiently")
     private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
         @Override
         public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java	Thu Jun 23 05:13:55 2016 +0000
@@ -35,7 +35,7 @@
     /** Written by the C++ code that performs deoptimization. */
     private volatile Object lastFailed;
 
-    /** All speculations that have been a deoptimization reason. */
+    /** All speculations that have caused a deoptimization. */
     private Set<SpeculationReason> failedSpeculations;
 
     /** Strong references to all reasons embedded in the current nmethod. */
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public boolean maySpeculate(SpeculationReason reason) {
+    public synchronized boolean maySpeculate(SpeculationReason reason) {
         if (failedSpeculations != null && failedSpeculations.contains(reason)) {
             return false;
         }
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Thu Jun 23 05:13:55 2016 +0000
@@ -23,6 +23,9 @@
 package jdk.vm.ci.hotspot;
 
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
+import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
+
+import jdk.internal.misc.Unsafe;
 
 /**
  * Used to access native configuration details.
@@ -52,13 +55,13 @@
         String arch = System.getProperty("os.arch");
         switch (arch) {
             case "x86_64":
-                arch = "amd64";
-                break;
+                return "amd64";
+
             case "sparcv9":
-                arch = "sparc";
-                break;
+                return "sparc";
+            default:
+                return arch;
         }
-        return arch;
     }
 
     final boolean useDeferredInitBarriers = getFlag("ReduceInitialCardMarks", Boolean.class);
@@ -231,6 +234,21 @@
     final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
     final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
 
+    /**
+     * Returns the symbol in the {@code vmSymbols} table at position {@code index} as a
+     * {@link String}.
+     *
+     * @param index position in the symbol table
+     * @return the symbol at position id
+     */
+    String symbolAt(int index) {
+        HotSpotJVMCIRuntimeProvider runtime = runtime();
+        assert vmSymbolsFirstSID <= index && index < vmSymbolsSIDLimit : "index " + index + " is out of bounds";
+        assert symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
+        int offset = index * symbolPointerSize;
+        return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(vmSymbolsSymbols + offset));
+    }
+
     final int universeBaseVtableSize = getFieldValue("CompilerToVM::Data::Universe_base_vtable_size", Integer.class, "int");
 
     final int baseVtableLength() {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Thu Jun 23 05:13:55 2016 +0000
@@ -126,7 +126,7 @@
         if (entry.address != 0) {
             throw new JVMCIError("cannot get offset of static field " + name);
         }
-        return entry == null ? notPresent : type.cast(convertValue(name, type, entry.offset, cppType));
+        return type.cast(convertValue(name, type, entry.offset, cppType));
     }
 
     /**
@@ -173,7 +173,7 @@
         if (entry.address == 0) {
             throw new JVMCIError(name + " is not a static field");
         }
-        return entry == null ? notPresent : entry.address;
+        return entry.address;
     }
 
     /**
@@ -313,7 +313,7 @@
                 return (int) (long) value;
             }
         } else if (toType == Long.class) {
-            return (long) value;
+            return value;
         }
 
         throw new JVMCIError("cannot convert " + name + " of type " + value.getClass().getSimpleName() + (cppType == null ? "" : " [" + cppType + "]") + " to " + toType.getSimpleName());
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVmSymbols.java	Wed Jun 22 23:31:33 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.
- *
- * 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.
- */
-package jdk.vm.ci.hotspot;
-
-import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
-import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE;
-import jdk.internal.misc.Unsafe;
-
-/**
- * Class to access the C++ {@code vmSymbols} table.
- */
-final class HotSpotVmSymbols {
-
-    /**
-     * Returns the symbol in the {@code vmSymbols} table at position {@code index} as {@link String}
-     * .
-     *
-     * @param index position in the symbol table
-     * @return the symbol at position id
-     */
-    static String symbolAt(int index) {
-        HotSpotJVMCIRuntimeProvider runtime = runtime();
-        HotSpotVMConfig config = runtime.getConfig();
-        assert config.vmSymbolsFirstSID <= index && index < config.vmSymbolsSIDLimit : "index " + index + " is out of bounds";
-        assert config.symbolPointerSize == Unsafe.ADDRESS_SIZE : "the following address read is broken";
-        return runtime.getCompilerToVM().getSymbol(UNSAFE.getAddress(config.vmSymbolsSymbols + index * config.symbolPointerSize));
-    }
-}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractJavaProfile.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractJavaProfile.java	Thu Jun 23 05:13:55 2016 +0000
@@ -37,6 +37,12 @@
     private final double notRecordedProbability;
     private final T[] pitems;
 
+    /**
+     *
+     * @param notRecordedProbability
+     * @param pitems
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of the `pitems` array parameter")
     public AbstractJavaProfile(double notRecordedProbability, T[] pitems) {
         this.pitems = pitems;
         assert !Double.isNaN(notRecordedProbability);
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractProfiledItem.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/AbstractProfiledItem.java	Thu Jun 23 05:13:55 2016 +0000
@@ -51,14 +51,14 @@
         return probability;
     }
 
+    /**
+     * Returns -1 if the {@linkplain #getProbability() probability} of this item is greater than
+     * {@code o}'s probability, 0 if there are equal otherwise 1.
+     */
     @Override
     public int compareTo(AbstractProfiledItem<?> o) {
-        if (getProbability() > o.getProbability()) {
-            return -1;
-        } else if (getProbability() < o.getProbability()) {
-            return 1;
-        }
-        return 0;
+        // Need to swap the order of operands so that higher probabilities are sorted first
+        return Double.compare(o.getProbability(), getProbability());
     }
 
     @Override
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTable.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LineNumberTable.java	Thu Jun 23 05:13:55 2016 +0000
@@ -22,24 +22,34 @@
  */
 package jdk.vm.ci.meta;
 
+/**
+ * Maps bytecode indexes to source line numbers.
+ *
+ * @see "https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.12"
+ */
 public class LineNumberTable {
 
     private final int[] lineNumbers;
     private final int[] bci;
 
+    /**
+     *
+     * @param lineNumbers an array or source line numbers. This array is now owned by this object
+     *            and should not be mutated by the caller.
+     * @param bci an array of bytecode indexes the same length at {@code lineNumbers} whose entries
+     *            are sorted in ascending order. This array is now owned by this object and must not
+     *            be mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `lineNumbers` and `bcis`")
     public LineNumberTable(int[] lineNumbers, int[] bci) {
+        assert bci.length == lineNumbers.length;
         this.lineNumbers = lineNumbers;
         this.bci = bci;
     }
 
-    public int[] getLineNumberEntries() {
-        return lineNumbers;
-    }
-
-    public int[] getBciEntries() {
-        return bci;
-    }
-
+    /**
+     * Gets a source line number for {@code atBci}.
+     */
     public int getLineNumber(int atBci) {
         for (int i = 0; i < this.bci.length - 1; i++) {
             if (this.bci[i] <= atBci && atBci < this.bci[i + 1]) {
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Local.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Local.java	Thu Jun 23 05:13:55 2016 +0000
@@ -22,6 +22,9 @@
  */
 package jdk.vm.ci.meta;
 
+/**
+ * Describes the type and bytecode index range in which a local variable is live.
+ */
 public class Local {
 
     private final String name;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTable.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/LocalVariableTable.java	Thu Jun 23 05:13:55 2016 +0000
@@ -25,10 +25,19 @@
 import java.util.ArrayList;
 import java.util.List;
 
+/**
+ * @see "https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.13"
+ */
 public class LocalVariableTable {
 
     private final Local[] locals;
 
+    /**
+     *
+     * @param locals array of objects describing local variables. This array is now owned by this
+     *            object and must not be mutated by the caller.
+     */
+    @SuppressFBWarnings(value = "EI_EXPOSE_REP2", justification = "caller transfers ownership of `locals`")
     public LocalVariableTable(Local[] locals) {
         this.locals = locals;
     }
@@ -47,10 +56,6 @@
         return result;
     }
 
-    public Local[] getLocals() {
-        return locals;
-    }
-
     public Local[] getLocalsAt(int bci) {
         List<Local> result = new ArrayList<>();
         for (Local l : locals) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/SuppressFBWarnings.java	Thu Jun 23 05:13:55 2016 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+package jdk.vm.ci.meta;
+
+/**
+ * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings.
+ */
+@interface SuppressFBWarnings {
+    /**
+     * The set of FindBugs
+     * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be
+     * suppressed in annotated element. The value can be a bug category, kind or pattern.
+     */
+    String[] value();
+
+    /**
+     * Reason why the warning is suppressed.
+     */
+    String justification();
+}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java	Thu Jun 23 05:13:55 2016 +0000
@@ -32,6 +32,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.Register.RegisterCategory;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.PlatformKind;
 
@@ -179,35 +180,35 @@
     public static final Register q60 = new Register(111, getQuadncoding(60), "q60", FPUq);
 
     // @formatter:off
-    public static final Register[] cpuRegisters = {
+    public static final RegisterArray cpuRegisters = new RegisterArray(
         g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
         o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
         l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
         i0,  i1,  i2,  i3,  i4,  i5,  i6,  i7
-    };
+    );
 
-    public static final Register[] fpusRegisters = {
+    public static final RegisterArray fpusRegisters = new RegisterArray(
         f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,
         f8,  f9,  f10, f11, f12, f13, f14, f15,
         f16, f17, f18, f19, f20, f21, f22, f23,
         f24, f25, f26, f27, f28, f29, f30, f31
-    };
+    );
 
-    public static final Register[] fpudRegisters = {
+    public static final RegisterArray fpudRegisters = new RegisterArray(
         d0, d2, d4, d6, d8,  d10, d12, d14,
         d16, d18, d20, d22, d24, d26, d28, d30,
         d32, d34, d36, d38, d40, d42, d44, d46,
         d48, d50, d52, d54, d56, d58, d60, d62
-    };
+    );
 
-    public static final Register[] fpuqRegisters = {
+    public static final RegisterArray fpuqRegisters = new RegisterArray(
         q0, q4, q8, q12,
         q16, q20, q24, q28,
         q32, q36, q40, q44,
-        q48, q52, q56, q60,
-    };
+        q48, q52, q56, q60
+    );
 
-    public static final Register[] allRegisters = {
+    public static final RegisterArray allRegisters = new RegisterArray(
         g0,  g1,  g2,  g3,  g4,  g5,  g6,  g7,
         o0,  o1,  o2,  o3,  o4,  o5,  o6,  o7,
         l0,  l1,  l2,  l3,  l4,  l5,  l6,  l7,
@@ -226,8 +227,8 @@
         q0, q4, q8, q12,
         q16, q20, q24, q28,
         q32, q36, q40, q44,
-        q48, q52, q56, q60,
-    };
+        q48, q52, q56, q60
+    );
     // @formatter:on
 
     /**
@@ -248,7 +249,7 @@
     }
 
     @Override
-    public Register[] getAvailableValueRegisters() {
+    public RegisterArray getAvailableValueRegisters() {
         return allRegisters;
     }
 
--- a/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/test/compiler/jvmci/errors/CodeInstallerTest.java	Thu Jun 23 05:13:55 2016 +0000
@@ -28,6 +28,7 @@
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.code.Register;
+import jdk.vm.ci.code.RegisterArray;
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.site.DataPatch;
 import jdk.vm.ci.code.site.Site;
@@ -80,11 +81,11 @@
 
     protected Register getRegister(PlatformKind kind, int index) {
         int idx = index;
-        Register[] allRegs = arch.getAvailableValueRegisters();
-        for (int i = 0; i < allRegs.length; i++) {
-            if (arch.canStoreValue(allRegs[i].getRegisterCategory(), kind)) {
+        RegisterArray allRegs = arch.getAvailableValueRegisters();
+        for (Register reg : allRegs) {
+            if (arch.canStoreValue(reg.getRegisterCategory(), kind)) {
                 if (idx-- == 0) {
-                    return allRegs[i];
+                    return reg;
                 }
             }
         }
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/amd64/AMD64TestAssembler.java	Thu Jun 23 05:13:55 2016 +0000
@@ -85,12 +85,12 @@
 
     @Override
     public Register emitIntArg0() {
-        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)[0];
+        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int).get(0);
     }
 
     @Override
     public Register emitIntArg1() {
-        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int)[1];
+        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCall, JavaKind.Int).get(1);
     }
 
     private void emitREX(boolean w, int r, int x, int b) {
--- a/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/sparc/SPARCTestAssembler.java	Wed Jun 22 23:31:33 2016 +0000
+++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/sparc/SPARCTestAssembler.java	Thu Jun 23 05:13:55 2016 +0000
@@ -121,12 +121,12 @@
 
     @Override
     public Register emitIntArg0() {
-        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int)[0];
+        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int).get(0);
     }
 
     @Override
     public Register emitIntArg1() {
-        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int)[1];
+        return codeCache.getRegisterConfig().getCallingConventionRegisters(HotSpotCallingConventionType.JavaCallee, JavaKind.Int).get(1);
     }
 
     @Override