changeset 36941:de88db753877

Merge
author amurillo
date Tue, 05 Apr 2016 20:02:21 -0700
parents 71f5c0728dfc 2696577a976c
children 6d430b388238
files
diffstat 96 files changed, 38771 insertions(+), 96 deletions(-) [+]
line wrap: on
line diff
--- a/jdk/make/gensrc/Gensrc-java.base.gmk	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/make/gensrc/Gensrc-java.base.gmk	Tue Apr 05 20:02:21 2016 -0700
@@ -33,6 +33,7 @@
 include GensrcCharsetCoder.gmk
 include GensrcBuffer.gmk
 include GensrcExceptions.gmk
+include GensrcVarHandles.gmk
 include GensrcModuleLoaderMap.gmk
 
 ################################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/gensrc/GensrcVarHandles.gmk	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,162 @@
+#
+# Copyright (c) 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.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+GENSRC_VARHANDLES :=
+
+VARHANDLES_GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/invoke
+VARHANDLES_SRC_DIR := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/invoke
+
+################################################################################
+# Setup a rule for generating a VarHandle java class
+# Param 1 - Variable declaration prefix
+# Param 2 - Type with first letter capitalized
+define GenerateVarHandle
+
+  $1_Type := $2
+
+  $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandle$$($1_Type)s.java
+
+  ifneq ($$(findstring $$($1_Type), Object Int Long), )
+    $1_ARGS += -KCAS
+  endif
+
+  ifneq ($$(findstring $$($1_Type), Int Long), )
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  $$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandle.java.template $(BUILD_TOOLS_JDK)
+        ifeq ($$($1_Type), Object)
+	  $$(eval $1_type := $$($1_Type))
+        else
+	  $$(eval $1_type := $$$$(shell $(TR) '[:upper:]' '[:lower:]' <<< $$$$($1_Type)))
+        endif
+	$$(call MakeDir, $$(@D))
+	$(TOOL_SPP) -nel -K$$($1_type) -Dtype=$$($1_type) -DType=$$($1_Type) \
+	    $$($1_ARGS) < $$< > $$@
+
+  GENSRC_VARHANDLES += $$($1_FILENAME)
+endef
+
+################################################################################
+
+################################################################################
+# Setup a rule for generating a VarHandleByteArray java class
+# Param 1 - Variable declaration prefix
+# Param 2 - Type with first letter capitalized
+define GenerateVarHandleByteArray
+
+  $1_Type := $2
+
+  $1_FILENAME := $(VARHANDLES_GENSRC_DIR)/VarHandleByteArrayAs$$($1_Type)s.java
+
+  ifeq ($$($1_Type), Short)
+    $1_type := short
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+  endif
+
+  ifeq ($$($1_Type), Char)
+    $1_type := char
+    $1_BoxType := Character
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+  endif
+
+  ifeq ($$($1_Type), Int)
+    $1_type := int
+    $1_BoxType := Integer
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  ifeq ($$($1_Type), Long)
+    $1_type := long
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := $$($1_type)
+    $1_RawType := $$($1_Type)
+    $1_RawBoxType := $$($1_BoxType)
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KAtomicAdd
+  endif
+
+  ifeq ($$($1_Type), Float)
+    $1_type := float
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := int
+    $1_RawType := Int
+    $1_RawBoxType := Integer
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KfloatingPoint
+  endif
+
+  ifeq ($$($1_Type), Double)
+    $1_type := double
+    $1_BoxType := $$($1_Type)
+
+    $1_rawType := long
+    $1_RawType := Long
+    $1_RawBoxType := Long
+
+    $1_ARGS += -KCAS
+    $1_ARGS += -KfloatingPoint
+  endif
+
+  $$($1_FILENAME): $(VARHANDLES_SRC_DIR)/X-VarHandleByteArrayView.java.template $(BUILD_TOOLS_JDK)
+	$$(call MakeDir, $$(@D))
+	$(TOOL_SPP) -nel -K$$($1_type) \
+	    -Dtype=$$($1_type) -DType=$$($1_Type) -DBoxType=$$($1_BoxType) \
+	    -DrawType=$$($1_rawType) -DRawType=$$($1_RawType) -DRawBoxType=$$($1_RawBoxType) \
+	    $$($1_ARGS) < $$< > $$@
+
+  GENSRC_VARHANDLES += $$($1_FILENAME)
+endef
+
+################################################################################
+
+# List the types to generate source for, with capitalized first letter
+VARHANDLES_TYPES := Boolean Byte Short Char Int Long Float Double Object
+$(foreach t, $(VARHANDLES_TYPES), \
+  $(eval $(call GenerateVarHandle,VAR_HANDLE_$t,$t)))
+
+# List the types to generate source for, with capitalized first letter
+VARHANDLES_BYTE_ARRAY_TYPES := Short Char Int Long Float Double
+$(foreach t, $(VARHANDLES_BYTE_ARRAY_TYPES), \
+  $(eval $(call GenerateVarHandleByteArray,VAR_HANDLE_BYTE_ARRAY_$t,$t)))
+
+GENSRC_JAVA_BASE += $(GENSRC_VARHANDLES)
--- a/jdk/src/java.base/share/classes/java/lang/StringCoding.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/StringCoding.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -146,7 +146,7 @@
     }
 
     @HotSpotIntrinsicCandidate
-    private static boolean hasNegatives(byte[] ba, int off, int len) {
+    public static boolean hasNegatives(byte[] ba, int off, int len) {
         for (int i = off; i < off + len; i++) {
             if (ba[i] < 0) {
                 return true;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InfoFromMemberName.java	Tue Apr 05 20:02:21 2016 -0700
@@ -41,7 +41,7 @@
     private final int referenceKind;
 
     InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
-        assert(member.isResolved() || member.isMethodHandleInvoke());
+        assert(member.isResolved() || member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke());
         assert(member.referenceKindIsConsistentWith(referenceKind));
         this.member = member;
         this.referenceKind = referenceKind;
@@ -79,7 +79,8 @@
 
     @Override
     public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
-        if (member.isMethodHandleInvoke() && !member.isVarargs()) {
+        if ((member.isMethodHandleInvoke() || member.isVarHandleMethodInvoke())
+            && !member.isVarargs()) {
             // This member is an instance of a signature-polymorphic method, which cannot be reflected
             // A method handle invoker can come in either of two forms:
             // A generic placeholder (present in the source code, and varargs)
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java	Tue Apr 05 20:02:21 2016 -0700
@@ -93,6 +93,16 @@
         return setCachedInvoker(INV_BASIC, invoker);
     }
 
+    /*non-public*/ MethodHandle varHandleMethodInvoker(VarHandle.AccessMode ak) {
+        // TODO cache invoker
+        return makeVarHandleMethodInvoker(ak);
+    }
+
+    /*non-public*/ MethodHandle varHandleMethodExactInvoker(VarHandle.AccessMode ak) {
+        // TODO cache invoker
+        return makeVarHandleMethodExactInvoker(ak);
+    }
+
     private MethodHandle cachedInvoker(int idx) {
         return invokers[idx];
     }
@@ -117,6 +127,36 @@
         return invoker;
     }
 
+    private MethodHandle makeVarHandleMethodInvoker(VarHandle.AccessMode ak) {
+        MethodType mtype = targetType;
+        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
+
+        LambdaForm lform = varHandleMethodGenericInvokerHandleForm(ak.name(), mtype);
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
+
+        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
+        assert(checkVarHandleInvoker(invoker));
+
+        maybeCompileToBytecode(invoker);
+        return invoker;
+    }
+
+    private MethodHandle makeVarHandleMethodExactInvoker(VarHandle.AccessMode ak) {
+        MethodType mtype = targetType;
+        MethodType invokerType = mtype.insertParameterTypes(0, VarHandle.class);
+
+        LambdaForm lform = varHandleMethodExactInvokerHandleForm(ak.name(), mtype);
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, ad);
+
+        invoker = invoker.withInternalMemberName(MemberName.makeVarHandleMethodInvoke(ak.name(), mtype), false);
+        assert(checkVarHandleInvoker(invoker));
+
+        maybeCompileToBytecode(invoker);
+        return invoker;
+    }
+
     /** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
     private void maybeCompileToBytecode(MethodHandle invoker) {
         final int EAGER_COMPILE_ARITY_LIMIT = 10;
@@ -146,6 +186,16 @@
         return true;
     }
 
+    private boolean checkVarHandleInvoker(MethodHandle invoker) {
+        MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class);
+        assert(invokerType.equals(invoker.type()))
+                : java.util.Arrays.asList(targetType, invokerType, invoker);
+        assert(invoker.internalMemberName() == null ||
+               invoker.internalMemberName().getMethodType().equals(targetType));
+        assert(!invoker.isVarargsCollector());
+        return true;
+    }
+
     /**
      * Find or create an invoker which passes unchanged a given number of arguments
      * and spreads the rest from a trailing array argument.
@@ -193,9 +243,9 @@
                                                      Object[] appendixResult) {
         int which;
         switch (name) {
-        case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
-        case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
-        default:             throw new InternalError("not invoker: "+name);
+            case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
+            case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
+            default:             throw new InternalError("not invoker: "+name);
         }
         LambdaForm lform;
         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
@@ -296,6 +346,199 @@
         return lform;
     }
 
+
+    static MemberName varHandleInvokeLinkerMethod(String name,
+                                                  MethodType mtype) {
+        LambdaForm lform;
+        if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
+            lform = varHandleMethodGenericLinkerHandleForm(name, mtype);
+        } else {
+            // TODO
+            throw newInternalError("Unsupported parameter slot count " + mtype.parameterSlotCount());
+        }
+        return lform.vmentry;
+    }
+
+    private static LambdaForm varHandleMethodGenericLinkerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_VH      = 0;
+        final int ARG_BASE     = THIS_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
+        final int LINKER_CALL  = nameCursor++;
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_VH] = argument(THIS_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+        names[VAD_ARG] = new Name(ARG_LIMIT, BasicType.basicType(Object.class));
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[THIS_VH], names[VAD_ARG]);
+
+        Object[] outArgs = new Object[ARG_LIMIT + 1];
+        outArgs[0] = names[CHECK_TYPE];
+        for (int i = 0; i < ARG_LIMIT; i++) {
+            outArgs[i + 1] = names[i];
+        }
+
+        if (CHECK_CUSTOM != -1) {
+            names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
+        }
+
+        MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType();
+        names[LINKER_CALL] = new Name(outCallType, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoke_MT_" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT + 1, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    private static LambdaForm varHandleMethodExactInvokerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_MH      = 0;
+        final int CALL_VH      = THIS_MH + 1;
+        final int ARG_BASE     = CALL_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int GET_MEMBER   = nameCursor++;
+        final int LINKER_CALL  = nameCursor++;
+
+        MethodType invokerFormType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType()
+                .appendParameterTypes(MemberName.class);
+
+        MemberName linker = new MemberName(MethodHandle.class, "linkToStatic", invokerFormType, REF_invokeStatic);
+        try {
+            linker = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
+        } catch (ReflectiveOperationException ex) {
+            throw newInternalError(ex);
+        }
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
+        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+
+        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+
+        NamedFunction getter = speciesData.getterFunction(0);
+        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
+
+        Object[] outArgs = Arrays.copyOfRange(names, CALL_VH, ARG_LIMIT + 1, Object[].class);
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleExactType, names[CALL_VH], names[VAD_ARG]);
+
+        names[GET_MEMBER] = new Name(NF_getVarHandleMemberName, names[CALL_VH], names[VAD_ARG]);
+        outArgs[outArgs.length - 1] = names[GET_MEMBER];
+
+        names[LINKER_CALL] = new Name(linker, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_exactInvoker" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    private static LambdaForm varHandleMethodGenericInvokerHandleForm(String name, MethodType mtype) {
+        // TODO Cache form?
+
+        final int THIS_MH      = 0;
+        final int CALL_VH      = THIS_MH + 1;
+        final int ARG_BASE     = CALL_VH + 1;
+        final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
+        int nameCursor = ARG_LIMIT;
+        final int VAD_ARG      = nameCursor++;
+        final int CHECK_TYPE   = nameCursor++;
+        final int LINKER_CALL  = nameCursor++;
+
+        Name[] names = new Name[LINKER_CALL + 1];
+        names[THIS_MH] = argument(THIS_MH, BasicType.basicType(Object.class));
+        names[CALL_VH] = argument(CALL_VH, BasicType.basicType(Object.class));
+        for (int i = 0; i < mtype.parameterCount(); i++) {
+            names[ARG_BASE + i] = argument(ARG_BASE + i, BasicType.basicType(mtype.parameterType(i)));
+        }
+
+        BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+        names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+
+        NamedFunction getter = speciesData.getterFunction(0);
+        names[VAD_ARG] = new Name(getter, names[THIS_MH]);
+
+        names[CHECK_TYPE] = new Name(NF_checkVarHandleGenericType, names[CALL_VH], names[VAD_ARG]);
+
+        Object[] outArgs = new Object[ARG_LIMIT];
+        outArgs[0] = names[CHECK_TYPE];
+        for (int i = 1; i < ARG_LIMIT; i++) {
+            outArgs[i] = names[i];
+        }
+
+        MethodType outCallType = mtype.insertParameterTypes(0, VarHandle.class)
+                .basicType();
+        names[LINKER_CALL] = new Name(outCallType, outArgs);
+        LambdaForm lform = new LambdaForm(name + ":VarHandle_invoker" + shortenSignature(basicTypeSignature(mtype)),
+                                          ARG_LIMIT, names);
+
+        lform.prepare();
+        return lform;
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    MethodHandle checkVarHandleGenericType(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MethodType expected = vad.symbolicMethodType;
+        MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
+
+        MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
+        if (mn == null)
+            throw vh.unsupported();
+        // TODO the following MH is not constant, cache in stable field array
+        // on VarForm?
+        MethodHandle mh = DirectMethodHandle.make(mn);
+        if (actual == expected) {
+            return mh;
+        }
+        else {
+            // Adapt to the actual (which should never fail since mh's method
+            // type is in the basic form), then to the expected (which my fail
+            // if the symbolic type descriptor does not match)
+            // TODO optimize for the case of actual.erased() == expected.erased()
+            return mh.asType(actual.insertParameterTypes(0, VarHandle.class)).
+                    asType(expected.insertParameterTypes(0, VarHandle.class));
+        }
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    void checkVarHandleExactType(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MethodType expected = vad.symbolicMethodType;
+        MethodType actual = VarHandle.AccessType.getMethodType(vad.type, vh);
+        if (actual != expected)
+            throw newWrongMethodTypeException(expected, actual);
+    }
+
+    /*non-public*/ static
+    @ForceInline
+    MemberName getVarHandleMemberName(VarHandle vh, VarHandle.AccessDescriptor vad) {
+        MemberName mn = VarHandle.AccessMode.getMemberName(vad.mode, vh.vform);
+        if (mn == null) {
+            throw vh.unsupported();
+        }
+        return mn;
+    }
+
     /*non-public*/ static
     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
         // FIXME: merge with JVM logic for throwing WMTE
@@ -415,7 +658,10 @@
         NF_checkExactType,
         NF_checkGenericType,
         NF_getCallSiteTarget,
-        NF_checkCustomized;
+        NF_checkCustomized,
+        NF_checkVarHandleGenericType,
+        NF_checkVarHandleExactType,
+        NF_getVarHandleMemberName;
     static {
         try {
             NamedFunction nfs[] = {
@@ -426,7 +672,13 @@
                 NF_getCallSiteTarget = new NamedFunction(Invokers.class
                         .getDeclaredMethod("getCallSiteTarget", CallSite.class)),
                 NF_checkCustomized = new NamedFunction(Invokers.class
-                        .getDeclaredMethod("checkCustomized", MethodHandle.class))
+                        .getDeclaredMethod("checkCustomized", MethodHandle.class)),
+                NF_checkVarHandleGenericType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkVarHandleGenericType", VarHandle.class, VarHandle.AccessDescriptor.class)),
+                NF_checkVarHandleExactType = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("checkVarHandleExactType", VarHandle.class, VarHandle.AccessDescriptor.class)),
+                NF_getVarHandleMemberName = new NamedFunction(Invokers.class
+                        .getDeclaredMethod("getVarHandleMemberName", VarHandle.class, VarHandle.AccessDescriptor.class))
             };
             // Each nf must be statically invocable or we get tied up in our bootstraps.
             assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java	Tue Apr 05 20:02:21 2016 -0700
@@ -363,6 +363,23 @@
             return false;
         }
     }
+    public boolean isVarHandleMethodInvoke() {
+        final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC;
+        final int negs = Modifier.STATIC;
+        if (testFlags(bits | negs, bits) &&
+            clazz == VarHandle.class) {
+            return isVarHandleMethodInvokeName(name);
+        }
+        return false;
+    }
+    public static boolean isVarHandleMethodInvokeName(String name) {
+        try {
+            VarHandle.AccessMode.valueOf(name);
+            return true;
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+    }
     private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
 
     /** Utility method to query the modifier flags of this member. */
@@ -538,6 +555,17 @@
                 if (isMethodHandleInvoke())
                     return;
             }
+            if (m.getDeclaringClass() == VarHandle.class &&
+                isVarHandleMethodInvokeName(m.getName())) {
+                // The JVM did not reify this signature-polymorphic instance.
+                // Need a special case here.
+                // See comments on MethodHandleNatives.linkMethod.
+                MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
+                int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
+                init(VarHandle.class, m.getName(), type, flags);
+                if (isVarHandleMethodInvoke())
+                    return;
+            }
             throw new LinkageError(m.toString());
         }
         assert(isResolved() && this.clazz != null);
@@ -666,6 +694,16 @@
         return mem;
     }
 
+    static MemberName makeVarHandleMethodInvoke(String name, MethodType type) {
+        return makeVarHandleMethodInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
+    }
+    static MemberName makeVarHandleMethodInvoke(String name, MethodType type, int mods) {
+        MemberName mem = new MemberName(VarHandle.class, name, type, REF_invokeVirtual);
+        mem.flags |= mods;  // it's not resolved, but add these modifiers anyway
+        assert(mem.isVarHandleMethodInvoke()) : mem;
+        return mem;
+    }
+
     // bare-bones constructor; the JVM will fill it in
     MemberName() { }
 
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Tue Apr 05 20:02:21 2016 -0700
@@ -26,9 +26,11 @@
 package java.lang.invoke;
 
 
-import java.util.*;
 import jdk.internal.HotSpotIntrinsicCandidate;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 import static java.lang.invoke.MethodHandleStatics.*;
 
 /**
@@ -92,14 +94,16 @@
  * and {@code invoke} compile to an {@code invokevirtual} instruction.
  * More unusually, the compiler must record the actual argument types,
  * and may not perform method invocation conversions on the arguments.
- * Instead, it must push them on the stack according to their own unconverted types.
- * The method handle object itself is pushed on the stack before the arguments.
- * The compiler then calls the method handle with a symbolic type descriptor which
- * describes the argument and return types.
+ * Instead, it must generate instructions that push them on the stack according
+ * to their own unconverted types.  The method handle object itself is pushed on
+ * the stack before the arguments.
+ * The compiler then generates an {@code invokevirtual} instruction that invokes
+ * the method handle with a symbolic type descriptor which describes the argument
+ * and return types.
  * <p>
  * To issue a complete symbolic type descriptor, the compiler must also determine
  * the return type.  This is based on a cast on the method invocation expression,
- * if there is one, or else {@code Object} if the invocation is an expression
+ * if there is one, or else {@code Object} if the invocation is an expression,
  * or else {@code void} if the invocation is a statement.
  * The cast may be to a primitive type (but not {@code void}).
  * <p>
@@ -109,12 +113,12 @@
  * {@code Void} except the null reference.
  *
  * <h1>Method handle invocation</h1>
- * The first time a {@code invokevirtual} instruction is executed
- * it is linked, by symbolically resolving the names in the instruction
+ * The first time an {@code invokevirtual} instruction is executed
+ * it is linked by symbolically resolving the names in the instruction
  * and verifying that the method call is statically legal.
- * This is true of calls to {@code invokeExact} and {@code invoke}.
+ * This also holds for calls to {@code invokeExact} and {@code invoke}.
  * In this case, the symbolic type descriptor emitted by the compiler is checked for
- * correct syntax and names it contains are resolved.
+ * correct syntax, and names it contains are resolved.
  * Thus, an {@code invokevirtual} instruction which invokes
  * a method handle will always link, as long
  * as the symbolic type descriptor is syntactically well-formed
@@ -163,7 +167,7 @@
  * in a program which uses method handles.
  * <p>
  * Because method types contain "live" {@code Class} objects,
- * method type matching takes into account both types names and class loaders.
+ * method type matching takes into account both type names and class loaders.
  * Thus, even if a method handle {@code M} is created in one
  * class loader {@code L1} and used in another {@code L2},
  * method handle calls are type-safe, because the caller's symbolic type
@@ -174,7 +178,7 @@
  * and its type is assigned, while the resolution in {@code L2} happens
  * when the {@code invokevirtual} instruction is linked.
  * <p>
- * Apart from the checking of type descriptors,
+ * Apart from type descriptor checks,
  * a method handle's capability to call its underlying method is unrestricted.
  * If a method handle is formed on a non-public method by a class
  * that has access to that method, the resulting handle can be used
@@ -196,7 +200,7 @@
  * Java code can create a method handle that directly accesses
  * any method, constructor, or field that is accessible to that code.
  * This is done via a reflective, capability-based API called
- * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
+ * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}.
  * For example, a static method handle can be obtained
  * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
  * There are also conversion methods from Core Reflection API objects,
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1060,6 +1060,19 @@
         FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
         return mh;
     }
+    static MethodHandle fakeVarHandleInvoke(MemberName method) {
+        // TODO caching, is it necessary?
+        MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
+                                                VarHandle.class, Object[].class);
+        MethodHandle mh = throwException(type);
+        mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
+        if (!method.getInvocationType().equals(mh.type()))
+            throw new InternalError(method.toString());
+        mh = mh.withInternalMemberName(method, false);
+        mh = mh.asVarargsCollector(Object[].class);
+        assert(method.isVarargs());
+        return mh;
+    }
 
     /**
      * Create an alias for the method handle which, when called,
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Apr 05 20:02:21 2016 -0700
@@ -25,12 +25,15 @@
 
 package java.lang.invoke;
 
+import jdk.internal.ref.CleanerFactory;
+import sun.invoke.util.Wrapper;
+
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Field;
+
 import static java.lang.invoke.MethodHandleNatives.Constants.*;
-import static java.lang.invoke.MethodHandleStatics.*;
+import static java.lang.invoke.MethodHandleStatics.TRACE_METHOD_LINKAGE;
 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
-import jdk.internal.ref.CleanerFactory;
 
 /**
  * The JVM interface for the method handles package is all here.
@@ -367,8 +370,14 @@
                                      Class<?> defc, String name, Object type,
                                      Object[] appendixResult) {
         try {
-            if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
-                return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
+            if (refKind == REF_invokeVirtual) {
+                if (defc == MethodHandle.class) {
+                    return Invokers.methodHandleInvokeLinkerMethod(
+                            name, fixMethodType(callerClass, type), appendixResult);
+                } else if (defc == VarHandle.class) {
+                    return varHandleOperationLinkerMethod(
+                            name, fixMethodType(callerClass, type), appendixResult);
+                }
             }
         } catch (Throwable ex) {
             if (ex instanceof LinkageError)
@@ -400,6 +409,80 @@
         }
     }
 
+    /**
+     * Obtain the method to link to the VarHandle operation.
+     * This method is located here and not in Invokers to avoid
+     * intializing that and other classes early on in VM bootup.
+     */
+    private static MemberName varHandleOperationLinkerMethod(String name,
+                                                             MethodType mtype,
+                                                             Object[] appendixResult) {
+        // Get the signature method type
+        MethodType sigType = mtype.basicType();
+
+        // Get the access kind from the method name
+        VarHandle.AccessMode ak;
+        try {
+            ak = VarHandle.AccessMode.valueOf(name);
+        } catch (IllegalArgumentException e) {
+            throw MethodHandleStatics.newInternalError(e);
+        }
+
+        // If not polymorphic in the return type, such as the compareAndSet
+        // methods that return boolean
+        if (ak.isPolyMorphicInReturnType) {
+            if (ak.returnType != mtype.returnType()) {
+                // The caller contains a different return type than that
+                // defined by the method
+                throw newNoSuchMethodErrorOnVarHandle(name, mtype);
+            }
+            // Adjust the return type of the signature method type
+            sigType = sigType.changeReturnType(ak.returnType);
+        }
+
+        // Get the guard method type for linking
+        MethodType guardType = sigType
+                // VarHandle at start
+                .insertParameterTypes(0, VarHandle.class)
+                // Access descriptor at end
+                .appendParameterTypes(VarHandle.AccessDescriptor.class);
+
+        // Create the appendix descriptor constant
+        VarHandle.AccessDescriptor ad = new VarHandle.AccessDescriptor(mtype, ak.at.ordinal(), ak.ordinal());
+        appendixResult[0] = ad;
+
+        if (MethodHandleStatics.VAR_HANDLE_GUARDS) {
+            MemberName linker = new MemberName(
+                    VarHandleGuards.class, "guard_" + getVarHandleMethodSignature(sigType),
+                    guardType, REF_invokeStatic);
+            try {
+                return MemberName.getFactory().resolveOrFail(
+                        REF_invokeStatic, linker, VarHandleGuards.class, ReflectiveOperationException.class);
+            } catch (ReflectiveOperationException ex) {
+                // Fall back to lambda form linkage if guard method is not available
+                // TODO Optionally log fallback ?
+            }
+        }
+        return Invokers.varHandleInvokeLinkerMethod(name, mtype);
+    }
+    static String getVarHandleMethodSignature(MethodType mt) {
+        StringBuilder sb = new StringBuilder(mt.parameterCount() + 1);
+
+        for (int i = 0; i < mt.parameterCount(); i++) {
+            Class<?> pt = mt.parameterType(i);
+            sb.append(getCharType(pt));
+        }
+
+        sb.append('_').append(getCharType(mt.returnType()));
+
+        return sb.toString();
+    }
+    static char getCharType(Class<?> pt) {
+        return Wrapper.forBasicType(pt).basicTypeChar();
+    }
+    static NoSuchMethodError newNoSuchMethodErrorOnVarHandle(String name, MethodType mtype) {
+        return new NoSuchMethodError("VarHandle." + name + mtype);
+    }
 
     /**
      * The JVM is resolving a CONSTANT_MethodHandle CP entry.  And it wants our help.
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Tue Apr 05 20:02:21 2016 -0700
@@ -50,9 +50,10 @@
     static final int PROFILE_LEVEL;
     static final boolean PROFILE_GWT;
     static final int CUSTOMIZE_THRESHOLD;
+    static final boolean VAR_HANDLE_GUARDS;
 
     static {
-        final Object[] values = new Object[9];
+        final Object[] values = new Object[10];
         AccessController.doPrivileged(new PrivilegedAction<>() {
                 public Void run() {
                     values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
@@ -64,6 +65,7 @@
                     values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
                     values[7] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.MethodHandle.PROFILE_GWT", "true"));
                     values[8] = Integer.getInteger("java.lang.invoke.MethodHandle.CUSTOMIZE_THRESHOLD", 127);
+                    values[9] = Boolean.parseBoolean(System.getProperty("java.lang.invoke.VarHandle.VAR_HANDLE_GUARDS", "true"));
                     return null;
                 }
             });
@@ -76,6 +78,7 @@
         PROFILE_LEVEL             = (Integer) values[6];
         PROFILE_GWT               = (Boolean) values[7];
         CUSTOMIZE_THRESHOLD       = (Integer) values[8];
+        VAR_HANDLE_GUARDS         = (Boolean) values[9];
 
         if (CUSTOMIZE_THRESHOLD < -1 || CUSTOMIZE_THRESHOLD > 127) {
             throw newInternalError("CUSTOMIZE_THRESHOLD should be in [-1...127] range");
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Tue Apr 05 20:02:21 2016 -0700
@@ -53,6 +53,10 @@
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Opcodes;
 
+import static java.lang.invoke.MethodHandleImpl.Intrinsic;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
+import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
+
 /**
  * This class consists exclusively of static methods that operate on or return
  * method handles. They fall into several categories:
@@ -873,7 +877,14 @@
          * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
          * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
          * with the same {@code type} argument.
-         *
+         * <p>
+         * If the class is {@code VarHandle} and the name string corresponds to
+         * the name of a signature-polymorphic access mode method, the resulting
+         * method handle is equivalent to one produced by
+         * {@link java.lang.invoke.MethodHandles#varHandleInvoker} with
+         * the access mode corresponding to the name string and with the same
+         * {@code type} arguments.
+         * <p>
          * <b>Example:</b>
          * <blockquote><pre>{@code
 import static java.lang.invoke.MethodHandles.*;
@@ -920,6 +931,9 @@
             if (refc == MethodHandle.class) {
                 MethodHandle mh = findVirtualForMH(name, type);
                 if (mh != null)  return mh;
+            } else if (refc == VarHandle.class) {
+                MethodHandle mh = findVirtualForVH(name, type);
+                if (mh != null)  return mh;
             }
             byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
             MemberName method = resolveOrFail(refKind, refc, name, type);
@@ -936,6 +950,13 @@
             assert(!MemberName.isMethodHandleInvokeName(name));
             return null;
         }
+        private MethodHandle findVirtualForVH(String name, MethodType type) {
+            try {
+                return varHandleInvoker(VarHandle.AccessMode.valueOf(name), type);
+            } catch (IllegalArgumentException e) {
+                return null;
+            }
+        }
 
         /**
          * Produces a method handle which creates an object and initializes it, using
@@ -1135,6 +1156,7 @@
          * @exception SecurityException if a security manager is present and it
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
+         * @see #findVarHandle(Class, String, Class)
          */
         public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(REF_getField, refc, name, type);
@@ -1157,6 +1179,7 @@
          * @exception SecurityException if a security manager is present and it
          *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
          * @throws NullPointerException if any argument is null
+         * @see #findVarHandle(Class, String, Class)
          */
         public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
             MemberName field = resolveOrFail(REF_putField, refc, name, type);
@@ -1164,6 +1187,53 @@
         }
 
         /**
+         * Produces a VarHandle giving access to non-static fields of type
+         * {@code T} declared by a receiver class of type {@code R}, supporting
+         * shape {@code (R : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param recv the receiver class, of type {@code R}, that declares the
+         * non-static field
+         * @param name the field's name
+         * @param type the field's type, of type {@code T}
+         * @return a VarHandle giving access to non-static fields.
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         * @since 9
+         */
+        public VarHandle findVarHandle(Class<?> recv, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            MemberName getField = resolveOrFail(REF_getField, recv, name, type);
+            MemberName putField = resolveOrFail(REF_putField, recv, name, type);
+            return getFieldVarHandle(REF_getField, REF_putField, recv, getField, putField);
+        }
+
+        /**
          * Produces a method handle giving read access to a static field.
          * The type of the method handle will have a return type of the field's
          * value type.
@@ -1212,6 +1282,55 @@
         }
 
         /**
+         * Produces a VarHandle giving access to a static field of type
+         * {@code T} declared by a given declaring class, supporting shape
+         * {@code ((empty) : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class.
+         * <p>
+         * If the returned VarHandle is operated on, the declaring class will be
+         * initialized, if it has not already been initialized.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param decl the class that declares the static field
+         * @param name the field's name
+         * @param type the field's type, of type {@code T}
+         * @return a VarHandle giving access to a static field
+         * @throws NoSuchFieldException if the field does not exist
+         * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
+         * @exception SecurityException if a security manager is present and it
+         *                              <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
+         * @throws NullPointerException if any argument is null
+         * @since 9
+         */
+        public VarHandle findStaticVarHandle(Class<?> decl, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
+            MemberName getField = resolveOrFail(REF_getStatic, decl, name, type);
+            MemberName putField = resolveOrFail(REF_putStatic, decl, name, type);
+            return getFieldVarHandle(REF_getStatic, REF_putStatic, decl, getField, putField);
+        }
+
+        /**
          * Produces an early-bound method handle for a non-static method.
          * The receiver must have a supertype {@code defc} in which a method
          * of the given name and type is accessible to the lookup class.
@@ -1297,6 +1416,10 @@
                 MethodHandle mh = unreflectForMH(m);
                 if (mh != null)  return mh;
             }
+            if (m.getDeclaringClass() == VarHandle.class) {
+                MethodHandle mh = unreflectForVH(m);
+                if (mh != null)  return mh;
+            }
             MemberName method = new MemberName(m);
             byte refKind = method.getReferenceKind();
             if (refKind == REF_invokeSpecial)
@@ -1311,6 +1434,12 @@
                 return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
             return null;
         }
+        private MethodHandle unreflectForVH(Method m) {
+            // these names require special lookups because they throw UnsupportedOperationException
+            if (MemberName.isVarHandleMethodInvokeName(m.getName()))
+                return MethodHandleImpl.fakeVarHandleInvoke(new MemberName(m));
+            return null;
+        }
 
         /**
          * Produces a method handle for a reflected method.
@@ -1435,6 +1564,57 @@
         }
 
         /**
+         * Produces a VarHandle that accesses fields of type {@code T} declared
+         * by a class of type {@code R}, as described by the given reflected
+         * field.
+         * If the field is non-static the VarHandle supports a shape of
+         * {@code (R : T)}, otherwise supports a shape of {@code ((empty) : T)}.
+         * <p>
+         * Access checking is performed immediately on behalf of the lookup
+         * class, regardless of the value of the field's {@code accessible}
+         * flag.
+         * <p>
+         * If the field is static, and if the returned VarHandle is operated
+         * on, the field's declaring class will be initialized, if it has not
+         * already been initialized.
+         * <p>
+         * Certain access modes of the returned VarHandle are unsupported under
+         * the following conditions:
+         * <ul>
+         * <li>if the field is declared {@code final}, then the write, atomic
+         *     update, and numeric atomic update access modes are unsupported.
+         * <li>if the field type is anything other than {@code int},
+         *     {@code long} or a reference type, then atomic update access modes
+         *     are unsupported.  (Future major platform releases of the JDK may
+         *     support additional types for certain currently unsupported access
+         *     modes.)
+         * <li>if the field type is anything other than {@code int} or
+         *     {@code long}, then numeric atomic update access modes are
+         *     unsupported.  (Future major platform releases of the JDK may
+         *     support additional numeric types for certain currently
+         *     unsupported access modes.)
+         * </ul>
+         * <p>
+         * If the field is declared {@code volatile} then the returned VarHandle
+         * will override access to the field (effectively ignore the
+         * {@code volatile} declaration) in accordance to it's specified
+         * access modes.
+         * @param f the reflected field, with a field of type {@code T}, and
+         * a declaring class of type {@code R}
+         * @return a VarHandle giving access to non-static fields or a static
+         * field
+         * @throws IllegalAccessException if access checking fails
+         * @throws NullPointerException if the argument is null
+         * @since 9
+         */
+        public VarHandle unreflectVarHandle(Field f) throws IllegalAccessException {
+            MemberName getField = new MemberName(f, false);
+            MemberName putField = new MemberName(f, true);
+            return getFieldVarHandleNoSecurityManager(getField.getReferenceKind(), putField.getReferenceKind(),
+                                                      f.getDeclaringClass(), getField, putField);
+        }
+
+        /**
          * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
          * created by this lookup object or a similar one.
          * Security and access checks are performed to ensure that this lookup object
@@ -1454,7 +1634,9 @@
          */
         public MethodHandleInfo revealDirect(MethodHandle target) {
             MemberName member = target.internalMemberName();
-            if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
+            if (member == null || (!member.isResolved() &&
+                                   !member.isMethodHandleInvoke() &&
+                                   !member.isVarHandleMethodInvoke()))
                 throw newIllegalArgumentException("not a direct method handle");
             Class<?> defc = member.getDeclaringClass();
             byte refKind = member.getReferenceKind();
@@ -1829,6 +2011,52 @@
                 return restrictReceiver(field, dmh, lookupClass());
             return dmh;
         }
+        private VarHandle getFieldVarHandle(byte getRefKind, byte putRefKind,
+                                            Class<?> refc, MemberName getField, MemberName putField)
+                throws IllegalAccessException {
+            final boolean checkSecurity = true;
+            return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
+        }
+        private VarHandle getFieldVarHandleNoSecurityManager(byte getRefKind, byte putRefKind,
+                                                             Class<?> refc, MemberName getField, MemberName putField)
+                throws IllegalAccessException {
+            final boolean checkSecurity = false;
+            return getFieldVarHandleCommon(getRefKind, putRefKind, refc, getField, putField, checkSecurity);
+        }
+        private VarHandle getFieldVarHandleCommon(byte getRefKind, byte putRefKind,
+                                                  Class<?> refc, MemberName getField, MemberName putField,
+                                                  boolean checkSecurity) throws IllegalAccessException {
+            assert getField.isStatic() == putField.isStatic();
+            assert getField.isGetter() && putField.isSetter();
+            assert MethodHandleNatives.refKindIsStatic(getRefKind) == MethodHandleNatives.refKindIsStatic(putRefKind);
+            assert MethodHandleNatives.refKindIsGetter(getRefKind) && MethodHandleNatives.refKindIsSetter(putRefKind);
+
+            checkField(getRefKind, refc, getField);
+            if (checkSecurity)
+                checkSecurityManager(refc, getField);
+
+            if (!putField.isFinal()) {
+                // A VarHandle does not support updates to final fields, any
+                // such VarHandle to a final field will be read-only and
+                // therefore the following write-based accessibility checks are
+                // only required for non-final fields
+                checkField(putRefKind, refc, putField);
+                if (checkSecurity)
+                    checkSecurityManager(refc, putField);
+            }
+
+            boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(getRefKind) &&
+                                  restrictProtectedReceiver(getField));
+            if (doRestrict) {
+                assert !getField.isStatic();
+                // receiver type of VarHandle is too wide; narrow to caller
+                if (!getField.getDeclaringClass().isAssignableFrom(lookupClass())) {
+                    throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
+                }
+                refc = lookupClass();
+            }
+            return VarHandles.makeFieldHandle(getField, refc, getField.getFieldType(), this.allowedModes == TRUSTED);
+        }
         /** Check access and get the requested constructor. */
         private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
             final boolean checkSecurity = true;
@@ -2018,6 +2246,205 @@
         return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
     }
 
+    /**
+     *
+     * Produces a VarHandle giving access to elements of an array type
+     * {@code T[]}, supporting shape {@code (T[], int : T)}.
+     * <p>
+     * Certain access modes of the returned VarHandle are unsupported under
+     * the following conditions:
+     * <ul>
+     * <li>if the component type is anything other than {@code int},
+     *     {@code long} or a reference type, then atomic update access modes
+     *     are unsupported.  (Future major platform releases of the JDK may
+     *     support additional types for certain currently unsupported access
+     *     modes.)
+     * <li>if the component type is anything other than {@code int} or
+     *     {@code long}, then numeric atomic update access modes are
+     *     unsupported.  (Future major platform releases of the JDK may
+     *     support additional numeric types for certain currently
+     *     unsupported access modes.)
+     * </ul>
+     * @param arrayClass the class of an array, of type {@code T[]}
+     * @return a VarHandle giving access to elements of an array
+     * @throws NullPointerException if the arrayClass is null
+     * @throws IllegalArgumentException if arrayClass is not an array type
+     * @since 9
+     */
+    public static
+    VarHandle arrayElementVarHandle(Class<?> arrayClass) throws IllegalArgumentException {
+        return VarHandles.makeArrayElementHandle(arrayClass);
+    }
+
+    /**
+     * Produces a VarHandle giving access to elements of a {@code byte[]} array
+     * viewed as if it were a different primitive array type, such as
+     * {@code int[]} or {@code long[]}.  The shape of the resulting VarHandle is
+     * {@code (byte[], int : T)}, where the {@code int} coordinate type
+     * corresponds to an argument that is an index in a {@code byte[]} array,
+     * and {@code T} is the component type of the given view array class.  The
+     * returned VarHandle accesses bytes at an index in a {@code byte[]} array,
+     * composing bytes to or from a value of {@code T} according to the given
+     * endianness.
+     * <p>
+     * The supported component types (variables types) are {@code short},
+     * {@code char}, {@code int}, {@code long}, {@code float} and
+     * {@code double}.
+     * <p>
+     * Access of bytes at a given index will result in an
+     * {@code IndexOutOfBoundsException} if the index is less than {@code 0}
+     * or greater than the {@code byte[]} array length minus the size (in bytes)
+     * of {@code T}.
+     * <p>
+     * Access of bytes at an index may be aligned or misaligned for {@code T},
+     * with respect to the underlying memory address, {@code A} say, associated
+     * with the array and index.
+     * If access is misaligned then access for anything other than the
+     * {@code get} and {@code set} access modes will result in an
+     * {@code IllegalStateException}.  In such cases atomic access is only
+     * guaranteed with respect to the largest power of two that divides the GCD
+     * of {@code A} and the size (in bytes) of {@code T}.
+     * If access is aligned then following access modes are supported and are
+     * guaranteed to support atomic access:
+     * <ul>
+     * <li>read write access modes for all {@code T};
+     * <li>atomic update access modes for {@code int}, {@code long},
+     *     {@code float} or {@code double}.
+     *     (Future major platform releases of the JDK may support additional
+     *     types for certain currently unsupported access modes.)
+     * <li>numeric atomic update access modes for {@code int} and {@code long}.
+     *     (Future major platform releases of the JDK may support additional
+     *     numeric types for certain currently unsupported access modes.)
+     * </ul>
+     * <p>
+     * Misaligned access, and therefore atomicity guarantees, may be determined
+     * for {@code byte[]} arrays without operating on a specific array.  Given
+     * an {@code index}, {@code T} and it's corresponding boxed type,
+     * {@code T_BOX}, misalignment may be determined as follows:
+     * <pre>{@code
+     * int sizeOfT = T_BOX.BYTES;  // size in bytes of T
+     * int misalignedAtZeroIndex = ByteBuffer.wrap(new byte[0]).
+     *     alignmentOffset(0, sizeOfT);
+     * int misalignedAtIndex = (misalignedAtZeroIndex + index) % sizeOfT;
+     * boolean isMisaligned = misalignedAtIndex != 0;
+     * }</pre>
+     *
+     * @implNote
+     * The variable types {@code float} and {@code double} are supported as if
+     * by transformation to and access with the variable types {@code int} and
+     * {@code long} respectively.  For example, the transformation of a
+     * {@code double} value to a long value is performed as if using
+     * {@link Double#doubleToRawLongBits(double)}, and the reverse
+     * transformation is performed as if using
+     * {@link Double#longBitsToDouble(long)}.
+     *
+     * @param viewArrayClass the view array class, with a component type of
+     * type {@code T}
+     * @param bigEndian true if the endianness of the view array elements, as
+     * stored in the underlying {@code byte} array, is big endian, otherwise
+     * little endian
+     * @return a VarHandle giving access to elements of a {@code byte[]} array
+     * viewed as if elements corresponding to the components type of the view
+     * array class
+     * @throws NullPointerException if viewArrayClass is null
+     * @throws IllegalArgumentException if viewArrayClass is not an array type
+     * @throws UnsupportedOperationException if the component type of
+     * viewArrayClass is not supported as a variable type
+     * @since 9
+     */
+    public static
+    VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
+                                     boolean bigEndian) throws IllegalArgumentException {
+        return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
+    }
+
+    /**
+     * Produces a VarHandle giving access to elements of a {@code ByteBuffer}
+     * viewed as if it were an array of elements of a different primitive
+     * component type to that of {@code byte}, such as {@code int[]} or
+     * {@code long[]}.  The shape of the resulting VarHandle is
+     * {@code (ByteBuffer, int : T)}, where the {@code int} coordinate type
+     * corresponds to an argument that is an index in a {@code ByteBuffer}, and
+     * {@code T} is the component type of the given view array class.  The
+     * returned VarHandle accesses bytes at an index in a {@code ByteBuffer},
+     * composing bytes to or from a value of {@code T} according to the given
+     * endianness.
+     * <p>
+     * The supported component types (variables types) are {@code short},
+     * {@code char}, {@code int}, {@code long}, {@code float} and
+     * {@code double}.
+     * <p>
+     * Access will result in a {@code ReadOnlyBufferException} for anything
+     * other than the read access modes if the {@code ByteBuffer} is read-only.
+     * <p>
+     * Access of bytes at a given index will result in an
+     * {@code IndexOutOfBoundsException} if the index is less than {@code 0}
+     * or greater than the {@code ByteBuffer} limit minus the size (in bytes) of
+     * {@code T}.
+     * <p>
+     * Access of bytes at an index may be aligned or misaligned for {@code T},
+     * with respect to the underlying memory address, {@code A} say, associated
+     * with the {@code ByteBuffer} and index.
+     * If access is misaligned then access for anything other than the
+     * {@code get} and {@code set} access modes will result in an
+     * {@code IllegalStateException}.  In such cases atomic access is only
+     * guaranteed with respect to the largest power of two that divides the GCD
+     * of {@code A} and the size (in bytes) of {@code T}.
+     * If access is aligned then following access modes are supported and are
+     * guaranteed to support atomic access:
+     * <ul>
+     * <li>read write access modes for all {@code T};
+     * <li>atomic update access modes for {@code int}, {@code long},
+     *     {@code float} or {@code double}.
+     *     (Future major platform releases of the JDK may support additional
+     *     types for certain currently unsupported access modes.)
+     * <li>numeric atomic update access modes for {@code int} and {@code long}.
+     *     (Future major platform releases of the JDK may support additional
+     *     numeric types for certain currently unsupported access modes.)
+     * </ul>
+     * <p>
+     * Misaligned access, and therefore atomicity guarantees, may be determined
+     * for a {@code ByteBuffer}, {@code bb} (direct or otherwise), an
+     * {@code index}, {@code T} and it's corresponding boxed type,
+     * {@code T_BOX}, as follows:
+     * <pre>{@code
+     * int sizeOfT = T_BOX.BYTES;  // size in bytes of T
+     * ByteBuffer bb = ...
+     * int misalignedAtIndex = bb.alignmentOffset(index, sizeOfT);
+     * boolean isMisaligned = misalignedAtIndex != 0;
+     * }</pre>
+     *
+     * @implNote
+     * The variable types {@code float} and {@code double} are supported as if
+     * by transformation to and access with the variable types {@code int} and
+     * {@code long} respectively.  For example, the transformation of a
+     * {@code double} value to a long value is performed as if using
+     * {@link Double#doubleToRawLongBits(double)}, and the reverse
+     * transformation is performed as if using
+     * {@link Double#longBitsToDouble(long)}.
+     *
+     * @param viewArrayClass the view array class, with a component type of
+     * type {@code T}
+     * @param bigEndian true if the endianness of the view array elements, as
+     * stored in the underlying {@code ByteBuffer}, is big endian, otherwise
+     * little endian (Note this overrides the endianness of a
+     * {@code ByteBuffer})
+     * @return a VarHandle giving access to elements of a {@code ByteBuffer}
+     * viewed as if elements corresponding to the components type of the view
+     * array class
+     * @throws NullPointerException if viewArrayClass is null
+     * @throws IllegalArgumentException if viewArrayClass is not an array type
+     * @throws UnsupportedOperationException if the component type of
+     * viewArrayClass is not supported as a variable type
+     * @since 9
+     */
+    public static
+    VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
+                                      boolean bigEndian) throws IllegalArgumentException {
+        return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
+    }
+
+
     /// method handle invocation (reflective style)
 
     /**
@@ -2153,6 +2580,54 @@
         return type.invokers().genericInvoker();
     }
 
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke a signature-polymorphic access mode method on any VarHandle whose
+     * associated access mode type is compatible with the given type.
+     * The resulting invoker will have a type which is exactly equal to the
+     * desired given type, except that it will accept an additional leading
+     * argument of type {@code VarHandle}.
+     *
+     * @param accessMode the VarHandle access mode
+     * @param type the desired target type
+     * @return a method handle suitable for invoking an access mode method of
+     *         any VarHandle whose access mode type is of the given type.
+     * @since 9
+     */
+    static public
+    MethodHandle varHandleExactInvoker(VarHandle.AccessMode accessMode, MethodType type) {
+        return type.invokers().varHandleMethodExactInvoker(accessMode);
+    }
+
+    /**
+     * Produces a special <em>invoker method handle</em> which can be used to
+     * invoke a signature-polymorphic access mode method on any VarHandle whose
+     * associated access mode type is compatible with the given type.
+     * The resulting invoker will have a type which is exactly equal to the
+     * desired given type, except that it will accept an additional leading
+     * argument of type {@code VarHandle}.
+     * <p>
+     * Before invoking its target, if the access mode type differs from the
+     * desired given type, the invoker will apply reference casts as necessary
+     * and box, unbox, or widen primitive values, as if by
+     * {@link MethodHandle#asType asType}.  Similarly, the return value will be
+     * converted as necessary.
+     * <p>
+     * This method is equivalent to the following code (though it may be more
+     * efficient): {@code publicLookup().findVirtual(VarHandle.class, accessMode.name(), type)}
+     *
+     * @param accessMode the VarHandle access mode
+     * @param type the desired target type
+     * @return a method handle suitable for invoking an access mode method of
+     *         any VarHandle whose access mode type is convertible to the given
+     *         type.
+     * @since 9
+     */
+    static public
+    MethodHandle varHandleInvoker(VarHandle.AccessMode accessMode, MethodType type) {
+        return type.invokers().varHandleMethodInvoker(accessMode);
+    }
+
     static /*non-public*/
     MethodHandle basicInvoker(MethodType type) {
         return type.invokers().basicInvoker();
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java	Tue Apr 05 20:02:21 2016 -0700
@@ -95,7 +95,7 @@
 
     // The rtype and ptypes fields define the structural identity of the method type:
     private final Class<?>   rtype;
-    private final Class<?>[] ptypes;
+    private final @Stable Class<?>[] ptypes;
 
     // The remaining fields are caches of various sorts:
     private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarForm.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,164 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.lang.invoke.VarHandle.AccessMode;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
+
+/**
+ * A var handle form containing a set of member name, one for each operation.
+ * Each member characterizes a static method.
+ */
+class VarForm {
+
+    // Holds VarForm for VarHandle implementation classes
+    private static final ClassValue<VarForm> VFORMS
+            = new ClassValue<VarForm>() {
+        @Override
+        protected VarForm computeValue(Class<?> impl) {
+            return new VarForm(link(staticMethodLinker(impl)));
+        }
+    };
+
+    final MemberName mbGet;
+    final MemberName mbSet;
+    final MemberName mbGetVolatile;
+    final MemberName mbSetVolatile;
+    final MemberName mbGetAcquire;
+    final MemberName mbSetRelease;
+    final MemberName mbCompareAndSet;
+    final MemberName mbCompareAndExchangeVolatile;
+    final MemberName mbCompareAndExchangeAcquire;
+    final MemberName mbCompareAndExchangeRelease;
+    final MemberName mbWeakCompareAndSet;
+    final MemberName mbWeakCompareAndSetAcquire;
+    final MemberName mbWeakCompareAndSetRelease;
+    final MemberName mbGetAndSet;
+    final MemberName mbGetAndAdd;
+    final MemberName mbAddAndGet;
+    final MemberName mbGetOpaque;
+    final MemberName mbSetOpaque;
+
+    VarForm(Map<AccessMode, MemberName> linkMap) {
+        mbGet = linkMap.get(AccessMode.get);
+        mbSet = linkMap.get(AccessMode.set);
+        mbGetVolatile = linkMap.get(AccessMode.getVolatile);
+        mbSetVolatile = linkMap.get(AccessMode.setVolatile);
+        mbGetOpaque = linkMap.get(AccessMode.getOpaque);
+        mbSetOpaque = linkMap.get(AccessMode.setOpaque);
+        mbGetAcquire = linkMap.get(AccessMode.getAcquire);
+        mbSetRelease = linkMap.get(AccessMode.setRelease);
+        mbCompareAndSet = linkMap.get(AccessMode.compareAndSet);
+        mbCompareAndExchangeVolatile = linkMap.get(AccessMode.compareAndExchangeVolatile);
+        mbCompareAndExchangeAcquire = linkMap.get(AccessMode.compareAndExchangeAcquire);
+        mbCompareAndExchangeRelease = linkMap.get(AccessMode.compareAndExchangeRelease);
+        mbWeakCompareAndSet = linkMap.get(AccessMode.weakCompareAndSet);
+        mbWeakCompareAndSetAcquire = linkMap.get(AccessMode.weakCompareAndSetAcquire);
+        mbWeakCompareAndSetRelease = linkMap.get(AccessMode.weakCompareAndSetRelease);
+        mbGetAndSet = linkMap.get(AccessMode.getAndSet);
+        mbGetAndAdd = linkMap.get(AccessMode.getAndAdd);
+        mbAddAndGet = linkMap.get(AccessMode.addAndGet);
+    }
+
+    /**
+     * Creates a var form given an VarHandle implementation class.
+     * Each signature polymorphic method is linked to a static method of the
+     * same name on the implementation class or a super class.
+     */
+    static VarForm createFromStatic(Class<? extends VarHandle> impl) {
+        return VFORMS.get(impl);
+    }
+
+    /**
+     * Link all signature polymorphic methods.
+     */
+    private static Map<AccessMode, MemberName> link(Function<AccessMode, MemberName> linker) {
+        Map<AccessMode, MemberName> links = new HashMap<>();
+        for (AccessMode ak : AccessMode.values()) {
+            links.put(ak, linker.apply(ak));
+        }
+        return links;
+    }
+
+
+    /**
+     * Returns a function that associates an AccessMode with a MemberName that
+     * is a static concrete method implementation for the access operation of
+     * the implementing class.
+     */
+    private static Function<AccessMode, MemberName> staticMethodLinker(Class<?> implClass) {
+        // Find all declared static methods on the implementation class and
+        // all super classes up to but not including VarHandle
+        List<Method> staticMethods = new ArrayList<>(AccessMode.values().length);
+        for (Class<?> c = implClass; c != VarHandle.class; c = c.getSuperclass()) {
+            for (Method m : c.getDeclaredMethods()) {
+                if (Modifier.isStatic(m.getModifiers())) {
+                    staticMethods.add(m);
+                }
+            }
+        }
+
+        // This needs to be an anonymous inner class and not a lambda expression
+        // The latter will cause the intialization of classes in java.lang.invoke
+        // resulting in circular dependencies if VarHandles are utilized early
+        // in the start up process.  For example, if ConcurrentHashMap
+        // is modified to use VarHandles.
+        return new Function<>() {
+            @Override
+            public MemberName apply(AccessMode ak) {
+                Method m = null;
+                for (Method to_m : staticMethods) {
+                    if (to_m.getName().equals(ak.name()) &&
+                        Modifier.isStatic(to_m.getModifiers())) {
+                        assert m == null : String.format(
+                                "Two or more static methods named %s are present on " +
+                                "class %s or a super class", ak.name(), implClass.getName());
+                        m = to_m;
+                    }
+                }
+
+                if (m == null)
+                    return null;
+
+                MemberName linkedMethod = new MemberName(m);
+                try {
+                    return MemberName.getFactory().resolveOrFail(
+                            REF_invokeStatic, linkedMethod, m.getDeclaringClass(), NoSuchMethodException.class);
+                }
+                catch (ReflectiveOperationException e) {
+                    throw new InternalError(e);
+                }
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,1416 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.ForceInline;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+import static java.lang.invoke.MethodHandleStatics.newInternalError;
+
+/**
+ * A VarHandle is a dynamically typed reference to a variable, or to a
+ * parametrically-defined family of variables, including static fields,
+ * non-static fields, array elements, or components of an off-heap data
+ * structure.  Access to such variables is supported under various
+ * <em>access modes</em>, including plain read/write access, volatile
+ * read/write access, and compare-and-swap.
+ *
+ * <p>VarHandles are immutable and have no visible state.  VarHandles cannot be
+ * subclassed by the user.
+ *
+ * <p>A VarHandle has:
+ * <ul>
+ * <li>a {@link #varType variable type}, referred to as {@code T}, which is the
+ * type of variable(s) referenced by this VarHandle;
+ * <li>a list of {@link #coordinateTypes coordinate types}, referred to as
+ * {@code CT}, where the types (primitive and reference) are represented by
+ * {@link Class} objects).  A list of arguments corresponding to instances of
+ * the coordinate types uniquely locates a variable referenced by this
+ * VarHandle; and
+ * <li>a <em>shape</em>, that combines the variable type and coordinate types,
+ * and is declared with the notation {@code (CT : T)}.  An empty list of
+ * coordinate types is declared as {@code (empty)}.
+ * </ul>
+ *
+ * <p>Factory methods that produce or {@link java.lang.invoke.MethodHandles.Lookup
+ * lookup} VarHandle instances document the supported variable type, coordinate
+ * types, and shape.
+ *
+ * For example, a VarHandle referencing a non-static field will declare a shape
+ * of {@code (R : T)}, where {@code R} is the receiver type and
+ * {@code T} is the field type, and where the VarHandle and an instance of the
+ * receiver type can be utilized to access the field variable.
+ * A VarHandle referencing array elements will declare a shape of
+ * {@code (T[], int : T)}, where {@code T[]} is the array type and {@code T}
+ * its component type, and where the VarHandle, an instance of the array type,
+ * and an {@code int} index can be utilized to access an array element variable.
+ *
+ * <p>Each access mode is associated with a
+ * <a href="MethodHandle.html#sigpoly">signature polymorphic</a> method of the
+ * same name, where the VarHandle shape and access mode uniquely determine the
+ * canonical {@link #accessModeType(AccessMode) access mode type},
+ * which in turn determines the matching constraints on a valid symbolic
+ * type descriptor at the call site of an access mode's method
+ * <a href="VarHandle.html#invoke">invocation</a>.
+ *
+ * As such, VarHandles are dynamically and strongly typed.  Their arity,
+ * argument types, and return type of an access mode method invocation are not
+ * statically checked.  If they, and associated values, do not match the arity
+ * and types of the access mode's type, an exception will be thrown.
+ *
+ * The parameter types of an access mode method type will consist of those that
+ * are the VarHandles's coordinate types (in order), followed by access mode
+ * parameter types specific to the access mode.
+ *
+ * <p>An access mode's method documents the form of its method signature, which
+ * is derived from the access mode parameter types.  The form is declared with
+ * the notation {@code (CT, P1 p1, P2 p2, ..., PN pn)R}, where {@code CT} is the
+ * coordinate types (as documented by a VarHandle factory method), {@code P1},
+ * {@code P2} and {@code PN} are the first, second and the n'th access mode
+ * parameters named {@code p1}, {@code p2} and {@code pn} respectively, and
+ * {@code R} is the return type.
+ *
+ * For example, for the generic shape of {@code (CT : T)} the
+ * {@link #compareAndSet} access mode method documents that its method
+ * signature is of the form {@code (CT, T expectedValue, T newValue)boolean},
+ * where the parameter types named {@code extendedValue} and {@code newValue}
+ * are the access mode parameter types.  If the VarHandle accesses array
+ * elements with a shape of say {@code (T[], int : T)} then the access mode
+ * method type is {@code (T[], int, T, T)boolean}.
+ *
+ * <p>Access modes are grouped into the following categories:
+ * <ul>
+ * <li>read access modes that get the value of a variable under specified
+ * memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #get get},
+ * {@link #getVolatile getVolatile},
+ * {@link #getAcquire getAcquire},
+ * {@link #getOpaque getOpaque}.
+ * <li>write access modes that set the value of a variable under specified
+ * memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #set set},
+ * {@link #setVolatile setVolatile},
+ * {@link #setRelease setRelease},
+ * {@link #setOpaque setOpaque}.
+ * <li>atomic update access modes that, for example, atomically compare and set
+ * the value of a variable under specified memory ordering effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #compareAndSet compareAndSet},
+ * {@link #weakCompareAndSet weakCompareAndSet},
+ * {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire},
+ * {@link #weakCompareAndSetRelease weakCompareAndSetRelease},
+ * {@link #compareAndExchangeAcquire compareAndExchangeAcquire},
+ * {@link #compareAndExchangeVolatile compareAndExchangeVolatile},
+ * {@link #compareAndExchangeRelease compareAndExchangeRelease},
+ * {@link #getAndSet getAndSet}.
+ * <li>numeric atomic update access modes that, for example, atomically get and
+ * set with addition the value of a variable under specified memory ordering
+ * effects.
+ * The set of corresponding access mode methods belonging to this group
+ * consists of the methods
+ * {@link #getAndAdd getAndAdd},
+ * {@link #addAndGet addAndGet}.
+ * </ul>
+ *
+ * <p>Factory methods that produce or {@link java.lang.invoke.MethodHandles.Lookup
+ * lookup} VarHandle instances document the set of access modes that are
+ * supported, which may also include documenting restrictions based on the
+ * variable type and whether a variable is read-only.  If an access mode is not
+ * supported then the corresponding signature-polymorphic method will on
+ * invocation throw an {@code UnsupportedOperationException}.
+ * The {@link #get get} access mode is supported for all
+ * VarHandle instances and the corresponding method never throws
+ * {@code UnsupportedOperationException}.
+ * If a VarHandle references a read-only variable (for example a {@code final}
+ * field) then write, atomic update and numeric atomic update access modes are
+ * not supported and corresponding methods throw
+ * {@code UnsupportedOperationException}.
+ * Read/write access modes (if supported), with the exception of
+ * {@code get} and {@code set}, provide atomic access for
+ * reference types and all primitive types.
+ * Unless stated otherwise in the documentation of a factory method, the access
+ * modes {@code get} and {@code set} (if supported) provide atomic access for
+ * reference types and all primitives types, with the exception of {@code long}
+ * and {@code double} on 32-bit platforms
+ *
+ * <p>Access modes will override any memory ordering effects specified at
+ * the declaration site of a variable.  For example, a VarHandle accessing a
+ * a field using the {@code get} access mode will access the field as
+ * specified <em>by its access mode</em> even if that field is declared
+ * {@code volatile}.  When mixed access is performed extreme care should be
+ * taken since the Java Memory Model may permit surprising results.
+ *
+ * <p>In addition to supporting access to variables under various access modes,
+ * a set of static methods, referred to as memory fence methods, is also
+ * provided for fine-grained control of memory ordering.
+ *
+ * The Java Language Specification permits other threads to observe operations
+ * as if they were executed in orders different than are apparent in program
+ * source code, subject to constraints arising, for example, from the use of
+ * locks, {@code volatile} fields or VarHandles.  The static methods,
+ * {@link #fullFence fullFence}, {@link #acquireFence acquireFence},
+ * {@link #releaseFence releaseFence}, {@link #loadLoadFence loadLoadFence} and
+ * {@link #storeStoreFence storeStoreFence}, can also be used to impose
+ * constraints.  Their specifications, as is the case for certain access modes,
+ * are phrased in terms of the lack of "reorderings" -- observable ordering
+ * effects that might otherwise occur if the fence was not present.  More
+ * precise phrasing of the specification of access mode methods and memory fence
+ * methods may accompany future updates of the Java Language Specification.
+ *
+ * <h1>Compilation of an access mode's method</h1>
+ * A Java method call expression naming an access mode method can invoke a
+ * VarHandle from Java source code.  From the viewpoint of source code, these
+ * methods can take any arguments and their polymorphic result (if expressed)
+ * can be cast to any return type.  Formally this is accomplished by giving the
+ * access mode methods variable arity {@code Object} arguments and
+ * {@code Object} return types (if the return type is polymorphic), but they
+ * have an additional quality called <em>signature polymorphism</em> which
+ * connects this freedom of invocation directly to the JVM execution stack.
+ * <p>
+ * As is usual with virtual methods, source-level calls to access mode methods
+ * compile to an {@code invokevirtual} instruction.  More unusually, the
+ * compiler must record the actual argument types, and may not perform method
+ * invocation conversions on the arguments.  Instead, it must generate
+ * instructions to push them on the stack according to their own unconverted
+ * types.  The VarHandle object itself will be pushed on the stack before the
+ * arguments.  The compiler then generates an {@code invokevirtual} instruction
+ * that invokes the access mode method with a symbolic type descriptor which
+ * describes the argument and return types.
+ * <p>
+ * To issue a complete symbolic type descriptor, the compiler must also
+ * determine the return type (if polymorphic).  This is based on a cast on the
+ * method invocation expression, if there is one, or else {@code Object} if the
+ * invocation is an expression, or else {@code void} if the invocation is a
+ * statement.  The cast may be to a primitive type (but not {@code void}).
+ * <p>
+ * As a corner case, an uncasted {@code null} argument is given a symbolic type
+ * descriptor of {@code java.lang.Void}.  The ambiguity with the type
+ * {@code Void} is harmless, since there are no references of type {@code Void}
+ * except the null reference.
+ *
+ *
+ * <h1><a name="invoke">Invocation of an access mode's method</a></h1>
+ * The first time an {@code invokevirtual} instruction is executed it is linked
+ * by symbolically resolving the names in the instruction and verifying that
+ * the method call is statically legal.  This also holds for calls to access mode
+ * methods.  In this case, the symbolic type descriptor emitted by the compiler
+ * is checked for correct syntax, and names it contains are resolved.  Thus, an
+ * {@code invokevirtual} instruction which invokes an access mode method will
+ * always link, as long as the symbolic type descriptor is syntactically
+ * well-formed and the types exist.
+ * <p>
+ * When the {@code invokevirtual} is executed after linking, the receiving
+ * VarHandle's access mode type is first checked by the JVM to ensure that it
+ * matches the symbolic type descriptor.  If the type
+ * match fails, it means that the access mode method which the caller is
+ * invoking is not present on the individual VarHandle being invoked.
+ *
+ * <p>
+ * Invocation of an access mode's signature-polymorphic method behaves as if an
+ * invocation of {@link MethodHandle#invoke}, where the receiving method handle
+ * is bound to a VarHandle instance and the access mode.  More specifically, the
+ * following:
+ * <pre> {@code
+ * VarHandle vh = ..
+ * R r = (R) vh.{access-mode}(p1, p2, ..., pN);
+ * }</pre>
+ * behaves as if (modulo the access mode methods do not declare throwing of
+ * {@code Throwable}):
+ * <pre> {@code
+ * VarHandle vh = ..
+ * MethodHandle mh = MethodHandles.varHandleExactInvoker(
+ *                       VarHandle.AccessMode.{access-mode},
+ *                       vh.accessModeType(VarHandle.AccessMode.{access-mode}));
+ *
+ * mh = mh.bindTo(vh);
+ * R r = (R) mh.invoke(p1, p2, ..., pN)
+ * }</pre>
+ * or, more concisely, behaves as if:
+ * <pre> {@code
+ * VarHandle vh = ..
+ * MethodHandle mh = vh.toMethodHandle(VarHandle.AccessMode.{access-mode});
+ *
+ * R r = (R) mh.invoke(p1, p2, ..., pN)
+ * }</pre>
+ * In terms of equivalent {@code invokevirtual} bytecode behaviour an access
+ * mode method invocation is equivalent to:
+ * <pre> {@code
+ * MethodHandle mh = MethodHandles.lookup().findVirtual(
+ *                       VarHandle.class,
+ *                       VarHandle.AccessMode.{access-mode}.name(),
+ *                       MethodType.methodType(R, p1, p2, ..., pN));
+ *
+ * R r = (R) mh.invokeExact(vh, p1, p2, ..., pN)
+ * }</pre>
+ * where the desired method type is the symbolic type descriptor and a
+ * {@link MethodHandle#invokeExact} is performed, since before invocation of the
+ * target, the handle will apply reference casts as necessary and box, unbox, or
+ * widen primitive values, as if by {@link MethodHandle#asType asType} (see also
+ * {@link MethodHandles#varHandleInvoker}).
+ *
+ * <h1>Invocation checking</h1>
+ * In typical programs, VarHandle access mode type matching will usually
+ * succeed.  But if a match fails, the JVM will throw a
+ * {@link WrongMethodTypeException}.
+ * <p>
+ * Thus, an access mode type mismatch which might show up as a linkage error
+ * in a statically typed program can show up as a dynamic
+ * {@code WrongMethodTypeException} in a program which uses VarHandles.
+ * <p>
+ * Because access mode types contain "live" {@code Class} objects, method type
+ * matching takes into account both type names and class loaders.
+ * Thus, even if a VarHandle {@code VH} is created in one class loader
+ * {@code L1} and used in another {@code L2}, VarHandle access mode method
+ * calls are type-safe, because the caller's symbolic type descriptor, as
+ * resolved in {@code L2}, is matched against the original callee method's
+ * symbolic type descriptor, as resolved in {@code L1}.  The resolution in
+ * {@code L1} happens when {@code VH} is created and its access mode types are
+ * assigned, while the resolution in {@code L2} happens when the
+ * {@code invokevirtual} instruction is linked.
+ * <p>
+ * Apart from type descriptor checks, a VarHandles's capability to
+ * access it's variables is unrestricted.
+ * If a VarHandle is formed on a non-public variable by a class that has access
+ * to that variable, the resulting VarHandle can be used in any place by any
+ * caller who receives a reference to it.
+ * <p>
+ * Unlike with the Core Reflection API, where access is checked every time a
+ * reflective method is invoked, VarHandle access checking is performed
+ * <a href="MethodHandles.Lookup.html#access">when the VarHandle is
+ * created</a>.
+ * Thus, VarHandles to non-public variables, or to variables in non-public
+ * classes, should generally be kept secret.  They should not be passed to
+ * untrusted code unless their use from the untrusted code would be harmless.
+ *
+ *
+ * <h1>VarHandle creation</h1>
+ * Java code can create a VarHandle that directly accesses any field that is
+ * accessible to that code.  This is done via a reflective, capability-based
+ * API called {@link java.lang.invoke.MethodHandles.Lookup
+ * MethodHandles.Lookup}.
+ * For example, a VarHandle for a non-static field can be obtained
+ * from {@link java.lang.invoke.MethodHandles.Lookup#findVarHandle
+ * Lookup.findVarHandle}.
+ * There is also a conversion method from Core Reflection API objects,
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflectVarHandle
+ * Lookup.unreflectVarHandle}.
+ * <p>
+ * Access to protected field members is restricted to receivers only of the
+ * accessing class, or one of its subclasses, and the accessing class must in
+ * turn be a subclass (or package sibling) of the protected member's defining
+ * class.  If a VarHandle refers to a protected non-static field of a declaring
+ * class outside the current package, the receiver argument will be narrowed to
+ * the type of the accessing class.
+ *
+ * <h1>Interoperation between VarHandles and the Core Reflection API</h1>
+ * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup
+ * Lookup} API, any field represented by a Core Reflection API object
+ * can be converted to a behaviorally equivalent VarHandle.
+ * For example, a reflective {@link java.lang.reflect.Field Field} can
+ * be converted to a VarHandle using
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflectVarHandle
+ * Lookup.unreflectVarHandle}.
+ * The resulting VarHandles generally provide more direct and efficient
+ * access to the underlying fields.
+ * <p>
+ * As a special case, when the Core Reflection API is used to view the
+ * signature polymorphic access mode methods in this class, they appear as
+ * ordinary non-polymorphic methods.  Their reflective appearance, as viewed by
+ * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
+ * is unaffected by their special status in this API.
+ * For example, {@link java.lang.reflect.Method#getModifiers
+ * Method.getModifiers}
+ * will report exactly those modifier bits required for any similarly
+ * declared method, including in this case {@code native} and {@code varargs}
+ * bits.
+ * <p>
+ * As with any reflected method, these methods (when reflected) may be invoked
+ * directly via {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke},
+ * via JNI, or indirectly via
+ * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
+ * However, such reflective calls do not result in access mode method
+ * invocations.  Such a call, if passed the required argument (a single one, of
+ * type {@code Object[]}), will ignore the argument and will throw an
+ * {@code UnsupportedOperationException}.
+ * <p>
+ * Since {@code invokevirtual} instructions can natively invoke VarHandle
+ * access mode methods under any symbolic type descriptor, this reflective view
+ * conflicts with the normal presentation of these methods via bytecodes.
+ * Thus, these native methods, when reflectively viewed by
+ * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
+ * <p>
+ * In order to obtain an invoker method for a particular access mode type,
+ * use {@link java.lang.invoke.MethodHandles#varHandleExactInvoker} or
+ * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.  The
+ * {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
+ * API is also able to return a method handle to call an access mode method for
+ * any specified access mode type and is equivalent in behaviour to
+ * {@link java.lang.invoke.MethodHandles#varHandleInvoker}.
+ *
+ * <h1>Interoperation between VarHandles and Java generics</h1>
+ * A VarHandle can be obtained for a variable, such as a a field, which is
+ * declared with Java generic types.  As with the Core Reflection API, the
+ * VarHandle's variable type will be constructed from the erasure of the
+ * source-level type.  When a VarHandle access mode method is invoked, the
+ * types
+ * of its arguments or the return value cast type may be generic types or type
+ * instances.  If this occurs, the compiler will replace those types by their
+ * erasures when it constructs the symbolic type descriptor for the
+ * {@code invokevirtual} instruction.
+ *
+ * @see MethodHandle
+ * @see MethodHandles
+ * @see MethodType
+ * @since 9
+ */
+public abstract class VarHandle {
+    // Use explicit final fields rather than an @Stable array as
+    // this can reduce the memory per handle
+    // e.g. by 24 bytes on 64 bit architectures
+    final MethodType typeGet;
+    final MethodType typeSet;
+    final MethodType typeCompareSwap;
+    final MethodType typeCompareExchange;
+    final MethodType typeGetAndUpdate;
+
+    final VarForm vform;
+
+    VarHandle(VarForm vform, Class<?> receiver, Class<?> value, Class<?>... intermediate) {
+        this.vform = vform;
+
+        // (Receiver, <Intermediates>)
+        List<Class<?>> l = new ArrayList<>();
+        if (receiver != null)
+            l.add(receiver);
+        l.addAll(Arrays.asList(intermediate));
+
+        // (Receiver, <Intermediates>)Value
+        this.typeGet = MethodType.methodType(value, l);
+
+        // (Receiver, <Intermediates>, Value)void
+        l.add(value);
+        this.typeSet = MethodType.methodType(void.class, l);
+
+        // (Receiver, <Intermediates>, Value)Value
+        this.typeGetAndUpdate = MethodType.methodType(value, l);
+
+        // (Receiver, <Intermediates>, Value, Value)boolean
+        l.add(value);
+        this.typeCompareSwap = MethodType.methodType(boolean.class, l);
+
+        // (Receiver, <Intermediates>, Value, Value)Value
+        this.typeCompareExchange = MethodType.methodType(value, l);
+    }
+
+    RuntimeException unsupported() {
+        return new UnsupportedOperationException();
+    }
+
+    // Plain accessors
+
+    /**
+     * Returns the value of a variable, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.  Commonly referred to
+     * as plain read access.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code get}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.get)} on this VarHandle.
+     *
+     * <p>This access mode is supported by all VarHandle instances and never
+     * throws {@code UnsupportedOperationException}.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object get(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, with memory
+     * semantics of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.  Commonly referred to as plain write access.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}
+     *
+     * <p>The symbolic type descriptor at the call site of {@code set}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.set)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void set(Object... args);
+
+
+    // Volatile accessors
+
+    /**
+     * Returns the value of a variable, with memory semantics of reading as if
+     * the variable was declared {@code volatile}.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getVolatile)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getVolatile(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, with memory
+     * semantics of setting as if the variable was declared {@code volatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setVolatile)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_seq_cst}.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setVolatile(Object... args);
+
+
+    /**
+     * Returns the value of a variable, accessed in program order, but with no
+     * assurance of memory ordering effects with respect to other threads.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getOpaque}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getOpaque)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getOpaque(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, in program order,
+     * but with no assurance of memory ordering effects with respect to other
+     * threads.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setOpaque}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setOpaque)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setOpaque(Object... args);
+
+
+    // Lazy accessors
+
+    /**
+     * Returns the value of a variable, and ensures that subsequent loads and
+     * stores are not reordered before this access.
+     *
+     * <p>The method signature is of the form {@code (CT)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAcquire)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the value of the
+     * variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_acquire} ordering.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAcquire(Object... args);
+
+    /**
+     * Sets the value of a variable to the {@code newValue}, and ensures that
+     * prior loads and stores are not reordered after this access.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)void}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code setRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.setRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code memory_order_release} ordering.
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    void setRelease(Object... args);
+
+
+    // Compare and set accessors
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndSet} must match the access mode type that is the result of
+     * calling {@code accessModeType(VarHandle.AccessMode.compareAndSet)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean compareAndSet(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeVolatile}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeVolatile)}
+     * on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeVolatile(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getAcquire}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeAcquire)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #getAcquire(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeAcquire(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setRelease} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * compareAndExchangeRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the witness value, which
+     * will be the same as the {@code expectedValue} if successful
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setRelease(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object compareAndExchangeRelease(Object... args);
+
+    // Weak (spurious failures allowed)
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSet} must match the access mode type that is the result of
+     * calling {@code accessModeType(VarHandle.AccessMode.weakCompareAndSet)} on
+     * this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSet(Object... args);
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #set} if the variable's current value,
+     * referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getAcquire}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSetAcquire}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetAcquire)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #set(Object...)
+     * @see #getAcquire(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSetAcquire(Object... args);
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the semantics of {@link #setRelease} if the variable's current
+     * value, referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #get}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the current value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSetRelease}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetRelease)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setRelease(Object...)
+     * @see #get(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSetRelease(Object... args);
+
+    /**
+     * Atomically sets the value of a variable to the {@code newValue} with the
+     * memory semantics of {@link #setVolatile} and returns the variable's
+     * previous value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T newValue)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAndSet}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAndSet)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T newValue)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the previous value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAndSet(Object... args);
+
+
+    // Primitive adders
+    // Throw UnsupportedOperationException for refs
+
+    /**
+     * Atomically adds the {@code value} to the current value of a variable with
+     * the memory semantics of {@link #setVolatile}, and returns the variable's
+     * previous value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T value)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code getAndAdd}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.getAndAdd)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T value)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the previous value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object getAndAdd(Object... args);
+
+    /**
+     * Atomically adds the {@code value} to the current value of a variable with
+     * the memory semantics of {@link #setVolatile}, and returns the variable's
+     * current (updated) value, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>The method signature is of the form {@code (CT, T value)T}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code addAndGet}
+     * must match the access mode type that is the result of calling
+     * {@code accessModeType(VarHandle.AccessMode.addAndGet)} on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T value)}
+     * , statically represented using varargs.
+     * @return the signature-polymorphic result that is the current value of
+     * the variable
+     * , statically represented using {@code Object}.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    Object addAndGet(Object... args);
+
+    enum AccessType {
+        get,                  // 0
+        set,                  // 1
+        compareAndSwap,       // 2
+        compareAndExchange,   // 3
+        getAndUpdate;         // 4
+
+        MethodType getMethodType(VarHandle vh) {
+            return getMethodType(this.ordinal(), vh);
+        }
+
+        @ForceInline
+        static MethodType getMethodType(int ordinal, VarHandle vh) {
+            if (ordinal == 0) {
+                return vh.typeGet;
+            }
+            else if (ordinal == 1) {
+                return vh.typeSet;
+            }
+            else if (ordinal == 2) {
+                return vh.typeCompareSwap;
+            }
+            else if (ordinal == 3) {
+                return vh.typeCompareExchange;
+            }
+            else if (ordinal == 4) {
+                return vh.typeGetAndUpdate;
+            }
+            else {
+                throw new IllegalStateException("Illegal access type: " + ordinal);
+            }
+        }
+    }
+
+    /**
+     * The set of access modes that specify how a variable, referenced by a
+     * VarHandle, is accessed.
+     */
+    public enum AccessMode {
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#get VarHandle.get}
+         */
+        get(AccessType.get, Object.class),   // 0
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#set VarHandle.set}
+         */
+        set(AccessType.set, void.class),     // 1
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getVolatile VarHandle.getVolatile}
+         */
+        getVolatile(AccessType.get, Object.class),  // 2
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setVolatile VarHandle.setVolatile}
+         */
+        setVolatile(AccessType.set, void.class),    // 3
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAcquire VarHandle.getAcquire}
+         */
+        getAcquire(AccessType.get, Object.class),   // 4
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setRelease VarHandle.setRelease}
+         */
+        setRelease(AccessType.set, void.class),     // 5
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getOpaque VarHandle.getOpaque}
+         */
+        getOpaque(AccessType.get, Object.class),    // 6
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#setOpaque VarHandle.setOpaque}
+         */
+        setOpaque(AccessType.set, void.class),      // 7
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndSet VarHandle.compareAndSet}
+         */
+        compareAndSet(AccessType.compareAndSwap, boolean.class),    // 8
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
+         */
+        compareAndExchangeVolatile(AccessType.compareAndExchange, Object.class), // 9
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
+         */
+        compareAndExchangeAcquire(AccessType.compareAndExchange, Object.class),  // 10
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
+         */
+        compareAndExchangeRelease(AccessType.compareAndExchange, Object.class),  // 11
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
+         */
+        weakCompareAndSet(AccessType.compareAndSwap, boolean.class),        // 12
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
+         */
+        weakCompareAndSetAcquire(AccessType.compareAndSwap, boolean.class), // 13
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
+         */
+        weakCompareAndSetRelease(AccessType.compareAndSwap, boolean.class), // 14
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAndSet VarHandle.getAndSet}
+         */
+        getAndSet(AccessType.getAndUpdate, Object.class),   // 15
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#getAndAdd VarHandle.getAndAdd}
+         */
+        getAndAdd(AccessType.getAndUpdate, Object.class),   // 16
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#addAndGet VarHandle.addAndGet}
+         */
+        addAndGet(AccessType.getAndUpdate, Object.class),   // 17
+        ;
+
+        final AccessType at;
+        final boolean isPolyMorphicInReturnType;
+        final Class<?> returnType;
+
+        AccessMode(AccessType at, Class<?> returnType) {
+            this.at = at;
+
+            // Assert that return type is correct
+            // Otherwise, when disabled avoid using reflection
+            assert returnType == getReturnType(name());
+
+            this.returnType = returnType;
+            isPolyMorphicInReturnType = returnType != Object.class;
+        }
+
+        private static Class<?> getReturnType(String name) {
+            try {
+                Method m = VarHandle.class.getMethod(name, Object[].class);
+                return m.getReturnType();
+            }
+            catch (Exception e) {
+                throw newInternalError(e);
+            }
+        }
+
+        @ForceInline
+        static MemberName getMemberName(int ordinal, VarForm vform) {
+            if (ordinal == 0) {
+                return vform.mbGet;
+            }
+            else if (ordinal == 1) {
+                return vform.mbSet;
+            }
+            else if (ordinal == 2) {
+                return vform.mbGetVolatile;
+            }
+            else if (ordinal == 3) {
+                return vform.mbSetVolatile;
+            }
+            else if (ordinal == 4) {
+                return vform.mbGetAcquire;
+            }
+            else if (ordinal == 5) {
+                return vform.mbSetRelease;
+            }
+            else if (ordinal == 6) {
+                return vform.mbGetOpaque;
+            }
+            else if (ordinal == 7) {
+                return vform.mbSetOpaque;
+            }
+            else if (ordinal == 8) {
+                return vform.mbCompareAndSet;
+            }
+            else if (ordinal == 9) {
+                return vform.mbCompareAndExchangeVolatile;
+            }
+            else if (ordinal == 10) {
+                return vform.mbCompareAndExchangeAcquire;
+            }
+            else if (ordinal == 11) {
+                return vform.mbCompareAndExchangeRelease;
+            }
+            else if (ordinal == 12) {
+                return vform.mbWeakCompareAndSet;
+            }
+            else if (ordinal == 13) {
+                return vform.mbWeakCompareAndSetAcquire;
+            }
+            else if (ordinal == 14) {
+                return vform.mbWeakCompareAndSetRelease;
+            }
+            else if (ordinal == 15) {
+                return vform.mbGetAndSet;
+            }
+            else if (ordinal == 16) {
+                return vform.mbGetAndAdd;
+            }
+            else if (ordinal == 17) {
+                return vform.mbAddAndGet;
+            }
+            else {
+                throw new IllegalStateException("Illegal access mode: " + ordinal);
+            }
+        }
+    }
+
+    static final class AccessDescriptor {
+        final MethodType symbolicMethodType;
+        final int type;
+        final int mode;
+
+        public AccessDescriptor(MethodType symbolicMethodType, int type, int mode) {
+            this.symbolicMethodType = symbolicMethodType;
+            this.type = type;
+            this.mode = mode;
+        }
+    }
+
+    /**
+     * Returns the variable type of variables referenced by this VarHandle.
+     *
+     * @return the variable type of variables referenced by this VarHandle
+     */
+    public final Class<?> varType() {
+        return typeSet.parameterType(typeSet.parameterCount() - 1);
+    }
+
+    /**
+     * Returns the coordinate types for this VarHandle.
+     *
+     * @return the coordinate types for this VarHandle. The returned
+     * list is unmodifiable
+     */
+    public final List<Class<?>> coordinateTypes() {
+        return typeGet.parameterList();
+    }
+
+    /**
+     * Obtains the canonical access mode type for this VarHandle and a given
+     * access mode.
+     *
+     * <p>The access mode type's parameter types will consist of a prefix that
+     * is the coordinate types of this VarHandle followed by further
+     * types as defined by the access mode's method.
+     * The access mode type's return type is defined by the return type of the
+     * access mode's method.
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return the access mode type for the given access mode
+     */
+    public final MethodType accessModeType(AccessMode accessMode) {
+        return accessMode.at.getMethodType(this);
+    }
+
+
+    /**
+     * Returns {@code true} if the given access mode is supported, otherwise
+     * {@code false}.
+     *
+     * <p>The return of a {@code false} value for a given access mode indicates
+     * that an {@code UnsupportedOperationException} is thrown on invocation
+     * of the corresponding access mode's signature-polymorphic method.
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return {@code true} if the given access mode is supported, otherwise
+     * {@code false}.
+     */
+    public final boolean isAccessModeSupported(AccessMode accessMode) {
+        return AccessMode.getMemberName(accessMode.ordinal(), vform) != null;
+    }
+
+    /**
+     * Obtains a method handle bound to this VarHandle and the given access
+     * mode.
+     *
+     * @apiNote This method, for a VarHandle {@code vh} and access mode
+     * {@code {access-mode}}, returns a method handle that is equivalent to
+     * method handle {@code bhm} in the following code (though it may be more
+     * efficient):
+     * <pre>{@code
+     * MethodHandle mh = MethodHandles.varHandleExactInvoker(
+     *                       vh.accessModeType(VarHandle.AccessMode.{access-mode}));
+     *
+     * MethodHandle bmh = mh.bindTo(vh);
+     * }</pre>
+     *
+     * @param accessMode the access mode, corresponding to the
+     * signature-polymorphic method of the same name
+     * @return a method handle bound to this VarHandle and the given access mode
+     */
+    public final MethodHandle toMethodHandle(AccessMode accessMode) {
+        MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform);
+        if (mn != null) {
+            return DirectMethodHandle.make(mn).
+                    bindTo(this).
+                    asType(accessMode.at.getMethodType(this));
+        }
+        else {
+            // Ensure an UnsupportedOperationException is thrown
+            return MethodHandles.varHandleInvoker(accessMode, accessModeType(accessMode)).
+                    bindTo(this);
+        }
+    }
+
+    /*non-public*/
+    final void updateVarForm(VarForm newVForm) {
+        if (vform == newVForm) return;
+        UNSAFE.putObject(this, VFORM_OFFSET, newVForm);
+        UNSAFE.fullFence();
+    }
+
+    static final BiFunction<Integer, Integer, ArrayIndexOutOfBoundsException> AIOOBE_SUPPLIER = new BiFunction<>() {
+        @Override
+        public ArrayIndexOutOfBoundsException apply(Integer a, Integer b) {
+            return new ArrayIndexOutOfBoundsException(a, b);
+        }
+    };
+
+    private static final long VFORM_OFFSET;
+
+    static {
+        try {
+            VFORM_OFFSET = UNSAFE.objectFieldOffset(VarHandle.class.getDeclaredField("vform"));
+        }
+        catch (ReflectiveOperationException e) {
+            throw newInternalError(e);
+        }
+    }
+
+
+    // Fence methods
+
+    /**
+     * Ensures that loads and stores before the fence will not be reordered
+     * with
+     * loads and stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_seq_cst)}
+     */
+    @ForceInline
+    public static void fullFence() {
+        UNSAFE.fullFence();
+    }
+
+    /**
+     * Ensures that loads before the fence will not be reordered with loads and
+     * stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_acquire)}
+     */
+    @ForceInline
+    public static void acquireFence() {
+        UNSAFE.loadFence();
+    }
+
+    /**
+     * Ensures that loads and stores before the fence will not be
+     * reordered with stores after the fence.
+     *
+     * @apiNote Ignoring the many semantic differences from C and C++, this
+     * method has memory ordering effects compatible with
+     * {@code atomic_thread_fence(memory_order_release)}
+     */
+    @ForceInline
+    public static void releaseFence() {
+        UNSAFE.storeFence();
+    }
+
+    /**
+     * Ensures that loads before the fence will not be reordered with
+     * loads after the fence.
+     */
+    @ForceInline
+    public static void loadLoadFence() {
+        UNSAFE.loadLoadFence();
+    }
+
+    /**
+     * Ensures that stores before the fence will not be reordered with
+     * stores after the fence.
+     */
+    @ForceInline
+    public static void storeStoreFence() {
+        UNSAFE.storeStoreFence();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandleByteArrayBase.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+/**
+ * The base class for generated byte array and byte buffer view
+ * implementations
+ */
+abstract class VarHandleByteArrayBase {
+    // Buffer.address
+    static final long BUFFER_ADDRESS;
+    // Buffer.limit
+    static final long BUFFER_LIMIT;
+    // ByteBuffer.hb
+    static final long BYTE_BUFFER_HB;
+    // ByteBuffer.isReadOnly
+    static final long BYTE_BUFFER_IS_READ_ONLY;
+
+    static {
+        try {
+            BUFFER_ADDRESS = UNSAFE.objectFieldOffset(
+                    Buffer.class.getDeclaredField("address"));
+
+            BUFFER_LIMIT = UNSAFE.objectFieldOffset(
+                    Buffer.class.getDeclaredField("limit"));
+
+            BYTE_BUFFER_HB = UNSAFE.objectFieldOffset(
+                    ByteBuffer.class.getDeclaredField("hb"));
+
+            BYTE_BUFFER_IS_READ_ONLY = UNSAFE.objectFieldOffset(
+                    ByteBuffer.class.getDeclaredField("isReadOnly"));
+        }
+        catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+    }
+
+    static final boolean BE = UNSAFE.isBigEndian();
+
+    static IllegalStateException newIllegalStateExceptionForMisalignedAccess(int index) {
+        return new IllegalStateException("Misaligned access at index: " + index);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandleGuards.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,1391 @@
+/*
+ * Copyright (c) 2014, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import jdk.internal.vm.annotation.ForceInline;
+
+// This class is auto-generated by java.lang.invoke.VarHandles$GuardMethodGenerator. Do not edit.
+final class VarHandleGuards {
+
+    @ForceInline
+    final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {
+        MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);
+        if (mn == null) {
+            throw handle.unsupported();
+        }
+        return mn;
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_L_L(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LL_V(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LL_L(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LLL_Z(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LLL_L(VarHandle handle, Object arg0, Object arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_L_I(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LI_V(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LI_I(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LII_Z(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LII_I(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_L_J(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJ_V(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJ_J(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_L_F(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LF_V(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LF_F(VarHandle handle, Object arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LFF_Z(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LFF_F(VarHandle handle, Object arg0, float arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_L_D(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LD_V(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LD_D(VarHandle handle, Object arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LDD_Z(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LDD_D(VarHandle handle, Object arg0, double arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard__L(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_L_V(VarHandle handle, Object arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LL_Z(VarHandle handle, Object arg0, Object arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard__I(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_I_V(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_I_I(VarHandle handle, int arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_II_Z(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_II_I(VarHandle handle, int arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard__J(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_J_V(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_J_J(VarHandle handle, long arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_JJ_Z(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_JJ_J(VarHandle handle, long arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard__F(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_F_V(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_F_F(VarHandle handle, float arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_FF_Z(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_FF_F(VarHandle handle, float arg0, float arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard__D(VarHandle handle, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_D_V(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_D_D(VarHandle handle, double arg0, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_DD_Z(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_DD_D(VarHandle handle, double arg0, double arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LI_L(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIL_V(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LIL_L(VarHandle handle, Object arg0, int arg1, Object arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LILL_Z(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static Object guard_LILL_L(VarHandle handle, Object arg0, int arg1, Object arg2, Object arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            Object r = MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+            return symbolic.returnType().cast(r);
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LII_V(VarHandle handle, Object arg0, int arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIII_Z(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LIII_I(VarHandle handle, Object arg0, int arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LI_J(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIJ_V(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LIJ_J(VarHandle handle, Object arg0, int arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIJJ_Z(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LIJJ_J(VarHandle handle, Object arg0, int arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LI_F(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LIF_V(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LIF_F(VarHandle handle, Object arg0, int arg1, float arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIFF_Z(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static float guard_LIFF_F(VarHandle handle, Object arg0, int arg1, float arg2, float arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (float) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (float) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LI_D(VarHandle handle, Object arg0, int arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LID_V(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LID_D(VarHandle handle, Object arg0, int arg1, double arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LIDD_Z(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static double guard_LIDD_D(VarHandle handle, Object arg0, int arg1, double arg2, double arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (double) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (double) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJ_I(VarHandle handle, Object arg0, long arg1, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJI_V(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJI_I(VarHandle handle, Object arg0, long arg1, int arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJII_Z(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static int guard_LJII_I(VarHandle handle, Object arg0, long arg1, int arg2, int arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (int) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (int) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static void guard_LJJ_V(VarHandle handle, Object arg0, long arg1, long arg2, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            MethodHandle.linkToStatic(handle, arg0, arg1, arg2, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            vh_invoker.invokeBasic(handle, arg0, arg1, arg2);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static boolean guard_LJJJ_Z(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (boolean) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (boolean) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+    @ForceInline
+    @LambdaForm.Compiled
+    final static long guard_LJJJ_J(VarHandle handle, Object arg0, long arg1, long arg2, long arg3, VarHandle.AccessDescriptor ad) throws Throwable {
+        MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);
+        MethodType symbolic = ad.symbolicMethodType;
+        if (target == symbolic) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else if (target.erase() == symbolic.erase()) {
+            return (long) MethodHandle.linkToStatic(handle, arg0, arg1, arg2, arg3, getMemberName(handle, ad));
+        }
+        else {
+            MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);
+            return (long) vh_invoker.invokeBasic(handle, arg0, arg1, arg2, arg3);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandles.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2014, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+final class VarHandles {
+
+    static VarHandle makeFieldHandle(MemberName f, Class<?> refc, Class<?> type, boolean isWriteAllowedOnFinalFields) {
+        if (!f.isStatic()) {
+            long foffset = MethodHandleNatives.objectFieldOffset(f);
+            if (!type.isPrimitive()) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleObjects.FieldInstanceReadOnly(refc, foffset, type)
+                       : new VarHandleObjects.FieldInstanceReadWrite(refc, foffset, type);
+            }
+            else if (type == boolean.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == byte.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == short.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == char.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleChars.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == int.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleInts.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == long.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == float.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset);
+            }
+            else if (type == double.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
+                       : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset);
+            }
+            else {
+                throw new UnsupportedOperationException();
+            }
+        }
+        else {
+            // TODO This is not lazy on first invocation
+            // and might cause some circular initialization issues
+
+            // Replace with something similar to direct method handles
+            // where a barrier is used then elided after use
+
+            if (UNSAFE.shouldBeInitialized(refc))
+                UNSAFE.ensureClassInitialized(refc);
+
+            Object base = MethodHandleNatives.staticFieldBase(f);
+            long foffset = MethodHandleNatives.staticFieldOffset(f);
+            if (!type.isPrimitive()) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleObjects.FieldStaticReadOnly(base, foffset, type)
+                       : new VarHandleObjects.FieldStaticReadWrite(base, foffset, type);
+            }
+            else if (type == boolean.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBooleans.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleBooleans.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == byte.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleBytes.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleBytes.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == short.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleShorts.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleShorts.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == char.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleChars.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleChars.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == int.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleInts.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleInts.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == long.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleLongs.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleLongs.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == float.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleFloats.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleFloats.FieldStaticReadWrite(base, foffset);
+            }
+            else if (type == double.class) {
+                return f.isFinal() && !isWriteAllowedOnFinalFields
+                       ? new VarHandleDoubles.FieldStaticReadOnly(base, foffset)
+                       : new VarHandleDoubles.FieldStaticReadWrite(base, foffset);
+            }
+            else {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
+
+    static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
+        if (!arrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + arrayClass);
+
+        Class<?> componentType = arrayClass.getComponentType();
+
+        int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
+        int ascale = UNSAFE.arrayIndexScale(arrayClass);
+        int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
+
+        if (!componentType.isPrimitive()) {
+            return new VarHandleObjects.Array(aoffset, ashift, arrayClass);
+        }
+        else if (componentType == boolean.class) {
+            return new VarHandleBooleans.Array(aoffset, ashift);
+        }
+        else if (componentType == byte.class) {
+            return new VarHandleBytes.Array(aoffset, ashift);
+        }
+        else if (componentType == short.class) {
+            return new VarHandleShorts.Array(aoffset, ashift);
+        }
+        else if (componentType == char.class) {
+            return new VarHandleChars.Array(aoffset, ashift);
+        }
+        else if (componentType == int.class) {
+            return new VarHandleInts.Array(aoffset, ashift);
+        }
+        else if (componentType == long.class) {
+            return new VarHandleLongs.Array(aoffset, ashift);
+        }
+        else if (componentType == float.class) {
+            return new VarHandleFloats.Array(aoffset, ashift);
+        }
+        else if (componentType == double.class) {
+            return new VarHandleDoubles.Array(aoffset, ashift);
+        }
+        else {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
+                                         boolean be) {
+        if (!viewArrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + viewArrayClass);
+
+        Class<?> viewComponentType = viewArrayClass.getComponentType();
+
+        if (viewComponentType == long.class) {
+            return new VarHandleByteArrayAsLongs.ArrayHandle(be);
+        }
+        else if (viewComponentType == int.class) {
+            return new VarHandleByteArrayAsInts.ArrayHandle(be);
+        }
+        else if (viewComponentType == short.class) {
+            return new VarHandleByteArrayAsShorts.ArrayHandle(be);
+        }
+        else if (viewComponentType == char.class) {
+            return new VarHandleByteArrayAsChars.ArrayHandle(be);
+        }
+        else if (viewComponentType == double.class) {
+            return new VarHandleByteArrayAsDoubles.ArrayHandle(be);
+        }
+        else if (viewComponentType == float.class) {
+            return new VarHandleByteArrayAsFloats.ArrayHandle(be);
+        }
+
+        throw new UnsupportedOperationException();
+    }
+
+    static VarHandle makeByteBufferViewHandle(Class<?> viewArrayClass,
+                                              boolean be) {
+        if (!viewArrayClass.isArray())
+            throw new IllegalArgumentException("not an array: " + viewArrayClass);
+
+        Class<?> viewComponentType = viewArrayClass.getComponentType();
+
+        if (viewComponentType == long.class) {
+            return new VarHandleByteArrayAsLongs.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == int.class) {
+            return new VarHandleByteArrayAsInts.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == short.class) {
+            return new VarHandleByteArrayAsShorts.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == char.class) {
+            return new VarHandleByteArrayAsChars.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == double.class) {
+            return new VarHandleByteArrayAsDoubles.ByteBufferHandle(be);
+        }
+        else if (viewComponentType == float.class) {
+            return new VarHandleByteArrayAsFloats.ByteBufferHandle(be);
+        }
+
+        throw new UnsupportedOperationException();
+    }
+
+//    /**
+//     * A helper program to generate the VarHandleGuards class with a set of
+//     * static guard methods each of which corresponds to a particular shape and
+//     * performs a type check of the symbolic type descriptor with the VarHandle
+//     * type descriptor before linking/invoking to the underlying operation as
+//     * characterized by the operation member name on the VarForm of the
+//     * VarHandle.
+//     * <p>
+//     * The generated class essentially encapsulates pre-compiled LambdaForms,
+//     * one for each method, for the most set of common method signatures.
+//     * This reduces static initialization costs, footprint costs, and circular
+//     * dependencies that may arise if a class is generated per LambdaForm.
+//     * <p>
+//     * A maximum of L*T*S methods will be generated where L is the number of
+//     * access modes kinds (or unique operation signatures) and T is the number
+//     * of variable types and S is the number of shapes (such as instance field,
+//     * static field, or array access).
+//     * If there are 4 unique operation signatures, 5 basic types (Object, int,
+//     * long, float, double), and 3 shapes then a maximum of 60 methods will be
+//     * generated.  However, the number is likely to be less since there
+//     * be duplicate signatures.
+//     * <p>
+//     * Each method is annotated with @LambdaForm.Compiled to inform the runtime
+//     * that such methods should be treated as if a method of a class that is the
+//     * result of compiling a LambdaForm.  Annotation of such methods is
+//     * important for correct evaluation of certain assertions and method return
+//     * type profiling in HotSpot.
+//     */
+//    public static class GuardMethodGenerator {
+//
+//        static final String GUARD_METHOD_SIG_TEMPLATE = "<RETURN> <NAME>_<SIGNATURE>(<PARAMS>)";
+//
+//        static final String GUARD_METHOD_TEMPLATE =
+//                "@ForceInline\n" +
+//                "@LambdaForm.Compiled\n" +
+//                "final static <METHOD> throws Throwable {\n" +
+//                "    MethodType target = VarHandle.AccessType.getMethodType(ad.type, handle);\n" +
+//                "    MethodType symbolic = ad.symbolicMethodType;\n" +
+//                "    if (target == symbolic) {\n" +
+//                "        <RETURN>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);\n" +
+//                "    }\n" +
+//                "    else if (target.erase() == symbolic.erase()) {\n" +
+//                "        <RESULT_ERASED>MethodHandle.linkToStatic(<LINK_TO_STATIC_ARGS>);<RETURN_ERASED>\n" +
+//                "    }\n" +
+//                "    else {\n" +
+//                "        MethodHandle vh_invoker = MethodHandles.varHandleInvoker(VarHandle.AccessMode.values()[ad.mode], symbolic);\n" +
+//                "        <RETURN>vh_invoker.invokeBasic(<LINK_TO_INVOKER_ARGS>);\n" +
+//                "    }\n" +
+//                "}";
+//
+//        static final String GET_MEMBER_NAME_METHOD =
+//                "@ForceInline\n" +
+//                "final static MemberName getMemberName(VarHandle handle, VarHandle.AccessDescriptor ad) {\n" +
+//                "    MemberName mn = VarHandle.AccessMode.getMemberName(ad.mode, handle.vform);\n" +
+//                "    if (mn == null) {\n" +
+//                "        throw handle.unsupported();\n" +
+//                "    }\n" +
+//                "    return mn;\n" +
+//                "}";
+//
+//        // A template for deriving the operations
+//        // could be supported by annotating VarHandle directly with the
+//        // operation kind and shape
+//        interface VarHandleTemplate {
+//            Object get();
+//
+//            void set(Object value);
+//
+//            boolean compareAndSwap(Object actualValue, Object expectedValue);
+//
+//            Object compareAndExchange(Object actualValue, Object expectedValue);
+//
+//            Object getAndUpdate(Object value);
+//        }
+//
+//        static class HandleType {
+//            final Class<?> receiver;
+//            final Class<?>[] intermediates;
+//            final Class<?> value;
+//
+//            HandleType(Class<?> receiver, Class<?> value, Class<?>... intermediates) {
+//                this.receiver = receiver;
+//                this.intermediates = intermediates;
+//                this.value = value;
+//            }
+//        }
+//
+//        /**
+//         * @param args parameters
+//         */
+//        public static void main(String[] args) {
+//            System.out.println("package java.lang.invoke;");
+//            System.out.println();
+//            System.out.println("import jdk.internal.vm.annotation.ForceInline;");
+//            System.out.println();
+//            System.out.println("// This class is auto-generated by " +
+//                               GuardMethodGenerator.class.getName() +
+//                               ". Do not edit.");
+//            System.out.println("final class VarHandleGuards {");
+//
+//            System.out.println();
+//            System.out.println(GET_MEMBER_NAME_METHOD);
+//            System.out.println();
+//
+//            // Declare the stream of shapes
+//            Stream<HandleType> hts = Stream.of(
+//                    // Object->Object
+//                    new HandleType(Object.class, Object.class),
+//                    // Object->int
+//                    new HandleType(Object.class, int.class),
+//                    // Object->long
+//                    new HandleType(Object.class, long.class),
+//                    // Object->float
+//                    new HandleType(Object.class, float.class),
+//                    // Object->double
+//                    new HandleType(Object.class, double.class),
+//
+//                    // <static>->Object
+//                    new HandleType(null, Object.class),
+//                    // <static>->int
+//                    new HandleType(null, int.class),
+//                    // <static>->long
+//                    new HandleType(null, long.class),
+//                    // <static>->float
+//                    new HandleType(null, float.class),
+//                    // <static>->double
+//                    new HandleType(null, double.class),
+//
+//                    // Array[int]->Object
+//                    new HandleType(Object.class, Object.class, int.class),
+//                    // Array[int]->int
+//                    new HandleType(Object.class, int.class, int.class),
+//                    // Array[int]->long
+//                    new HandleType(Object.class, long.class, int.class),
+//                    // Array[int]->float
+//                    new HandleType(Object.class, float.class, int.class),
+//                    // Array[int]->double
+//                    new HandleType(Object.class, double.class, int.class),
+//
+//                    // Array[long]->int
+//                    new HandleType(Object.class, int.class, long.class),
+//                    // Array[long]->long
+//                    new HandleType(Object.class, long.class, long.class)
+//            );
+//
+//            hts.flatMap(ht -> Stream.of(VarHandleTemplate.class.getMethods()).
+//                    map(m -> generateMethodType(m, ht.receiver, ht.value, ht.intermediates))).
+//                    distinct().
+//                    map(mt -> generateMethod(mt)).
+//                    forEach(s -> {
+//                        System.out.println(s);
+//                        System.out.println();
+//                    });
+//
+//            System.out.println("}");
+//        }
+//
+//        static MethodType generateMethodType(Method m, Class<?> receiver, Class<?> value, Class<?>... intermediates) {
+//            Class<?> returnType = m.getReturnType() == Object.class
+//                                  ? value : m.getReturnType();
+//
+//            List<Class<?>> params = new ArrayList<>();
+//            if (receiver != null)
+//                params.add(receiver);
+//            for (int i = 0; i < intermediates.length; i++) {
+//                params.add(intermediates[i]);
+//            }
+//            for (Parameter p : m.getParameters()) {
+//                params.add(value);
+//            }
+//            return MethodType.methodType(returnType, params);
+//        }
+//
+//        static String generateMethod(MethodType mt) {
+//            Class<?> returnType = mt.returnType();
+//
+//            LinkedHashMap<String, Class<?>> params = new LinkedHashMap<>();
+//            params.put("handle", VarHandle.class);
+//            for (int i = 0; i < mt.parameterCount(); i++) {
+//                params.put("arg" + i, mt.parameterType(i));
+//            }
+//            params.put("ad", VarHandle.AccessDescriptor.class);
+//
+//            // Generate method signature line
+//            String RETURN = className(returnType);
+//            String NAME = "guard";
+//            String SIGNATURE = getSignature(mt);
+//            String PARAMS = params.entrySet().stream().
+//                    map(e -> className(e.getValue()) + " " + e.getKey()).
+//                    collect(joining(", "));
+//            String METHOD = GUARD_METHOD_SIG_TEMPLATE.
+//                    replace("<RETURN>", RETURN).
+//                    replace("<NAME>", NAME).
+//                    replace("<SIGNATURE>", SIGNATURE).
+//                    replace("<PARAMS>", PARAMS);
+//
+//            // Generate method
+//            params.remove("ad");
+//
+//            List<String> LINK_TO_STATIC_ARGS = params.keySet().stream().
+//                    collect(toList());
+//            LINK_TO_STATIC_ARGS.add("getMemberName(handle, ad)");
+//
+//            List<String> LINK_TO_INVOKER_ARGS = params.keySet().stream().
+//                    collect(toList());
+//
+//            RETURN = returnType == void.class
+//                     ? ""
+//                     : returnType == Object.class
+//                       ? "return "
+//                       : "return (" + returnType.getName() + ") ";
+//
+//            String RESULT_ERASED = returnType == void.class
+//                                   ? ""
+//                                   : returnType != Object.class
+//                                     ? "return (" + returnType.getName() + ") "
+//                                     : "Object r = ";
+//
+//            String RETURN_ERASED = returnType != Object.class
+//                                   ? ""
+//                                   : " return symbolic.returnType().cast(r);";
+//
+//            return GUARD_METHOD_TEMPLATE.
+//                    replace("<METHOD>", METHOD).
+//                    replace("<NAME>", NAME).
+//                    replaceAll("<RETURN>", RETURN).
+//                    replace("<RESULT_ERASED>", RESULT_ERASED).
+//                    replace("<RETURN_ERASED>", RETURN_ERASED).
+//                    replaceAll("<LINK_TO_STATIC_ARGS>", LINK_TO_STATIC_ARGS.stream().
+//                            collect(joining(", "))).
+//                    replace("<LINK_TO_INVOKER_ARGS>", LINK_TO_INVOKER_ARGS.stream().
+//                            collect(joining(", ")))
+//                    ;
+//        }
+//
+//        static String className(Class<?> c) {
+//            String n = c.getName();
+//            if (n.startsWith("java.lang.")) {
+//                n = n.replace("java.lang.", "");
+//                if (n.startsWith("invoke.")) {
+//                    n = n.replace("invoke.", "");
+//                }
+//            }
+//            return n.replace('$', '.');
+//        }
+//
+//        static String getSignature(MethodType m) {
+//            StringBuilder sb = new StringBuilder(m.parameterCount() + 1);
+//
+//            for (int i = 0; i < m.parameterCount(); i++) {
+//                Class<?> pt = m.parameterType(i);
+//                sb.append(getCharType(pt));
+//            }
+//
+//            sb.append('_').append(getCharType(m.returnType()));
+//
+//            return sb.toString();
+//        }
+//
+//        static char getCharType(Class<?> pt) {
+//            if (pt == void.class) {
+//                return 'V';
+//            }
+//            else if (!pt.isPrimitive()) {
+//                return 'L';
+//            }
+//            else if (pt == boolean.class) {
+//                return 'Z';
+//            }
+//            else if (pt == int.class) {
+//                return 'I';
+//            }
+//            else if (pt == long.class) {
+//                return 'J';
+//            }
+//            else if (pt == float.class) {
+//                return 'F';
+//            }
+//            else if (pt == double.class) {
+//                return 'D';
+//            }
+//            else {
+//                throw new IllegalStateException(pt.getName());
+//            }
+//        }
+//    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,602 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import java.util.Objects;
+import jdk.internal.vm.annotation.ForceInline;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+#warn
+
+final class VarHandle$Type$s {
+
+    static class FieldInstanceReadOnly extends VarHandle {
+        final long fieldOffset;
+        final Class<?> receiverType;
+#if[Object]
+        final Class<?> fieldType;
+#end[Object]
+
+        FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            this(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadOnly.class);
+        }
+
+        protected FieldInstanceReadOnly(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType},
+                                        Class<? extends FieldInstanceReadOnly> handle) {
+            super(VarForm.createFromStatic(handle), receiverType, {#if[Object]?fieldType:$type$.class});
+            this.fieldOffset = fieldOffset;
+            this.receiverType = receiverType;
+#if[Object]
+            this.fieldType = fieldType;
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getVolatile(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getOpaque(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getAcquire(FieldInstanceReadOnly handle, Object holder) {
+            return UNSAFE.get$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                 handle.fieldOffset);
+        }
+    }
+
+    static class FieldInstanceReadWrite extends FieldInstanceReadOnly {
+
+        FieldInstanceReadWrite(Class<?> receiverType, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            super(receiverType, fieldOffset{#if[Object]?, fieldType}, FieldInstanceReadWrite.class);
+        }
+
+        @ForceInline
+        static void set(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                             handle.fieldOffset,
+                             {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setVolatile(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                     handle.fieldOffset,
+                                     {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setOpaque(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Opaque(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                   handle.fieldOffset,
+                                   {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setRelease(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            UNSAFE.put$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                    handle.fieldOffset,
+                                    {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Volatile(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Release(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndSet$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                          handle.fieldOffset,
+                                          {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                       handle.fieldOffset,
+                                       value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(FieldInstanceReadWrite handle, Object holder, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                       handle.fieldOffset,
+                                       value) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static class FieldStaticReadOnly extends VarHandle {
+        final Object base;
+        final long fieldOffset;
+#if[Object]
+        final Class<?> fieldType;
+#end[Object]
+
+        FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            this(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadOnly.class);
+        }
+
+        protected FieldStaticReadOnly(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType},
+                                      Class<? extends FieldStaticReadOnly> handle) {
+            super(VarForm.createFromStatic(handle), null, {#if[Object]?fieldType:$type$.class});
+            this.base = base;
+            this.fieldOffset = fieldOffset;
+#if[Object]
+            this.fieldType = fieldType;
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getVolatile(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Volatile(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getOpaque(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Opaque(handle.base,
+                                 handle.fieldOffset);
+        }
+
+        @ForceInline
+        static $type$ getAcquire(FieldStaticReadOnly handle) {
+            return UNSAFE.get$Type$Acquire(handle.base,
+                                 handle.fieldOffset);
+        }
+    }
+
+    static class FieldStaticReadWrite extends FieldStaticReadOnly {
+
+        FieldStaticReadWrite(Object base, long fieldOffset{#if[Object]?, Class<?> fieldType}) {
+            super(base, fieldOffset{#if[Object]?, fieldType}, FieldStaticReadWrite.class);
+        }
+
+        @ForceInline
+        static void set(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$(handle.base,
+                             handle.fieldOffset,
+                             {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setVolatile(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Volatile(handle.base,
+                                     handle.fieldOffset,
+                                     {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setOpaque(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Opaque(handle.base,
+                                   handle.fieldOffset,
+                                   {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static void setRelease(FieldStaticReadWrite handle, $type$ value) {
+            UNSAFE.put$Type$Release(handle.base,
+                                    handle.fieldOffset,
+                                    {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndSwap$Type$(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Volatile(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Acquire(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.compareAndExchange$Type$Release(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            return UNSAFE.weakCompareAndSwap$Type$Release(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndSet$Type$(handle.base,
+                                          handle.fieldOffset,
+                                          {#if[Object]?handle.fieldType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(handle.base,
+                                       handle.fieldOffset,
+                                       value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(FieldStaticReadWrite handle, $type$ value) {
+            return UNSAFE.getAndAdd$Type$(handle.base,
+                                       handle.fieldOffset,
+                                       value) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static final class Array extends VarHandle {
+        final int abase;
+        final int ashift;
+#if[Object]
+        final Class<{#if[Object]??:$type$[]}> arrayType;
+        final Class<?> componentType;
+#end[Object]
+
+        Array(int abase, int ashift{#if[Object]?, Class<?> arrayType}) {
+            super(VarForm.createFromStatic(Array.class),
+                  {#if[Object]?arrayType:$type$[].class}, {#if[Object]?arrayType.getComponentType():$type$.class}, int.class);
+            this.abase = abase;
+            this.ashift = ashift;
+#if[Object]
+            this.arrayType = {#if[Object]?arrayType:$type$[].class};
+            this.componentType = arrayType.getComponentType();
+#end[Object]
+        }
+
+        @ForceInline
+        static $type$ get(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return array[index];
+        }
+
+        @ForceInline
+        static void set(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            array[index] = {#if[Object]?handle.componentType.cast(value):value};
+        }
+
+        @ForceInline
+        static $type$ getVolatile(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setVolatile(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getOpaque(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Opaque(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setOpaque(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Opaque(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAcquire(Array handle, Object oarray, int index) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.get$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase);
+        }
+
+        @ForceInline
+        static void setRelease(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            UNSAFE.put$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndSwap$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Volatile(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.compareAndExchange$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$Acquire(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.weakCompareAndSwap$Type$Release(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
+        static $type$ getAndSet(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndSet$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndAdd$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    value);
+        }
+
+        @ForceInline
+        static $type$ addAndGet(Array handle, Object oarray, int index, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            return UNSAFE.getAndAdd$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    value) + value;
+        }
+#end[AtomicAdd]
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.invoke;
+
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.ForceInline;
+
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
+import static java.lang.invoke.MethodHandleStatics.UNSAFE;
+
+#warn
+
+final class VarHandleByteArrayAs$Type$s extends VarHandleByteArrayBase {
+
+    static final int ALIGN = $BoxType$.BYTES - 1;
+
+#if[floatingPoint]
+    @ForceInline
+    static $rawType$ convEndian(boolean big, $type$ v) {
+        $rawType$ rv = $Type$.$type$ToRaw$RawType$Bits(v);
+        return big == BE ? rv : $RawBoxType$.reverseBytes(rv);
+    }
+
+    @ForceInline
+    static $type$ convEndian(boolean big, $rawType$ rv) {
+        rv = big == BE ? rv : $RawBoxType$.reverseBytes(rv);
+        return $Type$.$rawType$BitsTo$Type$(rv);
+    }
+#else[floatingPoint]
+    @ForceInline
+    static $type$ convEndian(boolean big, $type$ n) {
+        return big == BE ? n : $BoxType$.reverseBytes(n);
+    }
+#end[floatingPoint]
+
+
+    private static class ByteArrayViewVarHandle extends VarHandle {
+        final boolean be;
+
+        ByteArrayViewVarHandle(Class<? extends ByteArrayViewVarHandle> implSubType,
+                               Class<?> arrayType, Class<?> component, boolean be) {
+            super(VarForm.createFromStatic(implSubType),
+                  arrayType, component, int.class);
+            this.be = be;
+        }
+    }
+
+    static final class ArrayHandle extends ByteArrayViewVarHandle {
+
+        ArrayHandle(boolean be) {
+            super(ArrayHandle.class, byte[].class, $type$.class, be);
+        }
+
+        @ForceInline
+        static int index(byte[] ba, int index) {
+            return Objects.checkIndex(index, ba.length - ALIGN, null);
+        }
+
+        @ForceInline
+        static long address(byte[] ba, int index) {
+            long address = ((long) index) + Unsafe.ARRAY_BYTE_BASE_OFFSET;
+            if ((address & ALIGN) != 0)
+                throw newIllegalStateExceptionForMisalignedAccess(index);
+            return address;
+        }
+
+        @ForceInline
+        static $type$ get(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+#if[floatingPoint]
+            $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    handle.be);
+            return $Type$.$rawType$BitsTo$Type$(rawValue);
+#else[floatingPoint]
+            return UNSAFE.get$Type$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static void set(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+#if[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    $Type$.$type$ToRaw$RawType$Bits(value),
+                    handle.be);
+#else[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    ba,
+                    ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
+                    value,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static $type$ getVolatile(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Volatile(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setVolatile(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Volatile(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAcquire(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Acquire(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setRelease(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Release(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getOpaque(ArrayHandle handle, Object oba, int index) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Opaque(
+                                      ba,
+                                      address(ba, index(ba, index))));
+        }
+
+        @ForceInline
+        static void setOpaque(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            UNSAFE.put$RawType$Opaque(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value));
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.compareAndSwap$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Volatile(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Acquire(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Release(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$Acquire(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return UNSAFE.weakCompareAndSwap$RawType$Release(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAndSet(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.getAndSet$RawType$(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, value)));
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      ba,
+                                      address(ba, index(ba, index)),
+                                      convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ArrayHandle handle, Object oba, int index, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            return convEndian(handle.be, UNSAFE.getAndAdd$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, value))) + value;
+        }
+#end[AtomicAdd]
+    }
+
+
+    static final class ByteBufferHandle extends ByteArrayViewVarHandle {
+
+        ByteBufferHandle(boolean be) {
+            super(ByteBufferHandle.class, ByteBuffer.class, $type$.class, be);
+        }
+
+        @ForceInline
+        static int index(ByteBuffer bb, int index) {
+            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+        }
+
+        @ForceInline
+        static int indexRO(ByteBuffer bb, int index) {
+            if (UNSAFE.getBoolean(bb, BYTE_BUFFER_IS_READ_ONLY))
+                throw new ReadOnlyBufferException();
+            return Objects.checkIndex(index, UNSAFE.getInt(bb, BUFFER_LIMIT) - ALIGN, null);
+        }
+
+        @ForceInline
+        static long address(ByteBuffer bb, int index) {
+            long address = ((long) index) + UNSAFE.getLong(bb, BUFFER_ADDRESS);
+            if ((address & ALIGN) != 0)
+                throw newIllegalStateExceptionForMisalignedAccess(index);
+            return address;
+        }
+
+        @ForceInline
+        static $type$ get(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+#if[floatingPoint]
+            $rawType$ rawValue = UNSAFE.get$RawType$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    handle.be);
+            return $Type$.$rawType$BitsTo$Type$(rawValue);
+#else[floatingPoint]
+            return UNSAFE.get$Type$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) index(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static void set(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+#if[floatingPoint]
+            UNSAFE.put$RawType$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    $Type$.$type$ToRaw$RawType$Bits(value),
+                    handle.be);
+#else[floatingPoint]
+            UNSAFE.put$Type$Unaligned(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    ((long) indexRO(bb, index)) + UNSAFE.getLong(bb, BUFFER_ADDRESS),
+                    value,
+                    handle.be);
+#end[floatingPoint]
+        }
+
+        @ForceInline
+        static $type$ getVolatile(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Volatile(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setVolatile(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Volatile(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAcquire(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Acquire(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setRelease(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Release(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getOpaque(ByteBufferHandle handle, Object obb, int index) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.get$RawType$Opaque(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, index(bb, index))));
+        }
+
+        @ForceInline
+        static void setOpaque(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            UNSAFE.put$RawType$Opaque(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, value));
+        }
+#if[CAS]
+
+        @ForceInline
+        static boolean compareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.compareAndSwap$RawType$(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Volatile(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Acquire(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ compareAndExchangeRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.compareAndExchange$RawType$Release(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, expected), convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSet(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$Acquire(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static boolean weakCompareAndSetRelease(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return UNSAFE.weakCompareAndSwap$RawType$Release(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
+        static $type$ getAndSet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndSet$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value)));
+        }
+#end[CAS]
+#if[AtomicAdd]
+
+        @ForceInline
+        static $type$ getAndAdd(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value)));
+        }
+
+        @ForceInline
+        static $type$ addAndGet(ByteBufferHandle handle, Object obb, int index, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            return convEndian(handle.be,
+                              UNSAFE.getAndAdd$RawType$(
+                                      UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                                      address(bb, indexRO(bb, index)),
+                                      convEndian(handle.be, value))) + value;
+        }
+#end[AtomicAdd]
+    }
+}
--- a/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/package-info.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -32,7 +32,8 @@
  * certain types in this package have special relations to dynamic
  * language support in the virtual machine:
  * <ul>
- * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
+ * <li>The classes {@link java.lang.invoke.MethodHandle MethodHandle}
+ * {@link java.lang.invoke.VarHandle VarHandle} contain
  * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
  * which can be linked regardless of their type descriptor.
  * Normally, method linkage requires exact matching of type descriptors.
--- a/jdk/src/java.base/share/classes/java/nio/Buffer.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Buffer.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -25,8 +25,9 @@
 
 package java.nio;
 
+import jdk.internal.HotSpotIntrinsicCandidate;
+
 import java.util.Spliterator;
-import jdk.internal.HotSpotIntrinsicCandidate;
 
 /**
  * A container for data of a specific primitive type.
@@ -188,7 +189,15 @@
     private int limit;
     private int capacity;
 
-    // Used only by direct buffers
+    // Used by heap byte buffers or direct buffers with Unsafe access
+    // For heap byte buffers this field will be the address relative to the
+    // array base address and offset into that array. The address might
+    // not align on a word boundary for slices, nor align at a long word
+    // (8 byte) boundary for byte[] allocations on 32-bit systems.
+    // For direct buffers it is the start address of the memory region. The
+    // address might not align on a word boundary for slices, nor when created
+    // using JNI, see NewDirectByteBuffer(void*, long).
+    // Should ideally be declared final
     // NOTE: hoisted here for speed in JNI GetDirectBufferAddress
     long address;
 
--- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Tue Apr 05 20:02:21 2016 -0700
@@ -140,6 +140,7 @@
         att = null;
 #else[rw]
         super(cap);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -180,6 +181,7 @@
         att = null;
 #else[rw]
         super(cap, addr, fd, unmapper);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -200,6 +202,7 @@
         att = db;
 #else[rw]
         super(db, mark, pos, lim, cap, off);
+        this.isReadOnly = true;
 #end[rw]
     }
 
@@ -213,6 +216,15 @@
         return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, off);
     }
 
+#if[byte]
+    public $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Direct$Type$Buffer$RW$$BO$(this, -1, 0, rem, rem, pos);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Direct$Type$Buffer$RW$$BO$(this,
                                               this.markValue(),
--- a/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -74,6 +74,9 @@
         super(cap, lim);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     Heap$Type$Buffer$RW$($type$[] buf, int off, int len) { // package-private
@@ -87,6 +90,9 @@
         super(buf, off, len);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset;
+#end[byte]
     }
 
     protected Heap$Type$Buffer$RW$($type$[] buf,
@@ -103,6 +109,9 @@
         super(buf, mark, pos, lim, cap, off);
         this.isReadOnly = true;
 #end[rw]
+#if[byte]
+        this.address = arrayBaseOffset + off;
+#end[byte]
     }
 
     public $Type$Buffer slice() {
@@ -114,6 +123,20 @@
                                         this.position() + offset);
     }
 
+#if[byte]
+    $Type$Buffer slice(int pos, int lim) {
+        assert (pos >= 0);
+        assert (pos <= lim);
+        int rem = lim - pos;
+        return new Heap$Type$Buffer$RW$(hb,
+                                        -1,
+                                        0,
+                                        rem,
+                                        rem,
+                                        pos + offset);
+    }
+#end[byte]
+
     public $Type$Buffer duplicate() {
         return new Heap$Type$Buffer$RW$(hb,
                                         this.markValue(),
@@ -144,7 +167,7 @@
 
 #if[byte]
     private long byteOffset(long i) {
-        return arrayBaseOffset + i + offset;
+        return address + i;
     }
 #end[byte]
 
--- a/jdk/src/java.base/share/classes/java/nio/StringCharBuffer.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/StringCharBuffer.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -39,6 +39,7 @@
         if ((start < 0) || (start > n) || (end < start) || (end > n))
             throw new IndexOutOfBoundsException();
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer slice() {
@@ -58,6 +59,7 @@
                              int offset) {
         super(mark, pos, limit, cap, null, offset);
         str = s;
+        this.isReadOnly = true;
     }
 
     public CharBuffer duplicate() {
--- a/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Apr 05 20:02:21 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -269,7 +269,7 @@
     //
     final $type$[] hb;                  // Non-null only for heap buffers
     final int offset;
-    boolean isReadOnly;                 // Valid only for heap buffers
+    boolean isReadOnly;
 
     // Creates a new buffer with the given mark, position, limit, capacity,
     // backing array, and array offset
@@ -530,6 +530,10 @@
      * it will be read-only if, and only if, this buffer is read-only.  </p>
      *
      * @return  The new $type$ buffer
+#if[byte]
+     *
+     * @see #alignedSlice(int)
+#end[byte]
      */
     public abstract $Type$Buffer slice();
 
@@ -1611,6 +1615,143 @@
         return this;
     }
 
+    /**
+     * Returns the memory address, pointing to the byte at the given index,
+     * modulus the given unit size.
+     *
+     * <p> A return value greater than zero indicates the address of the byte at
+     * the index is misaligned for the unit size, and the value's quantity
+     * indicates how much the index should be rounded up or down to locate a
+     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
+     * that the address of the byte at the index is aligned for the unit size.
+     *
+     * @apiNote
+     * This method may be utilized to determine if unit size bytes from an
+     * index can be accessed atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  index
+     *         The index to query for alignment offset, must be non-negative, no
+     *         upper bounds check is performed
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The indexed byte's memory address modulus the unit size
+     *
+     * @throws IllegalArgumentException
+     *         If the index is negative or the unit size is not a power of
+     *         {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable alignment offset
+     *         values for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignedSlice(int)
+     * @since 9
+     */
+    public final int alignmentOffset(int index, int unitSize) {
+        if (index < 0)
+            throw new IllegalArgumentException("Index less than zero: " + index);
+        if (unitSize < 1 || (unitSize & (unitSize - 1)) != 0)
+            throw new IllegalArgumentException("Unit size not a power of two: " + unitSize);
+        if (unitSize > 8 && !isDirect())
+            throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
+
+        return (int) ((address + index) % unitSize);
+    }
+
+    /**
+     * Creates a new byte buffer whose content is a shared and aligned
+     * subsequence of this buffer's content.
+     *
+     * <p> The content of the new buffer will start at this buffer's current
+     * position rounded up to the index of the nearest aligned byte for the
+     * given unit size, and end at this buffer's limit rounded down to the index
+     * of the nearest aligned byte for the given unit size.
+     * If rounding results in out-of-bound values then the new buffer's capacity
+     * and limit will be zero.  If rounding is within bounds the following
+     * expressions will be true for a new buffer {@code nb} and unit size
+     * {@code unitSize}:
+     * <pre>{@code
+     * nb.alignmentOffset(0, unitSize) == 0
+     * nb.alignmentOffset(nb.limit(), unitSize) == 0
+     * }</pre>
+     *
+     * <p> Changes to this buffer's content will be visible in the new
+     * buffer, and vice versa; the two buffers' position, limit, and mark
+     * values will be independent.
+     *
+     * <p> The new buffer's position will be zero, its capacity and its limit
+     * will be the number of bytes remaining in this buffer or fewer subject to
+     * alignment, its mark will be undefined, and its byte order will be
+     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}.
+     *
+     * The new buffer will be direct if, and only if, this buffer is direct, and
+     * it will be read-only if, and only if, this buffer is read-only.  </p>
+     *
+     * @apiNote
+     * This method may be utilized to create a new buffer where unit size bytes
+     * from index, that is a multiple of the unit size, may be accessed
+     * atomically, if supported by the native platform.
+     *
+     * @implNote
+     * This implementation throws {@code UnsupportedOperationException} for
+     * non-direct buffers when the given unit size is greater then {@code 8}.
+     *
+     * @param  unitSize
+     *         The unit size in bytes, must be a power of {@code 2}
+     *
+     * @return  The new byte buffer
+     *
+     * @throws IllegalArgumentException
+     *         If the unit size not a power of {@code 2}
+     *
+     * @throws UnsupportedOperationException
+     *         If the native platform does not guarantee stable aligned slices
+     *         for the given unit size when managing the memory regions
+     *         of buffers of the same kind as this buffer (direct or
+     *         non-direct).  For example, if garbage collection would result
+     *         in the moving of a memory region covered by a non-direct buffer
+     *         from one location to another and both locations have different
+     *         alignment characteristics.
+     *
+     * @see #alignmentOffset(int, int)
+     * @see #slice()
+     * @since 9
+     */
+    public final ByteBuffer alignedSlice(int unitSize) {
+        int pos = position();
+        int lim = limit();
+
+        int pos_mod = alignmentOffset(pos, unitSize);
+        int lim_mod = alignmentOffset(lim, unitSize);
+
+        // Round up the position to align with unit size
+        int aligned_pos = (pos_mod > 0)
+            ? pos + (unitSize - pos_mod)
+            : pos;
+
+        // Round down the limit to align with unit size
+        int aligned_lim = lim - lim_mod;
+
+        if (aligned_pos > lim || aligned_lim < pos) {
+            aligned_pos = aligned_lim = pos;
+        }
+
+        return slice(aligned_pos, aligned_lim);
+    }
+
+    abstract ByteBuffer slice(int pos, int lim);
+
     // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
     //
     abstract byte _get(int i);                          // package-private
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Tue Apr 05 20:02:21 2016 -0700
@@ -480,7 +480,7 @@
     }
 
     static void lazySetNext(Completion c, Completion next) {
-        U.putOrderedObject(c, NEXT, next);
+        U.putObjectRelease(c, NEXT, next);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Tue Apr 05 20:02:21 2016 -0700
@@ -309,7 +309,7 @@
         }
 
         void lazySetNext(Node<E> val) {
-            U.putOrderedObject(this, NEXT, val);
+            U.putObjectRelease(this, NEXT, val);
         }
 
         boolean casNext(Node<E> cmp, Node<E> val) {
@@ -317,7 +317,7 @@
         }
 
         void lazySetPrev(Node<E> val) {
-            U.putOrderedObject(this, PREV, val);
+            U.putObjectRelease(this, PREV, val);
         }
 
         boolean casPrev(Node<E> cmp, Node<E> val) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Tue Apr 05 20:02:21 2016 -0700
@@ -198,7 +198,7 @@
     }
 
     static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putOrderedObject(node, NEXT, val);
+        U.putObjectRelease(node, NEXT, val);
     }
 
     static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Tue Apr 05 20:02:21 2016 -0700
@@ -239,7 +239,7 @@
      * not to be as readily inlined by dynamic compilers when they are
      * hidden behind other methods that would more nicely name and
      * encapsulate the intended effects). This includes the use of
-     * putOrderedX to clear fields of the per-thread Nodes between
+     * putXRelease to clear fields of the per-thread Nodes between
      * uses. Note that field Node.item is not declared as volatile
      * even though it is read by releasing threads, because they only
      * do so after CAS operations that must precede access, and all
@@ -376,7 +376,7 @@
                     for (int h = p.hash, spins = SPINS;;) {
                         Object v = p.match;
                         if (v != null) {
-                            U.putOrderedObject(p, MATCH, null);
+                            U.putObjectRelease(p, MATCH, null);
                             p.item = null;             // clear for next use
                             p.hash = h;
                             return v;
@@ -507,7 +507,7 @@
                 break;
             }
         }
-        U.putOrderedObject(p, MATCH, null);
+        U.putObjectRelease(p, MATCH, null);
         p.item = null;
         p.hash = h;
         return v;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Tue Apr 05 20:02:21 2016 -0700
@@ -289,7 +289,7 @@
      * on to try or create other queues -- they block only when
      * creating and registering new queues. Because it is used only as
      * a spinlock, unlocking requires only a "releasing" store (using
-     * putOrderedInt).  The qlock is also used during termination
+     * putIntRelease).  The qlock is also used during termination
      * detection, in which case it is forced to a negative
      * non-lockable value.
      *
@@ -1071,7 +1071,7 @@
                         popped = true;
                         top = s;
                     }
-                    U.putOrderedInt(this, QLOCK, 0);
+                    U.putIntRelease(this, QLOCK, 0);
                 }
             }
             return popped;
@@ -1261,7 +1261,7 @@
                                         popped = true;
                                         top = s - 1;
                                     }
-                                    U.putOrderedInt(this, QLOCK, 0);
+                                    U.putIntRelease(this, QLOCK, 0);
                                     if (popped)
                                         return t;
                                 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Tue Apr 05 20:02:21 2016 -0700
@@ -92,7 +92,7 @@
     ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
                          AccessControlContext acc) {
         super(threadGroup, null, "aForkJoinWorkerThread");
-        U.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, acc);
+        U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
         eraseThreadLocals(); // clear before registering
         this.pool = pool;
         this.workQueue = pool.registerWorker(this);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Tue Apr 05 20:02:21 2016 -0700
@@ -174,7 +174,7 @@
                     if (t != null)
                         t.interrupt();
                 } finally { // final state
-                    U.putOrderedInt(this, STATE, INTERRUPTED);
+                    U.putIntRelease(this, STATE, INTERRUPTED);
                 }
             }
         } finally {
@@ -230,7 +230,7 @@
     protected void set(V v) {
         if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
             outcome = v;
-            U.putOrderedInt(this, STATE, NORMAL); // final state
+            U.putIntRelease(this, STATE, NORMAL); // final state
             finishCompletion();
         }
     }
@@ -248,7 +248,7 @@
     protected void setException(Throwable t) {
         if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
             outcome = t;
-            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
+            U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
             finishCompletion();
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1496,7 +1496,7 @@
                     else if (((c & CONSUME) != 0 ||
                               U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
                              U.compareAndSwapObject(a, i, x, null)) {
-                        U.putOrderedInt(this, HEAD, ++h);
+                        U.putIntRelease(this, HEAD, ++h);
                         U.getAndAddLong(this, DEMAND, -1L);
                         if ((w = waiter) != null)
                             signalWaiter(w);
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Tue Apr 05 20:02:21 2016 -0700
@@ -136,7 +136,7 @@
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putOrderedInt(this, VALUE, (newValue ? 1 : 0));
+        U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Tue Apr 05 20:02:21 2016 -0700
@@ -108,7 +108,7 @@
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putOrderedInt(this, VALUE, newValue);
+        U.putIntRelease(this, VALUE, newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Tue Apr 05 20:02:21 2016 -0700
@@ -136,7 +136,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putOrderedInt(array, checkedByteOffset(i), newValue);
+        U.putIntRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Tue Apr 05 20:02:21 2016 -0700
@@ -475,7 +475,7 @@
 
         public final void lazySet(T obj, int newValue) {
             accessCheck(obj);
-            U.putOrderedInt(obj, offset, newValue);
+            U.putIntRelease(obj, offset, newValue);
         }
 
         public final int get(T obj) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Tue Apr 05 20:02:21 2016 -0700
@@ -124,7 +124,7 @@
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putOrderedLong(this, VALUE, newValue);
+        U.putLongRelease(this, VALUE, newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Tue Apr 05 20:02:21 2016 -0700
@@ -135,7 +135,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putOrderedLong(array, checkedByteOffset(i), newValue);
+        U.putLongRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Tue Apr 05 20:02:21 2016 -0700
@@ -457,7 +457,7 @@
 
         public final void lazySet(T obj, long newValue) {
             accessCheck(obj);
-            U.putOrderedLong(obj, offset, newValue);
+            U.putLongRelease(obj, offset, newValue);
         }
 
         public final long get(T obj) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Tue Apr 05 20:02:21 2016 -0700
@@ -103,7 +103,7 @@
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putOrderedObject(this, VALUE, newValue);
+        U.putObjectRelease(this, VALUE, newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Tue Apr 05 20:02:21 2016 -0700
@@ -147,7 +147,7 @@
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putOrderedObject(array, checkedByteOffset(i), newValue);
+        U.putObjectRelease(array, checkedByteOffset(i), newValue);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Tue Apr 05 20:02:21 2016 -0700
@@ -426,7 +426,7 @@
         public final void lazySet(T obj, V newValue) {
             accessCheck(obj);
             valueCheck(newValue);
-            U.putOrderedObject(obj, offset, newValue);
+            U.putObjectRelease(obj, offset, newValue);
         }
 
         @SuppressWarnings("unchecked")
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java	Tue Apr 05 20:02:21 2016 -0700
@@ -86,8 +86,8 @@
 
     private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
         super(group, target, name, 0L, false);
-        UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
-        UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);
+        UNSAFE.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
+        UNSAFE.putObjectRelease(this, CONTEXTCLASSLOADER, tccl);
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1457,25 +1457,7 @@
     @HotSpotIntrinsicCandidate
     public native void    putDoubleVolatile(Object o, long offset, double x);
 
-    /**
-     * Version of {@link #putObjectVolatile(Object, long, Object)}
-     * that does not guarantee immediate visibility of the store to
-     * other threads. This method is generally only useful if the
-     * underlying field is a Java volatile (or if an array cell, one
-     * that is otherwise only accessed using volatile accesses).
-     *
-     * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
-     */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedObject(Object o, long offset, Object x);
 
-    /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedInt(Object o, long offset, int x);
-
-    /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
-    @HotSpotIntrinsicCandidate
-    public native void    putOrderedLong(Object o, long offset, long x);
 
     /** Acquire version of {@link #getObjectVolatile(Object, long)} */
     @HotSpotIntrinsicCandidate
@@ -1531,6 +1513,16 @@
         return getDoubleVolatile(o, offset);
     }
 
+    /*
+      * Versions of {@link #putObjectVolatile(Object, long, Object)}
+      * that do not guarantee immediate visibility of the store to
+      * other threads. This method is generally only useful if the
+      * underlying field is a Java volatile (or if an array cell, one
+      * that is otherwise only accessed using volatile accesses).
+      *
+      * Corresponds to C11 atomic_store_explicit(..., memory_order_release).
+      */
+
     /** Release version of {@link #putObjectVolatile(Object, long, Object)} */
     @HotSpotIntrinsicCandidate
     public final void putObjectRelease(Object o, long offset, Object x) {
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Tue Apr 05 21:18:01 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java	Tue Apr 05 20:02:21 2016 -0700
@@ -1068,19 +1068,19 @@
      */
     @ForceInline
     public void putOrderedObject(Object o, long offset, Object x) {
-        theInternalUnsafe.putOrderedObject(o, offset, x);
+        theInternalUnsafe.putObjectRelease(o, offset, x);
     }
 
     /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)}  */
     @ForceInline
     public void putOrderedInt(Object o, long offset, int x) {
-        theInternalUnsafe.putOrderedInt(o, offset, x);
+        theInternalUnsafe.putIntRelease(o, offset, x);
     }
 
     /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
     @ForceInline
     public void putOrderedLong(Object o, long offset, long x) {
-        theInternalUnsafe.putOrderedLong(o, offset, x);
+        theInternalUnsafe.putLongRelease(o, offset, x);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseByteArrayTest.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+
+import java.lang.invoke.VarHandle;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Function;
+
+public abstract class VarHandleBaseByteArrayTest extends VarHandleBaseTest {
+
+    enum MemoryMode {
+        ALIGNED(0, false), UNALIGNED(0, true),
+        BIG_ENDIAN(1, false), LITTLE_ENDIAN(1, true),
+        READ_WRITE(2, false), READ_ONLY(2, true),;
+
+        final int bit;
+        final int value;
+
+        MemoryMode(int bit, boolean value) {
+            this.bit = bit;
+            this.value = value ? 1 << bit : 0;
+        }
+
+        boolean isSet(int bitSet) {
+            return (bitSet & (1 << bit)) == value;
+        }
+
+        static int bitSet(MemoryMode... modes) {
+            if (modes == null) return 0;
+
+            int set = 0;
+            for (MemoryMode m : modes) {
+                set = (set & ~(1 << m.bit)) | m.value;
+            }
+            return set;
+        }
+
+        static EnumSet<MemoryMode> enumSet(int bitSet) {
+            EnumSet<MemoryMode> es = EnumSet.noneOf(MemoryMode.class);
+            for (MemoryMode m : values()) {
+                if (m.isSet(bitSet)) {
+                    es.add(m);
+                }
+            }
+            return es;
+        }
+    }
+
+    static class Source<T> {
+        final T s;
+        final int memoryModes;
+
+        public Source(T s, MemoryMode... modes) {
+            this.s = s;
+            memoryModes = MemoryMode.bitSet(modes);
+        }
+
+        @Override
+        public String toString() {
+            return s.getClass().getCanonicalName() + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static abstract class ByteArrayViewSource<T> extends Source<T> {
+        public ByteArrayViewSource(T t, MemoryMode... modes) {
+            super(t, modes);
+        }
+
+        abstract void fill(byte value);
+
+        abstract void fill(byte[] values);
+    }
+
+    static class ByteArraySource extends ByteArrayViewSource<byte[]> {
+        public ByteArraySource(byte[] bytes, MemoryMode... modes) {
+            super(bytes, modes);
+        }
+
+        void fill(byte value) {
+            Arrays.fill(s, value);
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.length; i++) {
+                s[i] = values[i % values.length];
+            }
+        }
+    }
+
+    static class ByteBufferSource extends ByteArrayViewSource<ByteBuffer> {
+        public ByteBufferSource(ByteBuffer buffer, MemoryMode... modes) {
+            super(buffer, modes);
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < s.limit(); i++) {
+                s.put(i, values[i % values.length]);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return s + " " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class ByteBufferReadOnlySource extends ByteBufferSource {
+        final ByteBuffer rwSource;
+
+        public ByteBufferReadOnlySource(ByteBuffer roBuffer, ByteBuffer rwSource, MemoryMode... modes) {
+            super(roBuffer, modes);
+            this.rwSource = rwSource;
+        }
+
+        void fill(byte value) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, value);
+            }
+        }
+
+        void fill(byte[] values) {
+            for (int i = 0; i < rwSource.limit(); i++) {
+                rwSource.put(i, values[i % values.length]);
+            }
+        }
+    }
+
+    static class VarHandleSource extends Source<VarHandle> {
+        VarHandleSource(VarHandle vh, MemoryMode... modes) {
+            super(vh, modes);
+        }
+
+        boolean matches(ByteArrayViewSource<?> bav) {
+            return s.coordinateTypes().get(0).isAssignableFrom(bav.s.getClass());
+        }
+
+        @Override
+        public String toString() {
+            return " VarHandle " + MemoryMode.enumSet(memoryModes);
+        }
+    }
+
+    static class VarHandleSourceAccessTestCase extends AccessTestCase<VarHandleSource> {
+        final ByteArrayViewSource<?> bs;
+        final VarHandleSource vhs;
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata) {
+            this(desc, bs, vhs, ata, true);
+        }
+
+        VarHandleSourceAccessTestCase(String desc, ByteArrayViewSource<?> bs, VarHandleSource vhs, AccessTestAction<VarHandleSource> ata, boolean loop) {
+            super(vhs + " -> " + bs + " " + desc, ata, loop);
+            this.bs = bs;
+            this.vhs = vhs;
+        }
+
+        @Override
+        VarHandleSource get() {
+            return vhs;
+        }
+    }
+
+
+    static double rotateLeft(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateLeft(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static double rotateRight(double i, int distance) {
+        return Double.longBitsToDouble(
+                Long.rotateRight(Double.doubleToRawLongBits(i), distance));
+    }
+
+    static float rotateLeft(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateLeft(Float.floatToRawIntBits(i), distance));
+    }
+
+    static float rotateRight(float i, int distance) {
+        return Float.intBitsToFloat(
+                Integer.rotateRight(Float.floatToRawIntBits(i), distance));
+    }
+
+    static long rotateLeft(long i, int distance) {
+        return Long.rotateLeft(i, distance);
+    }
+
+    static long rotateRight(long i, int distance) {
+        return Long.rotateRight(i, distance);
+    }
+
+    static int rotateLeft(int i, int distance) {
+        return Integer.rotateLeft(i, distance);
+    }
+
+    static int rotateRight(int i, int distance) {
+        return Integer.rotateRight(i, distance);
+    }
+
+    static short rotateLeft(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (short) v;
+    }
+
+    static short rotateRight(short i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (short) v;
+    }
+
+    static char rotateLeft(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateLeft(v, distance);
+        return (char) v;
+    }
+
+    static char rotateRight(char i, int distance) {
+        int v = (i << 16) | i;
+        v = Integer.rotateRight(v, distance);
+        return (char) v;
+    }
+
+    static final int LENGTH_BYTES = 32;
+
+    byte[] array;
+
+    List<ByteArrayViewSource<?>> bavss;
+
+    List<VarHandleSource> vhss;
+
+    public void setupByteSources() {
+        array = new byte[LENGTH_BYTES];
+
+        // Native endianess
+        MemoryMode ne = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN
+                        ? MemoryMode.BIG_ENDIAN : MemoryMode.LITTLE_ENDIAN;
+
+        bavss = new ArrayList<>();
+
+        // byte[] source
+        ByteArraySource a =
+                new ByteArraySource(array,
+                                    ne, MemoryMode.READ_WRITE);
+        bavss.add(a);
+
+
+        // Combinations of ByteBuffer sources
+        ByteBufferSource hbb =
+                new ByteBufferSource(ByteBuffer.wrap(array),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb);
+        ByteBufferReadOnlySource hbb_ro =
+                new ByteBufferReadOnlySource(hbb.s.asReadOnlyBuffer(), hbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_ro);
+
+        ByteBufferSource hbb_offset_aligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4, array.length / 2).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_aligned);
+        ByteBufferReadOnlySource hbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_aligned.s.asReadOnlyBuffer(), hbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_aligned_ro);
+
+        ByteBufferSource hbb_offset_unaligned =
+                new ByteBufferSource(ByteBuffer.wrap(array, array.length / 4 - 1, array.length / 2).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(hbb_offset_unaligned);
+        ByteBufferReadOnlySource hbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(hbb_offset_unaligned.s.asReadOnlyBuffer(), hbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(hbb_offset_unaligned_ro);
+
+
+        ByteBufferSource dbb =
+                new ByteBufferSource(ByteBuffer.allocateDirect(array.length),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb);
+        ByteBufferReadOnlySource dbb_ro =
+                new ByteBufferReadOnlySource(dbb.s.asReadOnlyBuffer(), dbb.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_ro);
+
+        ByteBufferSource dbb_offset_aligned =
+                new ByteBufferSource(dbb.s.slice().position(array.length / 4).limit(array.length / 4 + array.length / 2).slice(),
+                                     MemoryMode.ALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_aligned);
+        ByteBufferReadOnlySource dbb_offset_aligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_aligned.s.asReadOnlyBuffer(), dbb_offset_aligned.s,
+                                             MemoryMode.ALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_aligned_ro);
+
+        ByteBufferSource dbb_offset_unaligned =
+                new ByteBufferSource(dbb.s.slice().position(array.length / 4 - 1).limit(array.length / 4 - 1 + array.length / 2).slice(),
+                                     MemoryMode.UNALIGNED, ne, MemoryMode.READ_WRITE);
+        bavss.add(dbb_offset_unaligned);
+        ByteBufferReadOnlySource dbb_offset_unaligned_ro =
+                new ByteBufferReadOnlySource(dbb_offset_unaligned.s.asReadOnlyBuffer(), dbb_offset_unaligned.s,
+                                             MemoryMode.UNALIGNED, ne, MemoryMode.READ_ONLY);
+        bavss.add(dbb_offset_unaligned_ro);
+    }
+
+    @BeforeClass
+    public void setup() {
+        setupByteSources();
+        setupVarHandleSources();
+    }
+
+    abstract void setupVarHandleSources();
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        return vhss.stream().map(cvh -> new Object[]{cvh}).toArray(Object[][]::new);
+    }
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<java.lang.Class<?>> aepts = Arrays.asList(byte[].class, int.class);
+        List<java.lang.Class<?>> bbpts = Arrays.asList(ByteBuffer.class, int.class);
+
+        Function<VarHandle, List<Class<?>>> vhToPts = vh ->
+                vh.coordinateTypes().get(0) == byte[].class ? aepts : bbpts;
+
+        return vhss.stream().map(vh -> new Object[]{vh.s, vhToPts.apply(vh.s)}).toArray(Object[][]::new);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.VarHandle;
+import java.lang.invoke.WrongMethodTypeException;
+import java.lang.reflect.Method;
+import java.nio.ReadOnlyBufferException;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static org.testng.Assert.*;
+
+abstract class VarHandleBaseTest {
+    static final int ITERS = Integer.getInteger("iters", 1);
+
+    interface ThrowingRunnable {
+        void run() throws Throwable;
+    }
+
+    static void checkUOE(ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, null, r);
+    }
+
+    static void checkUOE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(UnsupportedOperationException.class, message, r);
+    }
+
+    static void checkROBE(ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, null, r);
+    }
+
+    static void checkROBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ReadOnlyBufferException.class, message, r);
+    }
+
+    static void checkIOOBE(ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, null, r);
+    }
+
+    static void checkIOOBE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IndexOutOfBoundsException.class, message, r);
+    }
+
+    static void checkISE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, null, r);
+    }
+
+    static void checkISE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalStateException.class, message, r);
+    }
+
+    static void checkIAE(ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, null, r);
+    }
+
+    static void checkIAE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(IllegalAccessException.class, message, r);
+    }
+
+    static void checkWMTE(ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, null, r);
+    }
+
+    static void checkWMTE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(WrongMethodTypeException.class, message, r);
+    }
+
+    static void checkCCE(ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, null, r);
+    }
+
+    static void checkCCE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(ClassCastException.class, message, r);
+    }
+
+    static void checkNPE(ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, null, r);
+    }
+
+    static void checkNPE(Object message, ThrowingRunnable r) {
+        checkWithThrowable(NullPointerException.class, message, r);
+    }
+
+    static void checkWithThrowable(Class<? extends Throwable> re,
+                                   Object message,
+                                   ThrowingRunnable r) {
+        Throwable _e = null;
+        try {
+            r.run();
+        }
+        catch (Throwable e) {
+            _e = e;
+        }
+        message = message == null ? "" : message + ". ";
+        assertNotNull(_e, String.format("%sNo throwable thrown. Expected %s", message, re));
+        assertTrue(re.isInstance(_e), String.format("%sIncorrect throwable thrown, %s. Expected %s", message, _e, re));
+    }
+
+
+    enum TestAccessType {
+        get,
+        set,
+        compareAndSet,
+        compareAndExchange,
+        getAndSet,
+        getAndAdd;
+    }
+
+    enum TestAccessMode {
+        get(TestAccessType.get),
+        set(TestAccessType.set),
+        getVolatile(TestAccessType.get),
+        setVolatile(TestAccessType.set),
+        getAcquire(TestAccessType.get),
+        setRelease(TestAccessType.set),
+        getOpaque(TestAccessType.get),
+        setOpaque(TestAccessType.set),
+        compareAndSet(TestAccessType.compareAndSet),
+        compareAndExchangeVolatile(TestAccessType.compareAndExchange),
+        compareAndExchangeAcquire(TestAccessType.compareAndExchange),
+        compareAndExchangeRelease(TestAccessType.compareAndExchange),
+        weakCompareAndSet(TestAccessType.compareAndSet),
+        weakCompareAndSetAcquire(TestAccessType.compareAndSet),
+        weakCompareAndSetRelease(TestAccessType.compareAndSet),
+        getAndSet(TestAccessType.getAndSet),
+        getAndAdd(TestAccessType.getAndAdd),
+        addAndGet(TestAccessType.getAndAdd),;
+
+        final TestAccessType at;
+        final boolean isPolyMorphicInReturnType;
+        final Class<?> returnType;
+
+        TestAccessMode(TestAccessType at) {
+            this.at = at;
+
+            try {
+                Method m = VarHandle.class.getMethod(name(), Object[].class);
+                this.returnType = m.getReturnType();
+                isPolyMorphicInReturnType = returnType != Object.class;
+            }
+            catch (Exception e) {
+                throw new Error(e);
+            }
+        }
+
+        boolean isOfType(TestAccessType at) {
+            return this.at == at;
+        }
+
+        VarHandle.AccessMode toAccessMode() {
+            return VarHandle.AccessMode.valueOf(name());
+        }
+    }
+
+    static List<TestAccessMode> testAccessModes() {
+        return Stream.of(TestAccessMode.values()).collect(toList());
+    }
+
+    static List<TestAccessMode> testAccessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        for (TestAccessType at : ats) {
+            s = s.filter(e -> e.isOfType(at));
+        }
+        return s.collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModes() {
+        return Stream.of(VarHandle.AccessMode.values()).collect(toList());
+    }
+
+    static List<VarHandle.AccessMode> accessModesOfType(TestAccessType... ats) {
+        Stream<TestAccessMode> s = Stream.of(TestAccessMode.values());
+        for (TestAccessType at : ats) {
+            s = s.filter(e -> e.isOfType(at));
+        }
+        return s.map(TestAccessMode::toAccessMode).collect(toList());
+    }
+
+    static MethodHandle toMethodHandle(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        return vh.toMethodHandle(tam.toAccessMode());
+    }
+
+    static MethodHandle findVirtual(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh;
+        try {
+            mh = MethodHandles.publicLookup().
+                    findVirtual(VarHandle.class,
+                                tam.name(),
+                                mt);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleInvokerWithSymbolicTypeDescriptor(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        MethodHandle mh = MethodHandles.varHandleInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    static MethodHandle varHandleExactInvokerWithAccessModeType(VarHandle vh, TestAccessMode tam, MethodType mt) {
+        mt = vh.accessModeType(tam.toAccessMode());
+        MethodHandle mh = MethodHandles.varHandleExactInvoker(
+                tam.toAccessMode(),
+                mt);
+
+        return bind(vh, tam, mh, mt);
+    }
+
+    private static MethodHandle bind(VarHandle vh, TestAccessMode testAccessMode, MethodHandle mh, MethodType emt) {
+        assertEquals(mh.type(), emt.insertParameterTypes(0, VarHandle.class),
+                     "MethodHandle type differs from access mode type");
+
+        MethodHandleInfo info = MethodHandles.lookup().revealDirect(mh);
+        assertEquals(info.getMethodType(), emt,
+                     "MethodHandleInfo method type differs from access mode type");
+
+        return mh.bindTo(vh);
+    }
+
+    private interface TriFunction<T, U, V, R> {
+        R apply(T t, U u, V v);
+    }
+
+    enum VarHandleToMethodHandle {
+        VAR_HANDLE_TO_METHOD_HANDLE(
+                "VarHandle.toMethodHandle",
+                VarHandleBaseTest::toMethodHandle),
+        METHOD_HANDLES_LOOKUP_FIND_VIRTUAL(
+                "Lookup.findVirtual",
+                VarHandleBaseTest::findVirtual),
+        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_ACCESS_MODE_TYPE(
+                "MethodHandles.varHandleInvoker(accessModeType)",
+                VarHandleBaseTest::varHandleInvokerWithAccessModeType),
+        METHOD_HANDLES_VAR_HANDLE_INVOKER_WITH_SYMBOLIC_TYPE_DESCRIPTOR(
+                "MethodHandles.varHandleInvoker(symbolicTypeDescriptor)",
+                VarHandleBaseTest::varHandleInvokerWithSymbolicTypeDescriptor),
+        METHOD_HANDLES_VAR_HANDLE_EXACT_INVOKER_WITH_ACCESS_MODE_TYPE(
+                "MethodHandles.varHandleExactInvoker(accessModeType)",
+                VarHandleBaseTest::varHandleExactInvokerWithAccessModeType);
+
+        final String desc;
+        final TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f;
+        final boolean exact;
+
+        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f) {
+            this(desc, f, false);
+        }
+
+        VarHandleToMethodHandle(String desc, TriFunction<VarHandle, TestAccessMode, MethodType, MethodHandle> f,
+                                boolean exact) {
+            this.desc = desc;
+            this.f = f;
+            this.exact = exact;
+        }
+
+        MethodHandle apply(VarHandle vh, TestAccessMode am, MethodType mt) {
+            return f.apply(vh, am, mt);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class Handles {
+        static class AccessModeAndType {
+            final TestAccessMode tam;
+            final MethodType t;
+
+            public AccessModeAndType(TestAccessMode tam, MethodType t) {
+                this.tam = tam;
+                this.t = t;
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+
+                AccessModeAndType x = (AccessModeAndType) o;
+
+                if (tam != x.tam) return false;
+                if (t != null ? !t.equals(x.t) : x.t != null) return false;
+
+                return true;
+            }
+
+            @Override
+            public int hashCode() {
+                int result = tam != null ? tam.hashCode() : 0;
+                result = 31 * result + (t != null ? t.hashCode() : 0);
+                return result;
+            }
+        }
+
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+        final EnumMap<TestAccessMode, MethodType> amToType;
+        final Map<AccessModeAndType, MethodHandle> amToHandle;
+
+        Handles(VarHandle vh, VarHandleToMethodHandle f) throws Exception {
+            this.vh = vh;
+            this.f = f;
+            this.amToHandle = new HashMap<>();
+
+            amToType = new EnumMap<>(TestAccessMode.class);
+            for (TestAccessMode am : testAccessModes()) {
+                amToType.put(am, vh.accessModeType(am.toAccessMode()));
+            }
+        }
+
+        MethodHandle get(TestAccessMode am) {
+            return get(am, amToType.get(am));
+        }
+
+        MethodHandle get(TestAccessMode am, MethodType mt) {
+            AccessModeAndType amt = new AccessModeAndType(am, mt);
+            return amToHandle.computeIfAbsent(
+                    amt, k -> f.apply(vh, am, mt));
+        }
+    }
+
+    interface AccessTestAction<T> {
+        void action(T t) throws Throwable;
+    }
+
+    static abstract class AccessTestCase<T> {
+        final String desc;
+        final AccessTestAction<T> ata;
+        final boolean loop;
+
+        AccessTestCase(String desc, AccessTestAction<T> ata, boolean loop) {
+            this.desc = desc;
+            this.ata = ata;
+            this.loop = loop;
+        }
+
+        boolean requiresLoop() {
+            return loop;
+        }
+
+        abstract T get() throws Exception;
+
+        void testAccess(T t) throws Throwable {
+            ata.action(t);
+        }
+
+        @Override
+        public String toString() {
+            return desc;
+        }
+    }
+
+    static class VarHandleAccessTestCase extends AccessTestCase<VarHandle> {
+        final VarHandle vh;
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata) {
+            this(desc, vh, ata, true);
+        }
+
+        VarHandleAccessTestCase(String desc, VarHandle vh, AccessTestAction<VarHandle> ata, boolean loop) {
+            super("VarHandle -> " + desc, ata, loop);
+            this.vh = vh;
+        }
+
+        @Override
+        VarHandle get() {
+            return vh;
+        }
+    }
+
+    static class MethodHandleAccessTestCase extends AccessTestCase<Handles> {
+        final VarHandle vh;
+        final VarHandleToMethodHandle f;
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata) {
+            this(desc, vh, f, ata, true);
+        }
+
+        MethodHandleAccessTestCase(String desc, VarHandle vh, VarHandleToMethodHandle f, AccessTestAction<Handles> ata, boolean loop) {
+            super("VarHandle -> " + f.toString() + " -> " + desc, ata, loop);
+            this.vh = vh;
+            this.f = f;
+        }
+
+        @Override
+        Handles get() throws Exception {
+            return new Handles(vh, f);
+        }
+    }
+
+    static void testTypes(VarHandle vh) {
+        List<Class<?>> pts = vh.coordinateTypes();
+
+        for (TestAccessMode accessMode : testAccessModes()) {
+            MethodType amt = vh.accessModeType(accessMode.toAccessMode());
+
+            assertEquals(amt.parameterList().subList(0, pts.size()), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.get)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterList(), pts);
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.set)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), void.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndSet)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), boolean.class);
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.compareAndExchange)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 2), vh.varType());
+        }
+
+        for (TestAccessMode testAccessMode : testAccessModesOfType(TestAccessType.getAndSet, TestAccessType.getAndAdd)) {
+            MethodType mt = vh.accessModeType(testAccessMode.toAccessMode());
+            assertEquals(mt.returnType(), vh.varType());
+            assertEquals(mt.parameterType(mt.parameterCount() - 1), vh.varType());
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessBoolean
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessBoolean
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessBoolean extends VarHandleBaseTest {
+    static final boolean static_final_v = true;
+
+    static boolean static_v;
+
+    final boolean final_v = true;
+
+    boolean v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "v", boolean.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(boolean[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessBoolean.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(boolean[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), boolean.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessBoolean.class, "v", boolean.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_final_v", boolean.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessBoolean.class, "static_v", boolean.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessBoolean::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessBoolean::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessBoolean::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessBoolean::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(recv, true);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "get boolean value");
+        }
+
+
+        // Volatile
+        {
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, true, "getVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "getRelease boolean value");
+        }
+
+        // Opaque
+        {
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, true, "getOpaque boolean value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(false);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(false);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(false);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(true);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, true);
+            boolean x = (boolean) vh.get(recv);
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, false);
+            boolean x = (boolean) vh.getVolatile(recv);
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, true);
+            boolean x = (boolean) vh.getAcquire(recv);
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, false);
+            boolean x = (boolean) vh.getOpaque(recv);
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessBoolean recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(recv, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(recv, true);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set(true);
+            boolean x = (boolean) vh.get();
+            assertEquals(x, true, "set boolean value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(false);
+            boolean x = (boolean) vh.getVolatile();
+            assertEquals(x, false, "setVolatile boolean value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(true);
+            boolean x = (boolean) vh.getAcquire();
+            assertEquals(x, true, "setRelease boolean value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(false);
+            boolean x = (boolean) vh.getOpaque();
+            assertEquals(x, false, "setOpaque boolean value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(true);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, true);
+                boolean x = (boolean) vh.get(array, i);
+                assertEquals(x, true, "get boolean value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, false);
+                boolean x = (boolean) vh.getVolatile(array, i);
+                assertEquals(x, false, "setVolatile boolean value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, true);
+                boolean x = (boolean) vh.getAcquire(array, i);
+                assertEquals(x, true, "setRelease boolean value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, false);
+                boolean x = (boolean) vh.getOpaque(array, i);
+                assertEquals(x, false, "setOpaque boolean value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        boolean[] array = new boolean[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeVolatile(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeAcquire(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = (boolean) vh.compareAndExchangeRelease(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, true, false);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.getAndAdd(array, i, true);
+        });
+
+        checkUOE(() -> {
+            boolean o = (boolean) vh.addAndGet(array, i, true);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        boolean[] array = new boolean[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, true);
+            });
+
+            checkIOOBE(() -> {
+                boolean x = (boolean) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, true);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessByte
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessByte
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessByte extends VarHandleBaseTest {
+    static final byte static_final_v = (byte)1;
+
+    static byte static_v;
+
+    final byte final_v = (byte)1;
+
+    byte v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "final_v", byte.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "v", byte.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_final_v", byte.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessByte.class, "static_v", byte.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(byte[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessByte.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(byte[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), byte.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "final_v", byte.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessByte.class, "v", byte.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_final_v", byte.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessByte.class, "static_v", byte.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessByte::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessByte::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessByte::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessByte::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessByte::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)1, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)1, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)1, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)1, "getOpaque byte value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(recv, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(recv, (byte)1);
+        });
+    }
+
+
+    static void testStaticFinalField(VarHandle vh) {
+        // Plain
+        {
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)1, "get byte value");
+        }
+
+
+        // Volatile
+        {
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)1, "getVolatile byte value");
+        }
+
+        // Lazy
+        {
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)1, "getRelease byte value");
+        }
+
+        // Opaque
+        {
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)1, "getOpaque byte value");
+        }
+    }
+
+    static void testStaticFinalFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            vh.set((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setRelease((byte)2);
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque((byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd((byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet((byte)1);
+        });
+    }
+
+
+    static void testInstanceField(VarHandleTestAccessByte recv, VarHandle vh) {
+        // Plain
+        {
+            vh.set(recv, (byte)1);
+            byte x = (byte) vh.get(recv);
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile(recv, (byte)2);
+            byte x = (byte) vh.getVolatile(recv);
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease(recv, (byte)1);
+            byte x = (byte) vh.getAcquire(recv);
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque(recv, (byte)2);
+            byte x = (byte) vh.getOpaque(recv);
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testInstanceFieldUnsupported(VarHandleTestAccessByte recv, VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(recv, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(recv, (byte)1);
+        });
+    }
+
+
+    static void testStaticField(VarHandle vh) {
+        // Plain
+        {
+            vh.set((byte)1);
+            byte x = (byte) vh.get();
+            assertEquals(x, (byte)1, "set byte value");
+        }
+
+
+        // Volatile
+        {
+            vh.setVolatile((byte)2);
+            byte x = (byte) vh.getVolatile();
+            assertEquals(x, (byte)2, "setVolatile byte value");
+        }
+
+        // Lazy
+        {
+            vh.setRelease((byte)1);
+            byte x = (byte) vh.getAcquire();
+            assertEquals(x, (byte)1, "setRelease byte value");
+        }
+
+        // Opaque
+        {
+            vh.setOpaque((byte)2);
+            byte x = (byte) vh.getOpaque();
+            assertEquals(x, (byte)2, "setOpaque byte value");
+        }
+
+
+    }
+
+    static void testStaticFieldUnsupported(VarHandle vh) {
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd((byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet((byte)1);
+        });
+    }
+
+
+    static void testArray(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        for (int i = 0; i < array.length; i++) {
+            // Plain
+            {
+                vh.set(array, i, (byte)1);
+                byte x = (byte) vh.get(array, i);
+                assertEquals(x, (byte)1, "get byte value");
+            }
+
+
+            // Volatile
+            {
+                vh.setVolatile(array, i, (byte)2);
+                byte x = (byte) vh.getVolatile(array, i);
+                assertEquals(x, (byte)2, "setVolatile byte value");
+            }
+
+            // Lazy
+            {
+                vh.setRelease(array, i, (byte)1);
+                byte x = (byte) vh.getAcquire(array, i);
+                assertEquals(x, (byte)1, "setRelease byte value");
+            }
+
+            // Opaque
+            {
+                vh.setOpaque(array, i, (byte)2);
+                byte x = (byte) vh.getOpaque(array, i);
+                assertEquals(x, (byte)2, "setOpaque byte value");
+            }
+
+
+        }
+    }
+
+    static void testArrayUnsupported(VarHandle vh) {
+        byte[] array = new byte[10];
+
+        int i = 0;
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeVolatile(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeAcquire(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte r = (byte) vh.compareAndExchangeRelease(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetRelease(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.getAndAdd(array, i, (byte)1);
+        });
+
+        checkUOE(() -> {
+            byte o = (byte) vh.addAndGet(array, i, (byte)1);
+        });
+    }
+
+    static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable {
+        byte[] array = new byte[10];
+
+        for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
+            final int ci = i;
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.get(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.set(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getVolatile(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setVolatile(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getAcquire(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setRelease(array, ci, (byte)1);
+            });
+
+            checkIOOBE(() -> {
+                byte x = (byte) vh.getOpaque(array, ci);
+            });
+
+            checkIOOBE(() -> {
+                vh.setOpaque(array, ci, (byte)1);
+            });
+
+
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Tue Apr 05 20:02:21 2016 -0700
@@ -0,0 +1,647 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @run testng/othervm -Diters=10    -Xint                   VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000                         VarHandleTestAccessChar
+ * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestAccessChar
+ */
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+public class VarHandleTestAccessChar extends VarHandleBaseTest {
+    static final char static_final_v = 'a';
+
+    static char static_v;
+
+    final char final_v = 'a';
+
+    char v;
+
+    VarHandle vhFinalField;
+
+    VarHandle vhField;
+
+    VarHandle vhStaticField;
+
+    VarHandle vhStaticFinalField;
+
+    VarHandle vhArray;
+
+    @BeforeClass
+    public void setup() throws Exception {
+        vhFinalField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "final_v", char.class);
+
+        vhField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "v", char.class);
+
+        vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_final_v", char.class);
+
+        vhStaticField = MethodHandles.lookup().findStaticVarHandle(
+            VarHandleTestAccessChar.class, "static_v", char.class);
+
+        vhArray = MethodHandles.arrayElementVarHandle(char[].class);
+    }
+
+
+    @DataProvider
+    public Object[][] varHandlesProvider() throws Exception {
+        List<VarHandle> vhs = new ArrayList<>();
+        vhs.add(vhField);
+        vhs.add(vhStaticField);
+        vhs.add(vhArray);
+
+        return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "varHandlesProvider")
+    public void testIsAccessModeSupported(VarHandle vh) {
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.get));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.set));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setVolatile));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getAcquire));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setRelease));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.getOpaque));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.setOpaque));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeVolatile));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.compareAndExchangeRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSet));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetAcquire));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.weakCompareAndSetRelease));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndSet));
+
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.getAndAdd));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.addAndGet));
+    }
+
+
+    @DataProvider
+    public Object[][] typesProvider() throws Exception {
+        List<Object[]> types = new ArrayList<>();
+        types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessChar.class)});
+        types.add(new Object[] {vhStaticField, Arrays.asList()});
+        types.add(new Object[] {vhArray, Arrays.asList(char[].class, int.class)});
+
+        return types.stream().toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "typesProvider")
+    public void testTypes(VarHandle vh, List<Class<?>> pts) {
+        assertEquals(vh.varType(), char.class);
+
+        assertEquals(vh.coordinateTypes(), pts);
+
+        testTypes(vh);
+    }
+
+
+    @Test
+    public void testLookupInstanceToStatic() {
+        checkIAE("Lookup of static final field to instance final field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "final_v", char.class);
+        });
+
+        checkIAE("Lookup of static field to instance field", () -> {
+            MethodHandles.lookup().findStaticVarHandle(
+                    VarHandleTestAccessChar.class, "v", char.class);
+        });
+    }
+
+    @Test
+    public void testLookupStaticToInstance() {
+        checkIAE("Lookup of instance final field to static final field", () -> {
+            MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_final_v", char.class);
+        });
+
+        checkIAE("Lookup of instance field to static field", () -> {
+            vhStaticField = MethodHandles.lookup().findVarHandle(
+                VarHandleTestAccessChar.class, "static_v", char.class);
+        });
+    }
+
+
+    @DataProvider
+    public Object[][] accessTestCaseProvider() throws Exception {
+        List<AccessTestCase<?>> cases = new ArrayList<>();
+
+        cases.add(new VarHandleAccessTestCase("Instance final field",
+                                              vhFinalField, vh -> testInstanceFinalField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance final field unsupported",
+                                              vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static final field",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalField));
+        cases.add(new VarHandleAccessTestCase("Static final field unsupported",
+                                              vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Instance field",
+                                              vhField, vh -> testInstanceField(this, vh)));
+        cases.add(new VarHandleAccessTestCase("Instance field unsupported",
+                                              vhField, vh -> testInstanceFieldUnsupported(this, vh),
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Static field",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticField));
+        cases.add(new VarHandleAccessTestCase("Static field unsupported",
+                                              vhStaticField, VarHandleTestAccessChar::testStaticFieldUnsupported,
+                                              false));
+
+        cases.add(new VarHandleAccessTestCase("Array",
+                                              vhArray, VarHandleTestAccessChar::testArray));
+        cases.add(new VarHandleAccessTestCase("Array unsupported",
+                                              vhArray, VarHandleTestAccessChar::testArrayUnsupported,
+                                              false));
+        cases.add(new VarHandleAccessTestCase("Array index out of bounds",
+                                              vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds,
+                                              false));
+
+        // Work around issue with jtreg summary reporting which truncates
+        // the String result of Object.toString to 30 characters, hence
+        // the first dummy argument
+        return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
+    }
+
+    @Test(dataProvider = "accessTestCaseProvider")
+    public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
+        T t = atc.get();
+        int iters = atc.requiresLoop() ? ITERS : 1;
+        for (int c = 0; c < iters; c++) {
+            atc.testAccess(t);
+        }
+    }
+
+
+
+
+    static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) {
+        // Plain
+        {
+            char x = (char) vh.get(recv);
+            assertEquals(x, 'a', "get char value");
+        }
+
+
+        // Volatile
+        {
+            char x = (char) vh.getVolatile(recv);
+            assertEquals(x, 'a', "getVolatile char value");
+        }
+
+        // Lazy
+        {
+            char x = (char) vh.getAcquire(recv);
+            assertEquals(x, 'a', "getRelease char value");
+        }
+
+        // Opaque
+        {
+            char x = (char) vh.getOpaque(recv);
+            assertEquals(x, 'a', "getOpaque char value");
+        }
+    }
+
+    static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) {
+        checkUOE(() -> {
+            vh.set(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setVolatile(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setRelease(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            vh.setOpaque(recv, 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.compareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSet(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');