# HG changeset patch # User psandoz # Date 1449137851 -3600 # Node ID 754852fba784283db7caa4342c4a52c5b1e1a185 # Parent 89dab2d4f7b9e2d98611443320203a1888cefe8a 8144223: Move j.l.invoke.{ForceInline, DontInline, Stable} to jdk.internal.vm.annotation package Reviewed-by: jrose, vlivanov, mchung, roland diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java Thu Dec 03 11:17:31 2015 +0100 @@ -25,25 +25,25 @@ package java.lang.invoke; -import static jdk.internal.org.objectweb.asm.Opcodes.*; -import static java.lang.invoke.LambdaForm.*; -import static java.lang.invoke.LambdaForm.BasicType.*; -import static java.lang.invoke.MethodHandleStatics.*; +import jdk.internal.vm.annotation.Stable; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import sun.invoke.util.ValueConversions; +import sun.invoke.util.Wrapper; import java.lang.invoke.LambdaForm.NamedFunction; import java.lang.invoke.MethodHandles.Lookup; import java.lang.reflect.Field; import java.util.Arrays; -import java.util.function.Function; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; -import jdk.internal.org.objectweb.asm.FieldVisitor; -import sun.invoke.util.ValueConversions; -import sun.invoke.util.Wrapper; - -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; +import static java.lang.invoke.LambdaForm.BasicType; +import static java.lang.invoke.LambdaForm.BasicType.*; +import static java.lang.invoke.MethodHandleStatics.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; /** * The flavor of method handle which emulates an invoke instruction @@ -459,7 +459,7 @@ static final String BMH_SIG = "L"+BMH+";"; static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData"; static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";"; - static final String STABLE_SIG = "Ljava/lang/invoke/Stable;"; + static final String STABLE_SIG = "Ljdk/internal/vm/annotation/Stable;"; static final String SPECIES_PREFIX_NAME = "Species_"; static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME; diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Thu Dec 03 11:17:31 2015 +0100 @@ -26,19 +26,23 @@ package java.lang.invoke; import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.ForceInline; +import sun.invoke.util.ValueConversions; +import sun.invoke.util.VerifyAccess; +import sun.invoke.util.VerifyType; +import sun.invoke.util.Wrapper; + +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; -import sun.invoke.util.VerifyAccess; +import java.util.Objects; + +import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; -import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.MethodHandleStatics.UNSAFE; +import static java.lang.invoke.MethodHandleStatics.newInternalError; import static java.lang.invoke.MethodTypeForm.*; -import static java.lang.invoke.MethodHandleStatics.*; -import java.lang.ref.WeakReference; -import java.lang.reflect.Field; -import java.util.Objects; -import sun.invoke.util.ValueConversions; -import sun.invoke.util.VerifyType; -import sun.invoke.util.Wrapper; /** * The flavor of method handle which implements a constant reference diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/DontInline.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/DontInline.java Thu Dec 03 22:30:21 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012, 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.annotation.*; - -/** - * Internal marker for some methods in the JSR 292 implementation. - */ -/*non-public*/ -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -@Retention(RetentionPolicy.RUNTIME) -@interface DontInline { -} diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/ForceInline.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/ForceInline.java Thu Dec 03 22:30:21 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012, 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.annotation.*; - -/** - * Internal marker for some methods in the JSR 292 implementation. - */ -/*non-public*/ -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) -@Retention(RetentionPolicy.RUNTIME) -@interface ForceInline { -} diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java Thu Dec 03 11:17:31 2015 +0100 @@ -608,9 +608,9 @@ if (lambdaForm.forceInline) { // Force inlining of this invoker method. - mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true); } else { - mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true); + mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true); } if (lambdaForm.customized != null) { @@ -1292,7 +1292,7 @@ mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); // Don't inline the interpreter entry. - mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true); + mv.visitAnnotation("Ljdk/internal/vm/annotation/DontInline;", true); // create parameter array emitIconstInsn(invokerType.parameterCount()); @@ -1351,7 +1351,7 @@ mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); // Force inlining of this invoker method. - mv.visitAnnotation("Ljava/lang/invoke/ForceInline;", true); + mv.visitAnnotation("Ljdk/internal/vm/annotation/ForceInline;", true); // Load receiver emitAloadInsn(0); diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java Thu Dec 03 11:17:31 2015 +0100 @@ -25,6 +25,10 @@ package java.lang.invoke; +import jdk.internal.vm.annotation.DontInline; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; + import java.lang.reflect.Array; import java.util.Arrays; diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java Thu Dec 03 11:17:31 2015 +0100 @@ -25,18 +25,24 @@ package java.lang.invoke; -import java.lang.annotation.*; +import jdk.internal.vm.annotation.DontInline; +import jdk.internal.vm.annotation.Stable; +import sun.invoke.util.Wrapper; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.List; import java.util.Arrays; import java.util.HashMap; - -import sun.invoke.util.Wrapper; -import java.lang.reflect.Field; +import java.util.List; import static java.lang.invoke.LambdaForm.BasicType.*; -import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.MethodHandleNatives.Constants.*; +import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; +import static java.lang.invoke.MethodHandleStatics.debugEnabled; +import static java.lang.invoke.MethodHandleStatics.newInternalError; /** * The symbolic, non-executable form of a method handle's invocation semantics. diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Thu Dec 03 11:17:31 2015 +0100 @@ -32,8 +32,8 @@ import java.util.Iterator; import java.util.List; import java.util.function.Function; -import java.util.stream.Collectors; +import jdk.internal.vm.annotation.Stable; import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; @@ -1483,7 +1483,7 @@ } private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1; - private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; + private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1]; /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) * fills a[L]..a[N-1] with corresponding arguments, * and then returns a. The value L is a global constant (LEFT_ARGS). diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Dec 03 11:17:31 2015 +0100 @@ -25,6 +25,7 @@ package java.lang.invoke; +import jdk.internal.vm.annotation.Stable; import sun.invoke.util.Wrapper; import java.lang.ref.WeakReference; import java.lang.ref.Reference; diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Thu Dec 03 22:30:21 2015 -0800 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java Thu Dec 03 11:17:31 2015 +0100 @@ -25,6 +25,7 @@ package java.lang.invoke; +import jdk.internal.vm.annotation.Stable; import sun.invoke.util.Wrapper; import java.lang.ref.SoftReference; import static java.lang.invoke.MethodHandleStatics.*; diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/java/lang/invoke/Stable.java --- a/jdk/src/java.base/share/classes/java/lang/invoke/Stable.java Thu Dec 03 22:30:21 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, 2013, 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.annotation.*; - -/** - * A field may be annotated as stable if all of its component variables - * changes value at most once. - * A field's value counts as its component value. - * If the field is typed as an array, then all the non-null components - * of the array, of depth up to the rank of the field's array type, - * also count as component values. - * By extension, any variable (either array or field) which has annotated - * as stable is called a stable variable, and its non-null or non-zero - * value is called a stable value. - *

- * Since all fields begin with a default value of null for references - * (resp., zero for primitives), it follows that this annotation indicates - * that the first non-null (resp., non-zero) value stored in the field - * will never be changed. - *

- * If the field is not of an array type, there are no array elements, - * then the value indicated as stable is simply the value of the field. - * If the dynamic type of the field value is an array but the static type - * is not, the components of the array are not regarded as stable. - *

- * If the field is an array type, then both the field value and - * all the components of the field value (if the field value is non-null) - * are indicated to be stable. - * If the field type is an array type with rank {@code N > 1}, - * then each component of the field value (if the field value is non-null), - * is regarded as a stable array of rank {@code N-1}. - *

- * Fields which are declared {@code final} may also be annotated as stable. - * Since final fields already behave as stable values, such an annotation - * indicates no additional information, unless the type of the field is - * an array type. - *

- * It is (currently) undefined what happens if a field annotated as stable - * is given a third value. In practice, if the JVM relies on this annotation - * to promote a field reference to a constant, it may be that the Java memory - * model would appear to be broken, if such a constant (the second value of the field) - * is used as the value of the field even after the field value has changed. - */ -/* package-private */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@interface Stable { -} diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/jdk/internal/vm/annotation/DontInline.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/DontInline.java Thu Dec 03 11:17:31 2015 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2012, 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 jdk.internal.vm.annotation; + +import java.lang.annotation.*; + +/** + * A method or constructor may be annotated as "don't inline" if the inlining of + * this method should not be performed by the HotSpot VM. + *

+ * This annotation must be used sparingly. It is useful when the only + * reasonable alternative is to bind the name of a specific method or + * constructor into the HotSpot VM for special handling by the inlining policy. + * This annotation must not be relied on as an alternative to avoid tuning the + * VM's inlining policy. In a few cases, it may act as a temporary workaround + * until the profiling and inlining performed by the HotSpot VM is sufficiently + * improved. + * + * @implNote + * This annotation only takes effect for methods or constructors of classes + * loaded by the boot loader. Annotations on methods or constructors of classes + * loaded outside of the boot loader are ignored. + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DontInline { +} diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/jdk/internal/vm/annotation/ForceInline.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/ForceInline.java Thu Dec 03 11:17:31 2015 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, 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 jdk.internal.vm.annotation; + +import java.lang.annotation.*; + +/** + * A method or constructor may be annotated as "force inline" if the standard + * inlining metrics are to be ignored when the HotSpot VM inlines the method + * or constructor. + *

+ * This annotation must be used sparingly. It is useful when the only + * reasonable alternative is to bind the name of a specific method or + * constructor into the HotSpot VM for special handling by the inlining policy. + * This annotation must not be relied on as an alternative to avoid tuning the + * VM's inlining policy. In a few cases, it may act as a temporary workaround + * until the profiling and inlining performed by the HotSpot VM is sufficiently + * improved. + * + * @implNote + * This annotation only takes effect for methods or constructors of classes + * loaded by the boot loader. Annotations on methods or constructors of classes + * loaded outside of the boot loader are ignored. + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ForceInline { +} diff -r 89dab2d4f7b9 -r 754852fba784 jdk/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/vm/annotation/Stable.java Thu Dec 03 11:17:31 2015 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012, 2013, 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 jdk.internal.vm.annotation; + +import java.lang.annotation.*; + +/** + * A field may be annotated as stable if all of its component variables + * changes value at most once. + * A field's value counts as its component value. + * If the field is typed as an array, then all the non-null components + * of the array, of depth up to the rank of the field's array type, + * also count as component values. + * By extension, any variable (either array or field) which has annotated + * as stable is called a stable variable, and its non-null or non-zero + * value is called a stable value. + *

+ * Since all fields begin with a default value of null for references + * (resp., zero for primitives), it follows that this annotation indicates + * that the first non-null (resp., non-zero) value stored in the field + * will never be changed. + *

+ * If the field is not of an array type, there are no array elements, + * then the value indicated as stable is simply the value of the field. + * If the dynamic type of the field value is an array but the static type + * is not, the components of the array are not regarded as stable. + *

+ * If the field is an array type, then both the field value and + * all the components of the field value (if the field value is non-null) + * are indicated to be stable. + * If the field type is an array type with rank {@code N > 1}, + * then each component of the field value (if the field value is non-null), + * is regarded as a stable array of rank {@code N-1}. + *

+ * Fields which are declared {@code final} may also be annotated as stable. + * Since final fields already behave as stable values, such an annotation + * conveys no additional information regarding change of the field's value, but + * still conveys information regarding change of additional components values if + * the type of the field is an array type (as described above). + *

+ * The HotSpot VM relies on this annotation to promote a non-null (resp., + * non-zero) component value to a constant, thereby enabling superior + * optimizations of code depending on such a value (such as constant folding). + * More specifically, the HotSpot VM will process non-null stable fields (final + * or otherwise) in a similar manner to static final fields with respect to + * promoting the field's value to a constant. Thus, placing aside the + * differences for null/non-null values and arrays, a final stable field is + * treated as if it is really final from both the Java language and the HotSpot + * VM. + *

+ * It is (currently) undefined what happens if a field annotated as stable + * is given a third value (by explicitly updating a stable field, a component of + * a stable array, or a final stable field via reflection or other means). + * Since the HotSpot VM promotes a non-null component value to constant, it may + * be that the Java memory model would appear to be broken, if such a constant + * (the second value of the field) is used as the value of the field even after + * the field value has changed (to a third value). + * + * @implNote + * This annotation only takes effect for fields of classes loaded by the boot + * loader. Annoations on fields of classes loaded outside of the boot loader + * are ignored. + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stable { +}