--- a/.hgtags Mon Jun 25 08:14:11 2018 -0700
+++ b/.hgtags Mon Jun 25 09:48:06 2018 -0700
@@ -491,3 +491,5 @@
64e4b1686141e57a681936a8283983341484676e jdk-11+17
e1b3def126240d5433902f3cb0e91a4c27f6db50 jdk-11+18
fb8b3f4672774e15654958295558a1af1b576919 jdk-11+19
+fb8b3f4672774e15654958295558a1af1b576919 jdk-11+19
+36ca515343e00b021dcfc902e986d26ec994a2e5 jdk-11+19
--- a/make/autoconf/flags-ldflags.m4 Mon Jun 25 08:14:11 2018 -0700
+++ b/make/autoconf/flags-ldflags.m4 Mon Jun 25 09:48:06 2018 -0700
@@ -81,7 +81,7 @@
elif test "x$TOOLCHAIN_TYPE" = xclang; then
BASIC_LDFLAGS_JVM_ONLY="-mno-omit-leaf-frame-pointer -mstack-alignment=16 \
- -stdlib=libc++ -fPIC"
+ -fPIC"
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
BASIC_LDFLAGS="-Wl,-z,defs"
--- a/make/data/jdwp/jdwp.spec Mon Jun 25 08:14:11 2018 -0700
+++ b/make/data/jdwp/jdwp.spec Mon Jun 25 09:48:06 2018 -0700
@@ -395,8 +395,8 @@
"Can the VM add methods when redefining "
"classes?")
(boolean canUnrestrictedlyRedefineClasses
- "Can the VM redefine classes"
- "in arbitrary ways?")
+ "Can the VM redefine classes "
+ "in ways that are normally restricted?")
(boolean canPopFrames
"Can the VM pop stack frames?")
(boolean canUseInstanceFilters
@@ -460,12 +460,23 @@
"<a href=\"#JDWP_StackFrame_PopFrames\">PopFrames</a> command can be used "
"to pop frames with obsolete methods."
"<p>"
+ "Unless the canUnrestrictedlyRedefineClasses capability is present the following "
+ "redefinitions are restricted: "
+ "<ul>"
+ "<li>changing the schema (the fields)</li>"
+ "<li>changing the hierarchy (superclasses, interfaces)</li>"
+ "<li>deleting a method</li>"
+ "<li>changing class modifiers</li>"
+ "<li>changing method modifiers</li>"
+ "<li>changing the <code>NestHost</code> or <code>NestMembers</code> class attributes</li>"
+ "</ul>"
+ "<p>"
"Requires canRedefineClasses capability - see "
"<a href=\"#JDWP_VirtualMachine_CapabilitiesNew\">CapabilitiesNew</a>. "
"In addition to the canRedefineClasses capability, the target VM must "
"have the canAddMethod capability to add methods when redefining classes, "
- "or the canUnrestrictedlyRedefineClasses to redefine classes in arbitrary "
- "ways."
+ "or the canUnrestrictedlyRedefineClasses capability to redefine classes in ways "
+ "that are normally restricted."
(Out
(Repeat classes "Number of reference types that follow."
(Group ClassDef
@@ -496,6 +507,7 @@
(Error DELETE_METHOD_NOT_IMPLEMENTED)
(Error CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
(Error METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
+ (Error CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED)
(Error VM_DEAD)
)
)
@@ -3148,12 +3160,16 @@
"different from the name in the old class object.")
(Constant CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED
=70 "The new class version has different modifiers and "
- "and canUnrestrictedlyRedefineClasses is false.")
+ "canUnrestrictedlyRedefineClasses is false.")
(Constant METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED
=71 "A method in the new class version has "
"different modifiers "
"than its counterpart in the old class version and "
- "and canUnrestrictedlyRedefineClasses is false.")
+ "canUnrestrictedlyRedefineClasses is false.")
+ (Constant CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED
+ =72 "The new class version has different NestHost or "
+ "NestMembers class attribute and "
+ "canUnrestrictedlyRedefineClasses is false.")
(Constant NOT_IMPLEMENTED =99 "The functionality is not implemented in "
"this virtual machine.")
(Constant NULL_POINTER =100 "Invalid pointer.")
--- a/make/data/symbols/jdk.scripting.nashorn-7.sym.txt Mon Jun 25 08:14:11 2018 -0700
+++ b/make/data/symbols/jdk.scripting.nashorn-7.sym.txt Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, 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
@@ -28,6 +28,8 @@
#
-class name jdk/nashorn/api/scripting/AbstractJSObject
+-class name jdk/nashorn/api/scripting/ClassFilter
+
-class name jdk/nashorn/api/scripting/JSObject
-class name jdk/nashorn/api/scripting/NashornException
--- a/make/data/symbols/jdk.scripting.nashorn-8.sym.txt Mon Jun 25 08:14:11 2018 -0700
+++ b/make/data/symbols/jdk.scripting.nashorn-8.sym.txt Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, 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
@@ -27,7 +27,7 @@
# ##########################################################
#
class name jdk/nashorn/api/scripting/AbstractJSObject
-header extends java/lang/Object implements jdk/nashorn/api/scripting/JSObject flags 421
+header extends java/lang/Object implements jdk/nashorn/api/scripting/JSObject flags 421 runtimeAnnotations @Ljdk/Exported;
method name <init> descriptor ()V flags 1
method name call descriptor (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; flags 81
method name newObject descriptor ([Ljava/lang/Object;)Ljava/lang/Object; flags 81
@@ -47,10 +47,16 @@
method name isFunction descriptor ()Z flags 1
method name isStrictFunction descriptor ()Z flags 1
method name isArray descriptor ()Z flags 1
-method name toNumber descriptor ()D flags 1
+method name toNumber descriptor ()D flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
+method name getDefaultValue descriptor (Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature (Ljava/lang/Class<*>;)Ljava/lang/Object;
+method name getDefaultValue descriptor (Ljdk/nashorn/api/scripting/JSObject;Ljava/lang/Class;)Ljava/lang/Object; flags 9 signature (Ljdk/nashorn/api/scripting/JSObject;Ljava/lang/Class<*>;)Ljava/lang/Object;
+
+class name jdk/nashorn/api/scripting/ClassFilter
+header extends java/lang/Object flags 601 runtimeAnnotations @Ljdk/Exported;
+method name exposeToScripts descriptor (Ljava/lang/String;)Z flags 401
class name jdk/nashorn/api/scripting/JSObject
-header extends java/lang/Object flags 601
+header extends java/lang/Object flags 601 runtimeAnnotations @Ljdk/Exported;
method name call descriptor (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; flags 481
method name newObject descriptor ([Ljava/lang/Object;)Ljava/lang/Object; flags 481
method name eval descriptor (Ljava/lang/String;)Ljava/lang/Object; flags 401
@@ -69,22 +75,28 @@
method name isFunction descriptor ()Z flags 401
method name isStrictFunction descriptor ()Z flags 401
method name isArray descriptor ()Z flags 401
-method name toNumber descriptor ()D flags 401
+method name toNumber descriptor ()D flags 401 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
class name jdk/nashorn/api/scripting/NashornException
-header extends java/lang/RuntimeException flags 421
-field name ENGINE_SCRIPT_SOURCE_NAME descriptor Ljava/lang/String; constantValue nashorn:engine/resources/engine.js flags 19
+header extends java/lang/RuntimeException flags 421 runtimeAnnotations @Ljdk/Exported;
method name <init> descriptor (Ljava/lang/String;Ljava/lang/String;II)V flags 4
method name <init> descriptor (Ljava/lang/String;Ljava/lang/Throwable;Ljava/lang/String;II)V flags 4
method name <init> descriptor (Ljava/lang/String;Ljava/lang/Throwable;)V flags 4
method name getFileName descriptor ()Ljava/lang/String; flags 11
+method name setFileName descriptor (Ljava/lang/String;)V flags 11
method name getLineNumber descriptor ()I flags 11
+method name setLineNumber descriptor (I)V flags 11
method name getColumnNumber descriptor ()I flags 11
+method name setColumnNumber descriptor (I)V flags 11
method name getScriptFrames descriptor (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement; flags 9
method name getScriptStackString descriptor (Ljava/lang/Throwable;)Ljava/lang/String; flags 9
+method name getThrown descriptor ()Ljava/lang/Object; flags 4
+method name initEcmaError descriptor (Ljdk/nashorn/internal/runtime/ScriptObject;)Ljdk/nashorn/api/scripting/NashornException; flags 4
+method name getEcmaError descriptor ()Ljava/lang/Object; flags 1
+method name setEcmaError descriptor (Ljava/lang/Object;)V flags 1
class name jdk/nashorn/api/scripting/NashornScriptEngine
-header extends javax/script/AbstractScriptEngine implements javax/script/Compilable,javax/script/Invocable flags 31
+header extends javax/script/AbstractScriptEngine implements javax/script/Compilable,javax/script/Invocable flags 31 runtimeAnnotations @Ljdk/Exported;
innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19
field name NASHORN_GLOBAL descriptor Ljava/lang/String; constantValue nashorn.global flags 19
method name eval descriptor (Ljava/io/Reader;Ljavax/script/ScriptContext;)Ljava/lang/Object; thrownTypes javax/script/ScriptException flags 1
@@ -97,10 +109,9 @@
method name invokeMethod descriptor (Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; thrownTypes javax/script/ScriptException,java/lang/NoSuchMethodException flags 81
method name getInterface descriptor (Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature <T:Ljava/lang/Object;>(Ljava/lang/Class<TT;>;)TT;
method name getInterface descriptor (Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature <T:Ljava/lang/Object;>(Ljava/lang/Object;Ljava/lang/Class<TT;>;)TT;
-method name __noSuchProperty__ descriptor (Ljava/lang/Object;Ljavax/script/ScriptContext;Ljava/lang/String;)Ljava/lang/Object; flags 1
class name jdk/nashorn/api/scripting/NashornScriptEngineFactory
-header extends java/lang/Object implements javax/script/ScriptEngineFactory flags 31
+header extends java/lang/Object implements javax/script/ScriptEngineFactory flags 31 runtimeAnnotations @Ljdk/Exported;
method name <init> descriptor ()V flags 1
method name getEngineName descriptor ()Ljava/lang/String; flags 1
method name getEngineVersion descriptor ()Ljava/lang/String; flags 1
@@ -115,11 +126,13 @@
method name getProgram descriptor ([Ljava/lang/String;)Ljava/lang/String; flags 81
method name getScriptEngine descriptor ()Ljavax/script/ScriptEngine; flags 1
method name getScriptEngine descriptor (Ljava/lang/ClassLoader;)Ljavax/script/ScriptEngine; flags 1
-method name getScriptEngine descriptor ([Ljava/lang/String;)Ljavax/script/ScriptEngine; flags 1
+method name getScriptEngine descriptor (Ljdk/nashorn/api/scripting/ClassFilter;)Ljavax/script/ScriptEngine; flags 1
+method name getScriptEngine descriptor ([Ljava/lang/String;)Ljavax/script/ScriptEngine; flags 81
method name getScriptEngine descriptor ([Ljava/lang/String;Ljava/lang/ClassLoader;)Ljavax/script/ScriptEngine; flags 1
+method name getScriptEngine descriptor ([Ljava/lang/String;Ljava/lang/ClassLoader;Ljdk/nashorn/api/scripting/ClassFilter;)Ljavax/script/ScriptEngine; flags 1
class name jdk/nashorn/api/scripting/ScriptObjectMirror
-header extends jdk/nashorn/api/scripting/AbstractJSObject implements javax/script/Bindings flags 31
+header extends jdk/nashorn/api/scripting/AbstractJSObject implements javax/script/Bindings flags 31 runtimeAnnotations @Ljdk/Exported;
innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609
method name equals descriptor (Ljava/lang/Object;)Z flags 1
method name hashCode descriptor ()I flags 1
@@ -135,6 +148,7 @@
method name removeMember descriptor (Ljava/lang/String;)V flags 1
method name setMember descriptor (Ljava/lang/String;Ljava/lang/Object;)V flags 1
method name setSlot descriptor (ILjava/lang/Object;)V flags 1
+method name setIndexedPropertiesToExternalArrayData descriptor (Ljava/nio/ByteBuffer;)V flags 1
method name isInstance descriptor (Ljava/lang/Object;)Z flags 1
method name getClassName descriptor ()Ljava/lang/String; flags 1
method name isFunction descriptor ()Z flags 1
@@ -166,25 +180,28 @@
method name isUndefined descriptor (Ljava/lang/Object;)Z flags 9
method name to descriptor (Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature <T:Ljava/lang/Object;>(Ljava/lang/Class<TT;>;)TT;
method name wrap descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
+method name wrapAsJSONCompatible descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
method name unwrap descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
method name wrapArray descriptor ([Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object; flags 9
method name unwrapArray descriptor ([Ljava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object; flags 9
-method name toNumber descriptor ()D flags 1
+method name identical descriptor (Ljava/lang/Object;Ljava/lang/Object;)Z flags 9
+method name toNumber descriptor ()D flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
+method name getDefaultValue descriptor (Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature (Ljava/lang/Class<*>;)Ljava/lang/Object;
method name put descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 1041
class name jdk/nashorn/api/scripting/ScriptUtils
-header extends java/lang/Object flags 31
+header extends java/lang/Object flags 31 runtimeAnnotations @Ljdk/Exported;
method name parse descriptor (Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String; flags 9
method name format descriptor (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String; flags 9
-method name makeSynchronizedFunction descriptor (Ljdk/nashorn/internal/runtime/ScriptFunction;Ljava/lang/Object;)Ljava/lang/Object; flags 9
-method name wrap descriptor (Ljava/lang/Object;)Ljava/lang/Object; flags 9
+method name makeSynchronizedFunction descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
+method name wrap descriptor (Ljava/lang/Object;)Ljdk/nashorn/api/scripting/ScriptObjectMirror; flags 9
method name unwrap descriptor (Ljava/lang/Object;)Ljava/lang/Object; flags 9
method name wrapArray descriptor ([Ljava/lang/Object;)[Ljava/lang/Object; flags 9
method name unwrapArray descriptor ([Ljava/lang/Object;)[Ljava/lang/Object; flags 9
method name convert descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
class name jdk/nashorn/api/scripting/URLReader
-header extends java/io/Reader flags 31
+header extends java/io/Reader flags 31 runtimeAnnotations @Ljdk/Exported;
method name <init> descriptor (Ljava/net/URL;)V flags 1
method name <init> descriptor (Ljava/net/URL;Ljava/lang/String;)V flags 1
method name <init> descriptor (Ljava/net/URL;Ljava/nio/charset/Charset;)V flags 1
--- a/make/data/symbols/jdk.scripting.nashorn-9.sym.txt Mon Jun 25 08:14:11 2018 -0700
+++ b/make/data/symbols/jdk.scripting.nashorn-9.sym.txt Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2018, 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
@@ -30,15 +30,16 @@
header exports jdk/nashorn/api/scripting,jdk/nashorn/api/tree requires name\u0020;jdk.dynalink\u0020;flags\u0020;0,name\u0020;java.logging\u0020;flags\u0020;0,name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.scripting\u0020;flags\u0020;20 provides interface\u0020;javax/script/ScriptEngineFactory\u0020;impls\u0020;jdk/nashorn/api/scripting/NashornScriptEngineFactory,interface\u0020;jdk/dynalink/linker/GuardingDynamicLinkerExporter\u0020;impls\u0020;jdk/nashorn/api/linker/NashornLinkerExporter flags 8000
class name jdk/nashorn/api/scripting/AbstractJSObject
--method name toNumber descriptor ()D
-method name toNumber descriptor ()D flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
+header extends java/lang/Object implements jdk/nashorn/api/scripting/JSObject flags 421
+-method name getDefaultValue descriptor (Ljava/lang/Class;)Ljava/lang/Object;
+-method name getDefaultValue descriptor (Ljdk/nashorn/api/scripting/JSObject;Ljava/lang/Class;)Ljava/lang/Object;
method name getDefaultValue descriptor (Ljdk/nashorn/api/scripting/JSObject;Ljava/lang/Class;)Ljava/lang/Object; flags 9 deprecated true signature (Ljdk/nashorn/api/scripting/JSObject;Ljava/lang/Class<*>;)Ljava/lang/Object; runtimeAnnotations @Ljava/lang/Deprecated;
class name jdk/nashorn/api/scripting/ClassFilter
header extends java/lang/Object flags 601
-method name exposeToScripts descriptor (Ljava/lang/String;)Z flags 401
class name jdk/nashorn/api/scripting/JSObject
+header extends java/lang/Object flags 601
-method name toNumber descriptor ()D
method name toNumber descriptor ()D flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
method name getDefaultValue descriptor (Ljava/lang/Class;)Ljava/lang/Object; thrownTypes java/lang/UnsupportedOperationException flags 1 signature (Ljava/lang/Class<*>;)Ljava/lang/Object;
@@ -46,41 +47,26 @@
class name jdk/nashorn/api/scripting/NashornException
header extends java/lang/RuntimeException flags 421
innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19
--field name ENGINE_SCRIPT_SOURCE_NAME descriptor Ljava/lang/String;
-method name setFileName descriptor (Ljava/lang/String;)V flags 11
-method name setLineNumber descriptor (I)V flags 11
-method name setColumnNumber descriptor (I)V flags 11
-method name getThrown descriptor ()Ljava/lang/Object; flags 4
-method name getEcmaError descriptor ()Ljava/lang/Object; flags 1
-method name setEcmaError descriptor (Ljava/lang/Object;)V flags 1
+-method name initEcmaError descriptor (Ljdk/nashorn/internal/runtime/ScriptObject;)Ljdk/nashorn/api/scripting/NashornException;
class name jdk/nashorn/api/scripting/NashornScriptEngine
--method name __noSuchProperty__ descriptor (Ljava/lang/Object;Ljavax/script/ScriptContext;Ljava/lang/String;)Ljava/lang/Object;
+header extends javax/script/AbstractScriptEngine implements javax/script/Compilable,javax/script/Invocable flags 31
+innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19
class name jdk/nashorn/api/scripting/NashornScriptEngineFactory
header extends java/lang/Object implements javax/script/ScriptEngineFactory flags 31
innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19
--method name getScriptEngine descriptor ([Ljava/lang/String;)Ljavax/script/ScriptEngine;
-method name getScriptEngine descriptor (Ljdk/nashorn/api/scripting/ClassFilter;)Ljavax/script/ScriptEngine; flags 1
-method name getScriptEngine descriptor ([Ljava/lang/String;)Ljavax/script/ScriptEngine; flags 81
-method name getScriptEngine descriptor ([Ljava/lang/String;Ljava/lang/ClassLoader;Ljdk/nashorn/api/scripting/ClassFilter;)Ljavax/script/ScriptEngine; flags 1
class name jdk/nashorn/api/scripting/ScriptObjectMirror
header extends jdk/nashorn/api/scripting/AbstractJSObject implements javax/script/Bindings flags 31
innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609
innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19
--method name toNumber descriptor ()D
-method name setIndexedPropertiesToExternalArrayData descriptor (Ljava/nio/ByteBuffer;)V flags 1
-method name wrapAsJSONCompatible descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
-method name identical descriptor (Ljava/lang/Object;Ljava/lang/Object;)Z flags 9
-method name toNumber descriptor ()D flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;
-method name getDefaultValue descriptor (Ljava/lang/Class;)Ljava/lang/Object; flags 1 signature (Ljava/lang/Class<*>;)Ljava/lang/Object;
class name jdk/nashorn/api/scripting/ScriptUtils
--method name makeSynchronizedFunction descriptor (Ljdk/nashorn/internal/runtime/ScriptFunction;Ljava/lang/Object;)Ljava/lang/Object;
--method name wrap descriptor (Ljava/lang/Object;)Ljava/lang/Object;
-method name makeSynchronizedFunction descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; flags 9
-method name wrap descriptor (Ljava/lang/Object;)Ljdk/nashorn/api/scripting/ScriptObjectMirror; flags 9
+header extends java/lang/Object flags 31
+
+class name jdk/nashorn/api/scripting/URLReader
+header extends java/io/Reader flags 31
class name jdk/nashorn/api/tree/ArrayAccessTree
header extends java/lang/Object implements jdk/nashorn/api/tree/ExpressionTree flags 601
--- a/make/hotspot/symbols/symbols-unix Mon Jun 25 08:14:11 2018 -0700
+++ b/make/hotspot/symbols/symbols-unix Mon Jun 25 09:48:06 2018 -0700
@@ -22,6 +22,7 @@
#
JVM_ActiveProcessorCount
+JVM_AreNestMates
JVM_ArrayCopy
JVM_AssertionStatusDirectives
JVM_BeforeHalt
@@ -118,6 +119,8 @@
JVM_GetMethodParameters
JVM_GetMethodTypeAnnotations
JVM_GetNanoTimeAdjustment
+JVM_GetNestHost
+JVM_GetNestMembers
JVM_GetPrimitiveArrayElement
JVM_GetProtectionDomain
JVM_GetSimpleBinaryName
--- a/src/hotspot/cpu/aarch64/aarch64.ad Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Mon Jun 25 09:48:06 2018 -0700
@@ -15852,81 +15852,88 @@
%}
instruct string_compareU(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
- iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr)
+ iRegI_R0 result, iRegP_R10 tmp1, iRegL_R11 tmp2, rFlagsReg cr)
%{
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1" %}
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$Register,
- fnoreg, fnoreg, StrIntrinsicNode::UU);
+ $tmp1$$Register, $tmp2$$Register,
+ fnoreg, fnoreg, fnoreg, StrIntrinsicNode::UU);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_compareL(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
- iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr)
+ iRegI_R0 result, iRegP_R10 tmp1, iRegL_R11 tmp2, rFlagsReg cr)
%{
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1" %}
ins_encode %{
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$Register,
- fnoreg, fnoreg, StrIntrinsicNode::LL);
+ $tmp1$$Register, $tmp2$$Register,
+ fnoreg, fnoreg, fnoreg, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_compareUL(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
- iRegI_R0 result, vRegD vtmp1, vRegD vtmp2, iRegP_R10 tmp1, rFlagsReg cr)
+ iRegI_R0 result, iRegP_R10 tmp1, iRegL_R11 tmp2,
+ vRegD_V0 vtmp1, vRegD_V1 vtmp2, vRegD_V2 vtmp3, rFlagsReg cr)
%{
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP vtmp1, TEMP vtmp2, KILL cr);
-
- format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1" %}
+ effect(KILL tmp1, KILL tmp2, KILL vtmp1, KILL vtmp2, KILL vtmp3,
+ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+ format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1, $tmp2, $vtmp1, $vtmp2, $vtmp3" %}
ins_encode %{
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$Register,
- $vtmp1$$FloatRegister, $vtmp2$$FloatRegister, StrIntrinsicNode::UL);
+ $tmp1$$Register, $tmp2$$Register,
+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister,
+ $vtmp3$$FloatRegister, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_compareLU(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
- iRegI_R0 result, vRegD vtmp1, vRegD vtmp2, iRegP_R10 tmp1, rFlagsReg cr)
+ iRegI_R0 result, iRegP_R10 tmp1, iRegL_R11 tmp2,
+ vRegD_V0 vtmp1, vRegD_V1 vtmp2, vRegD_V2 vtmp3, rFlagsReg cr)
%{
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP vtmp1, TEMP vtmp2, KILL cr);
-
- format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1" %}
+ effect(KILL tmp1, KILL tmp2, KILL vtmp1, KILL vtmp2, KILL vtmp3,
+ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
+
+ format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result # KILL $tmp1, $tmp2, $vtmp1, $vtmp2, $vtmp3" %}
ins_encode %{
__ string_compare($str1$$Register, $str2$$Register,
$cnt1$$Register, $cnt2$$Register, $result$$Register,
- $tmp1$$Register,
- $vtmp1$$FloatRegister, $vtmp2$$FloatRegister, StrIntrinsicNode::LU);
+ $tmp1$$Register, $tmp2$$Register,
+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister,
+ $vtmp3$$FloatRegister,StrIntrinsicNode::LU);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexofUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
+ iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UU)" %}
ins_encode %{
@@ -15934,18 +15941,20 @@
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
+ $tmp5$$Register, $tmp6$$Register,
-1, $result$$Register, StrIntrinsicNode::UU);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexofLL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
+ iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LL)" %}
ins_encode %{
@@ -15953,18 +15962,20 @@
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
+ $tmp5$$Register, $tmp6$$Register,
-1, $result$$Register, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_memory);
%}
instruct string_indexofUL(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
+ iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3,
+ iRegINoSp tmp4, iRegINoSp tmp5, iRegINoSp tmp6, rFlagsReg cr)
%{
predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL);
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, KILL cr);
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (UL)" %}
ins_encode %{
@@ -15972,30 +15983,12 @@
$cnt1$$Register, $cnt2$$Register,
$tmp1$$Register, $tmp2$$Register,
$tmp3$$Register, $tmp4$$Register,
+ $tmp5$$Register, $tmp6$$Register,
-1, $result$$Register, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_memory);
%}
-instruct string_indexofLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
- iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
-%{
- predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
- format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result (LU)" %}
-
- ins_encode %{
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, $cnt2$$Register,
- $tmp1$$Register, $tmp2$$Register,
- $tmp3$$Register, $tmp4$$Register,
- -1, $result$$Register, StrIntrinsicNode::LU);
- %}
- ins_pipe(pipe_class_memory);
-%}
-
instruct string_indexof_conUU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
immI_le_4 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
@@ -16011,7 +16004,7 @@
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
- $tmp3$$Register, $tmp4$$Register,
+ $tmp3$$Register, $tmp4$$Register, zr, zr,
icnt2, $result$$Register, StrIntrinsicNode::UU);
%}
ins_pipe(pipe_class_memory);
@@ -16032,7 +16025,7 @@
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
- $tmp3$$Register, $tmp4$$Register,
+ $tmp3$$Register, $tmp4$$Register, zr, zr,
icnt2, $result$$Register, StrIntrinsicNode::LL);
%}
ins_pipe(pipe_class_memory);
@@ -16053,33 +16046,12 @@
__ string_indexof($str1$$Register, $str2$$Register,
$cnt1$$Register, zr,
$tmp1$$Register, $tmp2$$Register,
- $tmp3$$Register, $tmp4$$Register,
+ $tmp3$$Register, $tmp4$$Register, zr, zr,
icnt2, $result$$Register, StrIntrinsicNode::UL);
%}
ins_pipe(pipe_class_memory);
%}
-instruct string_indexof_conLU(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
- immI_1 int_cnt2, iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
- iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr)
-%{
- predicate(((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LU);
- match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
- format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result (LU)" %}
-
- ins_encode %{
- int icnt2 = (int)$int_cnt2$$constant;
- __ string_indexof($str1$$Register, $str2$$Register,
- $cnt1$$Register, zr,
- $tmp1$$Register, $tmp2$$Register,
- $tmp3$$Register, $tmp4$$Register,
- icnt2, $result$$Register, StrIntrinsicNode::LU);
- %}
- ins_pipe(pipe_class_memory);
-%}
-
instruct string_indexofU_char(iRegP_R1 str1, iRegI_R2 cnt1, iRegI_R3 ch,
iRegI_R0 result, iRegINoSp tmp1, iRegINoSp tmp2,
iRegINoSp tmp3, rFlagsReg cr)
@@ -16196,7 +16168,7 @@
// fast byte[] to char[] inflation
instruct string_inflate(Universe dummy, iRegP_R0 src, iRegP_R1 dst, iRegI_R2 len,
- vRegD tmp1, vRegD tmp2, vRegD tmp3, iRegP_R3 tmp4, rFlagsReg cr)
+ vRegD_V0 tmp1, vRegD_V1 tmp2, vRegD_V2 tmp3, iRegP_R3 tmp4, rFlagsReg cr)
%{
match(Set dummy (StrInflatedCopy src (Binary dst len)));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1638,12 +1638,14 @@
#undef INSN
// Conditional compare (both kinds)
- void conditional_compare(unsigned op, int o2, int o3,
+ void conditional_compare(unsigned op, int o1, int o2, int o3,
Register Rn, unsigned imm5, unsigned nzcv,
unsigned cond) {
+ starti;
f(op, 31, 29);
f(0b11010010, 28, 21);
f(cond, 15, 12);
+ f(o1, 11);
f(o2, 10);
f(o3, 4);
f(nzcv, 3, 0);
@@ -1652,15 +1654,12 @@
#define INSN(NAME, op) \
void NAME(Register Rn, Register Rm, int imm, Condition cond) { \
- starti; \
- f(0, 11); \
- conditional_compare(op, 0, 0, Rn, (uintptr_t)Rm, imm, cond); \
+ int regNumber = (Rm == zr ? 31 : (uintptr_t)Rm); \
+ conditional_compare(op, 0, 0, 0, Rn, regNumber, imm, cond); \
} \
\
- void NAME(Register Rn, int imm5, int imm, Condition cond) { \
- starti; \
- f(1, 11); \
- conditional_compare(op, 0, 0, Rn, imm5, imm, cond); \
+ void NAME(Register Rn, int imm5, int imm, Condition cond) { \
+ conditional_compare(op, 1, 0, 0, Rn, imm5, imm, cond); \
}
INSN(ccmnw, 0b001);
@@ -2025,6 +2024,57 @@
fmovd(Vn, zr);
}
+ // Floating-point rounding
+ // type: half-precision = 11
+ // single = 00
+ // double = 01
+ // rmode: A = Away = 100
+ // I = current = 111
+ // M = MinusInf = 010
+ // N = eveN = 000
+ // P = PlusInf = 001
+ // X = eXact = 110
+ // Z = Zero = 011
+ void float_round(unsigned type, unsigned rmode, FloatRegister Rd, FloatRegister Rn) {
+ starti;
+ f(0b00011110, 31, 24);
+ f(type, 23, 22);
+ f(0b1001, 21, 18);
+ f(rmode, 17, 15);
+ f(0b10000, 14, 10);
+ rf(Rn, 5), rf(Rd, 0);
+ }
+#define INSN(NAME, type, rmode) \
+ void NAME(FloatRegister Vd, FloatRegister Vn) { \
+ float_round(type, rmode, Vd, Vn); \
+ }
+
+public:
+ INSN(frintah, 0b11, 0b100);
+ INSN(frintih, 0b11, 0b111);
+ INSN(frintmh, 0b11, 0b010);
+ INSN(frintnh, 0b11, 0b000);
+ INSN(frintph, 0b11, 0b001);
+ INSN(frintxh, 0b11, 0b110);
+ INSN(frintzh, 0b11, 0b011);
+
+ INSN(frintas, 0b00, 0b100);
+ INSN(frintis, 0b00, 0b111);
+ INSN(frintms, 0b00, 0b010);
+ INSN(frintns, 0b00, 0b000);
+ INSN(frintps, 0b00, 0b001);
+ INSN(frintxs, 0b00, 0b110);
+ INSN(frintzs, 0b00, 0b011);
+
+ INSN(frintad, 0b01, 0b100);
+ INSN(frintid, 0b01, 0b111);
+ INSN(frintmd, 0b01, 0b010);
+ INSN(frintnd, 0b01, 0b000);
+ INSN(frintpd, 0b01, 0b001);
+ INSN(frintxd, 0b01, 0b110);
+ INSN(frintzd, 0b01, 0b011);
+#undef INSN
+
/* SIMD extensions
*
* We just use FloatRegister in the following. They are exactly the same
@@ -2294,6 +2344,42 @@
#undef INSN
+#define INSN(NAME, op1, op2) \
+ void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index = 0) { \
+ starti; \
+ assert(T == T2S || T == T4S || T == T2D, "invalid arrangement"); \
+ assert(index >= 0 && ((T == T2D && index <= 1) || (T != T2D && index <= 3)), "invalid index"); \
+ f(0, 31), f((int)T & 1, 30), f(op1, 29); f(0b011111, 28, 23); \
+ f(T == T2D ? 1 : 0, 22), f(T == T2D ? 0 : index & 1, 21), rf(Vm, 16); \
+ f(op2, 15, 12), f(T == T2D ? index : (index >> 1), 11), f(0, 10); \
+ rf(Vn, 5), rf(Vd, 0); \
+ }
+
+ // FMLA/FMLS - Vector - Scalar
+ INSN(fmlavs, 0, 0b0001);
+ INSN(fmlsvs, 0, 0b0001);
+ // FMULX - Vector - Scalar
+ INSN(fmulxvs, 1, 0b1001);
+
+#undef INSN
+
+ // Floating-point Reciprocal Estimate
+ void frecpe(FloatRegister Vd, FloatRegister Vn, SIMD_RegVariant type) {
+ assert(type == D || type == S, "Wrong type for frecpe");
+ starti;
+ f(0b010111101, 31, 23);
+ f(type == D ? 1 : 0, 22);
+ f(0b100001110110, 21, 10);
+ rf(Vn, 5), rf(Vd, 0);
+ }
+
+ // (double) {a, b} -> (a + b)
+ void faddpd(FloatRegister Vd, FloatRegister Vn) {
+ starti;
+ f(0b0111111001110000110110, 31, 10);
+ rf(Vn, 5), rf(Vd, 0);
+ }
+
void ins(FloatRegister Vd, SIMD_RegVariant T, FloatRegister Vn, int didx, int sidx) {
starti;
assert(T != Q, "invalid register variant");
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -745,6 +745,14 @@
}
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
+ assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
+ if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog ||
+ x->id() == vmIntrinsics::_dpow || x->id() == vmIntrinsics::_dcos ||
+ x->id() == vmIntrinsics::_dsin || x->id() == vmIntrinsics::_dtan ||
+ x->id() == vmIntrinsics::_dlog10) {
+ do_LibmIntrinsic(x);
+ return;
+ }
switch (x->id()) {
case vmIntrinsics::_dabs:
case vmIntrinsics::_dsqrt: {
@@ -754,61 +762,100 @@
LIR_Opr dst = rlock_result(x);
switch (x->id()) {
- case vmIntrinsics::_dsqrt: {
- __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr);
- break;
- }
- case vmIntrinsics::_dabs: {
- __ abs(value.result(), dst, LIR_OprFact::illegalOpr);
- break;
- }
+ case vmIntrinsics::_dsqrt: {
+ __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr);
+ break;
+ }
+ case vmIntrinsics::_dabs: {
+ __ abs(value.result(), dst, LIR_OprFact::illegalOpr);
+ break;
+ }
}
break;
}
- case vmIntrinsics::_dlog10: // fall through
- case vmIntrinsics::_dlog: // fall through
- case vmIntrinsics::_dsin: // fall through
- case vmIntrinsics::_dtan: // fall through
- case vmIntrinsics::_dcos: // fall through
- case vmIntrinsics::_dexp: {
- assert(x->number_of_arguments() == 1, "wrong type");
+ }
+}
+
+void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
+ LIRItem value(x->argument_at(0), this);
+ value.set_destroys_register();
+
+ LIR_Opr calc_result = rlock_result(x);
+ LIR_Opr result_reg = result_register_for(x->type());
+
+ CallingConvention* cc = NULL;
+
+ if (x->id() == vmIntrinsics::_dpow) {
+ LIRItem value1(x->argument_at(1), this);
+
+ value1.set_destroys_register();
+
+ BasicTypeList signature(2);
+ signature.append(T_DOUBLE);
+ signature.append(T_DOUBLE);
+ cc = frame_map()->c_calling_convention(&signature);
+ value.load_item_force(cc->at(0));
+ value1.load_item_force(cc->at(1));
+ } else {
+ BasicTypeList signature(1);
+ signature.append(T_DOUBLE);
+ cc = frame_map()->c_calling_convention(&signature);
+ value.load_item_force(cc->at(0));
+ }
- address runtime_entry = NULL;
- switch (x->id()) {
- case vmIntrinsics::_dsin:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
- break;
- case vmIntrinsics::_dcos:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
- break;
- case vmIntrinsics::_dtan:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
- break;
- case vmIntrinsics::_dlog:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog);
- break;
- case vmIntrinsics::_dlog10:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10);
- break;
- case vmIntrinsics::_dexp:
- runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp);
- break;
- default:
- ShouldNotReachHere();
+ switch (x->id()) {
+ case vmIntrinsics::_dexp:
+ if (StubRoutines::dexp() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ case vmIntrinsics::_dlog:
+ if (StubRoutines::dlog() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ case vmIntrinsics::_dlog10:
+ if (StubRoutines::dlog10() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dlog10(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), getThreadTemp(), result_reg, cc->args());
}
-
- LIR_Opr result = call_runtime(x->argument_at(0), runtime_entry, x->type(), NULL);
- set_result(x, result);
+ break;
+ case vmIntrinsics::_dpow:
+ if (StubRoutines::dpow() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dpow(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dpow), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ case vmIntrinsics::_dsin:
+ if (StubRoutines::dsin() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dsin(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dsin), getThreadTemp(), result_reg, cc->args());
+ }
break;
- }
- case vmIntrinsics::_dpow: {
- assert(x->number_of_arguments() == 2, "wrong type");
- address runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dpow);
- LIR_Opr result = call_runtime(x->argument_at(0), x->argument_at(1), runtime_entry, x->type(), NULL);
- set_result(x, result);
+ case vmIntrinsics::_dcos:
+ if (StubRoutines::dcos() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dcos(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dcos), getThreadTemp(), result_reg, cc->args());
+ }
break;
- }
+ case vmIntrinsics::_dtan:
+ if (StubRoutines::dtan() != NULL) {
+ __ call_runtime_leaf(StubRoutines::dtan(), getThreadTemp(), result_reg, cc->args());
+ } else {
+ __ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtan), getThreadTemp(), result_reg, cc->args());
+ }
+ break;
+ default: ShouldNotReachHere();
}
+ __ move(result_reg, calc_result);
}
--- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -71,9 +71,20 @@
return false;
}
- // unextended sp must be within the stack and above or equal sp
- bool unextended_sp_safe = (unextended_sp < thread->stack_base()) &&
- (unextended_sp >= sp);
+ // When we are running interpreted code the machine stack pointer, SP, is
+ // set low enough so that the Java expression stack can grow and shrink
+ // without ever exceeding the machine stack bounds. So, ESP >= SP.
+
+ // When we call out of an interpreted method, SP is incremented so that
+ // the space between SP and ESP is removed. The SP saved in the callee's
+ // frame is the SP *before* this increment. So, when we walk a stack of
+ // interpreter frames the sender's SP saved in a frame might be less than
+ // the SP at the point of call.
+
+ // So unextended sp must be within the stack but we need not to check
+ // that unextended sp >= sp
+
+ bool unextended_sp_safe = (unextended_sp < thread->stack_base());
if (!unextended_sp_safe) {
return false;
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -43,7 +43,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count, RegSet saved_regs) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
if (!dest_uninitialized) {
__ push(saved_regs, sp);
if (count == c_rarg0) {
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,14 +37,14 @@
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool is_not_null = (decorators & IS_NOT_NULL) != 0;
switch (type) {
case T_OBJECT:
case T_ARRAY: {
if (in_heap) {
if (UseCompressedOops) {
__ ldrw(dst, src);
- if (oop_not_null) {
+ if (is_not_null) {
__ decode_heap_oop_not_null(dst);
} else {
__ decode_heap_oop(dst);
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -91,9 +91,9 @@
void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) {
bool in_heap = (decorators & IN_HEAP) != 0;
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
bool needs_post_barrier = val != noreg && in_heap;
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, noreg, noreg);
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -3991,7 +3991,7 @@
void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1,
Register thread_tmp, DecoratorSet decorators) {
- access_load_at(T_OBJECT, IN_HEAP | OOP_NOT_NULL | decorators, dst, src, tmp1, thread_tmp);
+ access_load_at(T_OBJECT, IN_HEAP | IS_NOT_NULL | decorators, dst, src, tmp1, thread_tmp);
}
void MacroAssembler::store_heap_oop(Address dst, Register src, Register tmp1,
@@ -4316,8 +4316,10 @@
Register cnt2, Register cnt1,
Register tmp1, Register tmp2,
Register tmp3, Register tmp4,
+ Register tmp5, Register tmp6,
int icnt1, Register result, int ae) {
- Label BM, LINEARSEARCH, DONE, NOMATCH, MATCH;
+ // NOTE: tmp5, tmp6 can be zr depending on specific method version
+ Label LINEARSEARCH, LINEARSTUB, LINEAR_MEDIUM, DONE, NOMATCH, MATCH;
Register ch1 = rscratch1;
Register ch2 = rscratch2;
@@ -4346,18 +4348,21 @@
// if (substr.count > string.count) return -1;
// if (substr.count == 0) return 0;
-// We have two strings, a source string in str2, cnt2 and a pattern string
-// in str1, cnt1. Find the 1st occurence of pattern in source or return -1.
-
-// For larger pattern and source we use a simplified Boyer Moore algorithm.
-// With a small pattern and source we use linear scan.
+ // We have two strings, a source string in str2, cnt2 and a pattern string
+ // in str1, cnt1. Find the 1st occurence of pattern in source or return -1.
+
+ // For larger pattern and source we use a simplified Boyer Moore algorithm.
+ // With a small pattern and source we use linear scan.
if (icnt1 == -1) {
- cmp(cnt1, 256); // Use Linear Scan if cnt1 < 8 || cnt1 >= 256
- ccmp(cnt1, 8, 0b0000, LO); // Can't handle skip >= 256 because we use
- br(LO, LINEARSEARCH); // a byte array.
- cmp(cnt1, cnt2, LSR, 2); // Source must be 4 * pattern for BM
- br(HS, LINEARSEARCH);
+ sub(result_tmp, cnt2, cnt1);
+ cmp(cnt1, 8); // Use Linear Scan if cnt1 < 8 || cnt1 >= 256
+ br(LT, LINEARSEARCH);
+ dup(v0, T16B, cnt1); // done in separate FPU pipeline. Almost no penalty
+ cmp(cnt1, 256);
+ lsr(tmp1, cnt2, 2);
+ ccmp(cnt1, tmp1, 0b0000, LT); // Source must be 4 * pattern for BM
+ br(GE, LINEARSTUB);
}
// The Boyer Moore alogorithm is based on the description here:-
@@ -4377,7 +4382,9 @@
//
// http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm
//
-// #define ASIZE 128
+// This particular implementation has few java-specific optimizations.
+//
+// #define ASIZE 256
//
// int bm(unsigned char *x, int m, unsigned char *y, int n) {
// int i, j;
@@ -4386,11 +4393,16 @@
//
// /* Preprocessing */
// for (i = 0; i < ASIZE; ++i)
-// bc[i] = 0;
+// bc[i] = m;
// for (i = 0; i < m - 1; ) {
// c = x[i];
// ++i;
-// if (c < ASIZE) bc[c] = i;
+// // c < 256 for Latin1 string, so, no need for branch
+// #ifdef PATTERN_STRING_IS_LATIN1
+// bc[c] = m - i;
+// #else
+// if (c < ASIZE) bc[c] = m - i;
+// #endif
// }
//
// /* Searching */
@@ -4400,84 +4412,160 @@
// if (x[m-1] == c)
// for (i = m - 2; i >= 0 && x[i] == y[i + j]; --i);
// if (i < 0) return j;
+// // c < 256 for Latin1 string, so, no need for branch
+// #ifdef SOURCE_STRING_IS_LATIN1
+// // LL case: (c< 256) always true. Remove branch
+// j += bc[y[j+m-1]];
+// #endif
+// #ifndef PATTERN_STRING_IS_UTF
+// // UU case: need if (c<ASIZE) check. Skip 1 character if not.
// if (c < ASIZE)
-// j = j - bc[y[j+m-1]] + m;
+// j += bc[y[j+m-1]];
// else
-// j += 1; // Advance by 1 only if char >= ASIZE
+// j += 1
+// #endif
+// #ifdef PATTERN_IS_LATIN1_AND_SOURCE_IS_UTF
+// // UL case: need if (c<ASIZE) check. Skip <pattern length> if not.
+// if (c < ASIZE)
+// j += bc[y[j+m-1]];
+// else
+// j += m
+// #endif
// }
// }
if (icnt1 == -1) {
- BIND(BM);
-
- Label ZLOOP, BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP;
- Label BMADV, BMMATCH, BMCHECKEND;
-
+ Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH,
+ BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP;
Register cnt1end = tmp2;
Register str2end = cnt2;
Register skipch = tmp2;
- // Restrict ASIZE to 128 to reduce stack space/initialisation.
- // The presence of chars >= ASIZE in the target string does not affect
- // performance, but we must be careful not to initialise them in the stack
- // array.
- // The presence of chars >= ASIZE in the source string may adversely affect
- // performance since we can only advance by one when we encounter one.
-
- stp(zr, zr, pre(sp, -128));
- for (int i = 1; i < 8; i++)
- stp(zr, zr, Address(sp, i*16));
-
- mov(cnt1tmp, 0);
- sub(cnt1end, cnt1, 1);
+ // str1 length is >=8, so, we can read at least 1 register for cases when
+ // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for
+ // UL case. We'll re-read last character in inner pre-loop code to have
+ // single outer pre-loop load
+ const int firstStep = isL ? 7 : 3;
+
+ const int ASIZE = 256;
+ const int STORED_BYTES = 32; // amount of bytes stored per instruction
+ sub(sp, sp, ASIZE);
+ mov(tmp5, ASIZE/STORED_BYTES); // loop iterations
+ mov(ch1, sp);
+ BIND(BM_INIT_LOOP);
+ stpq(v0, v0, Address(post(ch1, STORED_BYTES)));
+ subs(tmp5, tmp5, 1);
+ br(GT, BM_INIT_LOOP);
+
+ sub(cnt1tmp, cnt1, 1);
+ mov(tmp5, str2);
+ add(str2end, str2, result_tmp, LSL, str2_chr_shift);
+ sub(ch2, cnt1, 1);
+ mov(tmp3, str1);
BIND(BCLOOP);
- (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
- cmp(ch1, 128);
- add(cnt1tmp, cnt1tmp, 1);
- br(HS, BCSKIP);
- strb(cnt1tmp, Address(sp, ch1));
+ (this->*str1_load_1chr)(ch1, Address(post(tmp3, str1_chr_size)));
+ if (!str1_isL) {
+ cmp(ch1, ASIZE);
+ br(HS, BCSKIP);
+ }
+ strb(ch2, Address(sp, ch1));
BIND(BCSKIP);
- cmp(cnt1tmp, cnt1end);
- br(LT, BCLOOP);
-
- mov(result_tmp, str2);
-
- sub(cnt2, cnt2, cnt1);
- add(str2end, str2, cnt2, LSL, str2_chr_shift);
+ subs(ch2, ch2, 1);
+ br(GT, BCLOOP);
+
+ add(tmp6, str1, cnt1, LSL, str1_chr_shift); // address after str1
+ if (str1_isL == str2_isL) {
+ // load last 8 bytes (8LL/4UU symbols)
+ ldr(tmp6, Address(tmp6, -wordSize));
+ } else {
+ ldrw(tmp6, Address(tmp6, -wordSize/2)); // load last 4 bytes(4 symbols)
+ // convert Latin1 to UTF. We'll have to wait until load completed, but
+ // it's still faster than per-character loads+checks
+ lsr(tmp3, tmp6, BitsPerByte * (wordSize/2 - str1_chr_size)); // str1[N-1]
+ ubfx(ch1, tmp6, 8, 8); // str1[N-2]
+ ubfx(ch2, tmp6, 16, 8); // str1[N-3]
+ andr(tmp6, tmp6, 0xFF); // str1[N-4]
+ orr(ch2, ch1, ch2, LSL, 16);
+ orr(tmp6, tmp6, tmp3, LSL, 48);
+ orr(tmp6, tmp6, ch2, LSL, 16);
+ }
BIND(BMLOOPSTR2);
- sub(cnt1tmp, cnt1, 1);
- (this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
(this->*str2_load_1chr)(skipch, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
- cmp(ch1, skipch);
+ sub(cnt1tmp, cnt1tmp, firstStep); // cnt1tmp is positive here, because cnt1 >= 8
+ if (str1_isL == str2_isL) {
+ // re-init tmp3. It's for free because it's executed in parallel with
+ // load above. Alternative is to initialize it before loop, but it'll
+ // affect performance on in-order systems with 2 or more ld/st pipelines
+ lsr(tmp3, tmp6, BitsPerByte * (wordSize - str1_chr_size));
+ }
+ if (!isL) { // UU/UL case
+ lsl(ch2, cnt1tmp, 1); // offset in bytes
+ }
+ cmp(tmp3, skipch);
br(NE, BMSKIP);
- subs(cnt1tmp, cnt1tmp, 1);
- br(LT, BMMATCH);
+ ldr(ch2, Address(str2, isL ? cnt1tmp : ch2));
+ mov(ch1, tmp6);
+ if (isL) {
+ b(BMLOOPSTR1_AFTER_LOAD);
+ } else {
+ sub(cnt1tmp, cnt1tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8
+ b(BMLOOPSTR1_CMP);
+ }
BIND(BMLOOPSTR1);
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
(this->*str2_load_1chr)(ch2, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
+ BIND(BMLOOPSTR1_AFTER_LOAD);
+ subs(cnt1tmp, cnt1tmp, 1);
+ br(LT, BMLOOPSTR1_LASTCMP);
+ BIND(BMLOOPSTR1_CMP);
+ cmp(ch1, ch2);
+ br(EQ, BMLOOPSTR1);
+ BIND(BMSKIP);
+ if (!isL) {
+ // if we've met UTF symbol while searching Latin1 pattern, then we can
+ // skip cnt1 symbols
+ if (str1_isL != str2_isL) {
+ mov(result_tmp, cnt1);
+ } else {
+ mov(result_tmp, 1);
+ }
+ cmp(skipch, ASIZE);
+ br(HS, BMADV);
+ }
+ ldrb(result_tmp, Address(sp, skipch)); // load skip distance
+ BIND(BMADV);
+ sub(cnt1tmp, cnt1, 1);
+ add(str2, str2, result_tmp, LSL, str2_chr_shift);
+ cmp(str2, str2end);
+ br(LE, BMLOOPSTR2);
+ add(sp, sp, ASIZE);
+ b(NOMATCH);
+ BIND(BMLOOPSTR1_LASTCMP);
cmp(ch1, ch2);
br(NE, BMSKIP);
- subs(cnt1tmp, cnt1tmp, 1);
- br(GE, BMLOOPSTR1);
BIND(BMMATCH);
- sub(result, str2, result_tmp);
+ sub(result, str2, tmp5);
if (!str2_isL) lsr(result, result, 1);
- add(sp, sp, 128);
+ add(sp, sp, ASIZE);
b(DONE);
- BIND(BMADV);
- add(str2, str2, str2_chr_size);
- b(BMCHECKEND);
- BIND(BMSKIP);
- cmp(skipch, 128);
- br(HS, BMADV);
- ldrb(ch2, Address(sp, skipch));
- add(str2, str2, cnt1, LSL, str2_chr_shift);
- sub(str2, str2, ch2, LSL, str2_chr_shift);
- BIND(BMCHECKEND);
- cmp(str2, str2end);
- br(LE, BMLOOPSTR2);
- add(sp, sp, 128);
- b(NOMATCH);
+
+ BIND(LINEARSTUB);
+ cmp(cnt1, 16); // small patterns still should be handled by simple algorithm
+ br(LT, LINEAR_MEDIUM);
+ mov(result, zr);
+ RuntimeAddress stub = NULL;
+ if (isL) {
+ stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ll());
+ assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated");
+ } else if (str1_isL) {
+ stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ul());
+ assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated");
+ } else {
+ stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_uu());
+ assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated");
+ }
+ trampoline_call(stub);
+ b(DONE);
}
BIND(LINEARSEARCH);
@@ -4493,15 +4581,12 @@
cmp(cnt1, str1_isL == str2_isL ? 4 : 2);
br(LT, DOSHORT);
-
- sub(cnt2, cnt2, cnt1);
- mov(result_tmp, cnt2);
-
+ BIND(LINEAR_MEDIUM);
+ (this->*str1_load_1chr)(first, Address(str1));
lea(str1, Address(str1, cnt1, Address::lsl(str1_chr_shift)));
- lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
sub(cnt1_neg, zr, cnt1, LSL, str1_chr_shift);
- sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
- (this->*str1_load_1chr)(first, Address(str1, cnt1_neg));
+ lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
+ sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
BIND(FIRST_LOOP);
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
@@ -4539,10 +4624,9 @@
Label CH1_LOOP;
(this->*load_4chr)(ch1, str1);
- sub(cnt2, cnt2, 4);
- mov(result_tmp, cnt2);
- lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
- sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
+ sub(result_tmp, cnt2, 4);
+ lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
+ sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
BIND(CH1_LOOP);
(this->*load_4chr)(ch2, Address(str2, cnt2_neg));
@@ -4551,18 +4635,18 @@
adds(cnt2_neg, cnt2_neg, str2_chr_size);
br(LE, CH1_LOOP);
b(NOMATCH);
- }
+ }
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 2) {
Label CH1_LOOP;
BIND(DO2);
(this->*load_2chr)(ch1, str1);
- sub(cnt2, cnt2, 2);
- mov(result_tmp, cnt2);
- lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
- sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
-
+ if (icnt1 == 2) {
+ sub(result_tmp, cnt2, 2);
+ }
+ lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
+ sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
BIND(CH1_LOOP);
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmp(ch1, ch2);
@@ -4578,12 +4662,11 @@
BIND(DO3);
(this->*load_2chr)(first, str1);
(this->*str1_load_1chr)(ch1, Address(str1, 2*str1_chr_size));
-
- sub(cnt2, cnt2, 3);
- mov(result_tmp, cnt2);
- lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
- sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
-
+ if (icnt1 == 3) {
+ sub(result_tmp, cnt2, 3);
+ }
+ lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
+ sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
BIND(FIRST_LOOP);
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
cmpw(first, ch2);
@@ -4602,30 +4685,23 @@
}
if (icnt1 == -1 || icnt1 == 1) {
- Label CH1_LOOP, HAS_ZERO;
- Label DO1_SHORT, DO1_LOOP;
+ Label CH1_LOOP, HAS_ZERO, DO1_SHORT, DO1_LOOP;
BIND(DO1);
(this->*str1_load_1chr)(ch1, str1);
cmp(cnt2, 8);
br(LT, DO1_SHORT);
+ sub(result_tmp, cnt2, 8/str2_chr_size);
+ sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
+ mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
+ lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
+
if (str2_isL) {
- if (!str1_isL) {
- tst(ch1, 0xff00);
- br(NE, NOMATCH);
- }
orr(ch1, ch1, ch1, LSL, 8);
}
orr(ch1, ch1, ch1, LSL, 16);
orr(ch1, ch1, ch1, LSL, 32);
-
- sub(cnt2, cnt2, 8/str2_chr_size);
- mov(result_tmp, cnt2);
- lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
- sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
-
- mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
BIND(CH1_LOOP);
ldr(ch2, Address(str2, cnt2_neg));
eor(ch2, ch1, ch2);
@@ -4733,12 +4809,13 @@
// Compare strings.
void MacroAssembler::string_compare(Register str1, Register str2,
- Register cnt1, Register cnt2, Register result,
- Register tmp1,
- FloatRegister vtmp, FloatRegister vtmpZ, int ae) {
- Label LENGTH_DIFF, DONE, SHORT_LOOP, SHORT_STRING,
- NEXT_WORD, DIFFERENCE;
-
+ Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
+ FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
+ Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
+ DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
+ SHORT_LOOP_START, TAIL_CHECK;
+
+ const int STUB_THRESHOLD = 64 + 8;
bool isLL = ae == StrIntrinsicNode::LL;
bool isLU = ae == StrIntrinsicNode::LU;
bool isUL = ae == StrIntrinsicNode::UL;
@@ -4750,7 +4827,9 @@
int str2_chr_shift = str2_isL ? 0 : 1;
int str1_chr_size = str1_isL ? 1 : 2;
int str2_chr_size = str2_isL ? 1 : 2;
-
+ int minCharsInWord = isLL ? wordSize : wordSize/2;
+
+ FloatRegister vtmpZ = vtmp1, vtmp = vtmp2;
chr_insn str1_load_chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
(chr_insn)&MacroAssembler::ldrh;
chr_insn str2_load_chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
@@ -4766,73 +4845,116 @@
if (!str2_isL) asrw(cnt2, cnt2, 1);
// Compute the minimum of the string lengths and save the difference.
- subsw(tmp1, cnt1, cnt2);
+ subsw(result, cnt1, cnt2);
cselw(cnt2, cnt1, cnt2, Assembler::LE); // min
// A very short string
- cmpw(cnt2, isLL ? 8:4);
+ cmpw(cnt2, minCharsInWord);
br(Assembler::LT, SHORT_STRING);
- // Check if the strings start at the same location.
- cmp(str1, str2);
- br(Assembler::EQ, LENGTH_DIFF);
-
// Compare longwords
+ // load first parts of strings and finish initialization while loading
{
- subw(cnt2, cnt2, isLL ? 8:4); // The last longword is a special case
-
- // Move both string pointers to the last longword of their
- // strings, negate the remaining count, and convert it to bytes.
- lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
- lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
- if (isLU || isUL) {
- sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
+ if (str1_isL == str2_isL) { // LL or UU
+ ldr(tmp1, Address(str1));
+ cmp(str1, str2);
+ br(Assembler::EQ, DONE);
+ ldr(tmp2, Address(str2));
+ cmp(cnt2, STUB_THRESHOLD);
+ br(GE, STUB);
+ subsw(cnt2, cnt2, minCharsInWord);
+ br(EQ, TAIL_CHECK);
+ lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
+ lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
+ sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
+ } else if (isLU) {
+ ldrs(vtmp, Address(str1));
+ cmp(str1, str2);
+ br(Assembler::EQ, DONE);
+ ldr(tmp2, Address(str2));
+ cmp(cnt2, STUB_THRESHOLD);
+ br(GE, STUB);
+ subsw(cnt2, cnt2, 4);
+ br(EQ, TAIL_CHECK);
eor(vtmpZ, T16B, vtmpZ, vtmpZ);
- }
- sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
-
- // Loop, loading longwords and comparing them into rscratch2.
- bind(NEXT_WORD);
- if (isLU) {
- ldrs(vtmp, Address(str1, cnt1));
+ lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
+ lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
zip1(vtmp, T8B, vtmp, vtmpZ);
- umov(result, vtmp, D, 0);
- } else {
- ldr(result, Address(str1, isUL ? cnt1:cnt2));
- }
- if (isUL) {
- ldrs(vtmp, Address(str2, cnt2));
+ sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
+ sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
+ add(cnt1, cnt1, 4);
+ fmovd(tmp1, vtmp);
+ } else { // UL case
+ ldr(tmp1, Address(str1));
+ cmp(str1, str2);
+ br(Assembler::EQ, DONE);
+ ldrs(vtmp, Address(str2));
+ cmp(cnt2, STUB_THRESHOLD);
+ br(GE, STUB);
+ subsw(cnt2, cnt2, 4);
+ br(EQ, TAIL_CHECK);
+ lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
+ eor(vtmpZ, T16B, vtmpZ, vtmpZ);
+ lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
+ sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
zip1(vtmp, T8B, vtmp, vtmpZ);
- umov(rscratch1, vtmp, D, 0);
- } else {
- ldr(rscratch1, Address(str2, cnt2));
+ sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
+ add(cnt1, cnt1, 8);
+ fmovd(tmp2, vtmp);
}
- adds(cnt2, cnt2, isUL ? 4:8);
- if (isLU || isUL) add(cnt1, cnt1, isLU ? 4:8);
- eor(rscratch2, result, rscratch1);
+ adds(cnt2, cnt2, isUL ? 4 : 8);
+ br(GE, TAIL);
+ eor(rscratch2, tmp1, tmp2);
cbnz(rscratch2, DIFFERENCE);
- br(Assembler::LT, NEXT_WORD);
-
+ // main loop
+ bind(NEXT_WORD);
+ if (str1_isL == str2_isL) {
+ ldr(tmp1, Address(str1, cnt2));
+ ldr(tmp2, Address(str2, cnt2));
+ adds(cnt2, cnt2, 8);
+ } else if (isLU) {
+ ldrs(vtmp, Address(str1, cnt1));
+ ldr(tmp2, Address(str2, cnt2));
+ add(cnt1, cnt1, 4);
+ zip1(vtmp, T8B, vtmp, vtmpZ);
+ fmovd(tmp1, vtmp);
+ adds(cnt2, cnt2, 8);
+ } else { // UL
+ ldrs(vtmp, Address(str2, cnt2));
+ ldr(tmp1, Address(str1, cnt1));
+ zip1(vtmp, T8B, vtmp, vtmpZ);
+ add(cnt1, cnt1, 8);
+ fmovd(tmp2, vtmp);
+ adds(cnt2, cnt2, 4);
+ }
+ br(GE, TAIL);
+
+ eor(rscratch2, tmp1, tmp2);
+ cbz(rscratch2, NEXT_WORD);
+ b(DIFFERENCE);
+ bind(TAIL);
+ eor(rscratch2, tmp1, tmp2);
+ cbnz(rscratch2, DIFFERENCE);
// Last longword. In the case where length == 4 we compare the
// same longword twice, but that's still faster than another
// conditional branch.
-
- if (isLU) {
+ if (str1_isL == str2_isL) {
+ ldr(tmp1, Address(str1));
+ ldr(tmp2, Address(str2));
+ } else if (isLU) {
ldrs(vtmp, Address(str1));
+ ldr(tmp2, Address(str2));
zip1(vtmp, T8B, vtmp, vtmpZ);
- umov(result, vtmp, D, 0);
- } else {
- ldr(result, Address(str1));
+ fmovd(tmp1, vtmp);
+ } else { // UL
+ ldrs(vtmp, Address(str2));
+ ldr(tmp1, Address(str1));
+ zip1(vtmp, T8B, vtmp, vtmpZ);
+ fmovd(tmp2, vtmp);
}
- if (isUL) {
- ldrs(vtmp, Address(str2));
- zip1(vtmp, T8B, vtmp, vtmpZ);
- umov(rscratch1, vtmp, D, 0);
- } else {
- ldr(rscratch1, Address(str2));
- }
- eor(rscratch2, result, rscratch1);
- cbz(rscratch2, LENGTH_DIFF);
+ bind(TAIL_CHECK);
+ eor(rscratch2, tmp1, tmp2);
+ cbz(rscratch2, DONE);
// Find the first different characters in the longwords and
// compute their difference.
@@ -4840,31 +4962,78 @@
rev(rscratch2, rscratch2);
clz(rscratch2, rscratch2);
andr(rscratch2, rscratch2, isLL ? -8 : -16);
- lsrv(result, result, rscratch2);
- (this->*ext_chr)(result, result);
- lsrv(rscratch1, rscratch1, rscratch2);
- (this->*ext_chr)(rscratch1, rscratch1);
- subw(result, result, rscratch1);
+ lsrv(tmp1, tmp1, rscratch2);
+ (this->*ext_chr)(tmp1, tmp1);
+ lsrv(tmp2, tmp2, rscratch2);
+ (this->*ext_chr)(tmp2, tmp2);
+ subw(result, tmp1, tmp2);
b(DONE);
}
+ bind(STUB);
+ RuntimeAddress stub = NULL;
+ switch(ae) {
+ case StrIntrinsicNode::LL:
+ stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LL());
+ break;
+ case StrIntrinsicNode::UU:
+ stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UU());
+ break;
+ case StrIntrinsicNode::LU:
+ stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LU());
+ break;
+ case StrIntrinsicNode::UL:
+ stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UL());
+ break;
+ default:
+ ShouldNotReachHere();
+ }
+ assert(stub.target() != NULL, "compare_long_string stub has not been generated");
+ trampoline_call(stub);
+ b(DONE);
+
bind(SHORT_STRING);
// Is the minimum length zero?
- cbz(cnt2, LENGTH_DIFF);
-
+ cbz(cnt2, DONE);
+ // arrange code to do most branches while loading and loading next characters
+ // while comparing previous
+ (this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
+ subs(cnt2, cnt2, 1);
+ br(EQ, SHORT_LAST_INIT);
+ (this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
+ b(SHORT_LOOP_START);
bind(SHORT_LOOP);
- (this->*str1_load_chr)(result, Address(post(str1, str1_chr_size)));
+ subs(cnt2, cnt2, 1);
+ br(EQ, SHORT_LAST);
+ bind(SHORT_LOOP_START);
+ (this->*str1_load_chr)(tmp2, Address(post(str1, str1_chr_size)));
+ (this->*str2_load_chr)(rscratch1, Address(post(str2, str2_chr_size)));
+ cmp(tmp1, cnt1);
+ br(NE, SHORT_LOOP_TAIL);
+ subs(cnt2, cnt2, 1);
+ br(EQ, SHORT_LAST2);
+ (this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
- subw(result, result, cnt1);
- cbnz(result, DONE);
- sub(cnt2, cnt2, 1);
- cbnz(cnt2, SHORT_LOOP);
-
- // Strings are equal up to min length. Return the length difference.
- bind(LENGTH_DIFF);
- mov(result, tmp1);
-
- // That's it
+ cmp(tmp2, rscratch1);
+ br(EQ, SHORT_LOOP);
+ sub(result, tmp2, rscratch1);
+ b(DONE);
+ bind(SHORT_LOOP_TAIL);
+ sub(result, tmp1, cnt1);
+ b(DONE);
+ bind(SHORT_LAST2);
+ cmp(tmp2, rscratch1);
+ br(EQ, DONE);
+ sub(result, tmp2, rscratch1);
+
+ b(DONE);
+ bind(SHORT_LAST_INIT);
+ (this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
+ bind(SHORT_LAST);
+ cmp(tmp1, cnt1);
+ br(EQ, DONE);
+ sub(result, tmp1, cnt1);
+
bind(DONE);
BLOCK_COMMENT("} string_compare");
@@ -4928,9 +5097,8 @@
void MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
Register tmp4, Register tmp5, Register result,
- Register cnt1, int elem_size)
-{
- Label DONE;
+ Register cnt1, int elem_size) {
+ Label DONE, SAME;
Register tmp1 = rscratch1;
Register tmp2 = rscratch2;
Register cnt2 = tmp2; // cnt2 only used in array length compare
@@ -4952,21 +5120,21 @@
BLOCK_COMMENT(comment);
}
#endif
+
+ // if (a1 == a2)
+ // return true;
+ cmpoop(a1, a2); // May have read barriers for a1 and a2.
+ br(EQ, SAME);
+
if (UseSimpleArrayEquals) {
- Label NEXT_WORD, SHORT, SAME, TAIL03, TAIL01, A_MIGHT_BE_NULL, A_IS_NOT_NULL;
- // if (a1==a2)
- // return true;
- // if (a==null || a2==null)
+ Label NEXT_WORD, SHORT, TAIL03, TAIL01, A_MIGHT_BE_NULL, A_IS_NOT_NULL;
+ // if (a1 == null || a2 == null)
// return false;
// a1 & a2 == 0 means (some-pointer is null) or
// (very-rare-or-even-probably-impossible-pointer-values)
// so, we can save one branch in most cases
- cmpoop(a1, a2);
- br(EQ, SAME);
- eor(rscratch1, a1, a2);
tst(a1, a2);
mov(result, false);
- cbz(rscratch1, SAME);
br(EQ, A_MIGHT_BE_NULL);
// if (a1.length != a2.length)
// return false;
@@ -5032,22 +5200,18 @@
cbnzw(tmp5, DONE);
}
}
- bind(SAME);
- mov(result, true);
} else {
- Label NEXT_DWORD, A_IS_NULL, SHORT, TAIL, TAIL2, STUB, EARLY_OUT,
- CSET_EQ, LAST_CHECK, LEN_IS_ZERO, SAME;
- cbz(a1, A_IS_NULL);
+ Label NEXT_DWORD, SHORT, TAIL, TAIL2, STUB, EARLY_OUT,
+ CSET_EQ, LAST_CHECK;
+ mov(result, false);
+ cbz(a1, DONE);
ldrw(cnt1, Address(a1, length_offset));
- cbz(a2, A_IS_NULL);
+ cbz(a2, DONE);
ldrw(cnt2, Address(a2, length_offset));
- mov(result, false);
// on most CPUs a2 is still "locked"(surprisingly) in ldrw and it's
// faster to perform another branch before comparing a1 and a2
cmp(cnt1, elem_per_word);
br(LE, SHORT); // short or same
- cmpoop(a1, a2);
- br(EQ, SAME);
ldr(tmp3, Address(pre(a1, base_offset)));
cmp(cnt1, stubBytesThreshold);
br(GE, STUB);
@@ -5099,23 +5263,15 @@
trampoline_call(stub);
b(DONE);
- bind(SAME);
- mov(result, true);
- b(DONE);
- bind(A_IS_NULL);
- // a1 or a2 is null. if a2 == a2 then return true. else return false
- cmp(a1, a2);
- b(CSET_EQ);
bind(EARLY_OUT);
// (a1 != null && a2 == null) || (a1 != null && a2 != null && a1 == a2)
// so, if a2 == null => return false(0), else return true, so we can return a2
mov(result, a2);
b(DONE);
- bind(LEN_IS_ZERO);
- cmp(cnt2, zr);
- b(CSET_EQ);
bind(SHORT);
- cbz(cnt1, LEN_IS_ZERO);
+ cmp(cnt2, cnt1);
+ br(NE, DONE);
+ cbz(cnt1, SAME);
sub(tmp5, zr, cnt1, LSL, 3 + log_elem_size);
ldr(tmp3, Address(a1, base_offset));
ldr(tmp4, Address(a2, base_offset));
@@ -5125,8 +5281,11 @@
cmp(tmp5, zr);
bind(CSET_EQ);
cset(result, EQ);
+ b(DONE);
}
+ bind(SAME);
+ mov(result, true);
// That's it.
bind(DONE);
@@ -5418,65 +5577,103 @@
FloatRegister Vtmp1, FloatRegister Vtmp2,
FloatRegister Vtmp3, FloatRegister Vtmp4)
{
- Label DONE, NEXT_32, LOOP_8, NEXT_8, LOOP_1, NEXT_1;
- Register tmp1 = rscratch1;
+ Label DONE, SET_RESULT, NEXT_32, NEXT_32_PRFM, LOOP_8, NEXT_8, LOOP_1, NEXT_1,
+ NEXT_32_START, NEXT_32_PRFM_START;
+ Register tmp1 = rscratch1, tmp2 = rscratch2;
mov(result, len); // Save initial len
#ifndef BUILTIN_SIM
- subs(len, len, 32);
- br(LT, LOOP_8);
-
-// The following code uses the SIMD 'uqxtn' and 'uqxtn2' instructions
-// to convert chars to bytes. These set the 'QC' bit in the FPSR if
-// any char could not fit in a byte, so clear the FPSR so we can test it.
- clear_fpsr();
-
- BIND(NEXT_32);
- ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
- uqxtn(Vtmp1, T8B, Vtmp1, T8H); // uqxtn - write bottom half
- uqxtn(Vtmp1, T16B, Vtmp2, T8H); // uqxtn2 - write top half
- uqxtn(Vtmp2, T8B, Vtmp3, T8H);
- uqxtn(Vtmp2, T16B, Vtmp4, T8H); // uqxtn2
- get_fpsr(tmp1);
- cbnzw(tmp1, LOOP_8);
- st1(Vtmp1, Vtmp2, T16B, post(dst, 32));
- subs(len, len, 32);
+ cmp(len, 8); // handle shortest strings first
+ br(LT, LOOP_1);
+ cmp(len, 32);
+ br(LT, NEXT_8);
+ // The following code uses the SIMD 'uzp1' and 'uzp2' instructions
+ // to convert chars to bytes
+ if (SoftwarePrefetchHintDistance >= 0) {
+ ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
+ cmp(len, SoftwarePrefetchHintDistance/2 + 16);
+ br(LE, NEXT_32_START);
+ b(NEXT_32_PRFM_START);
+ BIND(NEXT_32_PRFM);
+ ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
+ BIND(NEXT_32_PRFM_START);
+ prfm(Address(src, SoftwarePrefetchHintDistance));
+ orr(v4, T16B, Vtmp1, Vtmp2);
+ orr(v5, T16B, Vtmp3, Vtmp4);
+ uzp1(Vtmp1, T16B, Vtmp1, Vtmp2);
+ uzp1(Vtmp3, T16B, Vtmp3, Vtmp4);
+ stpq(Vtmp1, Vtmp3, dst);
+ uzp2(v5, T16B, v4, v5); // high bytes
+ umov(tmp2, v5, D, 1);
+ fmovd(tmp1, v5);
+ orr(tmp1, tmp1, tmp2);
+ cbnz(tmp1, LOOP_8);
+ sub(len, len, 32);
+ add(dst, dst, 32);
+ add(src, src, 64);
+ cmp(len, SoftwarePrefetchHintDistance/2 + 16);
+ br(GE, NEXT_32_PRFM);
+ cmp(len, 32);
+ br(LT, LOOP_8);
+ BIND(NEXT_32);
+ ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
+ BIND(NEXT_32_START);
+ } else {
+ BIND(NEXT_32);
+ ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
+ }
+ prfm(Address(src, SoftwarePrefetchHintDistance));
+ uzp1(v4, T16B, Vtmp1, Vtmp2);
+ uzp1(v5, T16B, Vtmp3, Vtmp4);
+ stpq(v4, v5, dst);
+ orr(Vtmp1, T16B, Vtmp1, Vtmp2);
+ orr(Vtmp3, T16B, Vtmp3, Vtmp4);
+ uzp2(Vtmp1, T16B, Vtmp1, Vtmp3); // high bytes
+ umov(tmp2, Vtmp1, D, 1);
+ fmovd(tmp1, Vtmp1);
+ orr(tmp1, tmp1, tmp2);
+ cbnz(tmp1, LOOP_8);
+ sub(len, len, 32);
+ add(dst, dst, 32);
add(src, src, 64);
+ cmp(len, 32);
br(GE, NEXT_32);
+ cbz(len, DONE);
BIND(LOOP_8);
- adds(len, len, 32-8);
+ cmp(len, 8);
br(LT, LOOP_1);
- clear_fpsr(); // QC may be set from loop above, clear again
BIND(NEXT_8);
ld1(Vtmp1, T8H, src);
- uqxtn(Vtmp1, T8B, Vtmp1, T8H);
- get_fpsr(tmp1);
- cbnzw(tmp1, LOOP_1);
- st1(Vtmp1, T8B, post(dst, 8));
- subs(len, len, 8);
+ uzp1(Vtmp2, T16B, Vtmp1, Vtmp1); // low bytes
+ uzp2(Vtmp3, T16B, Vtmp1, Vtmp1); // high bytes
+ strd(Vtmp2, dst);
+ fmovd(tmp1, Vtmp3);
+ cbnz(tmp1, NEXT_1);
+
+ sub(len, len, 8);
+ add(dst, dst, 8);
add(src, src, 16);
+ cmp(len, 8);
br(GE, NEXT_8);
BIND(LOOP_1);
- adds(len, len, 8);
- br(LE, DONE);
-#else
- cbz(len, DONE);
#endif
+ cbz(len, DONE);
BIND(NEXT_1);
ldrh(tmp1, Address(post(src, 2)));
+ strb(tmp1, Address(post(dst, 1)));
tst(tmp1, 0xff00);
- br(NE, DONE);
- strb(tmp1, Address(post(dst, 1)));
+ br(NE, SET_RESULT);
subs(len, len, 1);
br(GT, NEXT_1);
- BIND(DONE);
+ BIND(SET_RESULT);
sub(result, result, len); // Return index where we stopped
// Return len == 0 if we processed all
// characters
+ BIND(DONE);
}
@@ -5484,26 +5681,24 @@
void MacroAssembler::byte_array_inflate(Register src, Register dst, Register len,
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3,
Register tmp4) {
- Label big, done;
+ Label big, done, after_init, to_stub;
assert_different_registers(src, dst, len, tmp4, rscratch1);
- fmovd(vtmp1 , zr);
- lsrw(rscratch1, len, 3);
-
- cbnzw(rscratch1, big);
-
+ fmovd(vtmp1, zr);
+ lsrw(tmp4, len, 3);
+ bind(after_init);
+ cbnzw(tmp4, big);
// Short string: less than 8 bytes.
{
- Label loop, around, tiny;
-
- subsw(len, len, 4);
- andw(len, len, 3);
- br(LO, tiny);
-
+ Label loop, tiny;
+
+ cmpw(len, 4);
+ br(LT, tiny);
// Use SIMD to do 4 bytes.
ldrs(vtmp2, post(src, 4));
zip1(vtmp3, T8B, vtmp2, vtmp1);
+ subw(len, len, 4);
strd(vtmp3, post(dst, 8));
cbzw(len, done);
@@ -5517,35 +5712,65 @@
bind(tiny);
cbnz(len, loop);
- bind(around);
b(done);
}
+ if (SoftwarePrefetchHintDistance >= 0) {
+ bind(to_stub);
+ RuntimeAddress stub = RuntimeAddress(StubRoutines::aarch64::large_byte_array_inflate());
+ assert(stub.target() != NULL, "large_byte_array_inflate stub has not been generated");
+ trampoline_call(stub);
+ b(after_init);
+ }
+
// Unpack the bytes 8 at a time.
bind(big);
- andw(len, len, 7);
-
{
- Label loop, around;
-
- bind(loop);
- ldrd(vtmp2, post(src, 8));
- sub(rscratch1, rscratch1, 1);
- zip1(vtmp3, T16B, vtmp2, vtmp1);
- st1(vtmp3, T8H, post(dst, 16));
- cbnz(rscratch1, loop);
-
- bind(around);
+ Label loop, around, loop_last, loop_start;
+
+ if (SoftwarePrefetchHintDistance >= 0) {
+ const int large_loop_threshold = (64 + 16)/8;
+ ldrd(vtmp2, post(src, 8));
+ andw(len, len, 7);
+ cmp(tmp4, large_loop_threshold);
+ br(GE, to_stub);
+ b(loop_start);
+
+ bind(loop);
+ ldrd(vtmp2, post(src, 8));
+ bind(loop_start);
+ subs(tmp4, tmp4, 1);
+ br(EQ, loop_last);
+ zip1(vtmp2, T16B, vtmp2, vtmp1);
+ ldrd(vtmp3, post(src, 8));
+ st1(vtmp2, T8H, post(dst, 16));
+ subs(tmp4, tmp4, 1);
+ zip1(vtmp3, T16B, vtmp3, vtmp1);
+ st1(vtmp3, T8H, post(dst, 16));
+ br(NE, loop);
+ b(around);
+ bind(loop_last);
+ zip1(vtmp2, T16B, vtmp2, vtmp1);
+ st1(vtmp2, T8H, post(dst, 16));
+ bind(around);
+ cbz(len, done);
+ } else {
+ andw(len, len, 7);
+ bind(loop);
+ ldrd(vtmp2, post(src, 8));
+ sub(tmp4, tmp4, 1);
+ zip1(vtmp3, T16B, vtmp2, vtmp1);
+ st1(vtmp3, T8H, post(dst, 16));
+ cbnz(tmp4, loop);
+ }
}
// Do the tail of up to 8 bytes.
- sub(src, src, 8);
- add(src, src, len, ext::uxtw, 0);
- ldrd(vtmp2, Address(src));
- sub(dst, dst, 16);
+ add(src, src, len);
+ ldrd(vtmp3, Address(src, -8));
add(dst, dst, len, ext::uxtw, 1);
- zip1(vtmp3, T16B, vtmp2, vtmp1);
- st1(vtmp3, T8H, Address(dst));
+ zip1(vtmp3, T16B, vtmp3, vtmp1);
+ strq(vtmp3, Address(dst, -16));
bind(done);
}
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1212,8 +1212,8 @@
void string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
- Register tmp1,
- FloatRegister vtmp, FloatRegister vtmpZ, int ae);
+ Register tmp1, Register tmp2, FloatRegister vtmp1,
+ FloatRegister vtmp2, FloatRegister vtmp3, int ae);
void has_negatives(Register ary1, Register len, Register result);
@@ -1247,11 +1247,25 @@
Register cnt1, Register cnt2,
Register tmp1, Register tmp2,
Register tmp3, Register tmp4,
+ Register tmp5, Register tmp6,
int int_cnt1, Register result, int ae);
void string_indexof_char(Register str1, Register cnt1,
Register ch, Register result,
Register tmp1, Register tmp2, Register tmp3);
-private:
+ void fast_log(FloatRegister vtmp0, FloatRegister vtmp1, FloatRegister vtmp2,
+ FloatRegister vtmp3, FloatRegister vtmp4, FloatRegister vtmp5,
+ FloatRegister tmpC1, FloatRegister tmpC2, FloatRegister tmpC3,
+ FloatRegister tmpC4, Register tmp1, Register tmp2,
+ Register tmp3, Register tmp4, Register tmp5);
+ void generate_dsin_dcos(bool isCos, address npio2_hw, address two_over_pi,
+ address pio2, address dsin_coef, address dcos_coef);
+ private:
+ // begin trigonometric functions support block
+ void generate__ieee754_rem_pio2(address npio2_hw, address two_over_pi, address pio2);
+ void generate__kernel_rem_pio2(address two_over_pi, address pio2);
+ void generate_kernel_sin(FloatRegister x, bool iyIsOne, address dsin_coef);
+ void generate_kernel_cos(FloatRegister x, address dcos_coef);
+ // end trigonometric functions support block
void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo,
Register src1, Register src2);
void add2_with_carry(Register dest_hi, Register dest_lo, Register src1, Register src2) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,365 @@
+/* Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT)
+ * Copyright (c) 2016, Intel Corporation.
+ * Intel Math Library (LIBM) Source Code
+ *
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "macroAssembler_aarch64.hpp"
+
+// Algorithm idea is taken from x86 hotspot intrinsic and adapted for AARCH64.
+//
+// For mathematical background please refer to the following literature:
+//
+// Tang, Ping-Tak Peter.
+// Table-driven implementation of the logarithm function
+// in IEEE floating-point arithmetic.
+// ACM Transactions on Mathematical Software (TOMS) 16, no. 4, 1990: 378-400.
+
+/******************************************************************************/
+// ALGORITHM DESCRIPTION - LOG()
+// ---------------------
+//
+// x=2^k * mx, mx in [1,2)
+//
+// Get B~1/mx based on the output of frecpe instruction (B0)
+// B = int((B0*2^7+0.5))/2^7
+//
+// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
+//
+// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
+// p(r) is a degree 7 polynomial
+// -log(B) read from data table (high, low parts)
+// Result is formed from high and low parts
+//
+// Special cases:
+// 1. log(NaN) = quiet NaN
+// 2. log(+INF) = that INF
+// 3. log(0) = -INF
+// 4. log(1) = +0
+// 5. log(x) = NaN if x < -0, including -INF
+//
+/******************************************************************************/
+
+// Table with p(r) polynomial coefficients
+// and table representation of logarithm values (hi and low parts)
+__attribute__ ((aligned(64))) juint _L_tbl[] =
+{
+ // coefficients of p(r) polynomial:
+ // _coeff[]
+ 0x00000000UL, 0xbfd00000UL, // C1_0 = -0.25
+ 0x92492492UL, 0x3fc24924UL, // C1_1 = 0.14285714285714285
+ 0x55555555UL, 0x3fd55555UL, // C2_0 = 0.3333333333333333
+ 0x3d6fb175UL, 0xbfc5555eUL, // C2_1 = -0.16666772842235003
+ 0x00000000UL, 0xbfe00000UL, // C3_0 = -0.5
+ 0x9999999aUL, 0x3fc99999UL, // C3_1 = 0.2
+ // _log2[]
+ 0xfefa3800UL, 0x3fa62e42UL, // C4_0 = 0.043321698784993146
+ 0x93c76730UL, 0x3ceef357UL, // C4_1 = 3.436201886692732e-15
+ // _L_tbl[] with logarithm values (hi and low parts)
+ 0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
+ 0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
+ 0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
+ 0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
+ 0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
+ 0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
+ 0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
+ 0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
+ 0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
+ 0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
+ 0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
+ 0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
+ 0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
+ 0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
+ 0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
+ 0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
+ 0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
+ 0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
+ 0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
+ 0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
+ 0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
+ 0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
+ 0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
+ 0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
+ 0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
+ 0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
+ 0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
+ 0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
+ 0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
+ 0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
+ 0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
+ 0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
+ 0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
+ 0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
+ 0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
+ 0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
+ 0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
+ 0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
+ 0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
+ 0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
+ 0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
+ 0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
+ 0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
+ 0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
+ 0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
+ 0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
+ 0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
+ 0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
+ 0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
+ 0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
+ 0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
+ 0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
+ 0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
+ 0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
+ 0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
+ 0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
+ 0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
+ 0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
+ 0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
+ 0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
+ 0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
+ 0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
+ 0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
+ 0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
+ 0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
+ 0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
+ 0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
+ 0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
+ 0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
+ 0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
+ 0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
+ 0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
+ 0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
+ 0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
+ 0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
+ 0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
+ 0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
+ 0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
+ 0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
+ 0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
+ 0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
+ 0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
+ 0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
+ 0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
+ 0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
+ 0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
+ 0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
+ 0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
+ 0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
+ 0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
+ 0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
+ 0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
+ 0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
+ 0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
+ 0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
+ 0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
+ 0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
+ 0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
+ 0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
+ 0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
+ 0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
+ 0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
+ 0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
+ 0x80000000UL
+};
+
+// BEGIN dlog PSEUDO CODE:
+// double dlog(double X) {
+// // p(r) polynomial coefficients initialized from _L_tbl table
+// double C1_0 = _L_tbl[0];
+// double C1_1 = _L_tbl[1];
+// double C2_0 = _L_tbl[2];
+// double C2_1 = _L_tbl[3];
+// double C3_0 = _L_tbl[4];
+// double C3_1 = _L_tbl[5];
+// double C4_0 = _L_tbl[6];
+// double C4_1 = _L_tbl[7];
+// // NOTE: operations with coefficients above are mostly vectorized in assembly
+// // Check corner cases first
+// if (X == 1.0d || AS_LONG_BITS(X) + 0x0010000000000000 <= 0x0010000000000000) {
+// // NOTE: AS_LONG_BITS(X) + 0x0010000000000000 <= 0x0010000000000000 means
+// // that X < 0 or X >= 0x7FF0000000000000 (0x7FF* is NaN or INF)
+// if (X < 0 || X is NaN) return NaN;
+// if (X == 1.0d) return 0.0d;
+// if (X == 0.0d) return -INFINITY;
+// if (X is INFINITY) return INFINITY;
+// }
+// // double representation is 2^exponent * mantissa
+// // split X into two multipliers: 2^exponent and 1.0 * mantissa
+// // pseudo function: zeroExponent(X) return value of X with exponent == 0
+// float vtmp5 = 1/(float)(zeroExponent(X)); // reciprocal estimate
+// // pseudo function: HI16(X) returns high 16 bits of double value
+// int hiWord = HI16(X);
+// double vtmp1 = (double) 0x77F0 << 48 | mantissa(X);
+// hiWord -= 16;
+// if (AS_LONG_BITS(hiWord) > 0x8000) {
+// // SMALL_VALUE branch
+// vtmp0 = vtmp1 = vtmp0 * AS_DOUBLE_BITS(0x47F0000000000000);
+// hiWord = HI16(vtmp1);
+// vtmp0 = AS_DOUBLE_BITS(AS_LONG_BITS(vtmp0) |= 0x3FF0000000000000);
+// vtmp5 = (double) (1/(float)vtmp0);
+// vtmp1 <<= 12;
+// vtmp1 >>= 12;
+// }
+// // MAIN branch
+// double vtmp3 = AS_LONG_BITS(vtmp1) & 0xffffe00000000000; // hi part
+// int intB0 = AS_INT_BITS(vtmp5) + 0x8000;
+// double vtmp0 = AS_DOUBLE_BITS(0xffffe00000000000 & (intB0<<29));
+// int index = (intB0 >> 16) && 0xFF;
+// double hiTableValue = _L_tbl[8+index]; // vtmp2[0]
+// double lowTableValue = _L_tbl[16+index]; // vtmp2[1]
+// vtmp5 = AS_DOUBLE_BITS(hiWord & 0x7FF0 - 0x3FE0); // 0x3FE = 1023 << 4
+// vtmp1 -= vtmp3; // low part
+// vtmp3 = vtmp3*vtmp0 - 1.0;
+// hiTableValue += C4_0 * vtmp5;
+// lowTableValue += C4_1 * vtmp5;
+// double r = vtmp1 * vtmp0 + vtmp3; // r = B*mx-1.0, computed in hi and low parts
+// vtmp0 = hiTableValue + r;
+// hiTableValue -= vtmp0;
+// double r2 = r*r;
+// double r3 = r2*r;
+// double p7 = C3_0*r2 + C2_0*r3 + C1_0*r2*r2 + C3_1*r3*r2 + C2_1*r3*r3
+// + C1_1*r3*r2*r2; // degree 7 polynomial
+// return p7 + (vtmp0 + ((r + hiTableValue) + lowTableValue));
+// }
+//
+// END dlog PSEUDO CODE
+
+
+// Generate log(X). X passed in register v0. Return log(X) into v0.
+// Generator parameters: 10 temporary FPU registers and temporary general
+// purpose registers
+void MacroAssembler::fast_log(FloatRegister vtmp0, FloatRegister vtmp1,
+ FloatRegister vtmp2, FloatRegister vtmp3,
+ FloatRegister vtmp4, FloatRegister vtmp5,
+ FloatRegister C1, FloatRegister C2,
+ FloatRegister C3, FloatRegister C4,
+ Register tmp1, Register tmp2, Register tmp3,
+ Register tmp4, Register tmp5) {
+ Label DONE, CHECK_CORNER_CASES, SMALL_VALUE, MAIN,
+ CHECKED_CORNER_CASES, RETURN_MINF_OR_NAN;
+ const long INF_OR_NAN_PREFIX = 0x7FF0;
+ const long MINF_OR_MNAN_PREFIX = 0xFFF0;
+ const long ONE_PREFIX = 0x3FF0;
+ movz(tmp2, ONE_PREFIX, 48);
+ movz(tmp4, 0x0010, 48);
+ fmovd(rscratch1, v0); // rscratch1 = AS_LONG_BITS(X)
+ lea(rscratch2, ExternalAddress((address)_L_tbl));
+ movz(tmp5, 0x7F);
+ add(tmp1, rscratch1, tmp4);
+ cmp(tmp2, rscratch1);
+ lsr(tmp3, rscratch1, 29);
+ ccmp(tmp1, tmp4, 0b1101 /* LE */, NE);
+ bfm(tmp3, tmp5, 41, 8);
+ fmovs(vtmp5, tmp3);
+ // Load coefficients from table. All coefficients are organized to be
+ // in specific order, because load below will load it in vectors to be used
+ // later in vector instructions. Load will be performed in parallel while
+ // branches are taken. C1 will contain vector of {C1_0, C1_1}, C2 =
+ // {C2_0, C2_1}, C3 = {C3_0, C3_1}, C4 = {C4_0, C4_1}
+ ld1(C1, C2, C3, C4, T2D, post(rscratch2, 64));
+ br(LE, CHECK_CORNER_CASES);
+ bind(CHECKED_CORNER_CASES);
+ // all corner cases are handled
+ frecpe(vtmp5, vtmp5, S); // vtmp5 ~= 1/vtmp5
+ lsr(tmp2, rscratch1, 48);
+ movz(tmp4, 0x77f0, 48);
+ fmovd(vtmp4, 1.0d);
+ movz(tmp1, INF_OR_NAN_PREFIX, 48);
+ bfm(tmp4, rscratch1, 0, 51); // tmp4 = 0x77F0 << 48 | mantissa(X)
+ // vtmp1 = AS_DOUBLE_BITS(0x77F0 << 48 | mantissa(X)) == mx
+ fmovd(vtmp1, tmp4);
+ subw(tmp2, tmp2, 16);
+ cmp(tmp2, 0x8000);
+ br(GE, SMALL_VALUE);
+ bind(MAIN);
+ fmovs(tmp3, vtmp5); // int intB0 = AS_INT_BITS(B);
+ mov(tmp5, 0x3FE0);
+ mov(rscratch1, 0xffffe00000000000);
+ andr(tmp2, tmp2, tmp1, LSR, 48); // hiWord & 0x7FF0
+ sub(tmp2, tmp2, tmp5); // tmp2 = hiWord & 0x7FF0 - 0x3FE0
+ scvtfwd(vtmp5, tmp2); // vtmp5 = (double)tmp2;
+ addw(tmp3, tmp3, 0x8000); // tmp3 = B
+ andr(tmp4, tmp4, rscratch1); // tmp4 == hi_part(mx)
+ andr(rscratch1, rscratch1, tmp3, LSL, 29); // rscratch1 = hi_part(B)
+ ubfm(tmp3, tmp3, 16, 23); // int index = (intB0 >> 16) && 0xFF
+ ldrq(vtmp2, Address(rscratch2, tmp3, Address::lsl(4))); // vtmp2 = _L_tbl[index]
+ // AS_LONG_BITS(vtmp1) & 0xffffe00000000000 // hi_part(mx)
+ fmovd(vtmp3, tmp4);
+ fmovd(vtmp0, rscratch1); // vtmp0 = hi_part(B)
+ fsubd(vtmp1, vtmp1, vtmp3); // vtmp1 -= vtmp3; // low_part(mx)
+ fnmsub(vtmp3, vtmp3, vtmp0, vtmp4); // vtmp3 = vtmp3*vtmp0 - vtmp4
+ fmlavs(vtmp2, T2D, C4, vtmp5, 0); // vtmp2 += {C4} * vtmp5
+ // vtmp1 = r = vtmp1 * vtmp0 + vtmp3 == low_part(mx) * hi_part(B) + (hi_part(mx)*hi_part(B) - 1.0)
+ fmaddd(vtmp1, vtmp1, vtmp0, vtmp3);
+ ins(vtmp5, D, vtmp2, 0, 1); // vtmp5 = vtmp2[1];
+ faddd(vtmp0, vtmp2, vtmp1); // vtmp0 = vtmp2 + vtmp1
+ fmlavs(C3, T2D, C2, vtmp1, 0); // {C3} += {C2}*vtmp1
+ fsubd(vtmp2, vtmp2, vtmp0); // vtmp2 -= vtmp0
+ fmuld(vtmp3, vtmp1, vtmp1); // vtmp3 = vtmp1*vtmp1
+ faddd(C4, vtmp1, vtmp2); // C4[0] = vtmp1 + vtmp2
+ fmlavs(C3, T2D, C1, vtmp3, 0); // {C3} += {C1}*vtmp3
+ faddd(C4, C4, vtmp5); // C4 += vtmp5
+ fmuld(vtmp4, vtmp3, vtmp1); // vtmp4 = vtmp3*vtmp1
+ faddd(vtmp0, vtmp0, C4); // vtmp0 += C4
+ fmlavs(C3, T2D, vtmp4, C3, 1); // {C3} += {vtmp4}*C3[1]
+ fmaddd(vtmp0, C3, vtmp3, vtmp0); // vtmp0 = C3 * vtmp3 + vtmp0
+ ret(lr);
+
+ block_comment("if (AS_LONG_BITS(hiWord) > 0x8000)"); {
+ bind(SMALL_VALUE);
+ movz(tmp2, 0x47F0, 48);
+ fmovd(vtmp1, tmp2);
+ fmuld(vtmp0, vtmp1, v0);
+ fmovd(vtmp1, vtmp0);
+ umov(tmp2, vtmp1, S, 3);
+ orr(vtmp0, T16B, vtmp0, vtmp4);
+ ushr(vtmp5, T2D, vtmp0, 27);
+ ushr(vtmp5, T4S, vtmp5, 2);
+ frecpe(vtmp5, vtmp5, S);
+ shl(vtmp1, T2D, vtmp1, 12);
+ ushr(vtmp1, T2D, vtmp1, 12);
+ b(MAIN);
+ }
+
+ block_comment("Corner cases"); {
+ bind(RETURN_MINF_OR_NAN);
+ movz(tmp1, MINF_OR_MNAN_PREFIX, 48);
+ orr(rscratch1, rscratch1, tmp1);
+ fmovd(v0, rscratch1);
+ ret(lr);
+ bind(CHECK_CORNER_CASES);
+ movz(tmp1, INF_OR_NAN_PREFIX, 48);
+ cmp(rscratch1, zr);
+ br(LE, RETURN_MINF_OR_NAN);
+ cmp(rscratch1, tmp1);
+ br(GE, DONE);
+ cmp(rscratch1, tmp2);
+ br(NE, CHECKED_CORNER_CASES);
+ fmovd(v0, 0.0d);
+ }
+ bind(DONE);
+ ret(lr);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64_trig.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,1488 @@
+/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT)
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "macroAssembler_aarch64.hpp"
+
+// The following code is a optimized version of fdlibm sin/cos implementation
+// (C code is in share/runtime/sharedRuntimeTrig.cpp) adapted for AARCH64.
+
+// Please refer to sin/cos approximation via polynomial and
+// trigonometric argument reduction techniques to the following literature:
+//
+// [1] Muller, Jean-Michel, Nicolas Brisebarre, Florent De Dinechin,
+// Claude-Pierre Jeannerod, Vincent Lefevre, Guillaume Melquiond,
+// Nathalie Revol, Damien Stehlé, and Serge Torres:
+// Handbook of floating-point arithmetic.
+// Springer Science & Business Media, 2009.
+// [2] K. C. Ng
+// Argument Reduction for Huge Arguments: Good to the Last Bit
+// July 13, 1992, SunPro
+//
+// HOW TO READ THIS CODE:
+// This code consists of several functions. Each function has following header:
+// 1) Description
+// 2) C-pseudo code with differences from fdlibm marked by comments starting
+// with "NOTE". Check unmodified fdlibm code in
+// share/runtime/SharedRuntimeTrig.cpp
+// 3) Brief textual description of changes between fdlibm and current
+// implementation along with optimization notes (if applicable)
+// 4) Assumptions, input and output
+// 5) (Optional) additional notes about intrinsic implementation
+// Each function is separated in blocks which follow the pseudo-code structure
+//
+// HIGH-LEVEL ALGORITHM DESCRIPTION:
+// - entry point: generate_dsin_dcos(...);
+// - check corner cases: NaN, INF, tiny argument.
+// - check if |x| < Pi/4. Then approximate sin/cos via polynomial (kernel_sin/kernel_cos)
+// -- else proceed to argument reduction routine (__ieee754_rem_pio2) and
+// use reduced argument to get result via kernel_sin/kernel_cos
+//
+// HIGH-LEVEL CHANGES BETWEEN INTRINSICS AND FDLIBM:
+// 1) two_over_pi table fdlibm representation is int[], while intrinsic version
+// has these int values converted to double representation to load converted
+// double values directly (see stubRoutines_aarch4::_two_over_pi)
+// 2) Several loops are unrolled and vectorized: see comments in code after
+// labels: SKIP_F_LOAD, RECOMP_FOR1_CHECK, RECOMP_FOR2
+// 3) fdlibm npio2_hw table now has "prefix" with constants used in
+// calculation. These constants are loaded from npio2_hw table instead of
+// constructing it in code (see stubRoutines_aarch64.cpp)
+// 4) Polynomial coefficients for sin and cos are moved to table sin_coef
+// and cos_coef to use the same optimization as in 3). It allows to load most of
+// required constants via single instruction
+//
+//
+//
+///* __ieee754_rem_pio2(x,y)
+// *
+// * returns the remainder of x rem pi/2 in y[0]+y[1] (i.e. like x div pi/2)
+// * x is input argument, y[] is hi and low parts of reduced argument (x)
+// * uses __kernel_rem_pio2()
+// */
+// // use tables(see stubRoutines_aarch64.cpp): two_over_pi and modified npio2_hw
+//
+// BEGIN __ieee754_rem_pio2 PSEUDO CODE
+//
+//static int __ieee754_rem_pio2(double x, double *y) {
+// double z,w,t,r,fn;
+// double tx[3];
+// int e0,i,j,nx,n,ix,hx,i0;
+//
+// i0 = ((*(int*)&two24A)>>30)^1; /* high word index */
+// hx = *(i0+(int*)&x); /* high word of x */
+// ix = hx&0x7fffffff;
+// if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */
+// if(hx>0) {
+// z = x - pio2_1;
+// if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+// y[0] = z - pio2_1t;
+// y[1] = (z-y[0])-pio2_1t;
+// } else { /* near pi/2, use 33+33+53 bit pi */
+// z -= pio2_2;
+// y[0] = z - pio2_2t;
+// y[1] = (z-y[0])-pio2_2t;
+// }
+// return 1;
+// } else { /* negative x */
+// z = x + pio2_1;
+// if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */
+// y[0] = z + pio2_1t;
+// y[1] = (z-y[0])+pio2_1t;
+// } else { /* near pi/2, use 33+33+53 bit pi */
+// z += pio2_2;
+// y[0] = z + pio2_2t;
+// y[1] = (z-y[0])+pio2_2t;
+// }
+// return -1;
+// }
+// }
+// if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
+// t = fabsd(x);
+// n = (int) (t*invpio2+half);
+// fn = (double)n;
+// r = t-fn*pio2_1;
+// w = fn*pio2_1t; /* 1st round good to 85 bit */
+// // NOTE: y[0] = r-w; is moved from if/else below to be before "if"
+// y[0] = r-w;
+// if(n<32&&ix!=npio2_hw[n-1]) {
+// // y[0] = r-w; /* quick check no cancellation */ // NOTE: moved earlier
+// } else {
+// j = ix>>20;
+// // y[0] = r-w; // NOTE: moved earlier
+// i = j-(((*(i0+(int*)&y[0]))>>20)&0x7ff);
+// if(i>16) { /* 2nd iteration needed, good to 118 */
+// t = r;
+// w = fn*pio2_2;
+// r = t-w;
+// w = fn*pio2_2t-((t-r)-w);
+// y[0] = r-w;
+// i = j-(((*(i0+(int*)&y[0]))>>20)&0x7ff);
+// if(i>49) { /* 3rd iteration need, 151 bits acc */
+// t = r; /* will cover all possible cases */
+// w = fn*pio2_3;
+// r = t-w;
+// w = fn*pio2_3t-((t-r)-w);
+// y[0] = r-w;
+// }
+// }
+// }
+// y[1] = (r-y[0])-w;
+// if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+// else return n;
+// }
+// /*
+// * all other (large) arguments
+// */
+// // NOTE: this check is removed, because it was checked in dsin/dcos
+// // if(ix>=0x7ff00000) { /* x is inf or NaN */
+// // y[0]=y[1]=x-x; return 0;
+// // }
+// /* set z = scalbn(|x|,ilogb(x)-23) */
+// *(1-i0+(int*)&z) = *(1-i0+(int*)&x);
+// e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */
+// *(i0+(int*)&z) = ix - (e0<<20);
+//
+// // NOTE: "for" loop below in unrolled. See comments in asm code
+// for(i=0;i<2;i++) {
+// tx[i] = (double)((int)(z));
+// z = (z-tx[i])*two24A;
+// }
+//
+// tx[2] = z;
+// nx = 3;
+//
+// // NOTE: while(tx[nx-1]==zeroA) nx--; is unrolled. See comments in asm code
+// while(tx[nx-1]==zeroA) nx--; /* skip zero term */
+//
+// n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
+// if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
+// return n;
+//}
+//
+// END __ieee754_rem_pio2 PSEUDO CODE
+//
+// Changes between fdlibm and intrinsic for __ieee754_rem_pio2:
+// 1. INF/NaN check for huge argument is removed in comparison with fdlibm
+// code, because this check is already done in dcos/dsin code
+// 2. Most constants are now loaded from table instead of direct initialization
+// 3. Two loops are unrolled
+// Assumptions:
+// 1. Assume |X| >= PI/4
+// 2. Assume rscratch1 = 0x3fe921fb00000000 (~ PI/4)
+// 3. Assume ix = r3
+// Input and output:
+// 1. Input: X = r0
+// 2. Return n in r2, y[0] == y0 == v4, y[1] == y1 == v5
+// NOTE: general purpose register names match local variable names in C code
+// NOTE: fpu registers are actively reused. See comments in code about their usage
+void MacroAssembler::generate__ieee754_rem_pio2(address npio2_hw,
+ address two_over_pi, address pio2) {
+ const long PIO2_1t = 0x3DD0B4611A626331UL;
+ const long PIO2_2 = 0x3DD0B4611A600000UL;
+ const long PIO2_2t = 0x3BA3198A2E037073UL;
+ Label X_IS_NEGATIVE, X_IS_MEDIUM_OR_LARGE, X_IS_POSITIVE_LONG_PI, LARGE_ELSE,
+ REDUCTION_DONE, X_IS_MEDIUM_BRANCH_DONE, X_IS_LARGE, NX_SET,
+ X_IS_NEGATIVE_LONG_PI;
+ Register X = r0, n = r2, ix = r3, jv = r4, tmp5 = r5, jx = r6,
+ tmp3 = r7, iqBase = r10, ih = r11, i = r17;
+ // initializing constants first
+ // rscratch1 = 0x3fe921fb00000000 (see assumptions)
+ movk(rscratch1, 0x3ff9, 48); // was 0x3fe921fb0..0 now it's 0x3ff921fb0..0
+ mov(rscratch2, 0x4002d97c); // 3*PI/4 high word
+ movk(rscratch1, 0x5440, 16); // now rscratch1 == PIO2_1
+ fmovd(v1, rscratch1); // v1 = PIO2_1
+ cmp(rscratch2, ix);
+ br(LE, X_IS_MEDIUM_OR_LARGE);
+
+ block_comment("if(ix<0x4002d97c) {... /* |x| ~< 3pi/4 */ "); {
+ cmp(X, zr);
+ br(LT, X_IS_NEGATIVE);
+
+ block_comment("if(hx>0) {"); {
+ fsubd(v2, v0, v1); // v2 = z = x - pio2_1
+ cmp(ix, rscratch1, LSR, 32);
+ mov(n, 1);
+ br(EQ, X_IS_POSITIVE_LONG_PI);
+
+ block_comment("case: hx > 0 && ix!=0x3ff921fb {"); { /* 33+53 bit pi is good enough */
+ mov(rscratch2, PIO2_1t);
+ fmovd(v27, rscratch2);
+ fsubd(v4, v2, v27); // v4 = y[0] = z - pio2_1t;
+ fsubd(v5, v2, v4);
+ fsubd(v5, v5, v27); // v5 = y[1] = (z-y[0])-pio2_1t
+ b(REDUCTION_DONE);
+ }
+
+ block_comment("case: hx > 0 &*& ix==0x3ff921fb {"); { /* near pi/2, use 33+33+53 bit pi */
+ bind(X_IS_POSITIVE_LONG_PI);
+ mov(rscratch1, PIO2_2);
+ mov(rscratch2, PIO2_2t);
+ fmovd(v27, rscratch1);
+ fmovd(v6, rscratch2);
+ fsubd(v2, v2, v27); // z-= pio2_2
+ fsubd(v4, v2, v6); // y[0] = z - pio2_2t
+ fsubd(v5, v2, v4);
+ fsubd(v5, v5, v6); // v5 = (z - y[0]) - pio2_2t
+ b(REDUCTION_DONE);
+ }
+ }
+
+ block_comment("case: hx <= 0)"); {
+ bind(X_IS_NEGATIVE);
+ faddd(v2, v0, v1); // v2 = z = x + pio2_1
+ cmp(ix, rscratch1, LSR, 32);
+ mov(n, -1);
+ br(EQ, X_IS_NEGATIVE_LONG_PI);
+
+ block_comment("case: hx <= 0 && ix!=0x3ff921fb) {"); { /* 33+53 bit pi is good enough */
+ mov(rscratch2, PIO2_1t);
+ fmovd(v27, rscratch2);
+ faddd(v4, v2, v27); // v4 = y[0] = z + pio2_1t;
+ fsubd(v5, v2, v4);
+ faddd(v5, v5, v27); // v5 = y[1] = (z-y[0]) + pio2_1t
+ b(REDUCTION_DONE);
+ }
+
+ block_comment("case: hx <= 0 && ix==0x3ff921fb"); { /* near pi/2, use 33+33+53 bit pi */
+ bind(X_IS_NEGATIVE_LONG_PI);
+ mov(rscratch1, PIO2_2);
+ mov(rscratch2, PIO2_2t);
+ fmovd(v27, rscratch1);
+ fmovd(v6, rscratch2);
+ faddd(v2, v2, v27); // z += pio2_2
+ faddd(v4, v2, v6); // y[0] = z + pio2_2t
+ fsubd(v5, v2, v4);
+ faddd(v5, v5, v6); // v5 = (z - y[0]) + pio2_2t
+ b(REDUCTION_DONE);
+ }
+ }
+ }
+ bind(X_IS_MEDIUM_OR_LARGE);
+ mov(rscratch1, 0x413921fb);
+ cmp(ix, rscratch1); // ix < = 0x413921fb ?
+ br(GT, X_IS_LARGE);
+
+ block_comment("|x| ~<= 2^19*(pi/2), medium size"); {
+ lea(ih, ExternalAddress(npio2_hw));
+ ld1(v4, v5, v6, v7, T1D, ih);
+ fabsd(v31, v0); // v31 = t = |x|
+ add(ih, ih, 64);
+ fmaddd(v2, v31, v5, v4); // v2 = t * invpio2 + half (invpio2 = 53 bits of 2/pi, half = 0.5)
+ fcvtzdw(n, v2); // n = (int) v2
+ frintzd(v2, v2);
+ fmsubd(v3, v2, v6, v31); // v3 = r = t - fn * pio2_1
+ fmuld(v26, v2, v7); // v26 = w = fn * pio2_1t
+ fsubd(v4, v3, v26); // y[0] = r - w. Calculated before branch
+ cmp(n, 32);
+ br(GT, LARGE_ELSE);
+ subw(tmp5, n, 1); // tmp5 = n - 1
+ ldrw(jv, Address(ih, tmp5, Address::lsl(2)));
+ cmp(ix, jv);
+ br(NE, X_IS_MEDIUM_BRANCH_DONE);
+
+ block_comment("else block for if(n<32&&ix!=npio2_hw[n-1])"); {
+ bind(LARGE_ELSE);
+ fmovd(jx, v4);
+ lsr(tmp5, ix, 20); // j = ix >> 20
+ lsl(jx, jx, 1);
+ sub(tmp3, tmp5, jx, LSR, 32 + 20 + 1); // r7 = j-(((*(i0+(int*)&y[0]))>>20)&0x7ff);
+
+ block_comment("if(i>16)"); {
+ cmp(tmp3, 16);
+ br(LE, X_IS_MEDIUM_BRANCH_DONE);
+ // i > 16. 2nd iteration needed
+ ldpd(v6, v7, Address(ih, -32));
+ fmovd(v28, v3); // t = r
+ fmuld(v29, v2, v6); // w = v29 = fn * pio2_2
+ fsubd(v3, v28, v29); // r = t - w
+ fsubd(v31, v28, v3); // v31 = (t - r)
+ fsubd(v31, v29, v31); // v31 = w - (t - r) = - ((t - r) - w)
+ fmaddd(v26, v2, v7, v31); // v26 = w = fn*pio2_2t - ((t - r) - w)
+ fsubd(v4, v3, v26); // y[0] = r - w
+ fmovd(jx, v4);
+ lsl(jx, jx, 1);
+ sub(tmp3, tmp5, jx, LSR, 32 + 20 + 1); // r7 = j-(((*(i0+(int*)&y[0]))>>20)&0x7ff);
+
+ block_comment("if(i>49)"); {
+ cmp(tmp3, 49);
+ br(LE, X_IS_MEDIUM_BRANCH_DONE);
+ // 3rd iteration need, 151 bits acc
+ ldpd(v6, v7, Address(ih, -16));
+ fmovd(v28, v3); // save "r"
+ fmuld(v29, v2, v6); // v29 = fn * pio2_3
+ fsubd(v3, v28, v29); // r = r - w
+ fsubd(v31, v28, v3); // v31 = (t - r)
+ fsubd(v31, v29, v31); // v31 = w - (t - r) = - ((t - r) - w)
+ fmaddd(v26, v2, v7, v31); // v26 = w = fn*pio2_3t - ((t - r) - w)
+ fsubd(v4, v3, v26); // y[0] = r - w
+ }
+ }
+ }
+ block_comment("medium x tail"); {
+ bind(X_IS_MEDIUM_BRANCH_DONE);
+ fsubd(v5, v3, v4); // v5 = y[1] = (r - y[0])
+ fsubd(v5, v5, v26); // v5 = y[1] = (r - y[0]) - w
+ cmp(X, zr);
+ br(GT, REDUCTION_DONE);
+ fnegd(v4, v4);
+ negw(n, n);
+ fnegd(v5, v5);
+ b(REDUCTION_DONE);
+ }
+ }
+
+ block_comment("all other (large) arguments"); {
+ bind(X_IS_LARGE);
+ lsr(rscratch1, ix, 20); // ix >> 20
+ movz(tmp5, 0x4170, 48);
+ subw(rscratch1, rscratch1, 1046); // e0
+ fmovd(v10, tmp5); // init two24A value
+ subw(jv, ix, rscratch1, LSL, 20); // ix - (e0<<20)
+ lsl(jv, jv, 32);
+ subw(rscratch2, rscratch1, 3);
+ bfm(jv, X, 0, 31); // jv = z
+ movw(i, 24);
+ fmovd(v26, jv); // v26 = z
+
+ block_comment("unrolled for(i=0;i<2;i++) {tx[i] = (double)((int)(z));z = (z-tx[i])*two24A;}"); {
+ // tx[0,1,2] = v6,v7,v26
+ frintzd(v6, v26); // v6 = (double)((int)v26)
+ sdivw(jv, rscratch2, i); // jv = (e0 - 3)/24
+ fsubd(v26, v26, v6);
+ sub(sp, sp, 560);
+ fmuld(v26, v26, v10);
+ frintzd(v7, v26); // v7 = (double)((int)v26)
+ movw(jx, 2); // calculate jx as nx - 1, which is initially 2. Not a part of unrolled loop
+ fsubd(v26, v26, v7);
+ }
+
+ block_comment("nx calculation with unrolled while(tx[nx-1]==zeroA) nx--;"); {
+ fcmpd(v26, 0.0d); // if NE then jx == 2. else it's 1 or 0
+ add(iqBase, sp, 480); // base of iq[]
+ fmuld(v3, v26, v10);
+ br(NE, NX_SET);
+ fcmpd(v7, 0.0d); // v7 == 0 => jx = 0. Else jx = 1
+ csetw(jx, NE);
+ }
+ bind(NX_SET);
+ generate__kernel_rem_pio2(two_over_pi, pio2);
+ // now we have y[0] = v4, y[1] = v5 and n = r2
+ cmp(X, zr);
+ br(GE, REDUCTION_DONE);
+ fnegd(v4, v4);
+ fnegd(v5, v5);
+ negw(n, n);
+ }
+ bind(REDUCTION_DONE);
+}
+
+///*
+// * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
+// * double x[],y[]; int e0,nx,prec; int ipio2[];
+// *
+// * __kernel_rem_pio2 return the last three digits of N with
+// * y = x - N*pi/2
+// * so that |y| < pi/2.
+// *
+// * The method is to compute the integer (mod 8) and fraction parts of
+// * (2/pi)*x without doing the full multiplication. In general we
+// * skip the part of the product that are known to be a huge integer (
+// * more accurately, = 0 mod 8 ). Thus the number of operations are
+// * independent of the exponent of the input.
+// *
+// * NOTE: 2/pi int representation is converted to double
+// * // (2/pi) is represented by an array of 24-bit integers in ipio2[].
+// *
+// * Input parameters:
+// * x[] The input value (must be positive) is broken into nx
+// * pieces of 24-bit integers in double precision format.
+// * x[i] will be the i-th 24 bit of x. The scaled exponent
+// * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
+// * match x's up to 24 bits.
+// *
+// * Example of breaking a double positive z into x[0]+x[1]+x[2]:
+// * e0 = ilogb(z)-23
+// * z = scalbn(z,-e0)
+// * for i = 0,1,2
+// * x[i] = floor(z)
+// * z = (z-x[i])*2**24
+// *
+// *
+// * y[] ouput result in an array of double precision numbers.
+// * The dimension of y[] is:
+// * 24-bit precision 1
+// * 53-bit precision 2
+// * 64-bit precision 2
+// * 113-bit precision 3
+// * The actual value is the sum of them. Thus for 113-bit
+// * precsion, one may have to do something like:
+// *
+// * long double t,w,r_head, r_tail;
+// * t = (long double)y[2] + (long double)y[1];
+// * w = (long double)y[0];
+// * r_head = t+w;
+// * r_tail = w - (r_head - t);
+// *
+// * e0 The exponent of x[0]
+// *
+// * nx dimension of x[]
+// *
+// * prec an interger indicating the precision:
+// * 0 24 bits (single)
+// * 1 53 bits (double)
+// * 2 64 bits (extended)
+// * 3 113 bits (quad)
+// *
+// * NOTE: ipio2[] array below is converted to double representation
+// * //ipio2[]
+// * // integer array, contains the (24*i)-th to (24*i+23)-th
+// * // bit of 2/pi after binary point. The corresponding
+// * // floating value is
+// *
+// * ipio2[i] * 2^(-24(i+1)).
+// *
+// * Here is the description of some local variables:
+// *
+// * jk jk+1 is the initial number of terms of ipio2[] needed
+// * in the computation. The recommended value is 2,3,4,
+// * 6 for single, double, extended,and quad.
+// *
+// * jz local integer variable indicating the number of
+// * terms of ipio2[] used.
+// *
+// * jx nx - 1
+// *
+// * jv index for pointing to the suitable ipio2[] for the
+// * computation. In general, we want
+// * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
+// * is an integer. Thus
+// * e0-3-24*jv >= 0 or (e0-3)/24 >= jv
+// * Hence jv = max(0,(e0-3)/24).
+// *
+// * jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
+// *
+// * q[] double array with integral value, representing the
+// * 24-bits chunk of the product of x and 2/pi.
+// *
+// * q0 the corresponding exponent of q[0]. Note that the
+// * exponent for q[i] would be q0-24*i.
+// *
+// * PIo2[] double precision array, obtained by cutting pi/2
+// * into 24 bits chunks.
+// *
+// * f[] ipio2[] in floating point
+// *
+// * iq[] integer array by breaking up q[] in 24-bits chunk.
+// *
+// * fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
+// *
+// * ih integer. If >0 it indicates q[] is >= 0.5, hence
+// * it also indicates the *sign* of the result.
+// *
+// */
+//
+// Use PIo2 table(see stubRoutines_aarch64.cpp)
+//
+// BEGIN __kernel_rem_pio2 PSEUDO CODE
+//
+//static int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, /* NOTE: converted to double */ const double *ipio2 // const int *ipio2) {
+// int jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
+// double z,fw,f[20],fq[20],q[20];
+//
+// /* initialize jk*/
+// // jk = init_jk[prec]; // NOTE: prec==2 for double. jk is always 4.
+// jp = jk; // NOTE: always 4
+//
+// /* determine jx,jv,q0, note that 3>q0 */
+// jx = nx-1;
+// jv = (e0-3)/24; if(jv<0) jv=0;
+// q0 = e0-24*(jv+1);
+//
+// /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
+// j = jv-jx; m = jx+jk;
+//
+// // NOTE: split into two for-loops: one with zeroB and one with ipio2[j]. It
+// // allows the use of wider loads/stores
+// for(i=0;i<=m;i++,j++) f[i] = (j<0)? zeroB : /* NOTE: converted to double */ ipio2[j]; //(double) ipio2[j];
+//
+// // NOTE: unrolled and vectorized "for". See comments in asm code
+// /* compute q[0],q[1],...q[jk] */
+// for (i=0;i<=jk;i++) {
+// for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+// }
+//
+// jz = jk;
+//recompute:
+// /* distill q[] into iq[] reversingly */
+// for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+// fw = (double)((int)(twon24* z));
+// iq[i] = (int)(z-two24B*fw);
+// z = q[j-1]+fw;
+// }
+//
+// /* compute n */
+// z = scalbnA(z,q0); /* actual value of z */
+// z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
+// n = (int) z;
+// z -= (double)n;
+// ih = 0;
+// if(q0>0) { /* need iq[jz-1] to determine n */
+// i = (iq[jz-1]>>(24-q0)); n += i;
+// iq[jz-1] -= i<<(24-q0);
+// ih = iq[jz-1]>>(23-q0);
+// }
+// else if(q0==0) ih = iq[jz-1]>>23;
+// else if(z>=0.5) ih=2;
+//
+// if(ih>0) { /* q > 0.5 */
+// n += 1; carry = 0;
+// for(i=0;i<jz ;i++) { /* compute 1-q */
+// j = iq[i];
+// if(carry==0) {
+// if(j!=0) {
+// carry = 1; iq[i] = 0x1000000- j;
+// }
+// } else iq[i] = 0xffffff - j;
+// }
+// if(q0>0) { /* rare case: chance is 1 in 12 */
+// switch(q0) {
+// case 1:
+// iq[jz-1] &= 0x7fffff; break;
+// case 2:
+// iq[jz-1] &= 0x3fffff; break;
+// }
+// }
+// if(ih==2) {
+// z = one - z;
+// if(carry!=0) z -= scalbnA(one,q0);
+// }
+// }
+//
+// /* check if recomputation is needed */
+// if(z==zeroB) {
+// j = 0;
+// for (i=jz-1;i>=jk;i--) j |= iq[i];
+// if(j==0) { /* need recomputation */
+// for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
+//
+// for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
+// f[jx+i] = /* NOTE: converted to double */ ipio2[jv+i]; //(double) ipio2[jv+i];
+// for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+// q[i] = fw;
+// }
+// jz += k;
+// goto recompute;
+// }
+// }
+//
+// /* chop off zero terms */
+// if(z==0.0) {
+// jz -= 1; q0 -= 24;
+// while(iq[jz]==0) { jz--; q0-=24;}
+// } else { /* break z into 24-bit if necessary */
+// z = scalbnA(z,-q0);
+// if(z>=two24B) {
+// fw = (double)((int)(twon24*z));
+// iq[jz] = (int)(z-two24B*fw);
+// jz += 1; q0 += 24;
+// iq[jz] = (int) fw;
+// } else iq[jz] = (int) z ;
+// }
+//
+// /* convert integer "bit" chunk to floating-point value */
+// fw = scalbnA(one,q0);
+// for(i=jz;i>=0;i--) {
+// q[i] = fw*(double)iq[i]; fw*=twon24;
+// }
+//
+// /* compute PIo2[0,...,jp]*q[jz,...,0] */
+// for(i=jz;i>=0;i--) {
+// for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+// fq[jz-i] = fw;
+// }
+//
+// // NOTE: switch below is eliminated, because prec is always 2 for doubles
+// /* compress fq[] into y[] */
+// //switch(prec) {
+// //case 0:
+// // fw = 0.0;
+// // for (i=jz;i>=0;i--) fw += fq[i];
+// // y[0] = (ih==0)? fw: -fw;
+// // break;
+// //case 1:
+// //case 2:
+// fw = 0.0;
+// for (i=jz;i>=0;i--) fw += fq[i];
+// y[0] = (ih==0)? fw: -fw;
+// fw = fq[0]-fw;
+// for (i=1;i<=jz;i++) fw += fq[i];
+// y[1] = (ih==0)? fw: -fw;
+// // break;
+// //case 3: /* painful */
+// // for (i=jz;i>0;i--) {
+// // fw = fq[i-1]+fq[i];
+// // fq[i] += fq[i-1]-fw;
+// // fq[i-1] = fw;
+// // }
+// // for (i=jz;i>1;i--) {
+// // fw = fq[i-1]+fq[i];
+// // fq[i] += fq[i-1]-fw;
+// // fq[i-1] = fw;
+// // }
+// // for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
+// // if(ih==0) {
+// // y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
+// // } else {
+// // y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
+// // }
+// //}
+// return n&7;
+//}
+//
+// END __kernel_rem_pio2 PSEUDO CODE
+//
+// Changes between fdlibm and intrinsic:
+// 1. One loop is unrolled and vectorized (see comments in code)
+// 2. One loop is split into 2 loops (see comments in code)
+// 3. Non-double code is removed(last switch). Sevaral variables became
+// constants because of that (see comments in code)
+// 4. Use of jx, which is nx-1 instead of nx
+// Assumptions:
+// 1. Assume |X| >= PI/4
+// Input and output:
+// 1. Input: X = r0, jx == nx - 1 == r6, e0 == rscratch1
+// 2. Return n in r2, y[0] == y0 == v4, y[1] == y1 == v5
+// NOTE: general purpose register names match local variable names in C code
+// NOTE: fpu registers are actively reused. See comments in code about their usage
+void MacroAssembler::generate__kernel_rem_pio2(address two_over_pi, address pio2) {
+ Label Q_DONE, JX_IS_0, JX_IS_2, COMP_INNER_LOOP, RECOMP_FOR2, Q0_ZERO_CMP_LT,
+ RECOMP_CHECK_DONE_NOT_ZERO, Q0_ZERO_CMP_DONE, COMP_FOR, Q0_ZERO_CMP_EQ,
+ INIT_F_ZERO, RECOMPUTE, IH_FOR_INCREMENT, IH_FOR_STORE, RECOMP_CHECK_DONE,
+ Z_IS_LESS_THAN_TWO24B, Z_IS_ZERO, FW_Y1_NO_NEGATION,
+ RECOMP_FW_UPDATED, Z_ZERO_CHECK_DONE, FW_FOR1, IH_AFTER_SWITCH, IH_HANDLED,
+ CONVERTION_FOR, FW_Y0_NO_NEGATION, FW_FOR1_DONE, FW_FOR2, FW_FOR2_DONE,
+ IH_FOR, SKIP_F_LOAD, RECOMP_FOR1, RECOMP_FIRST_FOR, INIT_F_COPY,
+ RECOMP_FOR1_CHECK;
+ Register tmp2 = r1, n = r2, jv = r4, tmp5 = r5, jx = r6,
+ tmp3 = r7, iqBase = r10, ih = r11, tmp4 = r12, tmp1 = r13,
+ jz = r14, j = r15, twoOverPiBase = r16, i = r17, qBase = r18;
+ // jp = jk == init_jk[prec] = init_jk[2] == {2,3,4,6}[2] == 4
+ // jx = nx - 1
+ lea(twoOverPiBase, ExternalAddress(two_over_pi));
+ cmpw(jv, zr);
+ addw(tmp4, jx, 4); // tmp4 = m = jx + jk = jx + 4. jx is in {0,1,2} so m is in [4,5,6]
+ cselw(jv, jv, zr, GE);
+ fmovd(v26, 0.0d);
+ addw(tmp5, jv, 1); // jv+1
+ subsw(j, jv, jx);
+ add(qBase, sp, 320); // base of q[]
+ msubw(rscratch1, i, tmp5, rscratch1); // q0 = e0-24*(jv+1)
+ // use double f[20], fq[20], q[20], iq[20] on stack, which is
+ // (20 + 20 + 20) x 8 + 20 x 4 = 560 bytes. From lower to upper addresses it
+ // will contain f[20], fq[20], q[20], iq[20]
+ // now initialize f[20] indexes 0..m (inclusive)
+ // for(i=0;i<=m;i++,j++) f[i] = (j<0)? zeroB : /* NOTE: converted to double */ ipio2[j]; // (double) ipio2[j];
+ mov(tmp5, sp);
+
+ block_comment("for(i=0;i<=m;i++,j++) f[i] = (j<0)? zeroB : /* NOTE: converted to double */ ipio2[j]; // (double) ipio2[j];"); {
+ eorw(i, i, i);
+ br(GE, INIT_F_COPY);
+ bind(INIT_F_ZERO);
+ stpq(v26, v26, Address(post(tmp5, 32)));
+ addw(i, i, 4);
+ addsw(j, j, 4);
+ br(LT, INIT_F_ZERO);
+ subw(i, i, j);
+ movw(j, zr);
+ bind(INIT_F_COPY);
+ add(tmp1, twoOverPiBase, j, LSL, 3); // ipio2[j] start address
+ ld1(v18, v19, v20, v21, T16B, tmp1);
+ add(tmp5, sp, i, ext::uxtx, 3);
+ st1(v18, v19, v20, v21, T16B, tmp5);
+ }
+ // v18..v21 can actually contain f[0..7]
+ cbz(i, SKIP_F_LOAD); // i == 0 => f[i] == f[0] => already loaded
+ ld1(v18, v19, v20, v21, T2D, Address(sp)); // load f[0..7]
+ bind(SKIP_F_LOAD);
+ // calculate 2^q0 and 2^-q0, which we'll need further.
+ // q0 is exponent. So, calculate biased exponent(q0+1023)
+ negw(tmp4, rscratch1);
+ addw(tmp5, rscratch1, 1023);
+ addw(tmp4, tmp4, 1023);
+ // Unroll following for(s) depending on jx in [0,1,2]
+ // for (i=0;i<=jk;i++) {
+ // for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
+ // }
+ // Unrolling for jx == 0 case:
+ // q[0] = x[0] * f[0]
+ // q[1] = x[0] * f[1]
+ // q[2] = x[0] * f[2]
+ // q[3] = x[0] * f[3]
+ // q[4] = x[0] * f[4]
+ //
+ // Vectorization for unrolled jx == 0 case:
+ // {q[0], q[1]} = {f[0], f[1]} * x[0]
+ // {q[2], q[3]} = {f[2], f[3]} * x[0]
+ // q[4] = f[4] * x[0]
+ //
+ // Unrolling for jx == 1 case:
+ // q[0] = x[0] * f[1] + x[1] * f[0]
+ // q[1] = x[0] * f[2] + x[1] * f[1]
+ // q[2] = x[0] * f[3] + x[1] * f[2]
+ // q[3] = x[0] * f[4] + x[1] * f[3]
+ // q[4] = x[0] * f[5] + x[1] * f[4]
+ //
+ // Vectorization for unrolled jx == 1 case:
+ // {q[0], q[1]} = {f[0], f[1]} * x[1]
+ // {q[2], q[3]} = {f[2], f[3]} * x[1]
+ // q[4] = f[4] * x[1]
+ // {q[0], q[1]} += {f[1], f[2]} * x[0]
+ // {q[2], q[3]} += {f[3], f[4]} * x[0]
+ // q[4] += f[5] * x[0]
+ //
+ // Unrolling for jx == 2 case:
+ // q[0] = x[0] * f[2] + x[1] * f[1] + x[2] * f[0]
+ // q[1] = x[0] * f[3] + x[1] * f[2] + x[2] * f[1]
+ // q[2] = x[0] * f[4] + x[1] * f[3] + x[2] * f[2]
+ // q[3] = x[0] * f[5] + x[1] * f[4] + x[2] * f[3]
+ // q[4] = x[0] * f[6] + x[1] * f[5] + x[2] * f[4]
+ //
+ // Vectorization for unrolled jx == 2 case:
+ // {q[0], q[1]} = {f[0], f[1]} * x[2]
+ // {q[2], q[3]} = {f[2], f[3]} * x[2]
+ // q[4] = f[4] * x[2]
+ // {q[0], q[1]} += {f[1], f[2]} * x[1]
+ // {q[2], q[3]} += {f[3], f[4]} * x[1]
+ // q[4] += f[5] * x[1]
+ // {q[0], q[1]} += {f[2], f[3]} * x[0]
+ // {q[2], q[3]} += {f[4], f[5]} * x[0]
+ // q[4] += f[6] * x[0]
+ block_comment("unrolled and vectorized computation of q[0]..q[jk]"); {
+ cmpw(jx, 1);
+ lsl(tmp5, tmp5, 52); // now it's 2^q0 double value
+ lsl(tmp4, tmp4, 52); // now it's 2^-q0 double value
+ br(LT, JX_IS_0);
+ add(i, sp, 8);
+ ldpq(v26, v27, i); // load f[1..4]
+ br(GT, JX_IS_2);
+ // jx == 1
+ fmulxvs(v28, T2D, v18, v7); // f[0,1] * x[1]
+ fmulxvs(v29, T2D, v19, v7); // f[2,3] * x[1]
+ fmuld(v30, v20, v7); // f[4] * x[1]
+ fmlavs(v28, T2D, v26, v6, 0);
+ fmlavs(v29, T2D, v27, v6, 0);
+ fmlavs(v30, T2D, v6, v20, 1); // v30 += f[5] * x[0]
+ b(Q_DONE);
+ bind(JX_IS_2);
+ fmulxvs(v28, T2D, v18, v3); // f[0,1] * x[2]
+ fmulxvs(v29, T2D, v19, v3); // f[2,3] * x[2]
+ fmuld(v30, v20, v3); // f[4] * x[2]
+ fmlavs(v28, T2D, v26, v7, 0);
+ fmlavs(v29, T2D, v27, v7, 0);
+ fmlavs(v30, T2D, v7, v20, 1); // v30 += f[5] * x[1]
+ fmlavs(v28, T2D, v19, v6, 0);
+ fmlavs(v29, T2D, v20, v6, 0);
+ fmlavs(v30, T2D, v6, v21, 0); // v30 += f[6] * x[0]
+ b(Q_DONE);
+ bind(JX_IS_0);
+ fmulxvs(v28, T2D, v18, v6); // f[0,1] * x[0]
+ fmulxvs(v29, T2D, v19, v6); // f[2,3] * x[0]
+ fmuld(v30, v20, v6); // f[4] * x[0]
+ bind(Q_DONE);
+ st1(v28, v29, v30, T2D, Address(qBase)); // save calculated q[0]...q[jk]
+ }
+ movz(i, 0x3E70, 48);
+ movw(jz, 4);
+ fmovd(v17, i); // v17 = twon24
+ fmovd(v30, tmp5); // 2^q0
+ fmovd(v21, 0.125d);
+ fmovd(v20, 8.0d);
+ fmovd(v22, tmp4); // 2^-q0
+
+ block_comment("recompute loop"); {
+ bind(RECOMPUTE);
+ // for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
+ // fw = (double)((int)(twon24* z));
+ // iq[i] = (int)(z-two24A*fw);
+ // z = q[j-1]+fw;
+ // }
+ block_comment("distill q[] into iq[] reversingly"); {
+ eorw(i, i, i);
+ movw(j, jz);
+ add(tmp2, qBase, jz, LSL, 3); // q[jz] address
+ ldrd(v18, post(tmp2, -8)); // z = q[j] and moving address to q[j-1]
+ bind(RECOMP_FIRST_FOR);
+ ldrd(v27, post(tmp2, -8));
+ fmuld(v29, v17, v18); // twon24*z
+ frintzd(v29, v29); // (double)(int)
+ fmsubd(v28, v10, v29, v18); // v28 = z-two24A*fw
+ fcvtzdw(tmp1, v28); // (int)(z-two24A*fw)
+ strw(tmp1, Address(iqBase, i, Address::lsl(2)));
+ faddd(v18, v27, v29);
+ add(i, i, 1);
+ subs(j, j, 1);
+ br(GT, RECOMP_FIRST_FOR);
+ }
+ // compute n
+ fmuld(v18, v18, v30);
+ fmuld(v2, v18, v21);
+ frintmd(v2, v2); // v2 = floor(v2) == rounding towards -inf
+ fmsubd(v18, v2, v20, v18); // z -= 8.0*floor(z*0.125);
+ movw(ih, 2);
+ frintzd(v2, v18); // v2 = (double)((int)z)
+ fcvtzdw(n, v18); // n = (int) z;
+ fsubd(v18, v18, v2); // z -= (double)n;
+
+ block_comment("q0-dependent initialization"); {
+ cmpw(rscratch1, 0); // if (q0 > 0)
+ br(LT, Q0_ZERO_CMP_LT);
+ subw(j, jz, 1); // j = jz - 1
+ ldrw(tmp2, Address(iqBase, j, Address::lsl(2))); // tmp2 = iq[jz-1]
+ br(EQ, Q0_ZERO_CMP_EQ);
+ movw(tmp4, 24);
+ subw(tmp4, tmp4, rscratch1); // == 24 - q0
+ lsrvw(i, tmp2, tmp4); // i = iq[jz-1] >> (24-q0)
+ lslvw(tmp5, i, tmp4);
+ subw(tmp2, tmp2, tmp5); // iq[jz-1] -= i<<(24-q0);
+ strw(tmp2, Address(iqBase, j, Address::lsl(2))); // store iq[jz-1]
+ subw(rscratch2, tmp4, 1); // == 23 - q0
+ addw(n, n, i); // n+=i
+ lsrvw(ih, tmp2, rscratch2); // ih = iq[jz-1] >> (23-q0)
+ b(Q0_ZERO_CMP_DONE);
+ bind(Q0_ZERO_CMP_EQ);
+ lsr(ih, tmp2, 23); // ih = iq[z-1] >> 23
+ b(Q0_ZERO_CMP_DONE);
+ bind(Q0_ZERO_CMP_LT);
+ fmovd(v4, 0.5d);
+ fcmpd(v18, v4);
+ cselw(ih, zr, ih, LT); // if (z<0.5) ih = 0
+ }
+ bind(Q0_ZERO_CMP_DONE);
+ cmpw(ih, zr);
+ br(LE, IH_HANDLED);
+
+ block_comment("if(ih>) {"); {
+ // use rscratch2 as carry
+
+ block_comment("for(i=0;i<jz ;i++) {...}"); {
+ addw(n, n, 1);
+ eorw(i, i, i);
+ eorw(rscratch2, rscratch2, rscratch2);
+ bind(IH_FOR);
+ ldrw(j, Address(iqBase, i, Address::lsl(2))); // j = iq[i]
+ movw(tmp3, 0x1000000);
+ subw(tmp3, tmp3, rscratch2);
+ cbnzw(rscratch2, IH_FOR_STORE);
+ cbzw(j, IH_FOR_INCREMENT);
+ movw(rscratch2, 1);
+ bind(IH_FOR_STORE);
+ subw(tmp3, tmp3, j);
+ strw(tmp3, Address(iqBase, i, Address::lsl(2))); // iq[i] = 0xffffff - j
+ bind(IH_FOR_INCREMENT);
+ addw(i, i, 1);
+ cmpw(i, jz);
+ br(LT, IH_FOR);
+ }
+
+ block_comment("if(q0>0) {"); {
+ cmpw(rscratch1, zr);
+ br(LE, IH_AFTER_SWITCH);
+ // tmp3 still has iq[jz-1] value. no need to reload
+ // now, zero high tmp3 bits (rscratch1 number of bits)
+ movw(j, -1);
+ subw(i, jz, 1); // set i to jz-1
+ lsrv(j, j, rscratch1);
+ andw(tmp3, tmp3, j, LSR, 8); // we have 24-bit-based constants
+ strw(tmp3, Address(iqBase, i, Address::lsl(2))); // save iq[jz-1]
+ }
+ bind(IH_AFTER_SWITCH);
+ cmpw(ih, 2);
+ br(NE, IH_HANDLED);
+
+ block_comment("if(ih==2) {"); {
+ fmovd(v25, 1.0d);
+ fsubd(v18, v25, v18); // z = one - z;
+ cbzw(rscratch2, IH_HANDLED);
+ fsubd(v18, v18, v30); // z -= scalbnA(one,q0);
+ }
+ }
+ bind(IH_HANDLED);
+ // check if recomputation is needed
+ fcmpd(v18, 0.0d);
+ br(NE, RECOMP_CHECK_DONE_NOT_ZERO);
+
+ block_comment("if(z==zeroB) {"); {
+
+ block_comment("for (i=jz-1;i>=jk;i--) j |= iq[i];"); {
+ subw(i, jz, 1);
+ eorw(j, j, j);
+ b(RECOMP_FOR1_CHECK);
+ bind(RECOMP_FOR1);
+ ldrw(tmp1, Address(iqBase, i, Address::lsl(2)));
+ orrw(j, j, tmp1);
+ subw(i, i, 1);
+ bind(RECOMP_FOR1_CHECK);
+ cmpw(i, 4);
+ br(GE, RECOMP_FOR1);
+ }
+ cbnzw(j, RECOMP_CHECK_DONE);
+
+ block_comment("if(j==0) {"); {
+ // for(k=1;iq[jk-k]==0;k++); // let's unroll it. jk == 4. So, read
+ // iq[3], iq[2], iq[1], iq[0] until non-zero value
+ ldp(tmp1, tmp3, iqBase); // iq[0..3]
+ movw(j, 2);
+ cmp(tmp3, zr);
+ csel(tmp1, tmp1, tmp3, EQ); // set register for further consideration
+ cselw(j, j, zr, EQ); // set initial k. Use j as k
+ cmp(zr, tmp1, LSR, 32);
+ addw(i, jz, 1);
+ csincw(j, j, j, NE);
+
+ block_comment("for(i=jz+1;i<=jz+k;i++) {...}"); {
+ addw(jz, i, j); // i = jz+1, j = k-1. j+i = jz+k (which is a new jz)
+ bind(RECOMP_FOR2);
+ addw(tmp1, jv, i);
+ ldrd(v29, Address(twoOverPiBase, tmp1, Address::lsl(3)));
+ addw(tmp2, jx, i);
+ strd(v29, Address(sp, tmp2, Address::lsl(3)));
+ // f[jx+i] = /* NOTE: converted to double */ ipio2[jv+i]; //(double) ipio2[jv+i];
+ // since jx = 0, 1 or 2 we can unroll it:
+ // for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
+ // f[jx+i-j] == (for first iteration) f[jx+i], which is already v29
+ add(tmp2, sp, tmp2, ext::uxtx, 3); // address of f[jx+i]
+ ldpd(v4, v5, Address(tmp2, -16)); // load f[jx+i-2] and f[jx+i-1]
+ fmuld(v26, v6, v29); // initial fw
+ cbzw(jx, RECOMP_FW_UPDATED);
+ fmaddd(v26, v7, v5, v26);
+ cmpw(jx, 1);
+ br(EQ, RECOMP_FW_UPDATED);
+ fmaddd(v26, v3, v4, v26);
+ bind(RECOMP_FW_UPDATED);
+ strd(v26, Address(qBase, i, Address::lsl(3))); // q[i] = fw;
+ addw(i, i, 1);
+ cmpw(i, jz); // jz here is "old jz" + k
+ br(LE, RECOMP_FOR2);
+ }
+ b(RECOMPUTE);
+ }
+ }
+ }
+ bind(RECOMP_CHECK_DONE);
+ // chop off zero terms
+ fcmpd(v18, 0.0d);
+ br(EQ, Z_IS_ZERO);
+
+ block_comment("else block of if(z==0.0) {"); {
+ bind(RECOMP_CHECK_DONE_NOT_ZERO);
+ fmuld(v18, v18, v22);
+ fcmpd(v18, v10); // v10 is stil two24A
+ br(LT, Z_IS_LESS_THAN_TWO24B);
+ fmuld(v1, v18, v17); // twon24*z
+ frintzd(v1, v1); // v1 = (double)(int)(v1)
+ fmaddd(v2, v10, v1, v18);
+ fcvtzdw(tmp3, v1); // (int)fw
+ fcvtzdw(tmp2, v2); // double to int
+ strw(tmp2, Address(iqBase, jz, Address::lsl(2)));
+ addw(rscratch1, rscratch1, 24);
+ addw(jz, jz, 1);
+ strw(tmp3, Address(iqBase, jz, Address::lsl(2))); // iq[jz] = (int) fw
+ b(Z_ZERO_CHECK_DONE);
+ bind(Z_IS_LESS_THAN_TWO24B);
+ fcvtzdw(tmp3, v18); // (int)z
+ strw(tmp3, Address(iqBase, jz, Address::lsl(2))); // iq[jz] = (int) z
+ b(Z_ZERO_CHECK_DONE);
+ }
+
+ block_comment("if(z==0.0) {"); {
+ bind(Z_IS_ZERO);
+ subw(jz, jz, 1);
+ ldrw(tmp1, Address(iqBase, jz, Address::lsl(2)));
+ subw(rscratch1, rscratch1, 24);
+ cbz(tmp1, Z_IS_ZERO);
+ }
+ bind(Z_ZERO_CHECK_DONE);
+ // convert integer "bit" chunk to floating-point value
+ // v17 = twon24
+ // update v30, which was scalbnA(1.0, <old q0>);
+ addw(tmp2, rscratch1, 1023); // biased exponent
+ lsl(tmp2, tmp2, 52); // put at correct position
+ mov(i, jz);
+ fmovd(v30, tmp2);
+
+ block_comment("for(i=jz;i>=0;i--) {q[i] = fw*(double)iq[i]; fw*=twon24;}"); {
+ bind(CONVERTION_FOR);
+ ldrw(tmp1, Address(iqBase, i, Address::lsl(2)));
+ scvtfwd(v31, tmp1);
+ fmuld(v31, v31, v30);
+ strd(v31, Address(qBase, i, Address::lsl(3)));
+ fmuld(v30, v30, v17);
+ subsw(i, i, 1);
+ br(GE, CONVERTION_FOR);
+ }
+ add(rscratch2, sp, 160); // base for fq
+ // reusing twoOverPiBase
+ lea(twoOverPiBase, ExternalAddress(pio2));
+
+ block_comment("compute PIo2[0,...,jp]*q[jz,...,0]. for(i=jz;i>=0;i--) {...}"); {
+ movw(i, jz);
+ movw(tmp2, zr); // tmp2 will keep jz - i == 0 at start
+ bind(COMP_FOR);
+ // for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
+ fmovd(v30, 0.0d);
+ add(tmp5, qBase, i, LSL, 3); // address of q[i+k] for k==0
+ movw(tmp3, 4);
+ movw(tmp4, zr); // used as k
+ cmpw(tmp2, 4);
+ add(tmp1, qBase, i, LSL, 3); // used as q[i] address
+ cselw(tmp3, tmp2, tmp3, LE); // min(jz - i, jp)
+
+ block_comment("for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];"); {
+ bind(COMP_INNER_LOOP);
+ ldrd(v18, Address(tmp1, tmp4, Address::lsl(3))); // q[i+k]
+ ldrd(v19, Address(twoOverPiBase, tmp4, Address::lsl(3))); // PIo2[k]
+ fmaddd(v30, v18, v19, v30); // fw += PIo2[k]*q[i+k];
+ addw(tmp4, tmp4, 1); // k++
+ cmpw(tmp4, tmp3);
+ br(LE, COMP_INNER_LOOP);
+ }
+ strd(v30, Address(rscratch2, tmp2, Address::lsl(3))); // fq[jz-i]
+ add(tmp2, tmp2, 1);
+ subsw(i, i, 1);
+ br(GE, COMP_FOR);
+ }
+
+ block_comment("switch(prec) {...}. case 2:"); {
+ // compress fq into y[]
+ // remember prec == 2
+
+ block_comment("for (i=jz;i>=0;i--) fw += fq[i];"); {
+ fmovd(v4, 0.0d);
+ mov(i, jz);
+ bind(FW_FOR1);
+ ldrd(v1, Address(rscratch2, i, Address::lsl(3)));
+ subsw(i, i, 1);
+ faddd(v4, v4, v1);
+ br(GE, FW_FOR1);
+ }
+ bind(FW_FOR1_DONE);
+ // v1 contains fq[0]. so, keep it so far
+ fsubd(v5, v1, v4); // fw = fq[0] - fw
+ cbzw(ih, FW_Y0_NO_NEGATION);
+ fnegd(v4, v4);
+ bind(FW_Y0_NO_NEGATION);
+
+ block_comment("for (i=1;i<=jz;i++) fw += fq[i];"); {
+ movw(i, 1);
+ cmpw(jz, 1);
+ br(LT, FW_FOR2_DONE);
+ bind(FW_FOR2);
+ ldrd(v1, Address(rscratch2, i, Address::lsl(3)));
+ addw(i, i, 1);
+ cmp(i, jz);
+ faddd(v5, v5, v1);
+ br(LE, FW_FOR2);
+ }
+ bind(FW_FOR2_DONE);
+ cbz(ih, FW_Y1_NO_NEGATION);
+ fnegd(v5, v5);
+ bind(FW_Y1_NO_NEGATION);
+ add(sp, sp, 560);
+ }
+}
+
+///* __kernel_sin( x, y, iy)
+// * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854
+// * Input x is assumed to be bounded by ~pi/4 in magnitude.
+// * Input y is the tail of x.
+// * Input iy indicates whether y is 0. (if iy=0, y assume to be 0).
+// *
+// * Algorithm
+// * 1. Since sin(-x) = -sin(x), we need only to consider positive x.
+// * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0.
+// * 3. sin(x) is approximated by a polynomial of degree 13 on
+// * [0,pi/4]
+// * 3 13
+// * sin(x) ~ x + S1*x + ... + S6*x
+// * where
+// *
+// * |sin(x) 2 4 6 8 10 12 | -58
+// * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2
+// * | x |
+// *
+// * 4. sin(x+y) = sin(x) + sin'(x')*y
+// * ~ sin(x) + (1-x*x/2)*y
+// * For better accuracy, let
+// * 3 2 2 2 2
+// * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6))))
+// * then 3 2
+// * sin(x) = x + (S1*x + (x *(r-y/2)+y))
+// */
+//static const double
+//S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */
+//S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */
+//S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */
+//S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */
+//S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */
+//S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */
+//
+// NOTE: S1..S6 were moved into a table: StubRoutines::aarch64::_dsin_coef
+//
+// BEGIN __kernel_sin PSEUDO CODE
+//
+//static double __kernel_sin(double x, double y, bool iy)
+//{
+// double z,r,v;
+//
+// // NOTE: not needed. moved to dsin/dcos
+// //int ix;
+// //ix = high(x)&0x7fffffff; /* high word of x */
+//
+// // NOTE: moved to dsin/dcos
+// //if(ix<0x3e400000) /* |x| < 2**-27 */
+// // {if((int)x==0) return x;} /* generate inexact */
+//
+// z = x*x;
+// v = z*x;
+// r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
+// if(iy==0) return x+v*(S1+z*r);
+// else return x-((z*(half*y-v*r)-y)-v*S1);
+//}
+//
+// END __kernel_sin PSEUDO CODE
+//
+// Changes between fdlibm and intrinsic:
+// 1. Removed |x| < 2**-27 check, because if was done earlier in dsin/dcos
+// 2. Constants are now loaded from table dsin_coef
+// 3. C code parameter "int iy" was modified to "bool iyIsOne", because
+// iy is always 0 or 1. Also, iyIsOne branch was moved into
+// generation phase instead of taking it during code execution
+// Input ans output:
+// 1. Input for generated function: X argument = x
+// 2. Input for generator: x = register to read argument from, iyIsOne
+// = flag to use low argument low part or not, dsin_coef = coefficients
+// table address
+// 3. Return sin(x) value in v0
+void MacroAssembler::generate_kernel_sin(FloatRegister x, bool iyIsOne,
+ address dsin_coef) {
+ FloatRegister y = v5, z = v6, v = v7, r = v16, S1 = v17, S2 = v18,
+ S3 = v19, S4 = v20, S5 = v21, S6 = v22, half = v23;
+ lea(rscratch2, ExternalAddress(dsin_coef));
+ ldpd(S5, S6, Address(rscratch2, 32));
+ fmuld(z, x, x); // z = x*x;
+ ld1(S1, S2, S3, S4, T1D, Address(rscratch2));
+ fmuld(v, z, x); // v = z*x;
+
+ block_comment("calculate r = S2+z*(S3+z*(S4+z*(S5+z*S6)))"); {
+ fmaddd(r, z, S6, S5);
+ // initialize "half" in current block to utilize 2nd FPU. However, it's
+ // not a part of this block
+ fmovd(half, 0.5);
+ fmaddd(r, z, r, S4);
+ fmaddd(r, z, r, S3);
+ fmaddd(r, z, r, S2);
+ }
+
+ if (!iyIsOne) {
+ // return x+v*(S1+z*r);
+ fmaddd(S1, z, r, S1);
+ fmaddd(v0, v, S1, x);
+ } else {
+ // return x-((z*(half*y-v*r)-y)-v*S1);
+ fmuld(S6, half, y); // half*y
+ fmsubd(S6, v, r, S6); // half*y-v*r
+ fmsubd(S6, z, S6, y); // y - z*(half*y-v*r) = - (z*(half*y-v*r)-y)
+ fmaddd(S6, v, S1, S6); // - (z*(half*y-v*r)-y) + v*S1 == -((z*(half*y-v*r)-y)-v*S1)
+ faddd(v0, x, S6);
+ }
+}
+
+///*
+// * __kernel_cos( x, y )
+// * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164
+// * Input x is assumed to be bounded by ~pi/4 in magnitude.
+// * Input y is the tail of x.
+// *
+// * Algorithm
+// * 1. Since cos(-x) = cos(x), we need only to consider positive x.
+// * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0.
+// * 3. cos(x) is approximated by a polynomial of degree 14 on
+// * [0,pi/4]
+// * 4 14
+// * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x
+// * where the remez error is
+// *
+// * | 2 4 6 8 10 12 14 | -58
+// * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2
+// * | |
+// *
+// * 4 6 8 10 12 14
+// * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then
+// * cos(x) = 1 - x*x/2 + r
+// * since cos(x+y) ~ cos(x) - sin(x)*y
+// * ~ cos(x) - x*y,
+// * a correction term is necessary in cos(x) and hence
+// * cos(x+y) = 1 - (x*x/2 - (r - x*y))
+// * For better accuracy when x > 0.3, let qx = |x|/4 with
+// * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125.
+// * Then
+// * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)).
+// * Note that 1-qx and (x*x/2-qx) is EXACT here, and the
+// * magnitude of the latter is at least a quarter of x*x/2,
+// * thus, reducing the rounding error in the subtraction.
+// */
+//
+//static const double
+//C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */
+//C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */
+//C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */
+//C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */
+//C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */
+//C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */
+//
+// NOTE: C1..C6 were moved into a table: StubRoutines::aarch64::_dcos_coef
+//
+// BEGIN __kernel_cos PSEUDO CODE
+//
+//static double __kernel_cos(double x, double y)
+//{
+// double a,h,z,r,qx=0;
+//
+// // NOTE: ix is already initialized in dsin/dcos. Reuse value from register
+// //int ix;
+// //ix = high(x)&0x7fffffff; /* ix = |x|'s high word*/
+//
+// // NOTE: moved to dsin/dcos
+// //if(ix<0x3e400000) { /* if x < 2**27 */
+// // if(((int)x)==0) return one; /* generate inexact */
+// //}
+//
+// z = x*x;
+// r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
+// if(ix < 0x3FD33333) /* if |x| < 0.3 */
+// return one - (0.5*z - (z*r - x*y));
+// else {
+// if(ix > 0x3fe90000) { /* x > 0.78125 */
+// qx = 0.28125;
+// } else {
+// set_high(&qx, ix-0x00200000); /* x/4 */
+// set_low(&qx, 0);
+// }
+// h = 0.5*z-qx;
+// a = one-qx;
+// return a - (h - (z*r-x*y));
+// }
+//}
+//
+// END __kernel_cos PSEUDO CODE
+//
+// Changes between fdlibm and intrinsic:
+// 1. Removed |x| < 2**-27 check, because if was done earlier in dsin/dcos
+// 2. Constants are now loaded from table dcos_coef
+// Input and output:
+// 1. Input for generated function: X argument = x
+// 2. Input for generator: x = register to read argument from, dcos_coef
+// = coefficients table address
+// 2. Return cos(x) value in v0
+void MacroAssembler::generate_kernel_cos(FloatRegister x, address dcos_coef) {
+ Register ix = r3;
+ FloatRegister qx = v1, h = v2, a = v3, y = v5, z = v6, r = v7, C1 = v18,
+ C2 = v19, C3 = v20, C4 = v21, C5 = v22, C6 = v23, one = v25, half = v26;
+ Label IX_IS_LARGE, SET_QX_CONST, DONE, QX_SET;
+ lea(rscratch2, ExternalAddress(dcos_coef));
+ ldpd(C5, C6, Address(rscratch2, 32)); // load C5, C6
+ fmuld(z, x, x); // z=x^2
+ ld1(C1, C2, C3, C4, T1D, Address(rscratch2)); // load C1..C3\4
+ block_comment("calculate r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))))"); {
+ fmaddd(r, z, C6, C5);
+ fmovd(half, 0.5d);
+ fmaddd(r, z, r, C4);
+ fmuld(y, x, y);
+ fmaddd(r, z, r, C3);
+ mov(rscratch1, 0x3FD33333);
+ fmaddd(r, z, r, C2);
+ fmuld(x, z, z); // x = z^2
+ fmaddd(r, z, r, C1); // r = C1+z(C2+z(C4+z(C5+z*C6)))
+ }
+ // need to multiply r by z to have "final" r value
+ fmovd(one, 1.0d);
+ cmp(ix, rscratch1);
+ br(GT, IX_IS_LARGE);
+ block_comment("if(ix < 0x3FD33333) return one - (0.5*z - (z*r - x*y))"); {
+ // return 1.0 - (0.5*z - (z*r - x*y)) = 1.0 - (0.5*z + (x*y - z*r))
+ fmsubd(v0, x, r, y);
+ fmaddd(v0, half, z, v0);
+ fsubd(v0, one, v0);
+ b(DONE);
+ }
+ block_comment("if(ix >= 0x3FD33333)"); {
+ bind(IX_IS_LARGE);
+ movz(rscratch2, 0x3FE9, 16);
+ cmp(ix, rscratch2);
+ br(GT, SET_QX_CONST);
+ block_comment("set_high(&qx, ix-0x00200000); set_low(&qx, 0);"); {
+ subw(rscratch2, ix, 0x00200000);
+ lsl(rscratch2, rscratch2, 32);
+ fmovd(qx, rscratch2);
+ }
+ b(QX_SET);
+ bind(SET_QX_CONST);
+ block_comment("if(ix > 0x3fe90000) qx = 0.28125;"); {
+ fmovd(qx, 0.28125d);
+ }
+ bind(QX_SET);
+ fnmsub(C6, x, r, y); // z*r - xy
+ fnmsub(h, half, z, qx); // h = 0.5*z - qx
+ fsubd(a, one, qx); // a = 1-qx
+ fsubd(C6, h, C6); // = h - (z*r - x*y)
+ fsubd(v0, a, C6);
+ }
+ bind(DONE);
+}
+
+// generate_dsin_dcos creates stub for dsin and dcos
+// Generation is done via single call because dsin and dcos code is almost the
+// same(see C code below). These functions work as follows:
+// 1) handle corner cases: |x| ~< pi/4, x is NaN or INF, |x| < 2**-27
+// 2) perform argument reduction if required
+// 3) call kernel_sin or kernel_cos which approximate sin/cos via polynomial
+//
+// BEGIN dsin/dcos PSEUDO CODE
+//
+//dsin_dcos(jdouble x, bool isCos) {
+// double y[2],z=0.0;
+// int n, ix;
+//
+// /* High word of x. */
+// ix = high(x);
+//
+// /* |x| ~< pi/4 */
+// ix &= 0x7fffffff;
+// if(ix <= 0x3fe921fb) return isCos ? __kernel_cos : __kernel_sin(x,z,0);
+//
+// /* sin/cos(Inf or NaN) is NaN */
+// else if (ix>=0x7ff00000) return x-x;
+// else if (ix<0x3e400000) { /* if ix < 2**27 */
+// if(((int)x)==0) return isCos ? one : x; /* generate inexact */
+// }
+// /* argument reduction needed */
+// else {
+// n = __ieee754_rem_pio2(x,y);
+// switch(n&3) {
+// case 0: return isCos ? __kernel_cos(y[0],y[1]) : __kernel_sin(y[0],y[1], true);
+// case 1: return isCos ? -__kernel_sin(y[0],y[1],true) : __kernel_cos(y[0],y[1]);
+// case 2: return isCos ? -__kernel_cos(y[0],y[1]) : -__kernel_sin(y[0],y[1], true);
+// default:
+// return isCos ? __kernel_sin(y[0],y[1],1) : -__kernel_cos(y[0],y[1]);
+// }
+// }
+//}
+// END dsin/dcos PSEUDO CODE
+//
+// Changes between fdlibm and intrinsic:
+// 1. Moved ix < 2**27 from kernel_sin/kernel_cos into dsin/dcos
+// 2. Final switch use equivalent bit checks(tbz/tbnz)
+// Input ans output:
+// 1. Input for generated function: X = r0
+// 2. Input for generator: isCos = generate sin or cos, npio2_hw = address
+// of npio2_hw table, two_over_pi = address of two_over_pi table,
+// pio2 = address if pio2 table, dsin_coef = address if dsin_coef table,
+// dcos_coef = address of dcos_coef table
+// 3. Return result in v0
+// NOTE: general purpose register names match local variable names in C code
+void MacroAssembler::generate_dsin_dcos(bool isCos, address npio2_hw,
+ address two_over_pi, address pio2, address dsin_coef, address dcos_coef) {
+ const int POSITIVE_INFINITY_OR_NAN_PREFIX = 0x7FF0;
+
+ Label DONE, ARG_REDUCTION, TINY_X, RETURN_SIN, EARLY_CASE;
+ Register X = r0, absX = r1, n = r2, ix = r3;
+ FloatRegister y0 = v4, y1 = v5;
+ block_comment("check |x| ~< pi/4, NaN, Inf and |x| < 2**-27 cases"); {
+ fmovd(X, v0);
+ mov(rscratch2, 0x3e400000);
+ mov(rscratch1, 0x3fe921fb00000000); // pi/4. shifted to reuse later
+ ubfm(absX, X, 0, 62); // absX
+ movz(r10, POSITIVE_INFINITY_OR_NAN_PREFIX, 48);
+ cmp(rscratch2, absX, LSR, 32);
+ lsr(ix, absX, 32); // set ix
+ br(GT, TINY_X); // handle tiny x (|x| < 2^-27)
+ cmp(ix, rscratch1, LSR, 32);
+ br(LE, EARLY_CASE); // if(ix <= 0x3fe921fb) return
+ cmp(absX, r10);
+ br(LT, ARG_REDUCTION);
+ // X is NaN or INF(i.e. 0x7FF* or 0xFFF*). Return NaN (mantissa != 0).
+ // Set last bit unconditionally to make it NaN
+ orr(r10, r10, 1);
+ fmovd(v0, r10);
+ ret(lr);
+ }
+ block_comment("kernel_sin/kernel_cos: if(ix<0x3e400000) {<fast return>}"); {
+ bind(TINY_X);
+ if (isCos) {
+ fmovd(v0, 1.0d);
+ }
+ ret(lr);
+ }
+ bind(ARG_REDUCTION); /* argument reduction needed */
+ block_comment("n = __ieee754_rem_pio2(x,y);"); {
+ generate__ieee754_rem_pio2(npio2_hw, two_over_pi, pio2);
+ }
+ block_comment("switch(n&3) {case ... }"); {
+ if (isCos) {
+ eorw(absX, n, n, LSR, 1);
+ tbnz(n, 0, RETURN_SIN);
+ } else {
+ tbz(n, 0, RETURN_SIN);
+ }
+ generate_kernel_cos(y0, dcos_coef);
+ if (isCos) {
+ tbz(absX, 0, DONE);
+ } else {
+ tbz(n, 1, DONE);
+ }
+ fnegd(v0, v0);
+ ret(lr);
+ bind(RETURN_SIN);
+ generate_kernel_sin(y0, true, dsin_coef);
+ if (isCos) {
+ tbz(absX, 0, DONE);
+ } else {
+ tbz(n, 1, DONE);
+ }
+ fnegd(v0, v0);
+ ret(lr);
+ }
+ bind(EARLY_CASE);
+ eor(y1, T8B, y1, y1);
+ if (isCos) {
+ generate_kernel_cos(v0, dcos_coef);
+ } else {
+ generate_kernel_sin(v0, false, dsin_coef);
+ }
+ bind(DONE);
+ ret(lr);
+}
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1351,9 +1351,9 @@
BLOCK_COMMENT("Entry:");
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1425,9 +1425,9 @@
__ cmp(rscratch1, count, Assembler::LSL, exact_log2(size));
__ br(Assembler::HS, nooverlap_target);
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1789,10 +1789,10 @@
}
#endif //ASSERT
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
bool is_oop = true;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
@@ -3990,6 +3990,701 @@
return entry;
}
+ address generate_dsin_dcos(bool isCos) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", isCos ? "libmDcos" : "libmDsin");
+ address start = __ pc();
+ __ generate_dsin_dcos(isCos, (address)StubRoutines::aarch64::_npio2_hw,
+ (address)StubRoutines::aarch64::_two_over_pi,
+ (address)StubRoutines::aarch64::_pio2,
+ (address)StubRoutines::aarch64::_dsin_coef,
+ (address)StubRoutines::aarch64::_dcos_coef);
+ return start;
+ }
+
+ address generate_dlog() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "dlog");
+ address entry = __ pc();
+ FloatRegister vtmp0 = v0, vtmp1 = v1, vtmp2 = v2, vtmp3 = v3, vtmp4 = v4,
+ vtmp5 = v5, tmpC1 = v16, tmpC2 = v17, tmpC3 = v18, tmpC4 = v19;
+ Register tmp1 = r0, tmp2 = r1, tmp3 = r2, tmp4 = r3, tmp5 = r4;
+ __ fast_log(vtmp0, vtmp1, vtmp2, vtmp3, vtmp4, vtmp5, tmpC1, tmpC2, tmpC3,
+ tmpC4, tmp1, tmp2, tmp3, tmp4, tmp5);
+ return entry;
+ }
+
+ // code for comparing 16 bytes of strings with same encoding
+ void compare_string_16_bytes_same(Label &DIFF1, Label &DIFF2) {
+ Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, tmp1 = r10, tmp2 = r11;
+ __ ldr(rscratch1, Address(__ post(str1, 8)));
+ __ eor(rscratch2, tmp1, tmp2);
+ __ ldr(cnt1, Address(__ post(str2, 8)));
+ __ cbnz(rscratch2, DIFF1);
+ __ ldr(tmp1, Address(__ post(str1, 8)));
+ __ eor(rscratch2, rscratch1, cnt1);
+ __ ldr(tmp2, Address(__ post(str2, 8)));
+ __ cbnz(rscratch2, DIFF2);
+ }
+
+ // code for comparing 16 characters of strings with Latin1 and Utf16 encoding
+ void compare_string_16_x_LU(Register tmpL, Register tmpU, Label &DIFF1,
+ Label &DIFF2) {
+ Register cnt1 = r2, tmp1 = r10, tmp2 = r11, tmp3 = r12;
+ FloatRegister vtmp = v1, vtmpZ = v0, vtmp3 = v2;
+
+ __ ldrq(vtmp, Address(__ post(tmp2, 16)));
+ __ ldr(tmpU, Address(__ post(cnt1, 8)));
+ __ zip1(vtmp3, __ T16B, vtmp, vtmpZ);
+ // now we have 32 bytes of characters (converted to U) in vtmp:vtmp3
+
+ __ fmovd(tmpL, vtmp3);
+ __ eor(rscratch2, tmp3, tmpL);
+ __ cbnz(rscratch2, DIFF2);
+
+ __ ldr(tmp3, Address(__ post(cnt1, 8)));
+ __ umov(tmpL, vtmp3, __ D, 1);
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbnz(rscratch2, DIFF1);
+
+ __ zip2(vtmp, __ T16B, vtmp, vtmpZ);
+ __ ldr(tmpU, Address(__ post(cnt1, 8)));
+ __ fmovd(tmpL, vtmp);
+ __ eor(rscratch2, tmp3, tmpL);
+ __ cbnz(rscratch2, DIFF2);
+
+ __ ldr(tmp3, Address(__ post(cnt1, 8)));
+ __ umov(tmpL, vtmp, __ D, 1);
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbnz(rscratch2, DIFF1);
+ }
+
+ // r0 = result
+ // r1 = str1
+ // r2 = cnt1
+ // r3 = str2
+ // r4 = cnt2
+ // r10 = tmp1
+ // r11 = tmp2
+ address generate_compare_long_string_different_encoding(bool isLU) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", isLU
+ ? "compare_long_string_different_encoding LU"
+ : "compare_long_string_different_encoding UL");
+ address entry = __ pc();
+ Label SMALL_LOOP, TAIL, TAIL_LOAD_16, LOAD_LAST, DIFF1, DIFF2,
+ DONE, CALCULATE_DIFFERENCE, LARGE_LOOP_PREFETCH, SMALL_LOOP_ENTER,
+ LARGE_LOOP_PREFETCH_REPEAT1, LARGE_LOOP_PREFETCH_REPEAT2;
+ Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, cnt2 = r4,
+ tmp1 = r10, tmp2 = r11, tmp3 = r12, tmp4 = r14;
+ FloatRegister vtmpZ = v0, vtmp = v1, vtmp3 = v2;
+ RegSet spilled_regs = RegSet::of(tmp3, tmp4);
+
+ int prefetchLoopExitCondition = MAX(32, SoftwarePrefetchHintDistance/2);
+
+ __ eor(vtmpZ, __ T16B, vtmpZ, vtmpZ);
+ // cnt2 == amount of characters left to compare
+ // Check already loaded first 4 symbols(vtmp and tmp2(LU)/tmp1(UL))
+ __ zip1(vtmp, __ T8B, vtmp, vtmpZ);
+ __ add(str1, str1, isLU ? wordSize/2 : wordSize);
+ __ add(str2, str2, isLU ? wordSize : wordSize/2);
+ __ fmovd(isLU ? tmp1 : tmp2, vtmp);
+ __ subw(cnt2, cnt2, 8); // Already loaded 4 symbols. Last 4 is special case.
+ __ add(str1, str1, cnt2, __ LSL, isLU ? 0 : 1);
+ __ eor(rscratch2, tmp1, tmp2);
+ __ add(str2, str2, cnt2, __ LSL, isLU ? 1 : 0);
+ __ mov(rscratch1, tmp2);
+ __ cbnz(rscratch2, CALCULATE_DIFFERENCE);
+ Register strU = isLU ? str2 : str1,
+ strL = isLU ? str1 : str2,
+ tmpU = isLU ? rscratch1 : tmp1, // where to keep U for comparison
+ tmpL = isLU ? tmp1 : rscratch1; // where to keep L for comparison
+ __ push(spilled_regs, sp);
+ __ sub(tmp2, strL, cnt2); // strL pointer to load from
+ __ sub(cnt1, strU, cnt2, __ LSL, 1); // strU pointer to load from
+
+ __ ldr(tmp3, Address(__ post(cnt1, 8)));
+
+ if (SoftwarePrefetchHintDistance >= 0) {
+ __ cmp(cnt2, prefetchLoopExitCondition);
+ __ br(__ LT, SMALL_LOOP);
+ __ bind(LARGE_LOOP_PREFETCH);
+ __ prfm(Address(tmp2, SoftwarePrefetchHintDistance));
+ __ mov(tmp4, 2);
+ __ prfm(Address(cnt1, SoftwarePrefetchHintDistance));
+ __ bind(LARGE_LOOP_PREFETCH_REPEAT1);
+ compare_string_16_x_LU(tmpL, tmpU, DIFF1, DIFF2);
+ __ subs(tmp4, tmp4, 1);
+ __ br(__ GT, LARGE_LOOP_PREFETCH_REPEAT1);
+ __ prfm(Address(cnt1, SoftwarePrefetchHintDistance));
+ __ mov(tmp4, 2);
+ __ bind(LARGE_LOOP_PREFETCH_REPEAT2);
+ compare_string_16_x_LU(tmpL, tmpU, DIFF1, DIFF2);
+ __ subs(tmp4, tmp4, 1);
+ __ br(__ GT, LARGE_LOOP_PREFETCH_REPEAT2);
+ __ sub(cnt2, cnt2, 64);
+ __ cmp(cnt2, prefetchLoopExitCondition);
+ __ br(__ GE, LARGE_LOOP_PREFETCH);
+ }
+ __ cbz(cnt2, LOAD_LAST); // no characters left except last load
+ __ subs(cnt2, cnt2, 16);
+ __ br(__ LT, TAIL);
+ __ b(SMALL_LOOP_ENTER);
+ __ bind(SMALL_LOOP); // smaller loop
+ __ subs(cnt2, cnt2, 16);
+ __ bind(SMALL_LOOP_ENTER);
+ compare_string_16_x_LU(tmpL, tmpU, DIFF1, DIFF2);
+ __ br(__ GE, SMALL_LOOP);
+ __ cbz(cnt2, LOAD_LAST);
+ __ bind(TAIL); // 1..15 characters left
+ __ cmp(cnt2, -8);
+ __ br(__ GT, TAIL_LOAD_16);
+ __ ldrd(vtmp, Address(tmp2));
+ __ zip1(vtmp3, __ T8B, vtmp, vtmpZ);
+
+ __ ldr(tmpU, Address(__ post(cnt1, 8)));
+ __ fmovd(tmpL, vtmp3);
+ __ eor(rscratch2, tmp3, tmpL);
+ __ cbnz(rscratch2, DIFF2);
+ __ umov(tmpL, vtmp3, __ D, 1);
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbnz(rscratch2, DIFF1);
+ __ b(LOAD_LAST);
+ __ bind(TAIL_LOAD_16);
+ __ ldrq(vtmp, Address(tmp2));
+ __ ldr(tmpU, Address(__ post(cnt1, 8)));
+ __ zip1(vtmp3, __ T16B, vtmp, vtmpZ);
+ __ zip2(vtmp, __ T16B, vtmp, vtmpZ);
+ __ fmovd(tmpL, vtmp3);
+ __ eor(rscratch2, tmp3, tmpL);
+ __ cbnz(rscratch2, DIFF2);
+
+ __ ldr(tmp3, Address(__ post(cnt1, 8)));
+ __ umov(tmpL, vtmp3, __ D, 1);
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbnz(rscratch2, DIFF1);
+
+ __ ldr(tmpU, Address(__ post(cnt1, 8)));
+ __ fmovd(tmpL, vtmp);
+ __ eor(rscratch2, tmp3, tmpL);
+ __ cbnz(rscratch2, DIFF2);
+
+ __ umov(tmpL, vtmp, __ D, 1);
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbnz(rscratch2, DIFF1);
+ __ b(LOAD_LAST);
+ __ bind(DIFF2);
+ __ mov(tmpU, tmp3);
+ __ bind(DIFF1);
+ __ pop(spilled_regs, sp);
+ __ b(CALCULATE_DIFFERENCE);
+ __ bind(LOAD_LAST);
+ __ pop(spilled_regs, sp);
+
+ __ ldrs(vtmp, Address(strL));
+ __ ldr(tmpU, Address(strU));
+ __ zip1(vtmp, __ T8B, vtmp, vtmpZ);
+ __ fmovd(tmpL, vtmp);
+
+ __ eor(rscratch2, tmpU, tmpL);
+ __ cbz(rscratch2, DONE);
+
+ // Find the first different characters in the longwords and
+ // compute their difference.
+ __ bind(CALCULATE_DIFFERENCE);
+ __ rev(rscratch2, rscratch2);
+ __ clz(rscratch2, rscratch2);
+ __ andr(rscratch2, rscratch2, -16);
+ __ lsrv(tmp1, tmp1, rscratch2);
+ __ uxthw(tmp1, tmp1);
+ __ lsrv(rscratch1, rscratch1, rscratch2);
+ __ uxthw(rscratch1, rscratch1);
+ __ subw(result, tmp1, rscratch1);
+ __ bind(DONE);
+ __ ret(lr);
+ return entry;
+ }
+
+ // r0 = result
+ // r1 = str1
+ // r2 = cnt1
+ // r3 = str2
+ // r4 = cnt2
+ // r10 = tmp1
+ // r11 = tmp2
+ address generate_compare_long_string_same_encoding(bool isLL) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", isLL
+ ? "compare_long_string_same_encoding LL"
+ : "compare_long_string_same_encoding UU");
+ address entry = __ pc();
+ Register result = r0, str1 = r1, cnt1 = r2, str2 = r3, cnt2 = r4,
+ tmp1 = r10, tmp2 = r11;
+ Label SMALL_LOOP, LARGE_LOOP_PREFETCH, CHECK_LAST, DIFF2, TAIL,
+ LENGTH_DIFF, DIFF, LAST_CHECK_AND_LENGTH_DIFF,
+ DIFF_LAST_POSITION, DIFF_LAST_POSITION2;
+ // exit from large loop when less than 64 bytes left to read or we're about
+ // to prefetch memory behind array border
+ int largeLoopExitCondition = MAX(64, SoftwarePrefetchHintDistance)/(isLL ? 1 : 2);
+ // cnt1/cnt2 contains amount of characters to compare. cnt1 can be re-used
+ // update cnt2 counter with already loaded 8 bytes
+ __ sub(cnt2, cnt2, wordSize/(isLL ? 1 : 2));
+ // update pointers, because of previous read
+ __ add(str1, str1, wordSize);
+ __ add(str2, str2, wordSize);
+ if (SoftwarePrefetchHintDistance >= 0) {
+ __ bind(LARGE_LOOP_PREFETCH);
+ __ prfm(Address(str1, SoftwarePrefetchHintDistance));
+ __ prfm(Address(str2, SoftwarePrefetchHintDistance));
+ compare_string_16_bytes_same(DIFF, DIFF2);
+ compare_string_16_bytes_same(DIFF, DIFF2);
+ __ sub(cnt2, cnt2, isLL ? 64 : 32);
+ compare_string_16_bytes_same(DIFF, DIFF2);
+ __ cmp(cnt2, largeLoopExitCondition);
+ compare_string_16_bytes_same(DIFF, DIFF2);
+ __ br(__ GT, LARGE_LOOP_PREFETCH);
+ __ cbz(cnt2, LAST_CHECK_AND_LENGTH_DIFF); // no more chars left?
+ // less than 16 bytes left?
+ __ subs(cnt2, cnt2, isLL ? 16 : 8);
+ __ br(__ LT, TAIL);
+ }
+ __ bind(SMALL_LOOP);
+ compare_string_16_bytes_same(DIFF, DIFF2);
+ __ subs(cnt2, cnt2, isLL ? 16 : 8);
+ __ br(__ GE, SMALL_LOOP);
+ __ bind(TAIL);
+ __ adds(cnt2, cnt2, isLL ? 16 : 8);
+ __ br(__ EQ, LAST_CHECK_AND_LENGTH_DIFF);
+ __ subs(cnt2, cnt2, isLL ? 8 : 4);
+ __ br(__ LE, CHECK_LAST);
+ __ eor(rscratch2, tmp1, tmp2);
+ __ cbnz(rscratch2, DIFF);
+ __ ldr(tmp1, Address(__ post(str1, 8)));
+ __ ldr(tmp2, Address(__ post(str2, 8)));
+ __ sub(cnt2, cnt2, isLL ? 8 : 4);
+ __ bind(CHECK_LAST);
+ if (!isLL) {
+ __ add(cnt2, cnt2, cnt2); // now in bytes
+ }
+ __ eor(rscratch2, tmp1, tmp2);
+ __ cbnz(rscratch2, DIFF);
+ __ ldr(rscratch1, Address(str1, cnt2));
+ __ ldr(cnt1, Address(str2, cnt2));
+ __ eor(rscratch2, rscratch1, cnt1);
+ __ cbz(rscratch2, LENGTH_DIFF);
+ // Find the first different characters in the longwords and
+ // compute their difference.
+ __ bind(DIFF2);
+ __ rev(rscratch2, rscratch2);
+ __ clz(rscratch2, rscratch2);
+ __ andr(rscratch2, rscratch2, isLL ? -8 : -16);
+ __ lsrv(rscratch1, rscratch1, rscratch2);
+ if (isLL) {
+ __ lsrv(cnt1, cnt1, rscratch2);
+ __ uxtbw(rscratch1, rscratch1);
+ __ uxtbw(cnt1, cnt1);
+ } else {
+ __ lsrv(cnt1, cnt1, rscratch2);
+ __ uxthw(rscratch1, rscratch1);
+ __ uxthw(cnt1, cnt1);
+ }
+ __ subw(result, rscratch1, cnt1);
+ __ b(LENGTH_DIFF);
+ __ bind(DIFF);
+ __ rev(rscratch2, rscratch2);
+ __ clz(rscratch2, rscratch2);
+ __ andr(rscratch2, rscratch2, isLL ? -8 : -16);
+ __ lsrv(tmp1, tmp1, rscratch2);
+ if (isLL) {
+ __ lsrv(tmp2, tmp2, rscratch2);
+ __ uxtbw(tmp1, tmp1);
+ __ uxtbw(tmp2, tmp2);
+ } else {
+ __ lsrv(tmp2, tmp2, rscratch2);
+ __ uxthw(tmp1, tmp1);
+ __ uxthw(tmp2, tmp2);
+ }
+ __ subw(result, tmp1, tmp2);
+ __ b(LENGTH_DIFF);
+ __ bind(LAST_CHECK_AND_LENGTH_DIFF);
+ __ eor(rscratch2, tmp1, tmp2);
+ __ cbnz(rscratch2, DIFF);
+ __ bind(LENGTH_DIFF);
+ __ ret(lr);
+ return entry;
+ }
+
+ void generate_compare_long_strings() {
+ StubRoutines::aarch64::_compare_long_string_LL
+ = generate_compare_long_string_same_encoding(true);
+ StubRoutines::aarch64::_compare_long_string_UU
+ = generate_compare_long_string_same_encoding(false);
+ StubRoutines::aarch64::_compare_long_string_LU
+ = generate_compare_long_string_different_encoding(true);
+ StubRoutines::aarch64::_compare_long_string_UL
+ = generate_compare_long_string_different_encoding(false);
+ }
+
+ // R0 = result
+ // R1 = str2
+ // R2 = cnt1
+ // R3 = str1
+ // R4 = cnt2
+ // This generic linear code use few additional ideas, which makes it faster:
+ // 1) we can safely keep at least 1st register of pattern(since length >= 8)
+ // in order to skip initial loading(help in systems with 1 ld pipeline)
+ // 2) we can use "fast" algorithm of finding single character to search for
+ // first symbol with less branches(1 branch per each loaded register instead
+ // of branch for each symbol), so, this is where constants like
+ // 0x0101...01, 0x00010001...0001, 0x7f7f...7f, 0x7fff7fff...7fff comes from
+ // 3) after loading and analyzing 1st register of source string, it can be
+ // used to search for every 1st character entry, saving few loads in
+ // comparison with "simplier-but-slower" implementation
+ // 4) in order to avoid lots of push/pop operations, code below is heavily
+ // re-using/re-initializing/compressing register values, which makes code
+ // larger and a bit less readable, however, most of extra operations are
+ // issued during loads or branches, so, penalty is minimal
+ address generate_string_indexof_linear(bool str1_isL, bool str2_isL) {
+ const char* stubName = str1_isL
+ ? (str2_isL ? "indexof_linear_ll" : "indexof_linear_ul")
+ : "indexof_linear_uu";
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", stubName);
+ address entry = __ pc();
+
+ int str1_chr_size = str1_isL ? 1 : 2;
+ int str2_chr_size = str2_isL ? 1 : 2;
+ int str1_chr_shift = str1_isL ? 0 : 1;
+ int str2_chr_shift = str2_isL ? 0 : 1;
+ bool isL = str1_isL && str2_isL;
+ // parameters
+ Register result = r0, str2 = r1, cnt1 = r2, str1 = r3, cnt2 = r4;
+ // temporary registers
+ Register tmp1 = r20, tmp2 = r21, tmp3 = r22, tmp4 = r23;
+ RegSet spilled_regs = RegSet::range(tmp1, tmp4);
+ // redefinitions
+ Register ch1 = rscratch1, ch2 = rscratch2, first = tmp3;
+
+ __ push(spilled_regs, sp);
+ Label L_LOOP, L_LOOP_PROCEED, L_SMALL, L_HAS_ZERO, L_SMALL_MATCH_LOOP,
+ L_HAS_ZERO_LOOP, L_CMP_LOOP, L_CMP_LOOP_NOMATCH, L_SMALL_PROCEED,
+ L_SMALL_HAS_ZERO_LOOP, L_SMALL_CMP_LOOP_NOMATCH, L_SMALL_CMP_LOOP,
+ L_POST_LOOP, L_CMP_LOOP_LAST_CMP, L_HAS_ZERO_LOOP_NOMATCH,
+ L_SMALL_CMP_LOOP_LAST_CMP, L_SMALL_CMP_LOOP_LAST_CMP2,
+ L_CMP_LOOP_LAST_CMP2, DONE, NOMATCH;
+ // Read whole register from str1. It is safe, because length >=8 here
+ __ ldr(ch1, Address(str1));
+ // Read whole register from str2. It is safe, because length >=8 here
+ __ ldr(ch2, Address(str2));
+ __ andr(first, ch1, str1_isL ? 0xFF : 0xFFFF);
+ if (str1_isL != str2_isL) {
+ __ eor(v0, __ T16B, v0, v0);
+ }
+ __ mov(tmp1, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
+ __ mul(first, first, tmp1);
+ // check if we have less than 1 register to check
+ __ subs(cnt2, cnt2, wordSize/str2_chr_size - 1);
+ if (str1_isL != str2_isL) {
+ __ fmovd(v1, ch1);
+ }
+ __ br(__ LE, L_SMALL);
+ __ eor(ch2, first, ch2);
+ if (str1_isL != str2_isL) {
+ __ zip1(v1, __ T16B, v1, v0);
+ }
+ __ sub(tmp2, ch2, tmp1);
+ __ orr(ch2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
+ __ bics(tmp2, tmp2, ch2);
+ if (str1_isL != str2_isL) {
+ __ fmovd(ch1, v1);
+ }
+ __ br(__ NE, L_HAS_ZERO);
+ __ subs(cnt2, cnt2, wordSize/str2_chr_size);
+ __ add(result, result, wordSize/str2_chr_size);
+ __ add(str2, str2, wordSize);
+ __ br(__ LT, L_POST_LOOP);
+ __ BIND(L_LOOP);
+ __ ldr(ch2, Address(str2));
+ __ eor(ch2, first, ch2);
+ __ sub(tmp2, ch2, tmp1);
+ __ orr(ch2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
+ __ bics(tmp2, tmp2, ch2);
+ __ br(__ NE, L_HAS_ZERO);
+ __ BIND(L_LOOP_PROCEED);
+ __ subs(cnt2, cnt2, wordSize/str2_chr_size);
+ __ add(str2, str2, wordSize);
+ __ add(result, result, wordSize/str2_chr_size);
+ __ br(__ GE, L_LOOP);
+ __ BIND(L_POST_LOOP);
+ __ cmp(cnt2, -wordSize/str2_chr_size); // no extra characters to check
+ __ br(__ LE, NOMATCH);
+ __ ldr(ch2, Address(str2));
+ __ sub(cnt2, zr, cnt2, __ LSL, LogBitsPerByte + str2_chr_shift);
+ __ eor(ch2, first, ch2);
+ __ sub(tmp2, ch2, tmp1);
+ __ orr(ch2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
+ __ mov(tmp4, -1); // all bits set
+ __ b(L_SMALL_PROCEED);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_SMALL);
+ __ sub(cnt2, zr, cnt2, __ LSL, LogBitsPerByte + str2_chr_shift);
+ __ eor(ch2, first, ch2);
+ if (str1_isL != str2_isL) {
+ __ zip1(v1, __ T16B, v1, v0);
+ }
+ __ sub(tmp2, ch2, tmp1);
+ __ mov(tmp4, -1); // all bits set
+ __ orr(ch2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
+ if (str1_isL != str2_isL) {
+ __ fmovd(ch1, v1); // move converted 4 symbols
+ }
+ __ BIND(L_SMALL_PROCEED);
+ __ lsrv(tmp4, tmp4, cnt2); // mask. zeroes on useless bits.
+ __ bic(tmp2, tmp2, ch2);
+ __ ands(tmp2, tmp2, tmp4); // clear useless bits and check
+ __ rbit(tmp2, tmp2);
+ __ br(__ EQ, NOMATCH);
+ __ BIND(L_SMALL_HAS_ZERO_LOOP);
+ __ clz(tmp4, tmp2); // potentially long. Up to 4 cycles on some cpu's
+ __ cmp(cnt1, wordSize/str2_chr_size);
+ __ br(__ LE, L_SMALL_CMP_LOOP_LAST_CMP2);
+ if (str2_isL) { // LL
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte); // address of "index"
+ __ ldr(ch2, Address(str2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4); // shift off leading zeroes from match info
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte);
+ __ lsl(tmp2, tmp2, 1); // shift off leading "1" from match info
+ } else {
+ __ mov(ch2, 0xE); // all bits in byte set except last one
+ __ andr(ch2, ch2, tmp4, __ LSR, LogBitsPerByte); // byte shift amount
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ lsl(tmp2, tmp2, 1); // shift off leading "1" from match info
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ }
+ __ cmp(ch1, ch2);
+ __ mov(tmp4, wordSize/str2_chr_size);
+ __ br(__ NE, L_SMALL_CMP_LOOP_NOMATCH);
+ __ BIND(L_SMALL_CMP_LOOP);
+ str1_isL ? __ ldrb(first, Address(str1, tmp4, Address::lsl(str1_chr_shift)))
+ : __ ldrh(first, Address(str1, tmp4, Address::lsl(str1_chr_shift)));
+ str2_isL ? __ ldrb(ch2, Address(str2, tmp4, Address::lsl(str2_chr_shift)))
+ : __ ldrh(ch2, Address(str2, tmp4, Address::lsl(str2_chr_shift)));
+ __ add(tmp4, tmp4, 1);
+ __ cmp(tmp4, cnt1);
+ __ br(__ GE, L_SMALL_CMP_LOOP_LAST_CMP);
+ __ cmp(first, ch2);
+ __ br(__ EQ, L_SMALL_CMP_LOOP);
+ __ BIND(L_SMALL_CMP_LOOP_NOMATCH);
+ __ cbz(tmp2, NOMATCH); // no more matches. exit
+ __ clz(tmp4, tmp2);
+ __ add(result, result, 1); // advance index
+ __ add(str2, str2, str2_chr_size); // advance pointer
+ __ b(L_SMALL_HAS_ZERO_LOOP);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_SMALL_CMP_LOOP_LAST_CMP);
+ __ cmp(first, ch2);
+ __ br(__ NE, L_SMALL_CMP_LOOP_NOMATCH);
+ __ b(DONE);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_SMALL_CMP_LOOP_LAST_CMP2);
+ if (str2_isL) { // LL
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte); // address of "index"
+ __ ldr(ch2, Address(str2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4); // shift off leading zeroes from match info
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte);
+ __ lsl(tmp2, tmp2, 1); // shift off leading "1" from match info
+ } else {
+ __ mov(ch2, 0xE); // all bits in byte set except last one
+ __ andr(ch2, ch2, tmp4, __ LSR, LogBitsPerByte); // byte shift amount
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ lsl(tmp2, tmp2, 1); // shift off leading "1" from match info
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ }
+ __ cmp(ch1, ch2);
+ __ br(__ NE, L_SMALL_CMP_LOOP_NOMATCH);
+ __ b(DONE);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_HAS_ZERO);
+ __ rbit(tmp2, tmp2);
+ __ clz(tmp4, tmp2); // potentially long. Up to 4 cycles on some CPU's
+ // Now, perform compression of counters(cnt2 and cnt1) into one register.
+ // It's fine because both counters are 32bit and are not changed in this
+ // loop. Just restore it on exit. So, cnt1 can be re-used in this loop.
+ __ orr(cnt2, cnt2, cnt1, __ LSL, BitsPerByte * wordSize / 2);
+ __ sub(result, result, 1);
+ __ BIND(L_HAS_ZERO_LOOP);
+ __ mov(cnt1, wordSize/str2_chr_size);
+ __ cmp(cnt1, cnt2, __ LSR, BitsPerByte * wordSize / 2);
+ __ br(__ GE, L_CMP_LOOP_LAST_CMP2); // case of 8 bytes only to compare
+ if (str2_isL) {
+ __ lsr(ch2, tmp4, LogBitsPerByte + str2_chr_shift); // char index
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(tmp4, tmp4, 1);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ lsl(tmp2, tmp2, 1);
+ __ mov(tmp4, wordSize/str2_chr_size);
+ } else {
+ __ mov(ch2, 0xE);
+ __ andr(ch2, ch2, tmp4, __ LSR, LogBitsPerByte); // byte shift amount
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(tmp4, tmp4, 1);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte);
+ __ lsl(tmp2, tmp2, 1);
+ __ mov(tmp4, wordSize/str2_chr_size);
+ __ sub(str2, str2, str2_chr_size);
+ }
+ __ cmp(ch1, ch2);
+ __ mov(tmp4, wordSize/str2_chr_size);
+ __ br(__ NE, L_CMP_LOOP_NOMATCH);
+ __ BIND(L_CMP_LOOP);
+ str1_isL ? __ ldrb(cnt1, Address(str1, tmp4, Address::lsl(str1_chr_shift)))
+ : __ ldrh(cnt1, Address(str1, tmp4, Address::lsl(str1_chr_shift)));
+ str2_isL ? __ ldrb(ch2, Address(str2, tmp4, Address::lsl(str2_chr_shift)))
+ : __ ldrh(ch2, Address(str2, tmp4, Address::lsl(str2_chr_shift)));
+ __ add(tmp4, tmp4, 1);
+ __ cmp(tmp4, cnt2, __ LSR, BitsPerByte * wordSize / 2);
+ __ br(__ GE, L_CMP_LOOP_LAST_CMP);
+ __ cmp(cnt1, ch2);
+ __ br(__ EQ, L_CMP_LOOP);
+ __ BIND(L_CMP_LOOP_NOMATCH);
+ // here we're not matched
+ __ cbz(tmp2, L_HAS_ZERO_LOOP_NOMATCH); // no more matches. Proceed to main loop
+ __ clz(tmp4, tmp2);
+ __ add(str2, str2, str2_chr_size); // advance pointer
+ __ b(L_HAS_ZERO_LOOP);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_CMP_LOOP_LAST_CMP);
+ __ cmp(cnt1, ch2);
+ __ br(__ NE, L_CMP_LOOP_NOMATCH);
+ __ b(DONE);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_CMP_LOOP_LAST_CMP2);
+ if (str2_isL) {
+ __ lsr(ch2, tmp4, LogBitsPerByte + str2_chr_shift); // char index
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(tmp4, tmp4, 1);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ lsl(tmp2, tmp2, 1);
+ } else {
+ __ mov(ch2, 0xE);
+ __ andr(ch2, ch2, tmp4, __ LSR, LogBitsPerByte); // byte shift amount
+ __ ldr(ch2, Address(str2, ch2)); // read whole register of str2. Safe.
+ __ lslv(tmp2, tmp2, tmp4);
+ __ add(tmp4, tmp4, 1);
+ __ add(result, result, tmp4, __ LSR, LogBitsPerByte + str2_chr_shift);
+ __ add(str2, str2, tmp4, __ LSR, LogBitsPerByte);
+ __ lsl(tmp2, tmp2, 1);
+ __ sub(str2, str2, str2_chr_size);
+ }
+ __ cmp(ch1, ch2);
+ __ br(__ NE, L_CMP_LOOP_NOMATCH);
+ __ b(DONE);
+ __ align(OptoLoopAlignment);
+ __ BIND(L_HAS_ZERO_LOOP_NOMATCH);
+ // 1) Restore "result" index. Index was wordSize/str2_chr_size * N until
+ // L_HAS_ZERO block. Byte octet was analyzed in L_HAS_ZERO_LOOP,
+ // so, result was increased at max by wordSize/str2_chr_size - 1, so,
+ // respective high bit wasn't changed. L_LOOP_PROCEED will increase
+ // result by analyzed characters value, so, we can just reset lower bits
+ // in result here. Clear 2 lower bits for UU/UL and 3 bits for LL
+ // 2) restore cnt1 and cnt2 values from "compressed" cnt2
+ // 3) advance str2 value to represent next str2 octet. result & 7/3 is
+ // index of last analyzed substring inside current octet. So, str2 in at
+ // respective start address. We need to advance it to next octet
+ __ andr(tmp2, result, wordSize/str2_chr_size - 1); // symbols analyzed
+ __ lsr(cnt1, cnt2, BitsPerByte * wordSize / 2);
+ __ bfm(result, zr, 0, 2 - str2_chr_shift);
+ __ sub(str2, str2, tmp2, __ LSL, str2_chr_shift); // restore str2
+ __ movw(cnt2, cnt2);
+ __ b(L_LOOP_PROCEED);
+ __ align(OptoLoopAlignment);
+ __ BIND(NOMATCH);
+ __ mov(result, -1);
+ __ BIND(DONE);
+ __ pop(spilled_regs, sp);
+ __ ret(lr);
+ return entry;
+ }
+
+ void generate_string_indexof_stubs() {
+ StubRoutines::aarch64::_string_indexof_linear_ll = generate_string_indexof_linear(true, true);
+ StubRoutines::aarch64::_string_indexof_linear_uu = generate_string_indexof_linear(false, false);
+ StubRoutines::aarch64::_string_indexof_linear_ul = generate_string_indexof_linear(true, false);
+ }
+
+ void inflate_and_store_2_fp_registers(bool generatePrfm,
+ FloatRegister src1, FloatRegister src2) {
+ Register dst = r1;
+ __ zip1(v1, __ T16B, src1, v0);
+ __ zip2(v2, __ T16B, src1, v0);
+ if (generatePrfm) {
+ __ prfm(Address(dst, SoftwarePrefetchHintDistance), PSTL1STRM);
+ }
+ __ zip1(v3, __ T16B, src2, v0);
+ __ zip2(v4, __ T16B, src2, v0);
+ __ st1(v1, v2, v3, v4, __ T16B, Address(__ post(dst, 64)));
+ }
+
+ // R0 = src
+ // R1 = dst
+ // R2 = len
+ // R3 = len >> 3
+ // V0 = 0
+ // v1 = loaded 8 bytes
+ address generate_large_byte_array_inflate() {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", "large_byte_array_inflate");
+ address entry = __ pc();
+ Label LOOP, LOOP_START, LOOP_PRFM, LOOP_PRFM_START, DONE;
+ Register src = r0, dst = r1, len = r2, octetCounter = r3;
+ const int large_loop_threshold = MAX(64, SoftwarePrefetchHintDistance)/8 + 4;
+
+ // do one more 8-byte read to have address 16-byte aligned in most cases
+ // also use single store instruction
+ __ ldrd(v2, __ post(src, 8));
+ __ sub(octetCounter, octetCounter, 2);
+ __ zip1(v1, __ T16B, v1, v0);
+ __ zip1(v2, __ T16B, v2, v0);
+ __ st1(v1, v2, __ T16B, __ post(dst, 32));
+ __ ld1(v3, v4, v5, v6, __ T16B, Address(__ post(src, 64)));
+ __ cmp(octetCounter, large_loop_threshold);
+ __ br(__ LE, LOOP_START);
+ __ b(LOOP_PRFM_START);
+ __ bind(LOOP_PRFM);
+ __ ld1(v3, v4, v5, v6, __ T16B, Address(__ post(src, 64)));
+ __ bind(LOOP_PRFM_START);
+ __ prfm(Address(src, SoftwarePrefetchHintDistance));
+ __ sub(octetCounter, octetCounter, 8);
+ __ cmp(octetCounter, large_loop_threshold);
+ inflate_and_store_2_fp_registers(true, v3, v4);
+ inflate_and_store_2_fp_registers(true, v5, v6);
+ __ br(__ GT, LOOP_PRFM);
+ __ cmp(octetCounter, 8);
+ __ br(__ LT, DONE);
+ __ bind(LOOP);
+ __ ld1(v3, v4, v5, v6, __ T16B, Address(__ post(src, 64)));
+ __ bind(LOOP_START);
+ __ sub(octetCounter, octetCounter, 8);
+ __ cmp(octetCounter, 8);
+ inflate_and_store_2_fp_registers(false, v3, v4);
+ inflate_and_store_2_fp_registers(false, v5, v6);
+ __ br(__ GE, LOOP);
+ __ bind(DONE);
+ __ ret(lr);
+ return entry;
+ }
/**
* Arguments:
@@ -5044,6 +5739,18 @@
if (UseCRC32CIntrinsics) {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
+
+ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dlog)) {
+ StubRoutines::_dlog = generate_dlog();
+ }
+
+ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) {
+ StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false);
+ }
+
+ if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dcos)) {
+ StubRoutines::_dcos = generate_dsin_dcos(/* isCos = */ true);
+ }
}
void generate_all() {
@@ -5078,6 +5785,13 @@
StubRoutines::aarch64::_large_array_equals = generate_large_array_equals();
}
+ generate_compare_long_strings();
+
+ generate_string_indexof_stubs();
+
+ // byte_array_inflate stub for large arrays.
+ StubRoutines::aarch64::_large_byte_array_inflate = generate_large_byte_array_inflate();
+
if (UseMultiplyToLenIntrinsic) {
StubRoutines::_multiplyToLen = generate_multiplyToLen();
}
--- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -48,6 +48,14 @@
address StubRoutines::aarch64::_has_negatives = NULL;
address StubRoutines::aarch64::_has_negatives_long = NULL;
address StubRoutines::aarch64::_large_array_equals = NULL;
+address StubRoutines::aarch64::_compare_long_string_LL = NULL;
+address StubRoutines::aarch64::_compare_long_string_UU = NULL;
+address StubRoutines::aarch64::_compare_long_string_LU = NULL;
+address StubRoutines::aarch64::_compare_long_string_UL = NULL;
+address StubRoutines::aarch64::_string_indexof_linear_ll = NULL;
+address StubRoutines::aarch64::_string_indexof_linear_uu = NULL;
+address StubRoutines::aarch64::_string_indexof_linear_ul = NULL;
+address StubRoutines::aarch64::_large_byte_array_inflate = NULL;
bool StubRoutines::aarch64::_completed = false;
/**
@@ -278,3 +286,87 @@
0x02D578EDUL, 0x7DAEED62UL, // word swap
0xD502ED78UL, 0xAE7D62EDUL, // byte swap of word swap
};
+
+juint StubRoutines::aarch64::_npio2_hw[] __attribute__ ((aligned(64))) = {
+ // first, various coefficient values: 0.5, invpio2, pio2_1, pio2_1t, pio2_2,
+ // pio2_2t, pio2_3, pio2_3t
+ // This is a small optimization wich keeping double[8] values in int[] table
+ // to have less address calculation instructions
+ //
+ // invpio2: 53 bits of 2/pi (enough for cases when trigonometric argument is small)
+ // pio2_1: first 33 bit of pi/2
+ // pio2_1t: pi/2 - pio2_1
+ // pio2_2: second 33 bit of pi/2
+ // pio2_2t: pi/2 - (pio2_1+pio2_2)
+ // pio2_3: third 33 bit of pi/2
+ // pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
+ 0x00000000, 0x3fe00000, // 0.5
+ 0x6DC9C883, 0x3FE45F30, // invpio2 = 6.36619772367581382433e-01
+ 0x54400000, 0x3FF921FB, // pio2_1 = 1.57079632673412561417e+00
+ 0x1A626331, 0x3DD0B461, // pio2_1t = 6.07710050650619224932e-11
+ 0x1A600000, 0x3DD0B461, // pio2_2 = 6.07710050630396597660e-11
+ 0x2E037073, 0x3BA3198A, // pio2_2t = 2.02226624879595063154e-21
+ 0x2E000000, 0x3BA3198A, // pio2_3 = 2.02226624871116645580e-21
+ 0x252049C1, 0x397B839A, // pio2_3t = 8.47842766036889956997e-32
+ // now, npio2_hw itself
+ 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
+ 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
+ 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
+ 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
+ 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
+ 0x404858EB, 0x404921FB
+};
+
+// Coefficients for sin(x) polynomial approximation: S1..S6.
+// See kernel_sin comments in macroAssembler_aarch64_trig.cpp for details
+jdouble StubRoutines::aarch64::_dsin_coef[] __attribute__ ((aligned(64))) = {
+ -1.66666666666666324348e-01, // 0xBFC5555555555549
+ 8.33333333332248946124e-03, // 0x3F8111111110F8A6
+ -1.98412698298579493134e-04, // 0xBF2A01A019C161D5
+ 2.75573137070700676789e-06, // 0x3EC71DE357B1FE7D
+ -2.50507602534068634195e-08, // 0xBE5AE5E68A2B9CEB
+ 1.58969099521155010221e-10 // 0x3DE5D93A5ACFD57C
+};
+
+// Coefficients for cos(x) polynomial approximation: C1..C6.
+// See kernel_cos comments in macroAssembler_aarch64_trig.cpp for details
+jdouble StubRoutines::aarch64::_dcos_coef[] __attribute__ ((aligned(64))) = {
+ 4.16666666666666019037e-02, // c0x3FA555555555554C
+ -1.38888888888741095749e-03, // 0xBF56C16C16C15177
+ 2.48015872894767294178e-05, // 0x3EFA01A019CB1590
+ -2.75573143513906633035e-07, // 0xBE927E4F809C52AD
+ 2.08757232129817482790e-09, // 0x3E21EE9EBDB4B1C4
+ -1.13596475577881948265e-11 // 0xBDA8FAE9BE8838D4
+};
+
+// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi.
+// Used in cases of very large argument. 396 hex digits is enough to support
+// required precision.
+// Converted to double to avoid unnecessary conversion in code
+// NOTE: table looks like original int table: {0xA2F983, 0x6E4E44,...} with
+// only (double) conversion added
+jdouble StubRoutines::aarch64::_two_over_pi[] __attribute__ ((aligned(64))) = {
+ (double)0xA2F983, (double)0x6E4E44, (double)0x1529FC, (double)0x2757D1, (double)0xF534DD, (double)0xC0DB62,
+ (double)0x95993C, (double)0x439041, (double)0xFE5163, (double)0xABDEBB, (double)0xC561B7, (double)0x246E3A,
+ (double)0x424DD2, (double)0xE00649, (double)0x2EEA09, (double)0xD1921C, (double)0xFE1DEB, (double)0x1CB129,
+ (double)0xA73EE8, (double)0x8235F5, (double)0x2EBB44, (double)0x84E99C, (double)0x7026B4, (double)0x5F7E41,
+ (double)0x3991D6, (double)0x398353, (double)0x39F49C, (double)0x845F8B, (double)0xBDF928, (double)0x3B1FF8,
+ (double)0x97FFDE, (double)0x05980F, (double)0xEF2F11, (double)0x8B5A0A, (double)0x6D1F6D, (double)0x367ECF,
+ (double)0x27CB09, (double)0xB74F46, (double)0x3F669E, (double)0x5FEA2D, (double)0x7527BA, (double)0xC7EBE5,
+ (double)0xF17B3D, (double)0x0739F7, (double)0x8A5292, (double)0xEA6BFB, (double)0x5FB11F, (double)0x8D5D08,
+ (double)0x560330, (double)0x46FC7B, (double)0x6BABF0, (double)0xCFBC20, (double)0x9AF436, (double)0x1DA9E3,
+ (double)0x91615E, (double)0xE61B08, (double)0x659985, (double)0x5F14A0, (double)0x68408D, (double)0xFFD880,
+ (double)0x4D7327, (double)0x310606, (double)0x1556CA, (double)0x73A8C9, (double)0x60E27B, (double)0xC08C6B,
+};
+
+// Pi over 2 value
+jdouble StubRoutines::aarch64::_pio2[] __attribute__ ((aligned(64))) = {
+ 1.57079625129699707031e+00, // 0x3FF921FB40000000
+ 7.54978941586159635335e-08, // 0x3E74442D00000000
+ 5.39030252995776476554e-15, // 0x3CF8469880000000
+ 3.28200341580791294123e-22, // 0x3B78CC5160000000
+ 1.27065575308067607349e-29, // 0x39F01B8380000000
+ 1.22933308981111328932e-36, // 0x387A252040000000
+ 2.73370053816464559624e-44, // 0x36E3822280000000
+ 2.16741683877804819444e-51, // 0x3569F31D00000000
+};
--- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -41,7 +41,7 @@
enum platform_dependent_constants {
code_size1 = 19000, // simply increase if too small (assembler will crash if too small)
- code_size2 = 22000 // simply increase if too small (assembler will crash if too small)
+ code_size2 = 28000 // simply increase if too small (assembler will crash if too small)
};
class aarch64 {
@@ -66,6 +66,14 @@
static address _has_negatives;
static address _has_negatives_long;
static address _large_array_equals;
+ static address _compare_long_string_LL;
+ static address _compare_long_string_LU;
+ static address _compare_long_string_UL;
+ static address _compare_long_string_UU;
+ static address _string_indexof_linear_ll;
+ static address _string_indexof_linear_uu;
+ static address _string_indexof_linear_ul;
+ static address _large_byte_array_inflate;
static bool _completed;
public:
@@ -136,6 +144,38 @@
return _large_array_equals;
}
+ static address compare_long_string_LL() {
+ return _compare_long_string_LL;
+ }
+
+ static address compare_long_string_LU() {
+ return _compare_long_string_LU;
+ }
+
+ static address compare_long_string_UL() {
+ return _compare_long_string_UL;
+ }
+
+ static address compare_long_string_UU() {
+ return _compare_long_string_UU;
+ }
+
+ static address string_indexof_linear_ul() {
+ return _string_indexof_linear_ul;
+ }
+
+ static address string_indexof_linear_ll() {
+ return _string_indexof_linear_ll;
+ }
+
+ static address string_indexof_linear_uu() {
+ return _string_indexof_linear_uu;
+ }
+
+ static address large_byte_array_inflate() {
+ return _large_byte_array_inflate;
+ }
+
static bool complete() {
return _completed;
}
@@ -146,7 +186,13 @@
private:
static juint _crc_table[];
-
+ // begin trigonometric tables block. See comments in .cpp file
+ static juint _npio2_hw[];
+ static jdouble _two_over_pi[];
+ static jdouble _pio2[];
+ static jdouble _dsin_coef[];
+ static jdouble _dcos_coef[];
+ // end trigonometric tables block
};
#endif // CPU_AARCH64_VM_STUBROUTINES_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -247,26 +247,54 @@
address fn;
switch (kind) {
case Interpreter::java_lang_math_sin :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
+ if (StubRoutines::dsin() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dsin);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dsin());
+ }
break;
case Interpreter::java_lang_math_cos :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
+ if (StubRoutines::dcos() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dcos);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dcos());
+ }
break;
case Interpreter::java_lang_math_tan :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
+ if (StubRoutines::dtan() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dtan);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dtan());
+ }
break;
case Interpreter::java_lang_math_log :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog);
+ if (StubRoutines::dlog() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog());
+ }
break;
case Interpreter::java_lang_math_log10 :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10);
+ if (StubRoutines::dlog10() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dlog10());
+ }
break;
case Interpreter::java_lang_math_exp :
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp);
+ if (StubRoutines::dexp() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dexp);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dexp());
+ }
break;
case Interpreter::java_lang_math_pow :
fpargs = 2;
- fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow);
+ if (StubRoutines::dpow() == NULL) {
+ fn = CAST_FROM_FN_PTR(address, SharedRuntime::dpow);
+ } else {
+ fn = CAST_FROM_FN_PTR(address, StubRoutines::dpow());
+ }
break;
default:
ShouldNotReachHere();
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -761,7 +761,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_INT) >> 2);
- __ access_load_at(T_INT, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(2)), noreg, noreg);
+ __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(2)), noreg, noreg);
}
void TemplateTable::laload()
@@ -773,7 +773,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_LONG) >> 3);
- __ access_load_at(T_LONG, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(3)), noreg, noreg);
+ __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(3)), noreg, noreg);
}
void TemplateTable::faload()
@@ -785,7 +785,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_FLOAT) >> 2);
- __ access_load_at(T_FLOAT, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(2)), noreg, noreg);
+ __ access_load_at(T_FLOAT, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(2)), noreg, noreg);
}
void TemplateTable::daload()
@@ -797,7 +797,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) >> 3);
- __ access_load_at(T_DOUBLE, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(3)), noreg, noreg);
+ __ access_load_at(T_DOUBLE, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(3)), noreg, noreg);
}
void TemplateTable::aaload()
@@ -812,7 +812,7 @@
do_oop_load(_masm,
Address(r0, r1, Address::uxtw(LogBytesPerHeapOop)),
r0,
- IN_HEAP_ARRAY);
+ IS_ARRAY);
}
void TemplateTable::baload()
@@ -824,7 +824,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_BYTE) >> 0);
- __ access_load_at(T_BYTE, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(0)), noreg, noreg);
+ __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(0)), noreg, noreg);
}
void TemplateTable::caload()
@@ -836,7 +836,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1);
- __ access_load_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
+ __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
}
// iload followed by caload frequent pair
@@ -853,7 +853,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1);
- __ access_load_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
+ __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
}
void TemplateTable::saload()
@@ -865,7 +865,7 @@
// r1: index
index_check(r0, r1); // leaves index in r1, kills rscratch1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_SHORT) >> 1);
- __ access_load_at(T_SHORT, IN_HEAP | IN_HEAP_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
+ __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, r0, Address(r0, r1, Address::uxtw(1)), noreg, noreg);
}
void TemplateTable::iload(int n)
@@ -1059,7 +1059,7 @@
// r3: array
index_check(r3, r1); // prefer index in r1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_INT) >> 2);
- __ access_store_at(T_INT, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(2)), r0, noreg, noreg);
+ __ access_store_at(T_INT, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(2)), r0, noreg, noreg);
}
void TemplateTable::lastore() {
@@ -1071,7 +1071,7 @@
// r3: array
index_check(r3, r1); // prefer index in r1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_LONG) >> 3);
- __ access_store_at(T_LONG, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(3)), r0, noreg, noreg);
+ __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(3)), r0, noreg, noreg);
}
void TemplateTable::fastore() {
@@ -1083,7 +1083,7 @@
// r3: array
index_check(r3, r1); // prefer index in r1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_FLOAT) >> 2);
- __ access_store_at(T_FLOAT, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(2)), noreg /* ftos */, noreg, noreg);
+ __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(2)), noreg /* ftos */, noreg, noreg);
}
void TemplateTable::dastore() {
@@ -1095,7 +1095,7 @@
// r3: array
index_check(r3, r1); // prefer index in r1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) >> 3);
- __ access_store_at(T_DOUBLE, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(3)), noreg /* dtos */, noreg, noreg);
+ __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(3)), noreg /* dtos */, noreg, noreg);
}
void TemplateTable::aastore() {
@@ -1136,7 +1136,7 @@
// Get the value we will store
__ ldr(r0, at_tos());
// Now store using the appropriate barrier
- do_oop_store(_masm, element_address, r0, IN_HEAP_ARRAY);
+ do_oop_store(_masm, element_address, r0, IS_ARRAY);
__ b(done);
// Have a NULL in r0, r3=array, r2=index. Store NULL at ary[idx]
@@ -1144,7 +1144,7 @@
__ profile_null_seen(r2);
// Store a NULL
- do_oop_store(_masm, element_address, noreg, IN_HEAP_ARRAY);
+ do_oop_store(_masm, element_address, noreg, IS_ARRAY);
// Pop stack arguments
__ bind(done);
@@ -1172,7 +1172,7 @@
__ bind(L_skip);
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_BYTE) >> 0);
- __ access_store_at(T_BYTE, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(0)), r0, noreg, noreg);
+ __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(0)), r0, noreg, noreg);
}
void TemplateTable::castore()
@@ -1185,7 +1185,7 @@
// r3: array
index_check(r3, r1); // prefer index in r1
__ add(r1, r1, arrayOopDesc::base_offset_in_bytes(T_CHAR) >> 1);
- __ access_store_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY, Address(r3, r1, Address::uxtw(1)), r0, noreg, noreg);
+ __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY, Address(r3, r1, Address::uxtw(1)), r0, noreg, noreg);
}
void TemplateTable::sastore()
@@ -3362,22 +3362,45 @@
// r2: receiver
// r3: flags
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
- Label notMethod;
- __ tbz(r3, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod);
+ // java.lang.Object. See cpCache.cpp for details.
+ Label notObjectMethod;
+ __ tbz(r3, ConstantPoolCacheEntry::is_forced_virtual_shift, notObjectMethod);
invokevirtual_helper(rmethod, r2, r3);
- __ bind(notMethod);
+ __ bind(notObjectMethod);
+
+ Label no_such_interface;
+
+ // Check for private method invocation - indicated by vfinal
+ Label notVFinal;
+ __ tbz(r3, ConstantPoolCacheEntry::is_vfinal_shift, notVFinal);
+
+ // Get receiver klass into r3 - also a null check
+ __ null_check(r2, oopDesc::klass_offset_in_bytes());
+ __ load_klass(r3, r2);
+
+ Label subtype;
+ __ check_klass_subtype(r3, r0, r4, subtype);
+ // If we get here the typecheck failed
+ __ b(no_such_interface);
+ __ bind(subtype);
+
+ __ profile_final_call(r0);
+ __ profile_arguments_type(r0, rmethod, r4, true);
+ __ jump_from_interpreted(rmethod, r0);
+
+ __ bind(notVFinal);
// Get receiver klass into r3 - also a null check
__ restore_locals();
__ null_check(r2, oopDesc::klass_offset_in_bytes());
__ load_klass(r3, r2);
- Label no_such_interface, no_such_method;
+ Label no_such_method;
// Preserve method for throw_AbstractMethodErrorVerbose.
__ mov(r16, rmethod);
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -53,7 +53,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count, int callee_saved_regs) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
if (!dest_uninitialized) {
assert( addr->encoding() < callee_saved_regs, "addr must be saved");
assert(count->encoding() < callee_saved_regs, "count must be saved");
--- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -75,9 +75,9 @@
void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) {
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
if (is_null) {
BarrierSetAssembler::store_at(masm, decorators, type, obj, new_val, tmp1, tmp2, tmp3, true);
--- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2945,7 +2945,7 @@
__ push(LR);
#endif // AARCH64
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (disjoint) {
decorators |= ARRAYCOPY_DISJOINT;
}
@@ -3217,7 +3217,7 @@
pushed+=1;
#endif // AARCH64
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->arraycopy_prologue(_masm, decorators, true, to, count, callee_saved_regs);
--- a/src/hotspot/cpu/arm/templateTable_arm.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/arm/templateTable_arm.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -943,7 +943,7 @@
const Register Rindex = R0_tos;
index_check(Rarray, Rindex);
- do_oop_load(_masm, R0_tos, get_array_elem_addr(T_OBJECT, Rarray, Rindex, Rtemp), IN_HEAP_ARRAY);
+ do_oop_load(_masm, R0_tos, get_array_elem_addr(T_OBJECT, Rarray, Rindex, Rtemp), IS_ARRAY);
}
@@ -1328,7 +1328,7 @@
__ add(Raddr_1, Raddr_1, AsmOperand(Rindex_4, lsl, LogBytesPerHeapOop));
// Now store using the appropriate barrier
- do_oop_store(_masm, Raddr_1, Rvalue_2, Rtemp, R0_tmp, R3_tmp, false, IN_HEAP_ARRAY);
+ do_oop_store(_masm, Raddr_1, Rvalue_2, Rtemp, R0_tmp, R3_tmp, false, IS_ARRAY);
__ b(done);
__ bind(throw_array_store);
@@ -1344,7 +1344,7 @@
__ profile_null_seen(R0_tmp);
// Store a NULL
- do_oop_store(_masm, Address::indexed_oop(Raddr_1, Rindex_4), Rvalue_2, Rtemp, R0_tmp, R3_tmp, true, IN_HEAP_ARRAY);
+ do_oop_store(_masm, Address::indexed_oop(Raddr_1, Rindex_4), Rvalue_2, Rtemp, R0_tmp, R3_tmp, true, IS_ARRAY);
// Pop stack arguments
__ bind(done);
@@ -4276,25 +4276,41 @@
const Register Rinterf = R5_tmp;
const Register Rindex = R4_tmp;
const Register Rflags = R3_tmp;
- const Register Rklass = R3_tmp;
+ const Register Rklass = R2_tmp; // Note! Same register with Rrecv
prepare_invoke(byte_no, Rinterf, Rmethod, Rrecv, Rflags);
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
- Label notMethod;
- __ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notMethod);
-
+ // java.lang.Object. See cpCache.cpp for details.
+ Label notObjectMethod;
+ __ tbz(Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift, notObjectMethod);
invokevirtual_helper(Rmethod, Rrecv, Rflags);
- __ bind(notMethod);
+ __ bind(notObjectMethod);
// Get receiver klass into Rklass - also a null check
__ load_klass(Rklass, Rrecv);
+ // Check for private method invocation - indicated by vfinal
Label no_such_interface;
+ Label notVFinal;
+ __ tbz(Rflags, ConstantPoolCacheEntry::is_vfinal_shift, notVFinal);
+
+ Label subtype;
+ __ check_klass_subtype(Rklass, Rinterf, R1_tmp, R3_tmp, noreg, subtype);
+ // If we get here the typecheck failed
+ __ b(no_such_interface);
+ __ bind(subtype);
+
+ // do the call
+ __ profile_final_call(R0_tmp);
+ __ jump_from_interpreted(Rmethod);
+
+ __ bind(notVFinal);
+
// Receiver subtype check against REFC.
__ lookup_interface_method(// inputs: rec. class, interface
Rklass, Rinterf, noreg,
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -44,7 +44,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register from, Register to, Register count,
Register preserve1, Register preserve2) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
// With G1, don't generate the call if we statically know that the target in uninitialized
if (!dest_uninitialized) {
int spill_slots = 3;
@@ -107,7 +107,7 @@
void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators, Register obj, RegisterOrConstant ind_or_offs, Register pre_val,
Register tmp1, Register tmp2, bool needs_frame) {
- bool not_null = (decorators & OOP_NOT_NULL) != 0,
+ bool not_null = (decorators & IS_NOT_NULL) != 0,
preloaded = obj == noreg;
Register nv_save = noreg;
@@ -205,7 +205,7 @@
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register store_addr, Register new_val,
Register tmp1, Register tmp2, Register tmp3) {
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
Label runtime, filtered;
assert_different_registers(store_addr, new_val, tmp1, tmp2);
@@ -279,9 +279,9 @@
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
// Load and record the previous value.
g1_write_barrier_pre(masm, decorators, base, ind_or_offs,
tmp1, tmp2, tmp3, needs_frame);
@@ -318,7 +318,7 @@
// these parameters the pre-barrier does not generate
// the load of the previous value
// We only reach here if value is not null.
- g1_write_barrier_pre(masm, decorators | OOP_NOT_NULL, noreg /* obj */, (intptr_t)0, dst /* pre_val */,
+ g1_write_barrier_pre(masm, decorators | IS_NOT_NULL, noreg /* obj */, (intptr_t)0, dst /* pre_val */,
tmp1, tmp2, needs_frame);
}
__ bind(done);
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -35,7 +35,7 @@
Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
assert(in_heap || in_native, "where?");
assert_different_registers(base, val, tmp1, tmp2, R0);
@@ -68,7 +68,7 @@
Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
assert(in_heap || in_native, "where?");
assert_different_registers(ind_or_offs.register_or_noreg(), dst, R0);
--- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -93,9 +93,9 @@
void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2046,7 +2046,7 @@
assert_different_registers(mtype_reg, mh_reg, temp_reg);
// Compare method type against that of the receiver.
load_heap_oop(temp_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg), mh_reg,
- noreg, noreg, false, OOP_NOT_NULL);
+ noreg, noreg, false, IS_NOT_NULL);
cmpd(CCR0, temp_reg, mtype_reg);
bne(CCR0, wrong_method_type);
}
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -329,7 +329,7 @@
inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs, Register val,
Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
- assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_NATIVE | OOP_NOT_NULL |
+ assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL |
ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator");
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bool as_raw = (decorators & AS_RAW) != 0;
@@ -348,7 +348,7 @@
inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs, Register dst,
Register tmp1, Register tmp2, bool needs_frame, Label *L_handle_null) {
- assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_NATIVE | OOP_NOT_NULL |
+ assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL |
ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator");
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
decorators = AccessInternal::decorator_fixup(decorators);
--- a/src/hotspot/cpu/ppc/methodHandles_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/methodHandles_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -174,13 +174,13 @@
// Load the invoker, as MH -> MH.form -> LF.vmentry
__ verify_oop(recv);
__ load_heap_oop(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv,
- temp2, noreg, false, OOP_NOT_NULL);
+ temp2, noreg, false, IS_NOT_NULL);
__ verify_oop(method_temp);
__ load_heap_oop(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp,
- temp2, noreg, false, OOP_NOT_NULL);
+ temp2, noreg, false, IS_NOT_NULL);
__ verify_oop(method_temp);
__ load_heap_oop(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp,
- temp2, noreg, false, OOP_NOT_NULL);
+ temp2, noreg, false, IS_NOT_NULL);
__ verify_oop(method_temp);
__ ld(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), method_temp);
@@ -342,7 +342,7 @@
Label L_ok;
Register temp2_defc = temp2;
__ load_heap_oop(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg,
- temp3, noreg, false, OOP_NOT_NULL);
+ temp3, noreg, false, IS_NOT_NULL);
load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
__ verify_klass_ptr(temp2_defc);
__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -370,7 +370,7 @@
verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
}
__ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg,
- temp3, noreg, false, OOP_NOT_NULL);
+ temp3, noreg, false, IS_NOT_NULL);
__ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method);
break;
@@ -379,7 +379,7 @@
verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
}
__ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg,
- temp3, noreg, false, OOP_NOT_NULL);
+ temp3, noreg, false, IS_NOT_NULL);
__ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method);
break;
@@ -422,7 +422,7 @@
Register temp2_intf = temp2;
__ load_heap_oop(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg,
- temp3, noreg, false, OOP_NOT_NULL);
+ temp3, noreg, false, IS_NOT_NULL);
load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
__ verify_klass_ptr(temp2_intf);
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2024,9 +2024,9 @@
STUB_ENTRY(arrayof_oop_disjoint_arraycopy) :
STUB_ENTRY(oop_disjoint_arraycopy);
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2063,9 +2063,9 @@
address start = __ function_entry();
assert_positive_int(R5_ARG3);
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2159,9 +2159,9 @@
}
#endif
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -688,7 +688,7 @@
Rtemp2 = R31;
__ index_check(Rarray, R17_tos /* index */, UseCompressedOops ? 2 : LogBytesPerWord, Rtemp, Rload_addr);
do_oop_load(_masm, Rload_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos, Rtemp, Rtemp2,
- IN_HEAP_ARRAY);
+ IS_ARRAY);
__ verify_oop(R17_tos);
//__ dcbt(R17_tos); // prefetch
}
@@ -1015,14 +1015,14 @@
__ bind(Lis_null);
do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), noreg /* 0 */,
- Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY);
+ Rscratch, Rscratch2, Rscratch3, IS_ARRAY);
__ profile_null_seen(Rscratch, Rscratch2);
__ b(Ldone);
// Store is OK.
__ bind(Lstore_ok);
do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos /* value */,
- Rscratch, Rscratch2, Rscratch3, IN_HEAP_ARRAY | OOP_NOT_NULL);
+ Rscratch, Rscratch2, Rscratch3, IS_ARRAY | IS_NOT_NULL);
__ bind(Ldone);
// Adjust sp (pops array, index and value).
@@ -3583,14 +3583,46 @@
prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1);
- // Get receiver klass.
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
+ // Get receiver klass - this is also a null check
__ null_check_throw(Rreceiver, oopDesc::klass_offset_in_bytes(), Rscratch2);
__ load_klass(Rrecv_klass, Rreceiver);
// Check corner case object method.
- Label LobjectMethod, L_no_such_interface, Lthrow_ame;
+ // Special case of invokeinterface called for virtual method of
+ // java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
+ // The invokeinterface was rewritten to a invokevirtual, hence we have
+ // to handle this corner case.
+
+ Label LnotObjectMethod, Lthrow_ame;
__ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_forced_virtual_shift);
- __ btrue(CCR0, LobjectMethod);
+ __ bfalse(CCR0, LnotObjectMethod);
+ invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rmethod, Rscratch1, Rscratch2);
+ __ bind(LnotObjectMethod);
+
+ // Check for private method invocation - indicated by vfinal
+ Label LnotVFinal, L_no_such_interface, L_subtype;
+
+ __ testbitdi(CCR0, R0, Rflags, ConstantPoolCacheEntry::is_vfinal_shift);
+ __ bfalse(CCR0, LnotVFinal);
+
+ __ check_klass_subtype(Rrecv_klass, Rinterface_klass, Rscratch1, Rscratch2, L_subtype);
+ // If we get here the typecheck failed
+ __ b(L_no_such_interface);
+ __ bind(L_subtype);
+
+ // do the call
+
+ Register Rscratch = Rflags; // Rflags is dead now.
+
+ __ profile_final_call(Rscratch1, Rscratch);
+ __ profile_arguments_type(Rindex, Rscratch, Rrecv_klass /* scratch */, true);
+
+ __ call_from_interpreter(Rindex, Rret_addr, Rscratch, Rrecv_klass /* scratch */);
+
+ __ bind(LnotVFinal);
__ lookup_interface_method(Rrecv_klass, Rinterface_klass, noreg, noreg, Rscratch1, Rscratch2,
L_no_such_interface, /*return_method=*/false);
@@ -3631,14 +3663,6 @@
call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose),
Rrecv_klass, Rinterface_klass);
DEBUG_ONLY( __ should_not_reach_here(); )
-
- // Special case of invokeinterface called for virtual method of
- // java.lang.Object. See ConstantPoolCacheEntry::set_method() for details:
- // The invokeinterface was rewritten to a invokevirtual, hence we have
- // to handle this corner case. This code isn't produced by javac, but could
- // be produced by another compliant java compiler.
- __ bind(LobjectMethod);
- invokeinterface_object_method(Rrecv_klass, Rret_addr, Rflags, Rmethod, Rscratch1, Rscratch2);
}
void TemplateTable::invokedynamic(int byte_no) {
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -46,7 +46,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
// With G1, don't generate the call if we statically know that the target is uninitialized.
if (!dest_uninitialized) {
@@ -108,7 +108,7 @@
if (on_oop && on_reference) {
// Generate the G1 pre-barrier code to log the value of
// the referent field in an SATB buffer.
- g1_write_barrier_pre(masm, decorators | OOP_NOT_NULL,
+ g1_write_barrier_pre(masm, decorators | IS_NOT_NULL,
NULL /* obj */,
dst /* pre_val */,
noreg/* preserve */ ,
@@ -127,7 +127,7 @@
bool pre_val_needed // Save Rpre_val across runtime call, caller uses it.
) {
- bool not_null = (decorators & OOP_NOT_NULL) != 0,
+ bool not_null = (decorators & IS_NOT_NULL) != 0,
preloaded = obj == NULL;
const Register Robj = obj ? obj->base() : noreg,
@@ -260,7 +260,7 @@
void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register Rstore_addr, Register Rnew_val,
Register Rtmp1, Register Rtmp2, Register Rtmp3) {
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2); // Most probably, Rnew_val == Rtmp3.
@@ -372,9 +372,9 @@
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
// Load and record the previous value.
g1_write_barrier_pre(masm, decorators, &dst, tmp3, val, tmp1, tmp2, false);
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -39,7 +39,7 @@
const Address& addr, Register dst, Register tmp1, Register tmp2, Label *L_handle_null) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
assert(in_heap || in_native, "where?");
switch (type) {
@@ -69,7 +69,7 @@
const Address& addr, Register val, Register tmp1, Register tmp2, Register tmp3) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool not_null = (decorators & IS_NOT_NULL) != 0;
assert(in_heap || in_native, "where?");
assert_different_registers(val, tmp1, tmp2);
--- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -156,9 +156,9 @@
void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -4051,7 +4051,7 @@
void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
const Address& addr, Register val,
Register tmp1, Register tmp2, Register tmp3) {
- assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_NATIVE | OOP_NOT_NULL |
+ assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL |
ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator");
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
decorators = AccessInternal::decorator_fixup(decorators);
@@ -4070,7 +4070,7 @@
void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
const Address& addr, Register dst,
Register tmp1, Register tmp2, Label *is_null) {
- assert((decorators & ~(AS_RAW | IN_HEAP | IN_HEAP_ARRAY | IN_NATIVE | OOP_NOT_NULL |
+ assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL |
ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator");
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
decorators = AccessInternal::decorator_fixup(decorators);
--- a/src/hotspot/cpu/s390/methodHandles_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/methodHandles_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -198,17 +198,17 @@
__ load_heap_oop(method_temp,
Address(recv,
NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())),
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp);
__ load_heap_oop(method_temp,
Address(method_temp,
NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())),
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp);
__ load_heap_oop(method_temp,
Address(method_temp,
NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())),
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
__ verify_oop(method_temp);
__ z_lg(method_temp,
Address(method_temp,
@@ -409,7 +409,7 @@
Register temp2_defc = temp2;
__ load_heap_oop(temp2_defc, member_clazz,
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
__ verify_klass_ptr(temp2_defc);
__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -436,7 +436,7 @@
verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3);
}
__ load_heap_oop(Z_method, member_vmtarget,
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
__ z_lg(Z_method, vmtarget_method);
method_is_live = true;
break;
@@ -446,7 +446,7 @@
verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3);
}
__ load_heap_oop(Z_method, member_vmtarget,
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
__ z_lg(Z_method, vmtarget_method);
method_is_live = true;
break;
@@ -488,7 +488,7 @@
Register temp3_intf = temp3;
__ load_heap_oop(temp3_intf, member_clazz,
- noreg, noreg, OOP_NOT_NULL);
+ noreg, noreg, IS_NOT_NULL);
load_klass_from_Class(_masm, temp3_intf, temp2, temp4);
Register Z_index = Z_method;
--- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1300,9 +1300,9 @@
unsigned int start_off = __ offset(); // Remember stub start address (is rtn value).
unsigned int size = UseCompressedOops ? 4 : 8;
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1392,9 +1392,9 @@
// Branch to disjoint_copy (if applicable) before pre_barrier to avoid double pre_barrier.
array_overlap_test(nooverlap_target, shift); // Branch away to nooverlap_target if disjoint.
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -853,7 +853,7 @@
index_check(Z_tmp_1, index, shift);
// Now load array element.
do_oop_load(_masm, Address(Z_tmp_1, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), Z_tos,
- Z_tmp_2, Z_tmp_3, IN_HEAP_ARRAY);
+ Z_tmp_2, Z_tmp_3, IS_ARRAY);
__ verify_oop(Z_tos);
}
@@ -1197,7 +1197,7 @@
// Store a NULL.
do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), noreg,
- tmp3, tmp2, tmp1, IN_HEAP_ARRAY);
+ tmp3, tmp2, tmp1, IS_ARRAY);
__ z_bru(done);
// Come here on success.
@@ -1205,7 +1205,7 @@
// Now store using the appropriate barrier.
do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), Rvalue,
- tmp3, tmp2, tmp1, IN_HEAP_ARRAY | OOP_NOT_NULL);
+ tmp3, tmp2, tmp1, IS_ARRAY | IS_NOT_NULL);
// Pop stack arguments.
__ bind(done);
@@ -3610,20 +3610,43 @@
BLOCK_COMMENT("invokeinterface {");
- prepare_invoke(byte_no, interface, method, // Get f1 klassOop, f2 itable index.
+ prepare_invoke(byte_no, interface, method, // Get f1 klassOop, f2 Method*.
receiver, flags);
// Z_R14 (== Z_bytecode) : return entry
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
- NearLabel notMethod, no_such_interface, no_such_method;
+ // java.lang.Object. See cpCache.cpp for details.
+ NearLabel notObjectMethod, no_such_method;
__ testbit(flags, ConstantPoolCacheEntry::is_forced_virtual_shift);
- __ z_brz(notMethod);
+ __ z_brz(notObjectMethod);
invokevirtual_helper(method, receiver, flags);
- __ bind(notMethod);
+ __ bind(notObjectMethod);
+
+ // Check for private method invocation - indicated by vfinal
+ NearLabel notVFinal;
+ __ testbit(flags, ConstantPoolCacheEntry::is_vfinal_shift);
+ __ z_brz(notVFinal);
+
+ // Get receiver klass into klass - also a null check.
+ __ load_klass(klass, receiver);
+
+ NearLabel subtype, no_such_interface;
+
+ __ check_klass_subtype(klass, interface, Z_tmp_2, Z_tmp_3, subtype);
+ // If we get here the typecheck failed
+ __ z_bru(no_such_interface);
+ __ bind(subtype);
+
+ // do the call
+ __ profile_final_call(Z_tmp_2);
+ __ profile_arguments_type(Z_tmp_2, method, Z_ARG5, true);
+ __ jump_from_interpreted(method, Z_tmp_2);
+
+ __ bind(notVFinal);
// Get receiver klass into klass - also a null check.
__ restore_locals();
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -43,7 +43,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
// With G1, don't generate the call if we statically know that the target in uninitialized
if (!dest_uninitialized) {
Register tmp = O5;
@@ -406,9 +406,9 @@
// No need for post barrier if storing NULL
bool needs_post_barrier = val != G0 && in_heap;
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
Register index = dst.has_index() ? dst.index() : noreg;
int disp = dst.has_disp() ? dst.disp() : 0;
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,7 @@
Register val, Address dst, Register tmp) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool is_not_null = (decorators & IS_NOT_NULL) != 0;
switch (type) {
case T_ARRAY:
@@ -47,7 +47,7 @@
}
if (UseCompressedOops) {
assert(dst.base() != val, "not enough registers");
- if (oop_not_null) {
+ if (is_not_null) {
__ encode_heap_oop_not_null(val);
} else {
__ encode_heap_oop(val);
@@ -70,7 +70,7 @@
Address src, Register dst, Register tmp) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool is_not_null = (decorators & IS_NOT_NULL) != 0;
switch (type) {
case T_ARRAY:
@@ -83,7 +83,7 @@
}
if (UseCompressedOops) {
__ lduw(src, dst);
- if (oop_not_null) {
+ if (is_not_null) {
__ decode_heap_oop_not_null(dst);
} else {
__ decode_heap_oop(dst);
--- a/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -90,9 +89,9 @@
Register val, Address dst, Register tmp) {
bool in_heap = (decorators & IN_HEAP) != 0;
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
// No need for post barrier if storing NULL
bool needs_post_barrier = val != G0 && in_heap;
--- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2269,9 +2269,9 @@
BLOCK_COMMENT("Entry:");
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2326,9 +2326,9 @@
array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2446,9 +2446,9 @@
BLOCK_COMMENT("Entry:");
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
--- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -697,7 +697,7 @@
arrayOopDesc::base_offset_in_bytes(T_OBJECT),
Otos_i,
G3_scratch,
- IN_HEAP_ARRAY);
+ IS_ARRAY);
__ verify_oop(Otos_i);
}
@@ -997,13 +997,13 @@
// Store is OK.
__ bind(store_ok);
- do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, IN_HEAP_ARRAY);
+ do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, IS_ARRAY);
__ ba(done);
__ delayed()->inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value)
__ bind(is_null);
- do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, IN_HEAP_ARRAY);
+ do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, IS_ARRAY);
__ profile_null_seen(G3_scratch);
__ inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value)
@@ -3202,28 +3202,56 @@
prepare_invoke(byte_no, Rinterface, Rret, Rmethod, O0_recv, O1_flags);
- // get receiver klass
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
+ // get receiver klass - this is also a null check
__ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
__ load_klass(O0_recv, O2_Klass);
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
- Label notMethod;
+ // java.lang.Object. See cpCache.cpp for details.
+ Label notObjectMethod;
__ set((1 << ConstantPoolCacheEntry::is_forced_virtual_shift), Rscratch);
__ btst(O1_flags, Rscratch);
- __ br(Assembler::zero, false, Assembler::pt, notMethod);
+ __ br(Assembler::zero, false, Assembler::pt, notObjectMethod);
__ delayed()->nop();
invokeinterface_object_method(O2_Klass, Rinterface, Rret, O1_flags);
- __ bind(notMethod);
+ __ bind(notObjectMethod);
+
+ Label L_no_such_interface;
+
+ // Check for private method invocation - indicated by vfinal
+ Label notVFinal;
+ {
+ __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), Rscratch);
+ __ btst(O1_flags, Rscratch);
+ __ br(Assembler::zero, false, Assembler::pt, notVFinal);
+ __ delayed()->nop();
+
+ Label subtype;
+ Register Rtemp = O1_flags;
+ __ check_klass_subtype(O2_Klass, Rinterface, Rscratch, Rtemp, subtype);
+ // If we get here the typecheck failed
+ __ ba(L_no_such_interface);
+ __ delayed()->nop();
+ __ bind(subtype);
+
+ // do the call
+ Register Rcall = Rinterface;
+ __ mov(Rmethod, G5_method);
+ assert_different_registers(Rcall, G5_method, Gargs, Rret);
+
+ __ profile_arguments_type(G5_method, Rcall, Gargs, true);
+ __ profile_final_call(Rscratch);
+ __ call_from_interpreter(Rcall, Gargs, Rret);
+ }
+ __ bind(notVFinal);
Register Rtemp = O1_flags;
- Label L_no_such_interface;
-
// Receiver subtype check against REFC.
__ lookup_interface_method(// inputs: rec. class, interface, itable index
O2_Klass, Rinterface, noreg,
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -43,7 +43,7 @@
void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count) {
- bool dest_uninitialized = (decorators & AS_DEST_NOT_INITIALIZED) != 0;
+ bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
if (!dest_uninitialized) {
Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -35,7 +35,7 @@
Register dst, Address src, Register tmp1, Register tmp_thread) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool is_not_null = (decorators & IS_NOT_NULL) != 0;
bool atomic = (decorators & MO_RELAXED) != 0;
switch (type) {
@@ -45,7 +45,7 @@
#ifdef _LP64
if (UseCompressedOops) {
__ movl(dst, src);
- if (oop_not_null) {
+ if (is_not_null) {
__ decode_heap_oop_not_null(dst);
} else {
__ decode_heap_oop(dst);
@@ -100,7 +100,7 @@
Address dst, Register val, Register tmp1, Register tmp2) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
- bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+ bool is_not_null = (decorators & IS_NOT_NULL) != 0;
bool atomic = (decorators & MO_RELAXED) != 0;
switch (type) {
@@ -108,7 +108,7 @@
case T_ARRAY: {
if (in_heap) {
if (val == noreg) {
- assert(!oop_not_null, "inconsistent access");
+ assert(!is_not_null, "inconsistent access");
#ifdef _LP64
if (UseCompressedOops) {
__ movl(dst, (int32_t)NULL_WORD);
@@ -122,7 +122,7 @@
#ifdef _LP64
if (UseCompressedOops) {
assert(!dst.uses(val), "not enough registers");
- if (oop_not_null) {
+ if (is_not_null) {
__ encode_heap_oop_not_null(val);
} else {
__ encode_heap_oop(val);
--- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -135,9 +135,9 @@
Address dst, Register val, Register tmp1, Register tmp2) {
bool in_heap = (decorators & IN_HEAP) != 0;
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
bool needs_post_barrier = val != noreg && in_heap;
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -6287,7 +6287,7 @@
// Doesn't do verfication, generates fixed size code
void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1,
Register thread_tmp, DecoratorSet decorators) {
- access_load_at(T_OBJECT, IN_HEAP | OOP_NOT_NULL | decorators, dst, src, tmp1, thread_tmp);
+ access_load_at(T_OBJECT, IN_HEAP | IS_NOT_NULL | decorators, dst, src, tmp1, thread_tmp);
}
void MacroAssembler::store_heap_oop(Address dst, Register src, Register tmp1,
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -837,9 +837,9 @@
__ jcc(Assembler::zero, L_0_count);
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1026,9 +1026,9 @@
__ jcc(Assembler::zero, L_0_count);
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1383,9 +1383,9 @@
Address to_element_addr(end_to, count, Address::times_ptr, 0);
Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes());
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
BasicType type = T_OBJECT;
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1832,9 +1832,9 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -1926,9 +1926,9 @@
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2030,9 +2030,9 @@
// r9 and r10 may be used to save non-volatile registers
// 'from', 'to' and 'qword_count' are now valid
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2123,9 +2123,9 @@
// r9 and r10 may be used to save non-volatile registers
// 'from', 'to' and 'qword_count' are now valid
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_DISJOINT;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_DISJOINT;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
if (aligned) {
decorators |= ARRAYCOPY_ALIGNED;
@@ -2306,9 +2306,9 @@
Address from_element_addr(end_from, count, TIMES_OOP, 0);
Address to_element_addr(end_to, count, TIMES_OOP, 0);
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY | ARRAYCOPY_CHECKCAST;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY | ARRAYCOPY_CHECKCAST;
if (dest_uninitialized) {
- decorators |= AS_DEST_NOT_INITIALIZED;
+ decorators |= IS_DEST_UNINITIALIZED;
}
BasicType type = T_OBJECT;
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -770,7 +770,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_INT, IN_HEAP | IN_HEAP_ARRAY, rax,
+ __ access_load_at(T_INT, IN_HEAP | IS_ARRAY, rax,
Address(rdx, rax, Address::times_4,
arrayOopDesc::base_offset_in_bytes(T_INT)),
noreg, noreg);
@@ -783,7 +783,7 @@
index_check(rdx, rax); // kills rbx
NOT_LP64(__ mov(rbx, rax));
// rbx,: index
- __ access_load_at(T_LONG, IN_HEAP | IN_HEAP_ARRAY, noreg /* ltos */,
+ __ access_load_at(T_LONG, IN_HEAP | IS_ARRAY, noreg /* ltos */,
Address(rdx, rbx, Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_LONG)),
noreg, noreg);
@@ -796,7 +796,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_FLOAT, IN_HEAP | IN_HEAP_ARRAY, noreg /* ftos */,
+ __ access_load_at(T_FLOAT, IN_HEAP | IS_ARRAY, noreg /* ftos */,
Address(rdx, rax,
Address::times_4,
arrayOopDesc::base_offset_in_bytes(T_FLOAT)),
@@ -808,7 +808,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_DOUBLE, IN_HEAP | IN_HEAP_ARRAY, noreg /* dtos */,
+ __ access_load_at(T_DOUBLE, IN_HEAP | IS_ARRAY, noreg /* dtos */,
Address(rdx, rax,
Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_DOUBLE)),
@@ -825,7 +825,7 @@
UseCompressedOops ? Address::times_4 : Address::times_ptr,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
rax,
- IN_HEAP_ARRAY);
+ IS_ARRAY);
}
void TemplateTable::baload() {
@@ -833,7 +833,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_BYTE, IN_HEAP | IN_HEAP_ARRAY, rax,
+ __ access_load_at(T_BYTE, IN_HEAP | IS_ARRAY, rax,
Address(rdx, rax, Address::times_1, arrayOopDesc::base_offset_in_bytes(T_BYTE)),
noreg, noreg);
}
@@ -843,7 +843,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY, rax,
+ __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax,
Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)),
noreg, noreg);
}
@@ -858,7 +858,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY, rax,
+ __ access_load_at(T_CHAR, IN_HEAP | IS_ARRAY, rax,
Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)),
noreg, noreg);
}
@@ -869,7 +869,7 @@
// rax: index
// rdx: array
index_check(rdx, rax); // kills rbx
- __ access_load_at(T_SHORT, IN_HEAP | IN_HEAP_ARRAY, rax,
+ __ access_load_at(T_SHORT, IN_HEAP | IS_ARRAY, rax,
Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)),
noreg, noreg);
}
@@ -1063,7 +1063,7 @@
// rbx: index
// rdx: array
index_check(rdx, rbx); // prefer index in rbx
- __ access_store_at(T_INT, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_INT, IN_HEAP | IS_ARRAY,
Address(rdx, rbx, Address::times_4,
arrayOopDesc::base_offset_in_bytes(T_INT)),
rax, noreg, noreg);
@@ -1077,7 +1077,7 @@
// rdx: high(value)
index_check(rcx, rbx); // prefer index in rbx,
// rbx,: index
- __ access_store_at(T_LONG, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_LONG, IN_HEAP | IS_ARRAY,
Address(rcx, rbx, Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_LONG)),
noreg /* ltos */, noreg, noreg);
@@ -1091,7 +1091,7 @@
// rbx: index
// rdx: array
index_check(rdx, rbx); // prefer index in rbx
- __ access_store_at(T_FLOAT, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_FLOAT, IN_HEAP | IS_ARRAY,
Address(rdx, rbx, Address::times_4,
arrayOopDesc::base_offset_in_bytes(T_FLOAT)),
noreg /* ftos */, noreg, noreg);
@@ -1104,7 +1104,7 @@
// rbx: index
// rdx: array
index_check(rdx, rbx); // prefer index in rbx
- __ access_store_at(T_DOUBLE, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_DOUBLE, IN_HEAP | IS_ARRAY,
Address(rdx, rbx, Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_DOUBLE)),
noreg /* dtos */, noreg, noreg);
@@ -1148,7 +1148,7 @@
__ movptr(rax, at_tos());
__ movl(rcx, at_tos_p1()); // index
// Now store using the appropriate barrier
- do_oop_store(_masm, element_address, rax, IN_HEAP_ARRAY);
+ do_oop_store(_masm, element_address, rax, IS_ARRAY);
__ jmp(done);
// Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx]
@@ -1156,7 +1156,7 @@
__ profile_null_seen(rbx);
// Store a NULL
- do_oop_store(_masm, element_address, noreg, IN_HEAP_ARRAY);
+ do_oop_store(_masm, element_address, noreg, IS_ARRAY);
// Pop stack arguments
__ bind(done);
@@ -1180,7 +1180,7 @@
__ jccb(Assembler::zero, L_skip);
__ andl(rax, 1); // if it is a T_BOOLEAN array, mask the stored value to 0/1
__ bind(L_skip);
- __ access_store_at(T_BYTE, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_BYTE, IN_HEAP | IS_ARRAY,
Address(rdx, rbx,Address::times_1,
arrayOopDesc::base_offset_in_bytes(T_BYTE)),
rax, noreg, noreg);
@@ -1193,7 +1193,7 @@
// rbx: index
// rdx: array
index_check(rdx, rbx); // prefer index in rbx
- __ access_store_at(T_CHAR, IN_HEAP | IN_HEAP_ARRAY,
+ __ access_store_at(T_CHAR, IN_HEAP | IS_ARRAY,
Address(rdx, rbx, Address::times_2,
arrayOopDesc::base_offset_in_bytes(T_CHAR)),
rax, noreg, noreg);
@@ -3792,30 +3792,61 @@
prepare_invoke(byte_no, rax, rbx, // get f1 Klass*, f2 Method*
rcx, rdx); // recv, flags
- // rax: reference klass (from f1)
+ // rax: reference klass (from f1) if interface method
// rbx: method (from f2)
// rcx: receiver
// rdx: flags
+ // First check for Object case, then private interface method,
+ // then regular interface method.
+
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
- Label notMethod;
+ // java.lang.Object. See cpCache.cpp for details.
+ Label notObjectMethod;
__ movl(rlocals, rdx);
__ andl(rlocals, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift));
-
- __ jcc(Assembler::zero, notMethod);
-
+ __ jcc(Assembler::zero, notObjectMethod);
invokevirtual_helper(rbx, rcx, rdx);
- __ bind(notMethod);
+ // no return from above
+ __ bind(notObjectMethod);
+
+ Label no_such_interface; // for receiver subtype check
+ Register recvKlass; // used for exception processing
+
+ // Check for private method invocation - indicated by vfinal
+ Label notVFinal;
+ __ movl(rlocals, rdx);
+ __ andl(rlocals, (1 << ConstantPoolCacheEntry::is_vfinal_shift));
+ __ jcc(Assembler::zero, notVFinal);
+
+ // Get receiver klass into rlocals - also a null check
+ __ null_check(rcx, oopDesc::klass_offset_in_bytes());
+ __ load_klass(rlocals, rcx);
+
+ Label subtype;
+ __ check_klass_subtype(rlocals, rax, rbcp, subtype);
+ // If we get here the typecheck failed
+ recvKlass = rdx;
+ __ mov(recvKlass, rlocals); // shuffle receiver class for exception use
+ __ jmp(no_such_interface);
+
+ __ bind(subtype);
+
+ // do the call - rbx is actually the method to call
+
+ __ profile_final_call(rdx);
+ __ profile_arguments_type(rdx, rbx, rbcp, true);
+
+ __ jump_from_interpreted(rbx, rdx);
+ // no return from above
+ __ bind(notVFinal);
// Get receiver klass into rdx - also a null check
__ restore_locals(); // restore r14
__ null_check(rcx, oopDesc::klass_offset_in_bytes());
__ load_klass(rdx, rcx);
- Label no_such_interface, no_such_method;
+ Label no_such_method;
// Preserve method for throw_AbstractMethodErrorVerbose.
__ mov(rcx, rbx);
@@ -3877,12 +3908,12 @@
__ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
// Pass arguments for generating a verbose error message.
#ifdef _LP64
- Register recvKlass = c_rarg1;
+ recvKlass = c_rarg1;
Register method = c_rarg2;
if (recvKlass != rdx) { __ movq(recvKlass, rdx); }
if (method != rcx) { __ movq(method, rcx); }
#else
- Register recvKlass = rdx;
+ recvKlass = rdx;
Register method = rcx;
#endif
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodErrorVerbose),
--- a/src/hotspot/cpu/zero/methodHandles_zero.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/zero/methodHandles_zero.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,6 +26,7 @@
#include "precompiled.hpp"
#include "interpreter/cppInterpreterGenerator.hpp"
#include "interpreter/interpreter.hpp"
+#include "interpreter/interpreterRuntime.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/method.inline.hpp"
@@ -65,6 +66,37 @@
}
+void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) {
+
+ JavaThread *thread = (JavaThread *) THREAD;
+ // Set up the frame anchor if it isn't already
+ bool has_last_Java_frame = thread->has_last_Java_frame();
+ if (!has_last_Java_frame) {
+ intptr_t *sp = thread->zero_stack()->sp();
+ ZeroFrame *frame = thread->top_zero_frame();
+ while (frame) {
+ if (frame->is_interpreter_frame()) {
+ interpreterState istate =
+ frame->as_interpreter_frame()->interpreter_state();
+ if (istate->self_link() == istate)
+ break;
+ }
+
+ sp = ((intptr_t *) frame) + 1;
+ frame = frame->next();
+ }
+
+ assert(frame != NULL, "must be");
+ thread->set_last_Java_frame(frame, sp);
+ }
+ InterpreterRuntime::throw_AbstractMethodErrorVerbose(thread, rcvr, interface_method);
+ // Reset the frame anchor if necessary
+ if (!has_last_Java_frame) {
+ thread->reset_last_Java_frame();
+ }
+
+}
+
int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) {
JavaThread *thread = (JavaThread *) THREAD;
@@ -124,8 +156,15 @@
itableMethodEntry* im = ki->first_method_entry(recv->klass());
Method* vmtarget = im[vmindex].method();
-
- invoke_target(vmtarget, THREAD);
+ // Check that the vmtarget entry is non-null. A null entry means
+ // that the method no longer exists (got deleted) or is private.
+ // Private class methods can never be an implementation of an
+ // interface method. In those cases, throw AME.
+ if (vmtarget != NULL) {
+ invoke_target(vmtarget, THREAD);
+ } else {
+ throw_AME(recv->klass(), target, THREAD);
+ }
return 0;
}
--- a/src/hotspot/cpu/zero/methodHandles_zero.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/cpu/zero/methodHandles_zero.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,6 +32,7 @@
private:
static oop popFromStack(TRAPS);
static void invoke_target(Method* method, TRAPS);
+ static void throw_AME(Klass* rcvr, Method* interface_method, TRAPS);
static int method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS);
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -96,11 +96,11 @@
address os::current_stack_pointer() {
#ifdef SPARC_WORKS
register void *esp;
- __asm__("mov %%"SPELL_REG_SP", %0":"=r"(esp));
+ __asm__("mov %%" SPELL_REG_SP ", %0":"=r"(esp));
return (address) ((char*)esp + sizeof(long)*2);
#elif defined(__clang__)
intptr_t* esp;
- __asm__ __volatile__ ("mov %%"SPELL_REG_SP", %0":"=r"(esp):);
+ __asm__ __volatile__ ("mov %%" SPELL_REG_SP ", %0":"=r"(esp):);
return (address) esp;
#else
register void *esp __asm__ (SPELL_REG_SP);
@@ -234,10 +234,10 @@
intptr_t* _get_previous_fp() {
#ifdef SPARC_WORKS
register intptr_t **ebp;
- __asm__("mov %%"SPELL_REG_FP", %0":"=r"(ebp));
+ __asm__("mov %%" SPELL_REG_FP ", %0":"=r"(ebp));
#elif defined(__clang__)
intptr_t **ebp;
- __asm__ __volatile__ ("mov %%"SPELL_REG_FP", %0":"=r"(ebp):);
+ __asm__ __volatile__ ("mov %%" SPELL_REG_FP ", %0":"=r"(ebp):);
#else
register intptr_t **ebp __asm__ (SPELL_REG_FP);
#endif
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1602,7 +1602,7 @@
array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci());
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
if (x->check_boolean()) {
decorators |= C1_MASK_BOOLEAN;
}
@@ -1847,7 +1847,7 @@
}
}
- DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ DecoratorSet decorators = IN_HEAP | IS_ARRAY;
LIR_Opr result = rlock_result(x, x->elt_type());
access_load_at(decorators, x->elt_type(),
--- a/src/hotspot/share/ci/ciField.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/ci/ciField.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -70,22 +70,22 @@
ciField::ciField(ciInstanceKlass* klass, int index) :
_known_to_link_with_put(NULL), _known_to_link_with_get(NULL) {
ASSERT_IN_VM;
- CompilerThread *thread = CompilerThread::current();
+ CompilerThread *THREAD = CompilerThread::current();
assert(ciObjectFactory::is_initialized(), "not a shared field");
assert(klass->get_instanceKlass()->is_linked(), "must be linked before using its constant-pool");
- constantPoolHandle cpool(thread, klass->get_instanceKlass()->constants());
+ constantPoolHandle cpool(THREAD, klass->get_instanceKlass()->constants());
// Get the field's name, signature, and type.
Symbol* name = cpool->name_ref_at(index);
- _name = ciEnv::current(thread)->get_symbol(name);
+ _name = ciEnv::current(THREAD)->get_symbol(name);
int nt_index = cpool->name_and_type_ref_index_at(index);
int sig_index = cpool->signature_ref_index_at(nt_index);
Symbol* signature = cpool->symbol_at(sig_index);
- _signature = ciEnv::current(thread)->get_symbol(signature);
+ _signature = ciEnv::current(THREAD)->get_symbol(signature);
BasicType field_type = FieldType::basic_type(signature);
@@ -95,12 +95,12 @@
bool ignore;
// This is not really a class reference; the index always refers to the
// field's type signature, as a symbol. Linkage checks do not apply.
- _type = ciEnv::current(thread)->get_klass_by_index(cpool, sig_index, ignore, klass);
+ _type = ciEnv::current(THREAD)->get_klass_by_index(cpool, sig_index, ignore, klass);
} else {
_type = ciType::make(field_type);
}
- _name = (ciSymbol*)ciEnv::current(thread)->get_symbol(name);
+ _name = (ciSymbol*)ciEnv::current(THREAD)->get_symbol(name);
// Get the field's declared holder.
//
@@ -109,7 +109,7 @@
int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible;
- ciKlass* generic_declared_holder = ciEnv::current(thread)->get_klass_by_index(cpool, holder_index,
+ ciKlass* generic_declared_holder = ciEnv::current(THREAD)->get_klass_by_index(cpool, holder_index,
holder_is_accessible,
klass);
@@ -126,7 +126,7 @@
// handling in ciField::will_link and will result in a
// java.lang.NoSuchFieldError exception being thrown by the compiled
// code (the expected behavior in this case).
- _holder = ciEnv::current(thread)->Object_klass();
+ _holder = ciEnv::current(THREAD)->Object_klass();
_offset = -1;
_is_constant = false;
return;
@@ -164,10 +164,22 @@
// to check access because it can erroneously succeed. If this check fails,
// propagate the declared holder to will_link() which in turn will bail out
// compilation for this field access.
- if (!Reflection::verify_field_access(klass->get_Klass(), declared_holder->get_Klass(), canonical_holder, field_desc.access_flags(), true)) {
+ bool can_access = Reflection::verify_member_access(klass->get_Klass(),
+ declared_holder->get_Klass(),
+ canonical_holder,
+ field_desc.access_flags(),
+ true, false, THREAD);
+ if (!can_access) {
_holder = declared_holder;
_offset = -1;
_is_constant = false;
+ // It's possible the access check failed due to a nestmate access check
+ // encountering an exception. We can't propagate the exception from here
+ // so we have to clear it. If the access check happens again in a different
+ // context then the exception will be thrown there.
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
return;
}
--- a/src/hotspot/share/classfile/classFileParser.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/classFileParser.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -955,9 +955,10 @@
if (!interf->is_interface()) {
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(),
- err_msg("Class %s can not implement %s, because it is not an interface",
+ err_msg("class %s can not implement %s, because it is not an interface (%s)",
_class_name->as_klass_external_name(),
- interf->class_loader_and_module_name()));
+ interf->external_name(),
+ interf->class_in_module_of_loader()));
}
if (InstanceKlass::cast(interf)->has_nonstatic_concrete_methods()) {
@@ -3148,7 +3149,6 @@
_inner_classes = inner_classes;
int index = 0;
- const int cp_size = _cp->length();
cfs->guarantee_more(8 * length, CHECK_0); // 4-tuples of u2
for (int n = 0; n < length; n++) {
// Inner class index
@@ -3222,6 +3222,38 @@
return length;
}
+u2 ClassFileParser::parse_classfile_nest_members_attribute(const ClassFileStream* const cfs,
+ const u1* const nest_members_attribute_start,
+ TRAPS) {
+ const u1* const current_mark = cfs->current();
+ u2 length = 0;
+ if (nest_members_attribute_start != NULL) {
+ cfs->set_current(nest_members_attribute_start);
+ cfs->guarantee_more(2, CHECK_0); // length
+ length = cfs->get_u2_fast();
+ }
+ const int size = length;
+ Array<u2>* const nest_members = MetadataFactory::new_array<u2>(_loader_data, size, CHECK_0);
+ _nest_members = nest_members;
+
+ int index = 0;
+ cfs->guarantee_more(2 * length, CHECK_0);
+ for (int n = 0; n < length; n++) {
+ const u2 class_info_index = cfs->get_u2_fast();
+ check_property(
+ valid_klass_reference_at(class_info_index),
+ "Nest member class_info_index %u has bad constant type in class file %s",
+ class_info_index, CHECK_0);
+ nest_members->at_put(index++, class_info_index);
+ }
+ assert(index == size, "wrong size");
+
+ // Restore buffer's current position.
+ cfs->set_current(current_mark);
+
+ return length;
+}
+
void ClassFileParser::parse_classfile_synthetic_attribute(TRAPS) {
set_class_synthetic_flag(true);
}
@@ -3329,10 +3361,14 @@
// Set inner classes attribute to default sentinel
_inner_classes = Universe::the_empty_short_array();
+ // Set nest members attribute to default sentinel
+ _nest_members = Universe::the_empty_short_array();
cfs->guarantee_more(2, CHECK); // attributes_count
u2 attributes_count = cfs->get_u2_fast();
bool parsed_sourcefile_attribute = false;
bool parsed_innerclasses_attribute = false;
+ bool parsed_nest_members_attribute = false;
+ bool parsed_nest_host_attribute = false;
bool parsed_enclosingmethod_attribute = false;
bool parsed_bootstrap_methods_attribute = false;
const u1* runtime_visible_annotations = NULL;
@@ -3350,6 +3386,9 @@
u4 inner_classes_attribute_length = 0;
u2 enclosing_method_class_index = 0;
u2 enclosing_method_method_index = 0;
+ const u1* nest_members_attribute_start = NULL;
+ u4 nest_members_attribute_length = 0;
+
// Iterate over attributes
while (attributes_count--) {
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
@@ -3498,6 +3537,40 @@
assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations");
}
cfs->skip_u1(attribute_length, CHECK);
+ } else if (_major_version >= JAVA_11_VERSION) {
+ if (tag == vmSymbols::tag_nest_members()) {
+ // Check for NestMembers tag
+ if (parsed_nest_members_attribute) {
+ classfile_parse_error("Multiple NestMembers attributes in class file %s", CHECK);
+ } else {
+ parsed_nest_members_attribute = true;
+ }
+ if (parsed_nest_host_attribute) {
+ classfile_parse_error("Conflicting NestHost and NestMembers attributes in class file %s", CHECK);
+ }
+ nest_members_attribute_start = cfs->current();
+ nest_members_attribute_length = attribute_length;
+ cfs->skip_u1(nest_members_attribute_length, CHECK);
+ } else if (tag == vmSymbols::tag_nest_host()) {
+ if (parsed_nest_host_attribute) {
+ classfile_parse_error("Multiple NestHost attributes in class file %s", CHECK);
+ } else {
+ parsed_nest_host_attribute = true;
+ }
+ if (parsed_nest_members_attribute) {
+ classfile_parse_error("Conflicting NestMembers and NestHost attributes in class file %s", CHECK);
+ }
+ if (_need_verify) {
+ guarantee_property(attribute_length == 2, "Wrong NestHost attribute length in class file %s", CHECK);
+ }
+ cfs->guarantee_more(2, CHECK);
+ u2 class_info_index = cfs->get_u2_fast();
+ check_property(
+ valid_klass_reference_at(class_info_index),
+ "Nest-host class_info_index %u has bad constant type in class file %s",
+ class_info_index, CHECK);
+ _nest_host = class_info_index;
+ }
} else {
// Unknown attribute
cfs->skip_u1(attribute_length, CHECK);
@@ -3526,13 +3599,25 @@
enclosing_method_class_index,
enclosing_method_method_index,
CHECK);
- if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
+ if (parsed_innerclasses_attribute && _need_verify && _major_version >= JAVA_1_5_VERSION) {
guarantee_property(
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
"Wrong InnerClasses attribute length in class file %s", CHECK);
}
}
+ if (parsed_nest_members_attribute) {
+ const u2 num_of_classes = parse_classfile_nest_members_attribute(
+ cfs,
+ nest_members_attribute_start,
+ CHECK);
+ if (_need_verify) {
+ guarantee_property(
+ nest_members_attribute_length == sizeof(num_of_classes) + sizeof(u2) * num_of_classes,
+ "Wrong NestMembers attribute length in class file %s", CHECK);
+ }
+ }
+
if (_max_bootstrap_specifier_index >= 0) {
guarantee_property(parsed_bootstrap_methods_attribute,
"Missing BootstrapMethods attribute in class file %s", CHECK);
@@ -3595,6 +3680,8 @@
this_klass->set_fields(_fields, java_fields_count);
this_klass->set_methods(_methods);
this_klass->set_inner_classes(_inner_classes);
+ this_klass->set_nest_members(_nest_members);
+ this_klass->set_nest_host_index(_nest_host);
this_klass->set_local_interfaces(_local_interfaces);
this_klass->set_annotations(_combined_annotations);
// Delay the setting of _transitive_interfaces until after initialize_supers() in
@@ -4605,24 +4692,26 @@
}
if (super_m->is_final() && !super_m->is_static() &&
- // matching method in super is final, and not static
- (Reflection::verify_field_access(this_klass,
- super_m->method_holder(),
- super_m->method_holder(),
- super_m->access_flags(), false))
- // this class can access super final method and therefore override
- ) {
- ResourceMark rm(THREAD);
- Exceptions::fthrow(
- THREAD_AND_LOCATION,
- vmSymbols::java_lang_VerifyError(),
- "class %s overrides final method %s.%s%s",
- this_klass->external_name(),
- super_m->method_holder()->external_name(),
- name->as_C_string(),
- signature->as_C_string()
- );
- return;
+ !super_m->access_flags().is_private()) {
+ // matching method in super is final, and not static or private
+ bool can_access = Reflection::verify_member_access(this_klass,
+ super_m->method_holder(),
+ super_m->method_holder(),
+ super_m->access_flags(),
+ false, false, CHECK);
+ if (can_access) {
+ // this class can access super final method and therefore override
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(THREAD_AND_LOCATION,
+ vmSymbols::java_lang_VerifyError(),
+ "class %s overrides final method %s.%s%s",
+ this_klass->external_name(),
+ super_m->method_holder()->external_name(),
+ name->as_C_string(),
+ signature->as_C_string()
+ );
+ return;
+ }
}
// continue to look from super_m's holder's super.
@@ -5470,6 +5559,7 @@
assert(NULL == _fields, "invariant");
assert(NULL == _methods, "invariant");
assert(NULL == _inner_classes, "invariant");
+ assert(NULL == _nest_members, "invariant");
assert(NULL == _local_interfaces, "invariant");
assert(NULL == _combined_annotations, "invariant");
@@ -5739,6 +5829,8 @@
_fields(NULL),
_methods(NULL),
_inner_classes(NULL),
+ _nest_members(NULL),
+ _nest_host(0),
_local_interfaces(NULL),
_transitive_interfaces(NULL),
_combined_annotations(NULL),
@@ -5843,6 +5935,7 @@
_fields = NULL;
_methods = NULL;
_inner_classes = NULL;
+ _nest_members = NULL;
_local_interfaces = NULL;
_combined_annotations = NULL;
_annotations = _type_annotations = NULL;
@@ -5868,6 +5961,10 @@
MetadataFactory::free_array<u2>(_loader_data, _inner_classes);
}
+ if (_nest_members != NULL && _nest_members != Universe::the_empty_short_array()) {
+ MetadataFactory::free_array<u2>(_loader_data, _nest_members);
+ }
+
// Free interfaces
InstanceKlass::deallocate_interfaces(_loader_data, _super_klass,
_local_interfaces, _transitive_interfaces);
--- a/src/hotspot/share/classfile/classFileParser.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/classFileParser.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -97,6 +97,8 @@
Array<u2>* _fields;
Array<Method*>* _methods;
Array<u2>* _inner_classes;
+ Array<u2>* _nest_members;
+ u2 _nest_host;
Array<Klass*>* _local_interfaces;
Array<Klass*>* _transitive_interfaces;
Annotations* _combined_annotations;
@@ -290,6 +292,10 @@
u2 enclosing_method_method_index,
TRAPS);
+ u2 parse_classfile_nest_members_attribute(const ClassFileStream* const cfs,
+ const u1* const nest_members_attribute_start,
+ TRAPS);
+
void parse_classfile_attributes(const ClassFileStream* const cfs,
ConstantPool* cp,
ClassAnnotationCollector* parsed_annotations,
--- a/src/hotspot/share/classfile/classLoaderData.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -109,10 +109,9 @@
// it will be available for error messages, logging, JFR, etc. The name
// and klass are available after the class_loader oop is no longer alive,
// during unloading.
-void ClassLoaderData::initialize_name_and_klass(Handle class_loader) {
+void ClassLoaderData::initialize_name(Handle class_loader) {
Thread* THREAD = Thread::current();
ResourceMark rm(THREAD);
- _class_loader_klass = class_loader->klass();
// Obtain the class loader's name. If the class loader's name was not
// explicitly set during construction, the CLD's _name field will be null.
@@ -159,6 +158,7 @@
if (!h_class_loader.is_null()) {
_class_loader = _handles.add(h_class_loader());
+ _class_loader_klass = h_class_loader->klass();
}
if (!is_anonymous) {
@@ -951,9 +951,11 @@
const char* ClassLoaderData::loader_name_and_id() const {
if (_class_loader_klass == NULL) {
return "'" BOOTSTRAP_LOADER_NAME "'";
+ } else if (_name_and_id != NULL) {
+ return _name_and_id->as_C_string();
} else {
- assert(_name_and_id != NULL, "encountered a class loader null name and id");
- return _name_and_id->as_C_string();
+ // May be called in a race before _name_and_id is initialized.
+ return _class_loader_klass->external_name();
}
}
@@ -1069,10 +1071,10 @@
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous) {
ClassLoaderData* loader_data = add_to_graph(loader, is_anonymous);
- // Initialize name and class after the loader data is added to the CLDG
- // because adding the Symbol for the name might safepoint.
+ // Initialize _name and _name_and_id after the loader data is added to the
+ // CLDG because adding the Symbol for _name and _name_and_id might safepoint.
if (loader.not_null()) {
- loader_data->initialize_name_and_klass(loader);
+ loader_data->initialize_name(loader);
}
return loader_data;
}
--- a/src/hotspot/share/classfile/classLoaderData.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/classLoaderData.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -210,7 +210,7 @@
friend class ClassLoaderDataGraphKlassIteratorAtomic;
friend class ClassLoaderDataGraphKlassIteratorStatic;
friend class ClassLoaderDataGraphMetaspaceIterator;
- friend class InstanceKlass;
+ friend class Klass;
friend class MetaDataFactory;
friend class Method;
@@ -305,7 +305,7 @@
Dictionary* create_dictionary();
- void initialize_name_and_klass(Handle class_loader);
+ void initialize_name(Handle class_loader);
public:
// GC interface.
void clear_claimed() { _claimed = 0; }
--- a/src/hotspot/share/classfile/moduleEntry.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/moduleEntry.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -40,10 +40,12 @@
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
-#define UNNAMED_MODULE "Unnamed Module"
+#define UNNAMED_MODULE "unnamed module"
+#define UNNAMED_MODULE_LEN 14
#define JAVAPKG "java"
#define JAVAPKG_LEN 4
#define JAVA_BASE_NAME "java.base"
+#define JAVA_BASE_NAME_LEN 9
class ModuleClosure;
--- a/src/hotspot/share/classfile/systemDictionary.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/systemDictionary.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -245,10 +245,6 @@
// Forwards to resolve_instance_class_or_null
Klass* SystemDictionary::resolve_or_null(Symbol* class_name, Handle class_loader, Handle protection_domain, TRAPS) {
- assert(THREAD->can_call_java(),
- "can not load classes with compiler thread: class=%s, classloader=%s",
- class_name->as_C_string(),
- class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string());
if (FieldType::is_array(class_name)) {
return resolve_array_class_or_null(class_name, class_loader, protection_domain, THREAD);
} else if (FieldType::is_obj(class_name)) {
@@ -692,6 +688,10 @@
PlaceholderEntry* placeholder;
Symbol* superclassname = NULL;
+ assert(THREAD->can_call_java(),
+ "can not load classes with compiler thread: class=%s, classloader=%s",
+ name->as_C_string(),
+ class_loader.is_null() ? "null" : class_loader->klass()->name()->as_C_string());
{
MutexLocker mu(SystemDictionary_lock, THREAD);
InstanceKlass* check = find_class(d_hash, name, dictionary);
--- a/src/hotspot/share/classfile/vmSymbols.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/classfile/vmSymbols.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -142,6 +142,8 @@
/* class file format tags */ \
template(tag_source_file, "SourceFile") \
template(tag_inner_classes, "InnerClasses") \
+ template(tag_nest_members, "NestMembers") \
+ template(tag_nest_host, "NestHost") \
template(tag_constant_value, "ConstantValue") \
template(tag_code, "Code") \
template(tag_exceptions, "Exceptions") \
--- a/src/hotspot/share/code/dependencies.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/code/dependencies.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -33,6 +33,7 @@
#include "compiler/compileBroker.hpp"
#include "compiler/compileTask.hpp"
#include "memory/resourceArea.hpp"
+#include "oops/klass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "runtime/flags/flagSetting.hpp"
@@ -1228,8 +1229,9 @@
} else if (!k->is_instance_klass()) {
return false; // no methods to find in an array type
} else {
- // Search class hierarchy first.
- Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature);
+ // Search class hierarchy first, skipping private implementations
+ // as they never override any inherited methods
+ Method* m = InstanceKlass::cast(k)->find_instance_method(_name, _signature, Klass::skip_private);
if (!Dependencies::is_concrete_method(m, k)) {
// Check for re-abstraction of method
if (!k->is_interface() && m != NULL && m->is_abstract()) {
--- a/src/hotspot/share/code/nmethod.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/code/nmethod.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2599,6 +2599,16 @@
st->move_to(column);
if (sd->bci() == SynchronizationEntryBCI) {
st->print(";*synchronization entry");
+ } else if (sd->bci() == AfterBci) {
+ st->print(";* method exit (unlocked if synchronized)");
+ } else if (sd->bci() == UnwindBci) {
+ st->print(";* unwind (locked if synchronized)");
+ } else if (sd->bci() == AfterExceptionBci) {
+ st->print(";* unwind (unlocked if synchronized)");
+ } else if (sd->bci() == UnknownBci) {
+ st->print(";* unknown");
+ } else if (sd->bci() == InvalidFrameStateBci) {
+ st->print(";* invalid frame state");
} else {
if (sd->method() == NULL) {
st->print("method is NULL");
--- a/src/hotspot/share/compiler/compilerDefinitions.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/compiler/compilerDefinitions.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -41,7 +41,13 @@
// Handy constants for deciding which compiler mode to use.
enum MethodCompilation {
- InvocationEntryBci = -1 // i.e., not a on-stack replacement compilation
+ InvocationEntryBci = -1, // i.e., not a on-stack replacement compilation
+ BeforeBci = InvocationEntryBci,
+ AfterBci = -2,
+ UnwindBci = -3,
+ AfterExceptionBci = -4,
+ UnknownBci = -5,
+ InvalidFrameStateBci = -6
};
// Enumeration to distinguish tiers of compilation
--- a/src/hotspot/share/gc/cms/cmsOopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/cms/cmsOopClosures.inline.hpp"
-#include "gc/cms/cms_specialized_oop_closures.hpp"
-#include "memory/iterator.inline.hpp"
-
-// Generate CMS specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/gc/cms/cmsOopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/cmsOopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -44,22 +44,17 @@
void do_oop(oop obj); \
template <class T> inline void do_oop_work(T* p);
-// TODO: This duplication of the MetadataAwareOopClosure class is only needed
+// TODO: This duplication of the MetadataVisitingOopIterateClosure class is only needed
// because some CMS OopClosures derive from OopsInGenClosure. It would be
// good to get rid of them completely.
-class MetadataAwareOopsInGenClosure: public OopsInGenClosure {
+class MetadataVisitingOopsInGenClosure: public OopsInGenClosure {
public:
- virtual bool do_metadata() { return do_metadata_nv(); }
- inline bool do_metadata_nv() { return true; }
-
+ virtual bool do_metadata() { return true; }
virtual void do_klass(Klass* k);
- void do_klass_nv(Klass* k);
-
- virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
- void do_cld_nv(ClassLoaderData* cld);
+ virtual void do_cld(ClassLoaderData* cld);
};
-class MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
+class MarkRefsIntoClosure: public MetadataVisitingOopsInGenClosure {
private:
const MemRegion _span;
CMSBitMap* _bitMap;
@@ -71,7 +66,7 @@
virtual void do_oop(narrowOop* p);
};
-class ParMarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
+class ParMarkRefsIntoClosure: public MetadataVisitingOopsInGenClosure {
private:
const MemRegion _span;
CMSBitMap* _bitMap;
@@ -85,7 +80,7 @@
// A variant of the above used in certain kinds of CMS
// marking verification.
-class MarkRefsIntoVerifyClosure: public MetadataAwareOopsInGenClosure {
+class MarkRefsIntoVerifyClosure: public MetadataVisitingOopsInGenClosure {
private:
const MemRegion _span;
CMSBitMap* _verification_bm;
@@ -100,7 +95,7 @@
};
// The non-parallel version (the parallel version appears further below).
-class PushAndMarkClosure: public MetadataAwareOopClosure {
+class PushAndMarkClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
MemRegion _span;
@@ -120,8 +115,6 @@
bool concurrent_precleaning);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
// In the parallel case, the bit map and the
@@ -130,7 +123,7 @@
// synchronization (for instance, via CAS). The marking stack
// used in the non-parallel case above is here replaced with
// an OopTaskQueue structure to allow efficient work stealing.
-class ParPushAndMarkClosure: public MetadataAwareOopClosure {
+class ParPushAndMarkClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
MemRegion _span;
@@ -146,12 +139,10 @@
OopTaskQueue* work_queue);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
// The non-parallel version (the parallel version appears further below).
-class MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
+class MarkRefsIntoAndScanClosure: public MetadataVisitingOopsInGenClosure {
private:
MemRegion _span;
CMSBitMap* _bit_map;
@@ -175,8 +166,6 @@
bool concurrent_precleaning);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
void set_freelistLock(Mutex* m) {
_freelistLock = m;
@@ -192,7 +181,7 @@
// stack and the bitMap are shared, so access needs to be suitably
// synchronized. An OopTaskQueue structure, supporting efficient
// work stealing, replaces a CMSMarkStack for storing grey objects.
-class ParMarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
+class ParMarkRefsIntoAndScanClosure: public MetadataVisitingOopsInGenClosure {
private:
MemRegion _span;
CMSBitMap* _bit_map;
@@ -209,8 +198,6 @@
OopTaskQueue* work_queue);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
void trim_queue(uint size);
};
@@ -218,7 +205,7 @@
// This closure is used during the concurrent marking phase
// following the first checkpoint. Its use is buried in
// the closure MarkFromRootsClosure.
-class PushOrMarkClosure: public MetadataAwareOopClosure {
+class PushOrMarkClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
MemRegion _span;
@@ -238,8 +225,6 @@
MarkFromRootsClosure* parent);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
// Deal with a stack overflow condition
void handle_stack_overflow(HeapWord* lost);
@@ -251,7 +236,7 @@
// This closure is used during the concurrent marking phase
// following the first checkpoint. Its use is buried in
// the closure ParMarkFromRootsClosure.
-class ParPushOrMarkClosure: public MetadataAwareOopClosure {
+class ParPushOrMarkClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
MemRegion _whole_span;
@@ -275,8 +260,6 @@
ParMarkFromRootsClosure* parent);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
// Deal with a stack overflow condition
void handle_stack_overflow(HeapWord* lost);
@@ -290,7 +273,7 @@
// processing phase of the CMS final checkpoint step, as
// well as during the concurrent precleaning of the discovered
// reference lists.
-class CMSKeepAliveClosure: public MetadataAwareOopClosure {
+class CMSKeepAliveClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
const MemRegion _span;
@@ -306,11 +289,9 @@
bool concurrent_precleaning() const { return _concurrent_precleaning; }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
-class CMSInnerParMarkAndPushClosure: public MetadataAwareOopClosure {
+class CMSInnerParMarkAndPushClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
MemRegion _span;
@@ -324,14 +305,12 @@
OopTaskQueue* work_queue);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
// A parallel (MT) version of the above, used when
// reference processing is parallel; the only difference
// is in the do_oop method.
-class CMSParKeepAliveClosure: public MetadataAwareOopClosure {
+class CMSParKeepAliveClosure: public MetadataVisitingOopIterateClosure {
private:
MemRegion _span;
OopTaskQueue* _work_queue;
--- a/src/hotspot/share/gc/cms/cmsOopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/cmsOopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,42 +32,38 @@
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-// MetadataAwareOopClosure and MetadataAwareOopsInGenClosure are duplicated,
+// MetadataVisitingOopIterateClosure and MetadataVisitingOopsInGenClosure are duplicated,
// until we get rid of OopsInGenClosure.
-inline void MetadataAwareOopsInGenClosure::do_klass_nv(Klass* k) {
+inline void MetadataVisitingOopsInGenClosure::do_klass(Klass* k) {
ClassLoaderData* cld = k->class_loader_data();
- do_cld_nv(cld);
+ MetadataVisitingOopsInGenClosure::do_cld(cld);
}
-inline void MetadataAwareOopsInGenClosure::do_klass(Klass* k) { do_klass_nv(k); }
-inline void MetadataAwareOopsInGenClosure::do_cld_nv(ClassLoaderData* cld) {
+inline void MetadataVisitingOopsInGenClosure::do_cld(ClassLoaderData* cld) {
bool claim = true; // Must claim the class loader data before processing.
cld->oops_do(this, claim);
}
// Decode the oop and call do_oop on it.
-#define DO_OOP_WORK_IMPL(cls) \
- template <class T> void cls::do_oop_work(T* p) { \
- T heap_oop = RawAccess<>::oop_load(p); \
- if (!CompressedOops::is_null(heap_oop)) { \
- oop obj = CompressedOops::decode_not_null(heap_oop); \
- do_oop(obj); \
- } \
- }
-
-#define DO_OOP_WORK_NV_IMPL(cls) \
- DO_OOP_WORK_IMPL(cls) \
- void cls::do_oop_nv(oop* p) { cls::do_oop_work(p); } \
- void cls::do_oop_nv(narrowOop* p) { cls::do_oop_work(p); }
+#define DO_OOP_WORK_IMPL(cls) \
+ template <class T> void cls::do_oop_work(T* p) { \
+ T heap_oop = RawAccess<>::oop_load(p); \
+ if (!CompressedOops::is_null(heap_oop)) { \
+ oop obj = CompressedOops::decode_not_null(heap_oop); \
+ do_oop(obj); \
+ } \
+ } \
+ inline void cls::do_oop(oop* p) { do_oop_work(p); } \
+ inline void cls::do_oop(narrowOop* p) { do_oop_work(p); }
DO_OOP_WORK_IMPL(MarkRefsIntoClosure)
DO_OOP_WORK_IMPL(ParMarkRefsIntoClosure)
DO_OOP_WORK_IMPL(MarkRefsIntoVerifyClosure)
-DO_OOP_WORK_NV_IMPL(PushAndMarkClosure)
-DO_OOP_WORK_NV_IMPL(ParPushAndMarkClosure)
-DO_OOP_WORK_NV_IMPL(MarkRefsIntoAndScanClosure)
-DO_OOP_WORK_NV_IMPL(ParMarkRefsIntoAndScanClosure)
+DO_OOP_WORK_IMPL(PushAndMarkClosure)
+DO_OOP_WORK_IMPL(ParPushAndMarkClosure)
+DO_OOP_WORK_IMPL(MarkRefsIntoAndScanClosure)
+DO_OOP_WORK_IMPL(ParMarkRefsIntoAndScanClosure)
// Trim our work_queue so its length is below max at return
inline void ParMarkRefsIntoAndScanClosure::trim_queue(uint max) {
@@ -84,10 +80,10 @@
}
}
-DO_OOP_WORK_NV_IMPL(PushOrMarkClosure)
-DO_OOP_WORK_NV_IMPL(ParPushOrMarkClosure)
-DO_OOP_WORK_NV_IMPL(CMSKeepAliveClosure)
-DO_OOP_WORK_NV_IMPL(CMSInnerParMarkAndPushClosure)
+DO_OOP_WORK_IMPL(PushOrMarkClosure)
+DO_OOP_WORK_IMPL(ParPushOrMarkClosure)
+DO_OOP_WORK_IMPL(CMSKeepAliveClosure)
+DO_OOP_WORK_IMPL(CMSInnerParMarkAndPushClosure)
DO_OOP_WORK_IMPL(CMSParKeepAliveClosure)
#endif // SHARE_VM_GC_CMS_CMSOOPCLOSURES_INLINE_HPP
--- a/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-#ifndef SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
-#define SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
-
-// The following OopClosure types get specialized versions of
-// "oop_oop_iterate" that invoke the closures' do_oop methods
-// non-virtually, using a mechanism defined in this file. Extend these
-// macros in the obvious way to add specializations for new closures.
-
-// Forward declarations.
-
-// ParNew
-class ParScanWithBarrierClosure;
-class ParScanWithoutBarrierClosure;
-
-// CMS
-class MarkRefsIntoAndScanClosure;
-class ParMarkRefsIntoAndScanClosure;
-class PushAndMarkClosure;
-class ParPushAndMarkClosure;
-class PushOrMarkClosure;
-class ParPushOrMarkClosure;
-class CMSKeepAliveClosure;
-class CMSInnerParMarkAndPushClosure;
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) \
- f(ParScanWithBarrierClosure,_nv) \
- f(ParScanWithoutBarrierClosure,_nv)
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f) \
- f(MarkRefsIntoAndScanClosure,_nv) \
- f(ParMarkRefsIntoAndScanClosure,_nv) \
- f(PushAndMarkClosure,_nv) \
- f(ParPushAndMarkClosure,_nv) \
- f(PushOrMarkClosure,_nv) \
- f(ParPushOrMarkClosure,_nv) \
- f(CMSKeepAliveClosure,_nv) \
- f(CMSInnerParMarkAndPushClosure,_nv)
-
-#endif // SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -30,12 +30,14 @@
#include "gc/cms/concurrentMarkSweepThread.hpp"
#include "gc/shared/blockOffsetTable.inline.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
+#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/space.inline.hpp"
#include "gc/shared/spaceDecorator.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/binaryTreeDictionary.inline.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/access.inline.hpp"
@@ -843,13 +845,13 @@
void walk_mem_region_with_cl_nopar(MemRegion mr, \
HeapWord* bottom, HeapWord* top, \
ClosureType* cl)
- walk_mem_region_with_cl_DECL(ExtendedOopClosure);
+ walk_mem_region_with_cl_DECL(OopIterateClosure);
walk_mem_region_with_cl_DECL(FilteringClosure);
public:
FreeListSpaceDCTOC(CompactibleFreeListSpace* sp,
CMSCollector* collector,
- ExtendedOopClosure* cl,
+ OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel) :
@@ -929,11 +931,11 @@
// (There are only two of these, rather than N, because the split is due
// only to the introduction of the FilteringClosure, a local part of the
// impl of this abstraction.)
-FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(ExtendedOopClosure)
+FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure)
FreeListSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
DirtyCardToOopClosure*
-CompactibleFreeListSpace::new_dcto_cl(ExtendedOopClosure* cl,
+CompactibleFreeListSpace::new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel) {
@@ -965,7 +967,7 @@
}
// Apply the given closure to each oop in the space.
-void CompactibleFreeListSpace::oop_iterate(ExtendedOopClosure* cl) {
+void CompactibleFreeListSpace::oop_iterate(OopIterateClosure* cl) {
assert_lock_strong(freelistLock());
HeapWord *cur, *limit;
size_t curSize;
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -433,7 +433,7 @@
Mutex* freelistLock() const { return &_freelistLock; }
// Iteration support
- void oop_iterate(ExtendedOopClosure* cl);
+ void oop_iterate(OopIterateClosure* cl);
void object_iterate(ObjectClosure* blk);
// Apply the closure to each object in the space whose references
@@ -463,7 +463,7 @@
ObjectClosureCareful* cl);
// Override: provides a DCTO_CL specific to this kind of space.
- DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
+ DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel);
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2467,7 +2467,7 @@
}
void
-ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
+ConcurrentMarkSweepGeneration::oop_iterate(OopIterateClosure* cl) {
if (freelistLock()->owned_by_self()) {
Generation::oop_iterate(cl);
} else {
@@ -3305,7 +3305,7 @@
pst->all_tasks_completed();
}
-class ParConcMarkingClosure: public MetadataAwareOopClosure {
+class ParConcMarkingClosure: public MetadataVisitingOopIterateClosure {
private:
CMSCollector* _collector;
CMSConcMarkingTask* _task;
@@ -3318,7 +3318,7 @@
public:
ParConcMarkingClosure(CMSCollector* collector, CMSConcMarkingTask* task, OopTaskQueue* work_queue,
CMSBitMap* bit_map, CMSMarkStack* overflow_stack):
- MetadataAwareOopClosure(collector->ref_processor()),
+ MetadataVisitingOopIterateClosure(collector->ref_processor()),
_collector(collector),
_task(task),
_span(collector->_span),
@@ -3382,9 +3382,6 @@
}
}
-void ParConcMarkingClosure::do_oop(oop* p) { ParConcMarkingClosure::do_oop_work(p); }
-void ParConcMarkingClosure::do_oop(narrowOop* p) { ParConcMarkingClosure::do_oop_work(p); }
-
void ParConcMarkingClosure::trim_queue(size_t max) {
while (_work_queue->size() > max) {
oop new_oop;
@@ -4065,9 +4062,9 @@
}
class PrecleanCLDClosure : public CLDClosure {
- MetadataAwareOopsInGenClosure* _cm_closure;
+ MetadataVisitingOopsInGenClosure* _cm_closure;
public:
- PrecleanCLDClosure(MetadataAwareOopsInGenClosure* oop_closure) : _cm_closure(oop_closure) {}
+ PrecleanCLDClosure(MetadataVisitingOopsInGenClosure* oop_closure) : _cm_closure(oop_closure) {}
void do_cld(ClassLoaderData* cld) {
if (cld->has_accumulated_modified_oops()) {
cld->clear_accumulated_modified_oops();
@@ -4429,7 +4426,7 @@
ResourceMark rm;
GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
for (int i = 0; i < array->length(); i++) {
- par_mrias_cl.do_cld_nv(array->at(i));
+ Devirtualizer::do_cld(&par_mrias_cl, array->at(i));
}
// We don't need to keep track of new CLDs anymore.
@@ -4970,7 +4967,7 @@
ResourceMark rm;
GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
for (int i = 0; i < array->length(); i++) {
- mrias_cl.do_cld_nv(array->at(i));
+ Devirtualizer::do_cld(&mrias_cl, array->at(i));
}
// We don't need to keep track of new CLDs anymore.
@@ -5803,9 +5800,6 @@
}
}
-void MarkRefsIntoClosure::do_oop(oop* p) { MarkRefsIntoClosure::do_oop_work(p); }
-void MarkRefsIntoClosure::do_oop(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); }
-
ParMarkRefsIntoClosure::ParMarkRefsIntoClosure(
MemRegion span, CMSBitMap* bitMap):
_span(span),
@@ -5825,9 +5819,6 @@
}
}
-void ParMarkRefsIntoClosure::do_oop(oop* p) { ParMarkRefsIntoClosure::do_oop_work(p); }
-void ParMarkRefsIntoClosure::do_oop(narrowOop* p) { ParMarkRefsIntoClosure::do_oop_work(p); }
-
// A variant of the above, used for CMS marking verification.
MarkRefsIntoVerifyClosure::MarkRefsIntoVerifyClosure(
MemRegion span, CMSBitMap* verification_bm, CMSBitMap* cms_bm):
@@ -5856,9 +5847,6 @@
}
}
-void MarkRefsIntoVerifyClosure::do_oop(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
-void MarkRefsIntoVerifyClosure::do_oop(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); }
-
//////////////////////////////////////////////////
// MarkRefsIntoAndScanClosure
//////////////////////////////////////////////////
@@ -5933,9 +5921,6 @@
}
}
-void MarkRefsIntoAndScanClosure::do_oop(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
-void MarkRefsIntoAndScanClosure::do_oop(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
-
void MarkRefsIntoAndScanClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token");
@@ -6016,9 +6001,6 @@
}
}
-void ParMarkRefsIntoAndScanClosure::do_oop(oop* p) { ParMarkRefsIntoAndScanClosure::do_oop_work(p); }
-void ParMarkRefsIntoAndScanClosure::do_oop(narrowOop* p) { ParMarkRefsIntoAndScanClosure::do_oop_work(p); }
-
// This closure is used to rescan the marked objects on the dirty cards
// in the mod union table and the card table proper.
size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m(
@@ -6597,7 +6579,7 @@
CMSCollector* collector, MemRegion span,
CMSBitMap* verification_bm, CMSBitMap* cms_bm,
CMSMarkStack* mark_stack):
- MetadataAwareOopClosure(collector->ref_processor()),
+ MetadataVisitingOopIterateClosure(collector->ref_processor()),
_collector(collector),
_span(span),
_verification_bm(verification_bm),
@@ -6654,7 +6636,7 @@
MemRegion span,
CMSBitMap* bitMap, CMSMarkStack* markStack,
HeapWord* finger, MarkFromRootsClosure* parent) :
- MetadataAwareOopClosure(collector->ref_processor()),
+ MetadataVisitingOopIterateClosure(collector->ref_processor()),
_collector(collector),
_span(span),
_bitMap(bitMap),
@@ -6671,7 +6653,7 @@
HeapWord* finger,
HeapWord* volatile* global_finger_addr,
ParMarkFromRootsClosure* parent) :
- MetadataAwareOopClosure(collector->ref_processor()),
+ MetadataVisitingOopIterateClosure(collector->ref_processor()),
_collector(collector),
_whole_span(collector->_span),
_span(span),
@@ -6752,9 +6734,6 @@
}
}
-void PushOrMarkClosure::do_oop(oop* p) { PushOrMarkClosure::do_oop_work(p); }
-void PushOrMarkClosure::do_oop(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); }
-
void ParPushOrMarkClosure::do_oop(oop obj) {
// Ignore mark word because we are running concurrent with mutators.
assert(oopDesc::is_oop_or_null(obj, true), "Expected an oop or NULL at " PTR_FORMAT, p2i(obj));
@@ -6801,9 +6780,6 @@
}
}
-void ParPushOrMarkClosure::do_oop(oop* p) { ParPushOrMarkClosure::do_oop_work(p); }
-void ParPushOrMarkClosure::do_oop(narrowOop* p) { ParPushOrMarkClosure::do_oop_work(p); }
-
PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
MemRegion span,
ReferenceDiscoverer* rd,
@@ -6811,7 +6787,7 @@
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
bool concurrent_precleaning):
- MetadataAwareOopClosure(rd),
+ MetadataVisitingOopIterateClosure(rd),
_collector(collector),
_span(span),
_bit_map(bit_map),
@@ -6883,7 +6859,7 @@
ReferenceDiscoverer* rd,
CMSBitMap* bit_map,
OopTaskQueue* work_queue):
- MetadataAwareOopClosure(rd),
+ MetadataVisitingOopIterateClosure(rd),
_collector(collector),
_span(span),
_bit_map(bit_map),
@@ -6892,9 +6868,6 @@
assert(ref_discoverer() != NULL, "ref_discoverer shouldn't be NULL");
}
-void PushAndMarkClosure::do_oop(oop* p) { PushAndMarkClosure::do_oop_work(p); }
-void PushAndMarkClosure::do_oop(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); }
-
// Grey object rescan during second checkpoint phase --
// the parallel version.
void ParPushAndMarkClosure::do_oop(oop obj) {
@@ -6937,9 +6910,6 @@
}
}
-void ParPushAndMarkClosure::do_oop(oop* p) { ParPushAndMarkClosure::do_oop_work(p); }
-void ParPushAndMarkClosure::do_oop(narrowOop* p) { ParPushAndMarkClosure::do_oop_work(p); }
-
void CMSPrecleanRefsYieldClosure::do_yield_work() {
Mutex* bml = _collector->bitMapLock();
assert_lock_strong(bml);
@@ -7606,9 +7576,6 @@
}
}
-void CMSKeepAliveClosure::do_oop(oop* p) { CMSKeepAliveClosure::do_oop_work(p); }
-void CMSKeepAliveClosure::do_oop(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); }
-
// CMSParKeepAliveClosure: a parallel version of the above.
// The work queues are private to each closure (thread),
// but (may be) available for stealing by other threads.
@@ -7629,9 +7596,6 @@
}
}
-void CMSParKeepAliveClosure::do_oop(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); }
-void CMSParKeepAliveClosure::do_oop(narrowOop* p) { CMSParKeepAliveClosure::do_oop_work(p); }
-
void CMSParKeepAliveClosure::trim_queue(uint max) {
while (_work_queue->size() > max) {
oop new_oop;
@@ -7677,9 +7641,6 @@
}
}
-void CMSInnerParMarkAndPushClosure::do_oop(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); }
-void CMSInnerParMarkAndPushClosure::do_oop(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); }
-
//////////////////////////////////////////////////////////////////
// CMSExpansionCause /////////////////////////////
//////////////////////////////////////////////////////////////////
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1190,7 +1190,7 @@
void save_sweep_limit();
// More iteration support
- virtual void oop_iterate(ExtendedOopClosure* cl);
+ virtual void oop_iterate(OopIterateClosure* cl);
virtual void safe_object_iterate(ObjectClosure* cl);
virtual void object_iterate(ObjectClosure* cl);
@@ -1307,7 +1307,7 @@
// The following closures are used to do certain kinds of verification of
// CMS marking.
-class PushAndMarkVerifyClosure: public MetadataAwareOopClosure {
+class PushAndMarkVerifyClosure: public MetadataVisitingOopIterateClosure {
CMSCollector* _collector;
MemRegion _span;
CMSBitMap* _verification_bm;
--- a/src/hotspot/share/gc/cms/parNewGeneration.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -51,6 +51,7 @@
#include "gc/shared/workgroup.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
@@ -502,12 +503,6 @@
_boundary = _g->reserved().end();
}
-void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); }
-void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
-
-void ParScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, false); }
-void ParScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); }
-
void ParRootScanWithBarrierTwoGensClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, true); }
void ParRootScanWithBarrierTwoGensClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, true); }
@@ -519,9 +514,6 @@
: ScanWeakRefClosure(g), _par_scan_state(par_scan_state)
{}
-void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); }
-void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
-
#ifdef WIN32
#pragma warning(disable: 4786) /* identifier was truncated to '255' characters in the browser information */
#endif
@@ -684,17 +676,17 @@
void /*ParNewGeneration::*/ParKeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
{
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// We never expect to see a null reference being processed
// as a weak reference.
assert(oopDesc::is_oop(obj), "expected an oop while scanning weak refs");
}
#endif // ASSERT
- _par_cl->do_oop_nv(p);
+ Devirtualizer::do_oop_no_verify(_par_cl, p);
if (CMSHeap::heap()->is_in_reserved(p)) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);;
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);;
_rs->write_ref_field_gc_par(p, obj);
}
}
@@ -710,17 +702,17 @@
void /*ParNewGeneration::*/KeepAliveClosure::do_oop_work(T* p) {
#ifdef ASSERT
{
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// We never expect to see a null reference being processed
// as a weak reference.
assert(oopDesc::is_oop(obj), "expected an oop while scanning weak refs");
}
#endif // ASSERT
- _cl->do_oop_nv(p);
+ Devirtualizer::do_oop_no_verify(_cl, p);
if (CMSHeap::heap()->is_in_reserved(p)) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
_rs->write_ref_field_gc_par(p, obj);
}
}
@@ -737,7 +729,7 @@
oop new_obj = obj->is_forwarded()
? obj->forwardee()
: _g->DefNewGeneration::copy_to_survivor_space(obj);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
if (_gc_barrier) {
// If p points to a younger generation, mark the card.
--- a/src/hotspot/share/gc/cms/parOopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/cms/parOopClosures.inline.hpp"
-#include "gc/cms/cms_specialized_oop_closures.hpp"
-#include "memory/iterator.inline.hpp"
-
-// Generate ParNew specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(ALL_KLASS_OOP_OOP_ITERATE_DEFN);
--- a/src/hotspot/share/gc/cms/parOopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/parOopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -57,8 +57,6 @@
ParScanClosure(g, par_scan_state) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
class ParScanWithoutBarrierClosure: public ParScanClosure {
@@ -68,8 +66,6 @@
ParScanClosure(g, par_scan_state) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
class ParRootScanWithBarrierTwoGensClosure: public ParScanClosure {
@@ -99,8 +95,6 @@
ParScanThreadState* par_scan_state);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
class ParEvacuateFollowersClosure: public VoidClosure {
--- a/src/hotspot/share/gc/cms/parOopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/cms/parOopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,7 +37,7 @@
#include "oops/oop.inline.hpp"
template <class T> inline void ParScanWeakRefClosure::do_oop_work(T* p) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// weak references are sometimes scanned twice; must check
// that to-space doesn't already contain this object
if ((HeapWord*)obj < _boundary && !_g->to()->is_in_reserved(obj)) {
@@ -53,16 +53,16 @@
new_obj = ((ParNewGeneration*)_g)->copy_to_survivor_space(_par_scan_state,
obj, obj_sz, m);
}
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
}
-inline void ParScanWeakRefClosure::do_oop_nv(oop* p) { ParScanWeakRefClosure::do_oop_work(p); }
-inline void ParScanWeakRefClosure::do_oop_nv(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
+inline void ParScanWeakRefClosure::do_oop(oop* p) { ParScanWeakRefClosure::do_oop_work(p); }
+inline void ParScanWeakRefClosure::do_oop(narrowOop* p) { ParScanWeakRefClosure::do_oop_work(p); }
template <class T> inline void ParScanClosure::par_do_barrier(T* p) {
assert(generation()->is_in_reserved(p), "expected ref in generation");
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// If p points to a younger generation, mark the card.
if ((HeapWord*)obj < gen_boundary()) {
rs()->write_ref_field_gc_par(p, obj);
@@ -112,14 +112,14 @@
oop new_obj;
if (m->is_marked()) { // Contains forwarding pointer.
new_obj = ParNewGeneration::real_forwardee(obj);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
log_develop_trace(gc, scavenge)("{%s %s ( " PTR_FORMAT " ) " PTR_FORMAT " -> " PTR_FORMAT " (%d)}",
"forwarded ",
new_obj->klass()->internal_name(), p2i(p), p2i((void *)obj), p2i((void *)new_obj), new_obj->size());
} else {
size_t obj_sz = obj->size_given_klass(objK);
new_obj = _g->copy_to_survivor_space(_par_scan_state, obj, obj_sz, m);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
if (root_scan) {
// This may have pushed an object. If we have a root
// category with a lot of roots, can't let the queue get too
@@ -137,10 +137,10 @@
}
}
-inline void ParScanWithBarrierClosure::do_oop_nv(oop* p) { ParScanClosure::do_oop_work(p, true, false); }
-inline void ParScanWithBarrierClosure::do_oop_nv(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
+inline void ParScanWithBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, true, false); }
+inline void ParScanWithBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, true, false); }
-inline void ParScanWithoutBarrierClosure::do_oop_nv(oop* p) { ParScanClosure::do_oop_work(p, false, false); }
-inline void ParScanWithoutBarrierClosure::do_oop_nv(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); }
+inline void ParScanWithoutBarrierClosure::do_oop(oop* p) { ParScanClosure::do_oop_work(p, false, false); }
+inline void ParScanWithoutBarrierClosure::do_oop(narrowOop* p) { ParScanClosure::do_oop_work(p, false, false); }
#endif // SHARE_VM_GC_CMS_PAROOPCLOSURES_INLINE_HPP
--- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,7 @@
template <DecoratorSet decorators, typename T>
inline void G1BarrierSet::write_ref_field_pre(T* field) {
- if (HasDecorator<decorators, AS_DEST_NOT_INITIALIZED>::value ||
+ if (HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value ||
HasDecorator<decorators, AS_NO_KEEPALIVE>::value) {
return;
}
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2116,7 +2116,7 @@
G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h,
G1CMTask* task)
- : MetadataAwareOopClosure(get_cm_oop_closure_ref_processor(g1h)),
+ : MetadataVisitingOopIterateClosure(get_cm_oop_closure_ref_processor(g1h)),
_g1h(g1h), _task(task)
{ }
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -29,6 +29,7 @@
#include "gc/g1/g1ConcurrentMark.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp"
+#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1Policy.hpp"
#include "gc/g1/g1RegionMarkStatsCache.inline.hpp"
#include "gc/g1/g1RemSetTrackingPolicy.hpp"
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -38,7 +38,7 @@
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-class UpdateRSetDeferred : public ExtendedOopClosure {
+class UpdateRSetDeferred : public BasicOopIterateClosure {
private:
G1CollectedHeap* _g1h;
DirtyCardQueue* _dcq;
--- a/src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCAdjustTask.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,6 +34,7 @@
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
+#include "memory/iterator.inline.hpp"
class G1AdjustLiveClosure : public StackObj {
G1AdjustClosure* _adjust_closure;
--- a/src/hotspot/share/gc/g1/g1FullGCMarkTask.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCMarkTask.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
#include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
+#include "memory/iterator.inline.hpp"
G1FullGCMarkTask::G1FullGCMarkTask(G1FullCollector* collector) :
G1FullGCTask("G1 Parallel Marking Task", collector),
--- a/src/hotspot/share/gc/g1/g1FullGCMarker.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCMarker.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
+#include "memory/iterator.inline.hpp"
G1FullGCMarker::G1FullGCMarker(uint worker_id, PreservedMarks* preserved_stack, G1CMBitMap* bitmap) :
_worker_id(worker_id),
--- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -28,6 +28,7 @@
#include "gc/g1/g1Allocator.inline.hpp"
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
#include "gc/g1/g1FullGCMarker.hpp"
+#include "gc/g1/g1FullGCOopClosures.inline.hpp"
#include "gc/g1/g1StringDedup.hpp"
#include "gc/g1/g1StringDedupQueue.hpp"
#include "gc/shared/preservedMarks.inline.hpp"
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,32 +26,12 @@
#include "gc/g1/g1CollectedHeap.hpp"
#include "gc/g1/g1FullGCMarker.inline.hpp"
#include "gc/g1/g1FullGCOopClosures.inline.hpp"
-#include "gc/g1/g1_specialized_oop_closures.hpp"
#include "logging/logStream.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-void G1MarkAndPushClosure::do_oop(oop* p) {
- do_oop_nv(p);
-}
-
-void G1MarkAndPushClosure::do_oop(narrowOop* p) {
- do_oop_nv(p);
-}
-
-bool G1MarkAndPushClosure::do_metadata() {
- return do_metadata_nv();
-}
-
-void G1MarkAndPushClosure::do_klass(Klass* k) {
- do_klass_nv(k);
-}
-
-void G1MarkAndPushClosure::do_cld(ClassLoaderData* cld) {
- do_cld_nv(cld);
-}
-
void G1FollowStackClosure::do_void() { _marker->drain_stack(); }
void G1FullKeepAliveClosure::do_oop(oop* p) { do_oop_work(p); }
@@ -75,7 +55,7 @@
#endif // PRODUCT
}
-template <class T> void G1VerifyOopClosure::do_oop_nv(T* p) {
+template <class T> void G1VerifyOopClosure::do_oop_work(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
_cc++;
@@ -121,8 +101,5 @@
}
}
-template void G1VerifyOopClosure::do_oop_nv(oop*);
-template void G1VerifyOopClosure::do_oop_nv(narrowOop*);
-
-// Generate G1 full GC specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
+template void G1VerifyOopClosure::do_oop_work(oop*);
+template void G1VerifyOopClosure::do_oop_work(narrowOop*);
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -55,7 +55,7 @@
virtual void do_oop(narrowOop* p);
};
-class G1MarkAndPushClosure : public ExtendedOopClosure {
+class G1MarkAndPushClosure : public OopIterateClosure {
G1FullGCMarker* _marker;
uint _worker_id;
@@ -63,26 +63,21 @@
G1MarkAndPushClosure(uint worker, G1FullGCMarker* marker, ReferenceDiscoverer* ref) :
_marker(marker),
_worker_id(worker),
- ExtendedOopClosure(ref) { }
+ OopIterateClosure(ref) { }
- template <class T> inline void do_oop_nv(T* p);
+ template <class T> inline void do_oop_work(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual bool do_metadata();
- bool do_metadata_nv();
-
virtual void do_klass(Klass* k);
- void do_klass_nv(Klass* k);
-
virtual void do_cld(ClassLoaderData* cld);
- void do_cld_nv(ClassLoaderData* cld);
};
-class G1AdjustClosure : public ExtendedOopClosure {
+class G1AdjustClosure : public BasicOopIterateClosure {
template <class T> static inline void adjust_pointer(T* p);
public:
- template <class T> void do_oop_nv(T* p) { adjust_pointer(p); }
+ template <class T> void do_oop_work(T* p) { adjust_pointer(p); }
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
@@ -107,10 +102,10 @@
bool failures() { return _failures; }
void print_object(outputStream* out, oop obj);
- template <class T> void do_oop_nv(T* p);
+ template <class T> void do_oop_work(T* p);
- void do_oop(oop* p) { do_oop_nv(p); }
- void do_oop(narrowOop* p) { do_oop_nv(p); }
+ void do_oop(oop* p) { do_oop_work(p); }
+ void do_oop(narrowOop* p) { do_oop_work(p); }
};
class G1FollowStackClosure: public VoidClosure {
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -36,19 +36,27 @@
#include "oops/oop.inline.hpp"
template <typename T>
-inline void G1MarkAndPushClosure::do_oop_nv(T* p) {
+inline void G1MarkAndPushClosure::do_oop_work(T* p) {
_marker->mark_and_push(p);
}
-inline bool G1MarkAndPushClosure::do_metadata_nv() {
+inline void G1MarkAndPushClosure::do_oop(oop* p) {
+ do_oop_work(p);
+}
+
+inline void G1MarkAndPushClosure::do_oop(narrowOop* p) {
+ do_oop_work(p);
+}
+
+inline bool G1MarkAndPushClosure::do_metadata() {
return true;
}
-inline void G1MarkAndPushClosure::do_klass_nv(Klass* k) {
+inline void G1MarkAndPushClosure::do_klass(Klass* k) {
_marker->follow_klass(k);
}
-inline void G1MarkAndPushClosure::do_cld_nv(ClassLoaderData* cld) {
+inline void G1MarkAndPushClosure::do_cld(ClassLoaderData* cld) {
_marker->follow_cld(cld);
}
@@ -78,11 +86,11 @@
// Forwarded, just update.
assert(Universe::heap()->is_in_reserved(forwardee), "should be in object space");
- RawAccess<OOP_NOT_NULL>::oop_store(p, forwardee);
+ RawAccess<IS_NOT_NULL>::oop_store(p, forwardee);
}
-inline void G1AdjustClosure::do_oop(oop* p) { do_oop_nv(p); }
-inline void G1AdjustClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+inline void G1AdjustClosure::do_oop(oop* p) { do_oop_work(p); }
+inline void G1AdjustClosure::do_oop(narrowOop* p) { do_oop_work(p); }
inline bool G1IsAliveClosure::do_object_b(oop p) {
return _bitmap->is_marked(p) || G1ArchiveAllocator::is_closed_archive_object(p);
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -35,6 +35,7 @@
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
#include "logging/log.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/ticks.hpp"
--- a/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1FullGCReferenceProcessorExecutor.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -30,6 +30,7 @@
#include "gc/g1/g1FullGCReferenceProcessorExecutor.hpp"
#include "gc/shared/gcTraceTime.inline.hpp"
#include "gc/shared/referenceProcessor.hpp"
+#include "memory/iterator.inline.hpp"
G1FullGCReferenceProcessingExecutor::G1FullGCReferenceProcessingExecutor(G1FullCollector* collector) :
_collector(collector),
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,6 +37,7 @@
#include "gc/g1/g1StringDedup.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
@@ -61,7 +62,7 @@
bool failures() { return _failures; }
- template <class T> void do_oop_nv(T* p) {
+ template <class T> void do_oop_work(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
oop obj = CompressedOops::decode_not_null(heap_oop);
@@ -76,8 +77,8 @@
}
}
- void do_oop(oop* p) { do_oop_nv(p); }
- void do_oop(narrowOop* p) { do_oop_nv(p); }
+ void do_oop(oop* p) { do_oop_work(p); }
+ void do_oop(narrowOop* p) { do_oop_work(p); }
};
class G1VerifyCodeRootOopClosure: public OopClosure {
--- a/src/hotspot/share/gc/g1/g1OopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1OopClosures.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,6 @@
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/g1OopClosures.inline.hpp"
#include "gc/g1/g1ParScanThreadState.hpp"
-#include "gc/g1/g1_specialized_oop_closures.hpp"
#include "memory/iterator.inline.hpp"
#include "utilities/stack.inline.hpp"
@@ -61,6 +60,3 @@
}
_count++;
}
-
-// Generate G1 specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/gc/g1/g1OopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -39,7 +39,7 @@
class G1CMTask;
class ReferenceProcessor;
-class G1ScanClosureBase : public ExtendedOopClosure {
+class G1ScanClosureBase : public BasicOopIterateClosure {
protected:
G1CollectedHeap* _g1h;
G1ParScanThreadState* _par_scan_state;
@@ -71,9 +71,9 @@
uint worker_i) :
G1ScanClosureBase(g1h, pss), _worker_i(worker_i) { }
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
- virtual void do_oop(oop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
+ virtual void do_oop(oop* p) { do_oop_work(p); }
};
// Used during the Scan RS phase to scan cards from the remembered set during garbage collection.
@@ -83,9 +83,9 @@
G1ParScanThreadState* par_scan_state):
G1ScanClosureBase(g1h, par_scan_state) { }
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop(oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop(oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
};
// This closure is applied to the fields of the objects that have just been copied during evacuation.
@@ -94,9 +94,9 @@
G1ScanEvacuatedObjClosure(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state) :
G1ScanClosureBase(g1h, par_scan_state) { }
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop(oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop(oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
void set_ref_discoverer(ReferenceDiscoverer* rd) {
set_ref_discoverer_internal(rd);
@@ -167,18 +167,18 @@
};
// Closure for iterating over object fields during concurrent marking
-class G1CMOopClosure : public MetadataAwareOopClosure {
+class G1CMOopClosure : public MetadataVisitingOopIterateClosure {
G1CollectedHeap* _g1h;
G1CMTask* _task;
public:
G1CMOopClosure(G1CollectedHeap* g1h,G1CMTask* task);
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop( oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop( oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
};
// Closure to scan the root regions during concurrent marking
-class G1RootRegionScanClosure : public MetadataAwareOopClosure {
+class G1RootRegionScanClosure : public MetadataVisitingOopIterateClosure {
private:
G1CollectedHeap* _g1h;
G1ConcurrentMark* _cm;
@@ -186,12 +186,12 @@
public:
G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, uint worker_id) :
_g1h(g1h), _cm(cm), _worker_id(worker_id) { }
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop( oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop( oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
};
-class G1ConcurrentRefineOopClosure: public ExtendedOopClosure {
+class G1ConcurrentRefineOopClosure: public BasicOopIterateClosure {
G1CollectedHeap* _g1h;
uint _worker_i;
@@ -204,21 +204,21 @@
// This closure needs special handling for InstanceRefKlass.
virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERED_AND_DISCOVERY; }
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
- virtual void do_oop(oop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
+ virtual void do_oop(oop* p) { do_oop_work(p); }
};
-class G1RebuildRemSetClosure : public ExtendedOopClosure {
+class G1RebuildRemSetClosure : public BasicOopIterateClosure {
G1CollectedHeap* _g1h;
uint _worker_id;
public:
G1RebuildRemSetClosure(G1CollectedHeap* g1h, uint worker_id) : _g1h(g1h), _worker_id(worker_id) {
}
- template <class T> void do_oop_nv(T* p);
- virtual void do_oop(oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ template <class T> void do_oop_work(T* p);
+ virtual void do_oop(oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
// This closure needs special handling for InstanceRefKlass.
virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERED_AND_DISCOVERY; }
};
--- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -72,7 +72,7 @@
}
template <class T>
-inline void G1ScanEvacuatedObjClosure::do_oop_nv(T* p) {
+inline void G1ScanEvacuatedObjClosure::do_oop_work(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (CompressedOops::is_null(heap_oop)) {
@@ -92,12 +92,12 @@
}
template <class T>
-inline void G1CMOopClosure::do_oop_nv(T* p) {
+inline void G1CMOopClosure::do_oop_work(T* p) {
_task->deal_with_reference(p);
}
template <class T>
-inline void G1RootRegionScanClosure::do_oop_nv(T* p) {
+inline void G1RootRegionScanClosure::do_oop_work(T* p) {
T heap_oop = RawAccess<MO_VOLATILE>::oop_load(p);
if (CompressedOops::is_null(heap_oop)) {
return;
@@ -128,7 +128,7 @@
}
template <class T>
-inline void G1ConcurrentRefineOopClosure::do_oop_nv(T* p) {
+inline void G1ConcurrentRefineOopClosure::do_oop_work(T* p) {
T o = RawAccess<MO_VOLATILE>::oop_load(p);
if (CompressedOops::is_null(o)) {
return;
@@ -157,7 +157,7 @@
}
template <class T>
-inline void G1ScanObjsDuringUpdateRSClosure::do_oop_nv(T* p) {
+inline void G1ScanObjsDuringUpdateRSClosure::do_oop_work(T* p) {
T o = RawAccess<>::oop_load(p);
if (CompressedOops::is_null(o)) {
return;
@@ -183,7 +183,7 @@
}
template <class T>
-inline void G1ScanObjsDuringScanRSClosure::do_oop_nv(T* p) {
+inline void G1ScanObjsDuringScanRSClosure::do_oop_work(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (CompressedOops::is_null(heap_oop)) {
return;
@@ -256,7 +256,7 @@
forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
}
assert(forwardee != NULL, "forwardee should not be NULL");
- RawAccess<OOP_NOT_NULL>::oop_store(p, forwardee);
+ RawAccess<IS_NOT_NULL>::oop_store(p, forwardee);
if (do_mark_object != G1MarkNone && forwardee != obj) {
// If the object is self-forwarded we don't need to explicitly
// mark it, the evacuation failure protocol will do so.
@@ -280,7 +280,7 @@
trim_queue_partially();
}
-template <class T> void G1RebuildRemSetClosure::do_oop_nv(T* p) {
+template <class T> void G1RebuildRemSetClosure::do_oop_work(T* p) {
oop const obj = RawAccess<MO_VOLATILE>::oop_load(p);
if (obj == NULL) {
return;
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -266,7 +266,7 @@
Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
const oop obj = oop(obj_ptr);
- const oop forward_ptr = old->forward_to_atomic(obj);
+ const oop forward_ptr = old->forward_to_atomic(obj, memory_order_relaxed);
if (forward_ptr == NULL) {
Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
@@ -356,7 +356,7 @@
oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markOop m) {
assert(_g1h->is_in_cset(old), "Object " PTR_FORMAT " should be in the CSet", p2i(old));
- oop forward_ptr = old->forward_to_atomic(old);
+ oop forward_ptr = old->forward_to_atomic(old, memory_order_relaxed);
if (forward_ptr == NULL) {
// Forward-to-self succeeded. We are the "owner" of the object.
HeapRegion* r = _g1h->heap_region_containing(old);
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,7 +32,7 @@
template <class T> void G1ParScanThreadState::do_oop_evac(T* p) {
// Reference should not be NULL here as such are never pushed to the task queue.
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// Although we never intentionally push references outside of the collection
// set, due to (benign) races in the claim mechanism during RSet scanning more
@@ -47,7 +47,7 @@
} else {
obj = copy_to_survivor_space(in_cset_state, obj, m);
}
- RawAccess<OOP_NOT_NULL>::oop_store(p, obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, obj);
} else if (in_cset_state.is_humongous()) {
_g1h->set_humongous_is_live(obj);
} else {
--- a/src/hotspot/share/gc/g1/g1_specialized_oop_closures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2001, 2018, 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.
- *
- */
-
-#ifndef SHARE_VM_GC_G1_G1_SPECIALIZED_OOP_CLOSURES_HPP
-#define SHARE_VM_GC_G1_G1_SPECIALIZED_OOP_CLOSURES_HPP
-
-// The following OopClosure types get specialized versions of
-// "oop_oop_iterate" that invoke the closures' do_oop methods
-// non-virtually, using a mechanism defined in this file. Extend these
-// macros in the obvious way to add specializations for new closures.
-
-// Forward declarations.
-
-class G1ScanEvacuatedObjClosure;
-
-class G1ScanObjsDuringUpdateRSClosure;
-class G1ScanObjsDuringScanRSClosure;
-class G1ConcurrentRefineOopClosure;
-
-class G1CMOopClosure;
-class G1RootRegionScanClosure;
-
-class G1MarkAndPushClosure;
-class G1AdjustClosure;
-
-class G1RebuildRemSetClosure;
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f) \
- f(G1ScanEvacuatedObjClosure,_nv) \
- f(G1ScanObjsDuringUpdateRSClosure,_nv) \
- f(G1ScanObjsDuringScanRSClosure,_nv) \
- f(G1ConcurrentRefineOopClosure,_nv) \
- f(G1CMOopClosure,_nv) \
- f(G1RootRegionScanClosure,_nv) \
- f(G1RebuildRemSetClosure,_nv)
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f) \
- f(G1MarkAndPushClosure,_nv) \
- f(G1AdjustClosure,_nv)
-
-#endif // SHARE_VM_GC_G1_G1_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/g1/heapRegion.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/g1/heapRegion.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,7 +37,7 @@
#include "gc/shared/space.inline.hpp"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
-#include "memory/iterator.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/compressedOops.inline.hpp"
@@ -450,7 +450,7 @@
p2i(prev_top_at_mark_start()), p2i(next_top_at_mark_start()), rem_set()->get_state_str());
}
-class G1VerificationClosure : public ExtendedOopClosure {
+class G1VerificationClosure : public BasicOopIterateClosure {
protected:
G1CollectedHeap* _g1h;
G1CardTable *_ct;
@@ -608,7 +608,7 @@
};
// Closure that applies the given two closures in sequence.
-class G1Mux2Closure : public ExtendedOopClosure {
+class G1Mux2Closure : public BasicOopIterateClosure {
OopClosure* _c1;
OopClosure* _c2;
public:
--- a/src/hotspot/share/gc/parallel/immutableSpace.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/immutableSpace.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/parallel/immutableSpace.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/macros.hpp"
@@ -39,7 +40,7 @@
_end = end;
}
-void ImmutableSpace::oop_iterate(ExtendedOopClosure* cl) {
+void ImmutableSpace::oop_iterate(OopIterateClosure* cl) {
HeapWord* obj_addr = bottom();
HeapWord* t = end();
// Could call objects iterate, but this is easier.
--- a/src/hotspot/share/gc/parallel/immutableSpace.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/immutableSpace.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -59,7 +59,7 @@
virtual size_t capacity_in_words(Thread*) const { return capacity_in_words(); }
// Iteration.
- virtual void oop_iterate(ExtendedOopClosure* cl);
+ virtual void oop_iterate(OopIterateClosure* cl);
virtual void object_iterate(ObjectClosure* cl);
// Debugging
--- a/src/hotspot/share/gc/parallel/mutableSpace.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "gc/parallel/mutableSpace.hpp"
#include "gc/shared/spaceDecorator.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/safepoint.hpp"
--- a/src/hotspot/share/gc/parallel/psCardTable.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCardTable.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
#include "gc/parallel/psScavenge.hpp"
#include "gc/parallel/psTasks.hpp"
#include "gc/parallel/psYoungGen.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
@@ -103,7 +104,7 @@
protected:
template <class T> void do_oop_work(T* p) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
if (_young_gen->is_in_reserved(obj)) {
assert(_card_table->addr_is_marked_precise(p), "Found unmarked precise oop");
_card_table->set_card_newgen(p);
--- a/src/hotspot/share/gc/parallel/psCompactionManager.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -140,7 +140,11 @@
// everything else.
ParCompactionManager::MarkAndPushClosure cl(cm);
- InstanceKlass::oop_oop_iterate_oop_maps<true>(obj, &cl);
+ if (UseCompressedOops) {
+ InstanceKlass::oop_oop_iterate_oop_maps<narrowOop>(obj, &cl);
+ } else {
+ InstanceKlass::oop_oop_iterate_oop_maps<oop>(obj, &cl);
+ }
}
void InstanceMirrorKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
@@ -169,7 +173,11 @@
}
ParCompactionManager::MarkAndPushClosure cl(cm);
- oop_oop_iterate_statics<true>(obj, &cl);
+ if (UseCompressedOops) {
+ oop_oop_iterate_statics<narrowOop>(obj, &cl);
+ } else {
+ oop_oop_iterate_statics<oop>(obj, &cl);
+ }
}
void InstanceClassLoaderKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) {
--- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -175,13 +175,13 @@
void update_contents(oop obj);
- class MarkAndPushClosure: public ExtendedOopClosure {
+ class MarkAndPushClosure: public BasicOopIterateClosure {
private:
ParCompactionManager* _compaction_manager;
public:
MarkAndPushClosure(ParCompactionManager* cm) : _compaction_manager(cm) { }
- template <typename T> void do_oop_nv(T* p);
+ template <typename T> void do_oop_work(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
--- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -85,12 +85,12 @@
}
template <typename T>
-inline void ParCompactionManager::MarkAndPushClosure::do_oop_nv(T* p) {
+inline void ParCompactionManager::MarkAndPushClosure::do_oop_work(T* p) {
_compaction_manager->mark_and_push(p);
}
-inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
-inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(oop* p) { do_oop_work(p); }
+inline void ParCompactionManager::MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); }
inline void ParCompactionManager::follow_klass(Klass* klass) {
oop holder = klass->klass_holder();
--- a/src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,6 +32,7 @@
#include "gc/parallel/psParallelCompact.inline.hpp"
#include "gc/serial/markSweep.inline.hpp"
#include "gc/shared/spaceDecorator.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/prefetch.inline.hpp"
--- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "aot/aotLoader.hpp"
+#include "classfile/javaClasses.inline.hpp"
#include "classfile/stringTable.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
@@ -53,8 +54,10 @@
#include "gc/shared/spaceDecorator.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "logging/log.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
+#include "oops/instanceClassLoaderKlass.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/instanceMirrorKlass.inline.hpp"
#include "oops/methodData.hpp"
@@ -3069,14 +3072,22 @@
void InstanceKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
PSParallelCompact::AdjustPointerClosure closure(cm);
- oop_oop_iterate_oop_maps<true>(obj, &closure);
+ if (UseCompressedOops) {
+ oop_oop_iterate_oop_maps<narrowOop>(obj, &closure);
+ } else {
+ oop_oop_iterate_oop_maps<oop>(obj, &closure);
+ }
}
void InstanceMirrorKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
InstanceKlass::oop_pc_update_pointers(obj, cm);
PSParallelCompact::AdjustPointerClosure closure(cm);
- oop_oop_iterate_statics<true>(obj, &closure);
+ if (UseCompressedOops) {
+ oop_oop_iterate_statics<narrowOop>(obj, &closure);
+ } else {
+ oop_oop_iterate_statics<oop>(obj, &closure);
+ }
}
void InstanceClassLoaderKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
@@ -3118,7 +3129,11 @@
void ObjArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
assert(obj->is_objArray(), "obj must be obj array");
PSParallelCompact::AdjustPointerClosure closure(cm);
- oop_oop_iterate_elements<true>(objArrayOop(obj), &closure);
+ if (UseCompressedOops) {
+ oop_oop_iterate_elements<narrowOop>(objArrayOop(obj), &closure);
+ } else {
+ oop_oop_iterate_elements<oop>(objArrayOop(obj), &closure);
+ }
}
void TypeArrayKlass::oop_pc_update_pointers(oop obj, ParCompactionManager* cm) {
--- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -934,13 +934,13 @@
virtual bool do_object_b(oop p);
};
- class AdjustPointerClosure: public ExtendedOopClosure {
+ class AdjustPointerClosure: public BasicOopIterateClosure {
public:
AdjustPointerClosure(ParCompactionManager* cm) {
assert(cm != NULL, "associate ParCompactionManage should not be NULL");
_cm = cm;
}
- template <typename T> void do_oop_nv(T* p);
+ template <typename T> void do_oop_work(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
--- a/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psParallelCompact.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -119,17 +119,17 @@
if (new_obj != NULL) {
assert(ParallelScavengeHeap::heap()->is_in_reserved(new_obj),
"should be in object space");
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
}
}
template <typename T>
-void PSParallelCompact::AdjustPointerClosure::do_oop_nv(T* p) {
+void PSParallelCompact::AdjustPointerClosure::do_oop_work(T* p) {
adjust_pointer(p, _cm);
}
-inline void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); }
-inline void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+inline void PSParallelCompact::AdjustPointerClosure::do_oop(oop* p) { do_oop_work(p); }
+inline void PSParallelCompact::AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_work(p); }
#endif // SHARE_VM_GC_PARALLEL_PSPARALLELCOMPACT_INLINE_HPP
--- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "classfile/javaClasses.inline.hpp"
#include "gc/parallel/gcTaskManager.hpp"
#include "gc/parallel/mutableSpace.hpp"
#include "gc/parallel/parallelScavengeHeap.hpp"
@@ -35,12 +36,14 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/memRegion.hpp"
#include "memory/padded.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/arrayOop.inline.hpp"
#include "oops/compressedOops.inline.hpp"
+#include "oops/instanceClassLoaderKlass.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/instanceMirrorKlass.inline.hpp"
#include "oops/objArrayKlass.inline.hpp"
@@ -394,19 +397,19 @@
}
}
-class PushContentsClosure : public ExtendedOopClosure {
+class PushContentsClosure : public BasicOopIterateClosure {
PSPromotionManager* _pm;
public:
PushContentsClosure(PSPromotionManager* pm) : _pm(pm) {}
- template <typename T> void do_oop_nv(T* p) {
+ template <typename T> void do_oop_work(T* p) {
if (PSScavenge::should_scavenge(p)) {
_pm->claim_or_forward_depth(p);
}
}
- virtual void do_oop(oop* p) { do_oop_nv(p); }
- virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+ virtual void do_oop(oop* p) { do_oop_work(p); }
+ virtual void do_oop(narrowOop* p) { do_oop_work(p); }
// Don't use the oop verification code in the oop_oop_iterate framework.
debug_only(virtual bool should_verify_oops() { return false; })
@@ -414,7 +417,11 @@
void InstanceKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) {
PushContentsClosure cl(pm);
- oop_oop_iterate_oop_maps_reverse<true>(obj, &cl);
+ if (UseCompressedOops) {
+ oop_oop_iterate_oop_maps_reverse<narrowOop>(obj, &cl);
+ } else {
+ oop_oop_iterate_oop_maps_reverse<oop>(obj, &cl);
+ }
}
void InstanceMirrorKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) {
@@ -425,7 +432,11 @@
InstanceKlass::oop_ps_push_contents(obj, pm);
PushContentsClosure cl(pm);
- oop_oop_iterate_statics<true>(obj, &cl);
+ if (UseCompressedOops) {
+ oop_oop_iterate_statics<narrowOop>(obj, &cl);
+ } else {
+ oop_oop_iterate_statics<oop>(obj, &cl);
+ }
}
void InstanceClassLoaderKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) {
@@ -469,7 +480,11 @@
void ObjArrayKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) {
assert(obj->is_objArray(), "obj must be obj array");
PushContentsClosure cl(pm);
- oop_oop_iterate_elements<true>(objArrayOop(obj), &cl);
+ if (UseCompressedOops) {
+ oop_oop_iterate_elements<narrowOop>(objArrayOop(obj), &cl);
+ } else {
+ oop_oop_iterate_elements<oop>(objArrayOop(obj), &cl);
+ }
}
void TypeArrayKlass::oop_ps_push_contents(oop obj, PSPromotionManager* pm) {
--- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -50,14 +50,14 @@
template <class T>
inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {
if (p != NULL) { // XXX: error if p != NULL here
- oop o = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop o = RawAccess<IS_NOT_NULL>::oop_load(p);
if (o->is_forwarded()) {
o = o->forwardee();
// Card mark
if (PSScavenge::is_obj_in_young(o)) {
PSScavenge::card_table()->inline_write_ref_field_gc(p, o);
}
- RawAccess<OOP_NOT_NULL>::oop_store(p, o);
+ RawAccess<IS_NOT_NULL>::oop_store(p, o);
} else {
push_depth(p);
}
@@ -281,7 +281,7 @@
inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) {
assert(should_scavenge(p, true), "revisiting object?");
- oop o = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop o = RawAccess<IS_NOT_NULL>::oop_load(p);
oop new_obj = o->is_forwarded()
? o->forwardee()
: copy_to_survivor_space<promote_immediately>(o);
@@ -294,7 +294,7 @@
new_obj->klass()->internal_name(), p2i((void *)o), p2i((void *)new_obj), new_obj->size());
}
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
// We cannot mark without test, as some code passes us pointers
// that are outside the heap. These pointers are either from roots
--- a/src/hotspot/share/gc/parallel/psScavenge.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psScavenge.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -97,7 +97,7 @@
}
template <class T> void do_oop_work(T* p) {
- assert (oopDesc::is_oop(RawAccess<OOP_NOT_NULL>::oop_load(p)),
+ assert (oopDesc::is_oop(RawAccess<IS_NOT_NULL>::oop_load(p)),
"expected an oop while scanning weak refs");
// Weak refs may be visited more than once.
--- a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -48,7 +48,7 @@
template <class T>
inline bool PSScavenge::should_scavenge(T* p, MutableSpace* to_space) {
if (should_scavenge(p)) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// Skip objects copied to to_space since the scavenge started.
HeapWord* const addr = (HeapWord*)obj;
return addr < to_space_top_before_gc() || addr >= to_space->end();
@@ -109,7 +109,7 @@
} else {
new_obj = _pm->copy_to_survivor_space</*promote_immediately=*/false>(o);
}
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
if (PSScavenge::is_obj_in_young(new_obj)) {
do_cld_barrier();
--- a/src/hotspot/share/gc/parallel/psYoungGen.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/parallel/psYoungGen.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -168,7 +168,7 @@
HeapWord** end_addr() const { return eden_space()->end_addr(); }
// Iteration.
- void oop_iterate(ExtendedOopClosure* cl);
+ void oop_iterate(OopIterateClosure* cl);
void object_iterate(ObjectClosure* cl);
virtual void reset_after_change();
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -46,7 +46,7 @@
#include "gc/shared/strongRootsScope.hpp"
#include "gc/shared/weakProcessor.hpp"
#include "logging/log.hpp"
-#include "memory/iterator.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
@@ -112,18 +112,12 @@
_boundary = _g->reserved().end();
}
-void ScanClosure::do_oop(oop* p) { ScanClosure::do_oop_work(p); }
-void ScanClosure::do_oop(narrowOop* p) { ScanClosure::do_oop_work(p); }
-
FastScanClosure::FastScanClosure(DefNewGeneration* g, bool gc_barrier) :
OopsInClassLoaderDataOrGenClosure(g), _g(g), _gc_barrier(gc_barrier)
{
_boundary = _g->reserved().end();
}
-void FastScanClosure::do_oop(oop* p) { FastScanClosure::do_oop_work(p); }
-void FastScanClosure::do_oop(narrowOop* p) { FastScanClosure::do_oop_work(p); }
-
void CLDScanClosure::do_cld(ClassLoaderData* cld) {
NOT_PRODUCT(ResourceMark rm);
log_develop_trace(gc, scavenge)("CLDScanClosure::do_cld " PTR_FORMAT ", %s, dirty: %s",
@@ -155,9 +149,6 @@
_boundary = _g->reserved().end();
}
-void ScanWeakRefClosure::do_oop(oop* p) { ScanWeakRefClosure::do_oop_work(p); }
-void ScanWeakRefClosure::do_oop(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
-
DefNewGeneration::DefNewGeneration(ReservedSpace rs,
size_t initial_size,
const char* policy)
--- a/src/hotspot/share/gc/serial/defNewGeneration.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -96,8 +96,8 @@
PreservedMarksSet _preserved_marks_set;
// Promotion failure handling
- ExtendedOopClosure *_promo_failure_scan_stack_closure;
- void set_promo_failure_scan_stack_closure(ExtendedOopClosure *scan_stack_closure) {
+ OopIterateClosure *_promo_failure_scan_stack_closure;
+ void set_promo_failure_scan_stack_closure(OopIterateClosure *scan_stack_closure) {
_promo_failure_scan_stack_closure = scan_stack_closure;
}
--- a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -40,12 +40,12 @@
{
// We never expect to see a null reference being processed
// as a weak reference.
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
assert (oopDesc::is_oop(obj), "expected an oop while scanning weak refs");
}
#endif // ASSERT
- _cl->do_oop_nv(p);
+ Devirtualizer::do_oop_no_verify(_cl, p);
// Card marking is trickier for weak refs.
// This oop is a 'next' field which was filled in while we
@@ -61,7 +61,7 @@
// dirty cards in the young gen are never scanned, so the
// extra check probably isn't worthwhile.
if (GenCollectedHeap::heap()->is_in_reserved(p)) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
_rs->inline_write_ref_field_gc(p, obj);
}
}
@@ -72,17 +72,17 @@
{
// We never expect to see a null reference being processed
// as a weak reference.
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
assert (oopDesc::is_oop(obj), "expected an oop while scanning weak refs");
}
#endif // ASSERT
- _cl->do_oop_nv(p);
+ Devirtualizer::do_oop_no_verify(_cl, p);
// Optimized for Defnew generation if it's the youngest generation:
// we set a younger_gen card if we have an older->youngest
// generation pointer.
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
if (((HeapWord*)obj < _boundary) && GenCollectedHeap::heap()->is_in_reserved(p)) {
_rs->inline_write_ref_field_gc(p, obj);
}
--- a/src/hotspot/share/gc/serial/markSweep.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/markSweep.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,6 @@
#include "precompiled.hpp"
#include "compiler/compileBroker.hpp"
#include "gc/serial/markSweep.inline.hpp"
-#include "gc/serial/serial_specialized_oop_closures.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
#include "gc/shared/gcTimer.hpp"
#include "gc/shared/gcTrace.hpp"
@@ -63,48 +62,6 @@
CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure);
CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
-inline void MarkSweep::mark_object(oop obj) {
- // some marks may contain information we need to preserve so we store them away
- // and overwrite the mark. We'll restore it at the end of markSweep.
- markOop mark = obj->mark_raw();
- obj->set_mark_raw(markOopDesc::prototype()->set_marked());
-
- if (mark->must_be_preserved(obj)) {
- preserve_mark(obj, mark);
- }
-}
-
-template <class T> inline void MarkSweep::mark_and_push(T* p) {
- T heap_oop = RawAccess<>::oop_load(p);
- if (!CompressedOops::is_null(heap_oop)) {
- oop obj = CompressedOops::decode_not_null(heap_oop);
- if (!obj->mark_raw()->is_marked()) {
- mark_object(obj);
- _marking_stack.push(obj);
- }
- }
-}
-
-inline void MarkSweep::follow_klass(Klass* klass) {
- oop op = klass->klass_holder();
- MarkSweep::mark_and_push(&op);
-}
-
-inline void MarkSweep::follow_cld(ClassLoaderData* cld) {
- MarkSweep::follow_cld_closure.do_cld(cld);
-}
-
-template <typename T>
-inline void MarkAndPushClosure::do_oop_nv(T* p) { MarkSweep::mark_and_push(p); }
-void MarkAndPushClosure::do_oop(oop* p) { do_oop_nv(p); }
-void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-inline bool MarkAndPushClosure::do_metadata_nv() { return true; }
-bool MarkAndPushClosure::do_metadata() { return do_metadata_nv(); }
-inline void MarkAndPushClosure::do_klass_nv(Klass* k) { MarkSweep::follow_klass(k); }
-void MarkAndPushClosure::do_klass(Klass* k) { do_klass_nv(k); }
-inline void MarkAndPushClosure::do_cld_nv(ClassLoaderData* cld) { MarkSweep::follow_cld(cld); }
-void MarkAndPushClosure::do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
-
template <class T> inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) {
mark_and_push(p);
}
@@ -216,11 +173,6 @@
AdjustPointerClosure MarkSweep::adjust_pointer_closure;
-template <typename T>
-void AdjustPointerClosure::do_oop_nv(T* p) { MarkSweep::adjust_pointer(p); }
-void AdjustPointerClosure::do_oop(oop* p) { do_oop_nv(p); }
-void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-
void MarkSweep::adjust_marks() {
assert( _preserved_oop_stack.size() == _preserved_mark_stack.size(),
"inconsistent preserved oop stacks");
@@ -269,6 +221,3 @@
MarkSweep::_gc_timer = new (ResourceObj::C_HEAP, mtGC) STWGCTimer();
MarkSweep::_gc_tracer = new (ResourceObj::C_HEAP, mtGC) SerialOldTracer();
}
-
-// Generate MS specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/gc/serial/markSweep.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/markSweep.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -56,7 +56,7 @@
//
// Inline closure decls
//
- class FollowRootClosure: public OopsInGenClosure {
+ class FollowRootClosure: public BasicOopsInGenClosure {
public:
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
@@ -170,29 +170,24 @@
static void follow_array_chunk(objArrayOop array, int index);
};
-class MarkAndPushClosure: public ExtendedOopClosure {
+class MarkAndPushClosure: public OopIterateClosure {
public:
- template <typename T> void do_oop_nv(T* p);
+ template <typename T> void do_oop_work(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- virtual bool do_metadata();
- bool do_metadata_nv();
-
+ virtual bool do_metadata() { return true; }
virtual void do_klass(Klass* k);
- void do_klass_nv(Klass* k);
-
virtual void do_cld(ClassLoaderData* cld);
- void do_cld_nv(ClassLoaderData* cld);
void set_ref_discoverer(ReferenceDiscoverer* rd) {
set_ref_discoverer_internal(rd);
}
};
-class AdjustPointerClosure: public OopsInGenClosure {
+class AdjustPointerClosure: public BasicOopsInGenClosure {
public:
- template <typename T> void do_oop_nv(T* p);
+ template <typename T> void do_oop_work(T* p);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; }
--- a/src/hotspot/share/gc/serial/markSweep.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_SERIAL_MARKSWEEP_INLINE_HPP
#define SHARE_VM_GC_SERIAL_MARKSWEEP_INLINE_HPP
+#include "classfile/classLoaderData.inline.hpp"
#include "gc/serial/markSweep.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/universe.hpp"
@@ -33,10 +34,44 @@
#include "oops/compressedOops.inline.hpp"
#include "oops/oop.inline.hpp"
-inline int MarkSweep::adjust_pointers(oop obj) {
- return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure);
+inline void MarkSweep::mark_object(oop obj) {
+ // some marks may contain information we need to preserve so we store them away
+ // and overwrite the mark. We'll restore it at the end of markSweep.
+ markOop mark = obj->mark_raw();
+ obj->set_mark_raw(markOopDesc::prototype()->set_marked());
+
+ if (mark->must_be_preserved(obj)) {
+ preserve_mark(obj, mark);
+ }
}
+template <class T> inline void MarkSweep::mark_and_push(T* p) {
+ T heap_oop = RawAccess<>::oop_load(p);
+ if (!CompressedOops::is_null(heap_oop)) {
+ oop obj = CompressedOops::decode_not_null(heap_oop);
+ if (!obj->mark_raw()->is_marked()) {
+ mark_object(obj);
+ _marking_stack.push(obj);
+ }
+ }
+}
+
+inline void MarkSweep::follow_klass(Klass* klass) {
+ oop op = klass->klass_holder();
+ MarkSweep::mark_and_push(&op);
+}
+
+inline void MarkSweep::follow_cld(ClassLoaderData* cld) {
+ MarkSweep::follow_cld_closure.do_cld(cld);
+}
+
+template <typename T>
+inline void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); }
+inline void MarkAndPushClosure::do_oop(oop* p) { do_oop_work(p); }
+inline void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); }
+inline void MarkAndPushClosure::do_klass(Klass* k) { MarkSweep::follow_klass(k); }
+inline void MarkAndPushClosure::do_cld(ClassLoaderData* cld) { MarkSweep::follow_cld(cld); }
+
template <class T> inline void MarkSweep::adjust_pointer(T* p) {
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
@@ -54,9 +89,19 @@
if (new_obj != NULL) {
assert(Universe::heap()->is_in_reserved(new_obj),
"should be in object space");
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
}
}
+template <typename T>
+void AdjustPointerClosure::do_oop_work(T* p) { MarkSweep::adjust_pointer(p); }
+inline void AdjustPointerClosure::do_oop(oop* p) { do_oop_work(p); }
+inline void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_work(p); }
+
+
+inline int MarkSweep::adjust_pointers(oop obj) {
+ return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure);
+}
+
#endif // SHARE_VM_GC_SERIAL_MARKSWEEP_INLINE_HPP
--- a/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-#ifndef SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
-#define SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
-
-// The following OopClosure types get specialized versions of
-// "oop_oop_iterate" that invoke the closures' do_oop methods
-// non-virtually, using a mechanism defined in this file. Extend these
-// macros in the obvious way to add specializations for new closures.
-
-// Forward declarations.
-
-// DefNew
-class ScanClosure;
-class FastScanClosure;
-class FilteringClosure;
-
-// MarkSweep
-class MarkAndPushClosure;
-class AdjustPointerClosure;
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \
- f(ScanClosure,_nv) \
- f(FastScanClosure,_nv) \
- f(FilteringClosure,_nv)
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f) \
- f(MarkAndPushClosure,_nv) \
- f(AdjustPointerClosure,_nv)
-
-#endif // SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -40,7 +40,7 @@
LIR_Opr BarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
DecoratorSet decorators = access.decorators();
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
LIRItem& base = access.base().item();
@@ -48,7 +48,7 @@
LIRGenerator *gen = access.gen();
LIR_Opr addr_opr;
- if (on_array) {
+ if (is_array) {
addr_opr = LIR_OprFact::address(gen->emit_array_address(base.result(), offset, access.type()));
} else if (needs_patching) {
// we need to patch the offset in the instruction so don't allow
--- a/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,7 @@
void ModRefBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
DecoratorSet decorators = access.decorators();
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
if (access.is_oop()) {
@@ -45,7 +45,7 @@
BarrierSetC1::store_at_resolved(access, value);
if (access.is_oop()) {
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
LIR_Opr post_addr = precise ? access.resolved_addr() : access.base().opr();
post_barrier(access, post_addr, value);
}
@@ -87,9 +87,9 @@
DecoratorSet decorators = access.decorators();
bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
bool is_write = (decorators & C1_WRITE_ACCESS) != 0;
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
- bool precise = on_array || on_anonymous;
+ bool precise = is_array || on_anonymous;
resolve_in_register |= !needs_patching && is_write && access.is_oop() && precise;
return BarrierSetC1::resolve_address(access, resolve_in_register);
}
--- a/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/c2/modRefBarrierSetC2.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,10 +37,10 @@
const TypePtr* adr_type = access.addr().type();
Node* adr = access.addr().node();
- bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+ bool is_array = (decorators & IS_ARRAY) != 0;
bool anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
bool in_heap = (decorators & IN_HEAP) != 0;
- bool use_precise = on_array || anonymous;
+ bool use_precise = is_array || anonymous;
if (!access.is_oop() || (!in_heap && !anonymous)) {
return BarrierSetC2::store_at_resolved(access, val);
--- a/src/hotspot/share/gc/shared/cardTableRS.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/cardTableRS.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -29,6 +29,7 @@
#include "gc/shared/generation.hpp"
#include "gc/shared/space.inline.hpp"
#include "memory/allocation.inline.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1047,7 +1047,7 @@
oop_iterate(&no_header_cl);
}
-void GenCollectedHeap::oop_iterate(ExtendedOopClosure* cl) {
+void GenCollectedHeap::oop_iterate(OopIterateClosure* cl) {
_young_gen->oop_iterate(cl);
_old_gen->oop_iterate(cl);
}
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -259,7 +259,7 @@
// Iteration functions.
void oop_iterate_no_header(OopClosure* cl);
- void oop_iterate(ExtendedOopClosure* cl);
+ void oop_iterate(OopIterateClosure* cl);
void object_iterate(ObjectClosure* cl);
void safe_object_iterate(ObjectClosure* cl);
Space* space_containing(const void* addr) const;
--- a/src/hotspot/share/gc/shared/genOopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/* 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/shared/genOopClosures.inline.hpp"
-#include "memory/iterator.inline.hpp"
-#if INCLUDE_SERIALGC
-#include "gc/serial/serial_specialized_oop_closures.hpp"
-#endif
-
-void FilteringClosure::do_oop(oop* p) { do_oop_nv(p); }
-void FilteringClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
-
-#if INCLUDE_SERIALGC
-// Generate Serial GC specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
-#endif
--- a/src/hotspot/share/gc/shared/genOopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/genOopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -40,7 +40,7 @@
// method at the end of their own do_oop method!
// Note: no do_oop defined, this is an abstract class.
-class OopsInGenClosure : public ExtendedOopClosure {
+class OopsInGenClosure : public OopIterateClosure {
private:
Generation* _orig_gen; // generation originally set in ctor
Generation* _gen; // generation being scanned
@@ -62,7 +62,7 @@
template <class T> void par_do_barrier(T* p);
public:
- OopsInGenClosure() : ExtendedOopClosure(NULL),
+ OopsInGenClosure() : OopIterateClosure(NULL),
_orig_gen(NULL), _gen(NULL), _gen_boundary(NULL), _rs(NULL) {};
OopsInGenClosure(Generation* gen);
@@ -81,11 +81,21 @@
};
+class BasicOopsInGenClosure: public OopsInGenClosure {
+ public:
+ BasicOopsInGenClosure() : OopsInGenClosure() {}
+ BasicOopsInGenClosure(Generation* gen);
+
+ virtual bool do_metadata() { return false; }
+ virtual void do_klass(Klass* k) { ShouldNotReachHere(); }
+ virtual void do_cld(ClassLoaderData* cld) { ShouldNotReachHere(); }
+};
+
// Super class for scan closures. It contains code to dirty scanned class loader data.
-class OopsInClassLoaderDataOrGenClosure: public OopsInGenClosure {
+class OopsInClassLoaderDataOrGenClosure: public BasicOopsInGenClosure {
ClassLoaderData* _scanned_cld;
public:
- OopsInClassLoaderDataOrGenClosure(Generation* g) : OopsInGenClosure(g), _scanned_cld(NULL) {}
+ OopsInClassLoaderDataOrGenClosure(Generation* g) : BasicOopsInGenClosure(g), _scanned_cld(NULL) {}
void set_scanned_cld(ClassLoaderData* cld) {
assert(cld == NULL || _scanned_cld == NULL, "Must be");
_scanned_cld = cld;
@@ -110,8 +120,6 @@
ScanClosure(DefNewGeneration* g, bool gc_barrier);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
// Closure for scanning DefNewGeneration.
@@ -129,8 +137,6 @@
FastScanClosure(DefNewGeneration* g, bool gc_barrier);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
#endif // INCLUDE_SERIALGC
@@ -146,22 +152,21 @@
void do_cld(ClassLoaderData* cld);
};
-class FilteringClosure: public ExtendedOopClosure {
+class FilteringClosure: public OopIterateClosure {
private:
HeapWord* _boundary;
- ExtendedOopClosure* _cl;
+ OopIterateClosure* _cl;
protected:
template <class T> inline void do_oop_work(T* p);
public:
- FilteringClosure(HeapWord* boundary, ExtendedOopClosure* cl) :
- ExtendedOopClosure(cl->ref_discoverer()), _boundary(boundary),
+ FilteringClosure(HeapWord* boundary, OopIterateClosure* cl) :
+ OopIterateClosure(cl->ref_discoverer()), _boundary(boundary),
_cl(cl) {}
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
- virtual bool do_metadata() { return do_metadata_nv(); }
- inline bool do_metadata_nv() { assert(!_cl->do_metadata(), "assumption broken, must change to 'return _cl->do_metadata()'"); return false; }
+ virtual bool do_metadata() { assert(!_cl->do_metadata(), "assumption broken, must change to 'return _cl->do_metadata()'"); return false; }
+ virtual void do_klass(Klass*) { ShouldNotReachHere(); }
+ virtual void do_cld(ClassLoaderData*) { ShouldNotReachHere(); }
};
#if INCLUDE_SERIALGC
@@ -179,8 +184,6 @@
ScanWeakRefClosure(DefNewGeneration* g);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
- inline void do_oop_nv(oop* p);
- inline void do_oop_nv(narrowOop* p);
};
#endif // INCLUDE_SERIALGC
--- a/src/hotspot/share/gc/shared/genOopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/genOopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -38,7 +38,7 @@
#endif
inline OopsInGenClosure::OopsInGenClosure(Generation* gen) :
- ExtendedOopClosure(gen->ref_processor()), _orig_gen(gen), _rs(NULL) {
+ OopIterateClosure(gen->ref_processor()), _orig_gen(gen), _rs(NULL) {
set_generation(gen);
}
@@ -73,6 +73,9 @@
}
}
+inline BasicOopsInGenClosure::BasicOopsInGenClosure(Generation* gen) : OopsInGenClosure(gen) {
+}
+
inline void OopsInClassLoaderDataOrGenClosure::do_cld_barrier() {
assert(_scanned_cld != NULL, "Must be");
if (!_scanned_cld->has_modified_oops()) {
@@ -93,7 +96,7 @@
assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?");
oop new_obj = obj->is_forwarded() ? obj->forwardee()
: _g->copy_to_survivor_space(obj);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
if (is_scanning_a_cld()) {
@@ -105,8 +108,8 @@
}
}
-inline void ScanClosure::do_oop_nv(oop* p) { ScanClosure::do_oop_work(p); }
-inline void ScanClosure::do_oop_nv(narrowOop* p) { ScanClosure::do_oop_work(p); }
+inline void ScanClosure::do_oop(oop* p) { ScanClosure::do_oop_work(p); }
+inline void ScanClosure::do_oop(narrowOop* p) { ScanClosure::do_oop_work(p); }
// NOTE! Any changes made here should also be made
// in ScanClosure::do_oop_work()
@@ -119,7 +122,7 @@
assert(!_g->to()->is_in_reserved(obj), "Scanning field twice?");
oop new_obj = obj->is_forwarded() ? obj->forwardee()
: _g->copy_to_survivor_space(obj);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
if (is_scanning_a_cld()) {
do_cld_barrier();
} else if (_gc_barrier) {
@@ -130,8 +133,8 @@
}
}
-inline void FastScanClosure::do_oop_nv(oop* p) { FastScanClosure::do_oop_work(p); }
-inline void FastScanClosure::do_oop_nv(narrowOop* p) { FastScanClosure::do_oop_work(p); }
+inline void FastScanClosure::do_oop(oop* p) { FastScanClosure::do_oop_work(p); }
+inline void FastScanClosure::do_oop(narrowOop* p) { FastScanClosure::do_oop_work(p); }
#endif // INCLUDE_SERIALGC
@@ -145,26 +148,26 @@
}
}
-void FilteringClosure::do_oop_nv(oop* p) { FilteringClosure::do_oop_work(p); }
-void FilteringClosure::do_oop_nv(narrowOop* p) { FilteringClosure::do_oop_work(p); }
+inline void FilteringClosure::do_oop(oop* p) { FilteringClosure::do_oop_work(p); }
+inline void FilteringClosure::do_oop(narrowOop* p) { FilteringClosure::do_oop_work(p); }
#if INCLUDE_SERIALGC
// Note similarity to ScanClosure; the difference is that
// the barrier set is taken care of outside this closure.
template <class T> inline void ScanWeakRefClosure::do_oop_work(T* p) {
- oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
+ oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
// weak references are sometimes scanned twice; must check
// that to-space doesn't already contain this object
if ((HeapWord*)obj < _boundary && !_g->to()->is_in_reserved(obj)) {
oop new_obj = obj->is_forwarded() ? obj->forwardee()
: _g->copy_to_survivor_space(obj);
- RawAccess<OOP_NOT_NULL>::oop_store(p, new_obj);
+ RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
}
}
-inline void ScanWeakRefClosure::do_oop_nv(oop* p) { ScanWeakRefClosure::do_oop_work(p); }
-inline void ScanWeakRefClosure::do_oop_nv(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
+inline void ScanWeakRefClosure::do_oop(oop* p) { ScanWeakRefClosure::do_oop_work(p); }
+inline void ScanWeakRefClosure::do_oop(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
#endif // INCLUDE_SERIALGC
--- a/src/hotspot/share/gc/shared/generation.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/generation.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -253,15 +253,15 @@
class GenerationOopIterateClosure : public SpaceClosure {
public:
- ExtendedOopClosure* _cl;
+ OopIterateClosure* _cl;
virtual void do_space(Space* s) {
s->oop_iterate(_cl);
}
- GenerationOopIterateClosure(ExtendedOopClosure* cl) :
+ GenerationOopIterateClosure(OopIterateClosure* cl) :
_cl(cl) {}
};
-void Generation::oop_iterate(ExtendedOopClosure* cl) {
+void Generation::oop_iterate(OopIterateClosure* cl) {
GenerationOopIterateClosure blk(cl);
space_iterate(&blk);
}
--- a/src/hotspot/share/gc/shared/generation.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/generation.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -474,7 +474,7 @@
// Iterate over all the ref-containing fields of all objects in the
// generation, calling "cl.do_oop" on each.
- virtual void oop_iterate(ExtendedOopClosure* cl);
+ virtual void oop_iterate(OopIterateClosure* cl);
// Iterate over all objects in the generation, calling "cl.do_object" on
// each.
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -102,7 +102,7 @@
if (!HasDecorator<decorators, ARRAYCOPY_CHECKCAST>::value) {
// Optimized covariant case
bs->write_ref_array_pre(dst_raw, length,
- HasDecorator<decorators, AS_DEST_NOT_INITIALIZED>::value);
+ HasDecorator<decorators, IS_DEST_UNINITIALIZED>::value);
Raw::oop_arraycopy(NULL, 0, src_raw, NULL, 0, dst_raw, length);
bs->write_ref_array((HeapWord*)dst_raw, length);
} else {
--- a/src/hotspot/share/gc/shared/space.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/space.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,6 +32,7 @@
#include "gc/shared/space.hpp"
#include "gc/shared/space.inline.hpp"
#include "gc/shared/spaceDecorator.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
@@ -181,7 +182,7 @@
}
}
-DirtyCardToOopClosure* Space::new_dcto_cl(ExtendedOopClosure* cl,
+DirtyCardToOopClosure* Space::new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel) {
@@ -257,11 +258,11 @@
// (There are only two of these, rather than N, because the split is due
// only to the introduction of the FilteringClosure, a local part of the
// impl of this abstraction.)
-ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(ExtendedOopClosure)
+ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(OopIterateClosure)
ContiguousSpaceDCTOC__walk_mem_region_with_cl_DEFN(FilteringClosure)
DirtyCardToOopClosure*
-ContiguousSpace::new_dcto_cl(ExtendedOopClosure* cl,
+ContiguousSpace::new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel) {
@@ -480,7 +481,7 @@
}
}
-void Space::oop_iterate(ExtendedOopClosure* blk) {
+void Space::oop_iterate(OopIterateClosure* blk) {
ObjectToOopClosure blk2(blk);
object_iterate(&blk2);
}
@@ -490,7 +491,7 @@
return true;
}
-void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) {
+void ContiguousSpace::oop_iterate(OopIterateClosure* blk) {
if (is_empty()) return;
HeapWord* obj_addr = bottom();
HeapWord* t = top();
--- a/src/hotspot/share/gc/shared/space.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/shared/space.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -169,7 +169,7 @@
// Iterate over all the ref-containing fields of all objects in the
// space, calling "cl.do_oop" on each. Fields in objects allocated by
// applications of the closure are not included in the iteration.
- virtual void oop_iterate(ExtendedOopClosure* cl);
+ virtual void oop_iterate(OopIterateClosure* cl);
// Iterate over all objects in the space, calling "cl.do_object" on
// each. Objects allocated by applications of the closure are not
@@ -183,7 +183,7 @@
// overridden to return the appropriate type of closure
// depending on the type of space in which the closure will
// operate. ResourceArea allocated.
- virtual DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
+ virtual DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel);
@@ -256,7 +256,7 @@
class DirtyCardToOopClosure: public MemRegionClosureRO {
protected:
- ExtendedOopClosure* _cl;
+ OopIterateClosure* _cl;
Space* _sp;
CardTable::PrecisionStyle _precision;
HeapWord* _boundary; // If non-NULL, process only non-NULL oops
@@ -286,7 +286,7 @@
virtual void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top);
public:
- DirtyCardToOopClosure(Space* sp, ExtendedOopClosure* cl,
+ DirtyCardToOopClosure(Space* sp, OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary) :
_sp(sp), _cl(cl), _precision(precision), _boundary(boundary),
@@ -582,7 +582,7 @@
HeapWord* allocate_aligned(size_t word_size);
// Iteration
- void oop_iterate(ExtendedOopClosure* cl);
+ void oop_iterate(OopIterateClosure* cl);
void object_iterate(ObjectClosure* blk);
// For contiguous spaces this method will iterate safely over objects
// in the space (i.e., between bottom and top) when at a safepoint.
@@ -621,7 +621,7 @@
}
// Override.
- DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
+ DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary,
bool parallel);
@@ -689,13 +689,13 @@
// apparent.
virtual void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
- ExtendedOopClosure* cl) = 0;
+ OopIterateClosure* cl) = 0;
virtual void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
FilteringClosure* cl) = 0;
public:
- FilteringDCTOC(Space* sp, ExtendedOopClosure* cl,
+ FilteringDCTOC(Space* sp, OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary) :
DirtyCardToOopClosure(sp, cl, precision, boundary) {}
@@ -718,13 +718,13 @@
virtual void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
- ExtendedOopClosure* cl);
+ OopIterateClosure* cl);
virtual void walk_mem_region_with_cl(MemRegion mr,
HeapWord* bottom, HeapWord* top,
FilteringClosure* cl);
public:
- ContiguousSpaceDCTOC(ContiguousSpace* sp, ExtendedOopClosure* cl,
+ ContiguousSpaceDCTOC(ContiguousSpace* sp, OopIterateClosure* cl,
CardTable::PrecisionStyle precision,
HeapWord* boundary) :
FilteringDCTOC(sp, cl, precision, boundary)
--- a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- */
-
-#ifndef SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
-#define SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
-
-#include "utilities/macros.hpp"
-#if INCLUDE_CMSGC
-#include "gc/cms/cms_specialized_oop_closures.hpp"
-#endif
-#if INCLUDE_G1GC
-#include "gc/g1/g1_specialized_oop_closures.hpp"
-#endif
-#if INCLUDE_SERIALGC
-#include "gc/serial/serial_specialized_oop_closures.hpp"
-#endif
-#if INCLUDE_ZGC
-#include "gc/z/z_specialized_oop_closures.hpp"
-#endif
-
-// The following OopClosure types get specialized versions of
-// "oop_oop_iterate" that invoke the closures' do_oop methods
-// non-virtually, using a mechanism defined in this file. Extend these
-// macros in the obvious way to add specializations for new closures.
-
-// Forward declarations.
-class ExtendedOopClosure;
-class NoHeaderExtendedOopClosure;
-class OopsInGenClosure;
-
-// This macro applies an argument macro to all OopClosures for which we
-// want specialized bodies of "oop_oop_iterate". The arguments to "f" are:
-// "f(closureType, non_virtual)"
-// where "closureType" is the name of the particular subclass of ExtendedOopClosure,
-// and "non_virtual" will be the string "_nv" if the closure type should
-// have its "do_oop" method invoked non-virtually, or else the
-// string "_v". ("ExtendedOopClosure" itself will be the only class in the latter
-// category.)
-
-// This is split into several because of a Visual C++ 6.0 compiler bug
-// where very long macros cause the compiler to crash
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) \
- f(NoHeaderExtendedOopClosure,_nv) \
- SERIALGC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)) \
- CMSGC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f))
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \
- SERIALGC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)) \
- CMSGC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f)) \
- G1GC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f)) \
- G1GC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f)) \
- ZGC_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_Z(f))
-
-// We separate these out, because sometime the general one has
-// a different definition from the specialized ones, and sometimes it
-// doesn't.
-
-#define ALL_OOP_OOP_ITERATE_CLOSURES_1(f) \
- f(ExtendedOopClosure,_v) \
- SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f)
-
-#define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \
- SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)
-
-#endif // SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/z/zBarrier.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zBarrier.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,6 +26,7 @@
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zOop.inline.hpp"
#include "gc/z/zOopClosures.inline.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/debug.hpp"
--- a/src/hotspot/share/gc/z/zHeapIterator.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zHeapIterator.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -28,6 +28,7 @@
#include "gc/z/zHeapIterator.hpp"
#include "gc/z/zOop.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/stack.inline.hpp"
@@ -73,7 +74,7 @@
}
};
-class ZHeapIteratorPushOopClosure : public ExtendedOopClosure {
+class ZHeapIteratorPushOopClosure : public BasicOopIterateClosure {
private:
ZHeapIterator* const _iter;
const oop _base;
@@ -83,23 +84,15 @@
_iter(iter),
_base(base) {}
- void do_oop_nv(oop* p) {
+ virtual void do_oop(oop* p) {
const oop obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(_base, _base->field_offset(p));
_iter->push(obj);
}
- void do_oop_nv(narrowOop* p) {
+ virtual void do_oop(narrowOop* p) {
ShouldNotReachHere();
}
- virtual void do_oop(oop* p) {
- do_oop_nv(p);
- }
-
- virtual void do_oop(narrowOop* p) {
- do_oop_nv(p);
- }
-
#ifdef ASSERT
virtual bool should_verify_oops() {
return false;
--- a/src/hotspot/share/gc/z/zMark.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zMark.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,6 +37,7 @@
#include "gc/z/zUtils.inline.hpp"
#include "gc/z/zWorkers.inline.hpp"
#include "logging/log.hpp"
+#include "memory/iterator.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
--- a/src/hotspot/share/gc/z/zOopClosures.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zOopClosures.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -69,6 +69,3 @@
ZVerifyHeapOopClosure cl(o);
o->oop_iterate(&cl);
}
-
-// Generate Z specialized oop_oop_iterate functions.
-SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_Z(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/gc/z/zOopClosures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zOopClosures.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,11 +26,8 @@
#include "memory/iterator.hpp"
-class ZLoadBarrierOopClosure : public ExtendedOopClosure {
+class ZLoadBarrierOopClosure : public BasicOopIterateClosure {
public:
- void do_oop_nv(oop* p);
- void do_oop_nv(narrowOop* p);
-
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
@@ -54,13 +51,10 @@
};
template <bool finalizable>
-class ZMarkBarrierOopClosure : public ExtendedOopClosure {
+class ZMarkBarrierOopClosure : public BasicOopIterateClosure {
public:
ZMarkBarrierOopClosure();
- void do_oop_nv(oop* p);
- void do_oop_nv(narrowOop* p);
-
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
@@ -88,7 +82,7 @@
virtual void do_oop(narrowOop* p);
};
-class ZVerifyHeapOopClosure : public ExtendedOopClosure {
+class ZVerifyHeapOopClosure : public BasicOopIterateClosure {
private:
const oop _base;
--- a/src/hotspot/share/gc/z/zOopClosures.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zOopClosures.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -32,22 +32,14 @@
#include "runtime/atomic.hpp"
#include "utilities/debug.hpp"
-inline void ZLoadBarrierOopClosure::do_oop_nv(oop* p) {
+inline void ZLoadBarrierOopClosure::do_oop(oop* p) {
ZBarrier::load_barrier_on_oop_field(p);
}
-inline void ZLoadBarrierOopClosure::do_oop_nv(narrowOop* p) {
+inline void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {
ShouldNotReachHere();
}
-inline void ZLoadBarrierOopClosure::do_oop(oop* p) {
- do_oop_nv(p);
-}
-
-inline void ZLoadBarrierOopClosure::do_oop(narrowOop* p) {
- do_oop_nv(p);
-}
-
inline void ZMarkRootOopClosure::do_oop(oop* p) {
ZBarrier::mark_barrier_on_root_oop_field(p);
}
@@ -66,28 +58,18 @@
template <bool finalizable>
inline ZMarkBarrierOopClosure<finalizable>::ZMarkBarrierOopClosure() :
- ExtendedOopClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
+ BasicOopIterateClosure(finalizable ? NULL : ZHeap::heap()->reference_discoverer()) {}
template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_oop_nv(oop* p) {
+inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) {
ZBarrier::mark_barrier_on_oop_field(p, finalizable);
}
template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_oop_nv(narrowOop* p) {
+inline void ZMarkBarrierOopClosure<finalizable>::do_oop(narrowOop* p) {
ShouldNotReachHere();
}
-template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_oop(oop* p) {
- do_oop_nv(p);
-}
-
-template <bool finalizable>
-inline void ZMarkBarrierOopClosure<finalizable>::do_oop(narrowOop* p) {
- do_oop_nv(p);
-}
-
inline bool ZPhantomIsAliveObjectClosure::do_object_b(oop o) {
return ZBarrier::is_alive_barrier_on_phantom_oop(o);
}
--- a/src/hotspot/share/gc/z/zTracer.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/gc/z/zTracer.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -28,6 +28,44 @@
#include "gc/shared/gcLocker.hpp"
#include "jfr/jfrEvents.hpp"
#include "runtime/safepointVerifiers.hpp"
+#if INCLUDE_JFR
+#include "jfr/metadata/jfrSerializer.hpp"
+#endif
+
+#if INCLUDE_JFR
+class ZStatisticsCounterTypeConstant : public JfrSerializer {
+public:
+ virtual void serialize(JfrCheckpointWriter& writer) {
+ writer.write_count(ZStatCounter::count());
+ for (ZStatCounter* counter = ZStatCounter::first(); counter != NULL; counter = counter->next()) {
+ writer.write_key(counter->id());
+ writer.write(counter->name());
+ }
+ }
+};
+
+class ZStatisticsSamplerTypeConstant : public JfrSerializer {
+public:
+ virtual void serialize(JfrCheckpointWriter& writer) {
+ writer.write_count(ZStatSampler::count());
+ for (ZStatSampler* sampler = ZStatSampler::first(); sampler != NULL; sampler = sampler->next()) {
+ writer.write_key(sampler->id());
+ writer.write(sampler->name());
+ }
+ }
+};
+
+static void register_jfr_type_serializers() {
+ JfrSerializer::register_serializer(TYPE_ZSTATISTICSCOUNTERTYPE,
+ false /* require_safepoint */,
+ true /* permit_cache */,
+ new ZStatisticsCounterTypeConstant());
+ JfrSerializer::register_serializer(TYPE_ZSTATISTICSSAMPLERTYPE,
+ false /* require_safepoint */,
+ true /* permit_cache */,
+ new ZStatisticsSamplerTypeConstant());
+}
+#endif
ZTracer* ZTracer::_tracer = NULL;
@@ -35,7 +73,9 @@
GCTracer(Z) {}
void ZTracer::initialize() {
+ assert(_tracer == NULL, "Already initialized");
_tracer = new (ResourceObj::C_HEAP, mtGC) ZTracer();
+ JFR_ONLY(register_jfr_type_serializers());
}
void ZTracer::send_stat_counter(uint32_t counter_id, uint64_t increment, uint64_t value) {
--- a/src/hotspot/share/gc/z/z_specialized_oop_closures.hpp Mon Jun 25 08:14:11 2018 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-#ifndef SHARE_GC_Z_Z_SPECIALIZED_OOP_CLOSURES_HPP
-#define SHARE_GC_Z_Z_SPECIALIZED_OOP_CLOSURES_HPP
-
-class ZLoadBarrierOopClosure;
-template <bool> class ZMarkBarrierOopClosure;
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_Z(f) \
- f(ZLoadBarrierOopClosure,_nv) \
- f(ZMarkBarrierOopClosure<true>,_nv) \
- f(ZMarkBarrierOopClosure<false>,_nv)
-
-#endif // SHARE_GC_Z_Z_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/include/jvm.h Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/include/jvm.h Mon Jun 25 09:48:06 2018 -0700
@@ -522,6 +522,17 @@
JNIEXPORT jint JNICALL
JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
+/* Nestmates - since JDK 11 */
+
+JNIEXPORT jboolean JNICALL
+JVM_AreNestMates(JNIEnv *env, jclass current, jclass member);
+
+JNIEXPORT jclass JNICALL
+JVM_GetNestHost(JNIEnv *env, jclass current);
+
+JNIEXPORT jobjectArray JNICALL
+JVM_GetNestMembers(JNIEnv *env, jclass current);
+
/* The following two reflection routines are still needed due to startup time issues */
/*
* java.lang.reflect.Method
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -2524,11 +2524,9 @@
istate->set_msg(call_method);
// Special case of invokeinterface called for virtual method of
- // java.lang.Object. See cpCacheOop.cpp for details.
- // This code isn't produced by javac, but could be produced by
- // another compliant java compiler.
+ // java.lang.Object. See cpCache.cpp for details.
+ Method* callee = NULL;
if (cache->is_forced_virtual()) {
- Method* callee;
CHECK_NULL(STACK_OBJECT(-(cache->parameter_size())));
if (cache->is_vfinal()) {
callee = cache->f2_as_vfinal_method();
@@ -2545,6 +2543,29 @@
// Profile 'special case of invokeinterface' virtual call.
BI_PROFILE_UPDATE_VIRTUALCALL(rcvrKlass);
}
+ } else if (cache->is_vfinal()) {
+ // private interface method invocations
+ //
+ // Ensure receiver class actually implements
+ // the resolved interface class. The link resolver
+ // does this, but only for the first time this
+ // interface is being called.
+ int parms = cache->parameter_size();
+ oop rcvr = STACK_OBJECT(-parms);
+ CHECK_NULL(rcvr);
+ Klass* recv_klass = rcvr->klass();
+ Klass* resolved_klass = cache->f1_as_klass();
+ if (!recv_klass->is_subtype_of(resolved_klass)) {
+ ResourceMark rm(THREAD);
+ char buf[200];
+ jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s",
+ recv_klass->external_name(),
+ resolved_klass->external_name());
+ VM_JAVA_ERROR(vmSymbols::java_lang_IncompatibleClassChangeError(), buf, note_no_trap);
+ }
+ callee = cache->f2_as_vfinal_method();
+ }
+ if (callee != NULL) {
istate->set_callee(callee);
istate->set_callee_entry_point(callee->from_interpreted_entry());
#ifdef VM_JVMTI
@@ -2557,7 +2578,6 @@
}
// this could definitely be cleaned up QQQ
- Method* callee;
Method *interface_method = cache->f2_as_interface_method();
InstanceKlass* iclass = interface_method->method_holder();
--- a/src/hotspot/share/interpreter/linkResolver.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/interpreter/linkResolver.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -387,12 +387,13 @@
// Looks up method in classes, then looks up local default methods
methodHandle LinkResolver::lookup_instance_method_in_klasses(Klass* klass,
Symbol* name,
- Symbol* signature, TRAPS) {
- Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
+ Symbol* signature,
+ Klass::PrivateLookupMode private_mode, TRAPS) {
+ Method* result = klass->uncached_lookup_method(name, signature, Klass::find_overpass, private_mode);
while (result != NULL && result->is_static() && result->method_holder()->super() != NULL) {
Klass* super_klass = result->method_holder()->super();
- result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass);
+ result = super_klass->uncached_lookup_method(name, signature, Klass::find_overpass, private_mode);
}
if (klass->is_array_klass()) {
@@ -582,20 +583,27 @@
}
// assert(extra_arg_result_or_null != NULL, "must be able to return extra argument");
- if (!Reflection::verify_field_access(ref_klass,
- resolved_klass,
- sel_klass,
- flags,
- true)) {
+ bool can_access = Reflection::verify_member_access(ref_klass,
+ resolved_klass,
+ sel_klass,
+ flags,
+ true, false, CHECK);
+ // Any existing exceptions that may have been thrown, for example LinkageErrors
+ // from nest-host resolution, have been allowed to propagate.
+ if (!can_access) {
ResourceMark rm(THREAD);
+ bool same_module = (sel_klass->module() == ref_klass->module());
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IllegalAccessError(),
- "tried to access method %s.%s%s from class %s",
+ "class %s tried to access method %s.%s%s (%s%s%s)",
+ ref_klass->external_name(),
sel_klass->external_name(),
sel_method->name()->as_C_string(),
sel_method->signature()->as_C_string(),
- ref_klass->external_name()
+ (same_module) ? ref_klass->joint_in_module_of_loader(sel_klass) : ref_klass->class_in_module_of_loader(),
+ (same_module) ? "" : "; ",
+ (same_module) ? "" : sel_klass->class_in_module_of_loader()
);
return;
}
@@ -757,7 +765,7 @@
nested_exception, NULL);
}
- // 5. access checks, access checking may be turned off when calling from within the VM.
+ // 6. access checks, access checking may be turned off when calling from within the VM.
Klass* current_klass = link_info.current_klass();
if (link_info.check_access()) {
assert(current_klass != NULL , "current_klass should not be null");
@@ -773,6 +781,24 @@
check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL);
}
+ // For private method invocation we should only find the method in the resolved class.
+ // If that is not the case then we have a found a supertype method that we have nestmate
+ // access to.
+ if (resolved_method->is_private() && resolved_method->method_holder() != resolved_klass) {
+ ResourceMark rm(THREAD);
+ DEBUG_ONLY(bool is_nestmate = InstanceKlass::cast(link_info.current_klass())->has_nestmate_access_to(InstanceKlass::cast(resolved_klass), THREAD);)
+ assert(is_nestmate, "was only expecting nestmates to get here!");
+ Exceptions::fthrow(
+ THREAD_AND_LOCATION,
+ vmSymbols::java_lang_NoSuchMethodError(),
+ "%s: method %s%s not found",
+ resolved_klass->external_name(),
+ resolved_method->name()->as_C_string(),
+ resolved_method->signature()->as_C_string()
+ );
+ return NULL;
+ }
+
return resolved_method;
}
@@ -874,19 +900,6 @@
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
- if (code == Bytecodes::_invokeinterface && resolved_method->is_private()) {
- ResourceMark rm(THREAD);
- char buf[200];
-
- Klass* current_klass = link_info.current_klass();
- jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s, caller-class:%s",
- Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()),
- (current_klass == NULL ? "<NULL>" : current_klass->internal_name()));
- THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
- }
-
if (log_develop_is_enabled(Trace, itables)) {
char buf[200];
jio_snprintf(buf, sizeof(buf), "%s resolved interface method: caller-class:",
@@ -906,11 +919,14 @@
Klass* sel_klass,
const fieldDescriptor& fd,
TRAPS) {
- if (!Reflection::verify_field_access(ref_klass,
- resolved_klass,
- sel_klass,
- fd.access_flags(),
- true)) {
+ bool can_access = Reflection::verify_member_access(ref_klass,
+ resolved_klass,
+ sel_klass,
+ fd.access_flags(),
+ true, false, CHECK);
+ // Any existing exceptions that may have been thrown, for example LinkageErrors
+ // from nest-host resolution, have been allowed to propagate.
+ if (!can_access) {
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
@@ -1128,7 +1144,8 @@
return NULL;
}
- // check if invokespecial's interface method reference is in an indirect superinterface
+ // ensure that invokespecial's interface method reference is in
+ // a direct superinterface, not an indirect superinterface
Klass* current_klass = link_info.current_klass();
if (current_klass != NULL && resolved_klass->is_interface()) {
InstanceKlass* ck = InstanceKlass::cast(current_klass);
@@ -1146,8 +1163,8 @@
jio_snprintf(buf, sizeof(buf),
"Interface method reference: %s, is in an indirect superinterface of %s",
Method::name_and_sig_as_C_string(resolved_klass,
- resolved_method->name(),
- resolved_method->signature()),
+ resolved_method->name(),
+ resolved_method->signature()),
current_klass->external_name());
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
@@ -1192,7 +1209,7 @@
resolved_method->name() != vmSymbols::object_initializer_name()) {
// check if this is an old-style super call and do a new lookup if so
- // a) check if ACC_SUPER flag is set for the current class
+ // a) check if ACC_SUPER flag is set for the current class
Klass* current_klass = link_info.current_klass();
if ((current_klass->is_super() || !AllowNonVirtualCalls) &&
// b) check if the class of the resolved_klass is a superclass
@@ -1200,12 +1217,14 @@
// This check is not performed for super.invoke for interface methods
// in super interfaces.
current_klass->is_subclass_of(resolved_klass) &&
- current_klass != resolved_klass) {
+ current_klass != resolved_klass
+ ) {
// Lookup super method
Klass* super_klass = current_klass->super();
sel_method = lookup_instance_method_in_klasses(super_klass,
- resolved_method->name(),
- resolved_method->signature(), CHECK);
+ resolved_method->name(),
+ resolved_method->signature(),
+ Klass::find_private, CHECK);
// check if found
if (sel_method.is_null()) {
ResourceMark rm(THREAD);
@@ -1356,11 +1375,12 @@
// a default or miranda method; therefore, it must have a valid vtable index.
assert(!resolved_method->has_itable_index(), "");
vtable_index = resolved_method->vtable_index();
- // We could get a negative vtable_index for final methods,
- // because as an optimization they are never put in the vtable,
- // unless they override an existing method.
- // If we do get a negative, it means the resolved method is the the selected
- // method, and it can never be changed by an override.
+ // We could get a negative vtable_index of nonvirtual_vtable_index for private
+ // methods, or for final methods. Private methods never appear in the vtable
+ // and never override other methods. As an optimization, final methods are
+ // never put in the vtable, unless they override an existing method.
+ // So if we do get nonvirtual_vtable_index, it means the selected method is the
+ // resolved method, and it can never be changed by an override.
if (vtable_index == Method::nonvirtual_vtable_index) {
assert(resolved_method->can_be_statically_bound(), "cannot override this method");
selected_method = resolved_method;
@@ -1415,6 +1435,7 @@
Handle recv,
Klass* recv_klass,
bool check_null_and_abstract, TRAPS) {
+
// check if receiver exists
if (check_null_and_abstract && recv.is_null()) {
THROW(vmSymbols::java_lang_NullPointerException());
@@ -1430,35 +1451,43 @@
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
- // do lookup based on receiver klass
- // This search must match the linktime preparation search for itable initialization
- // to correctly enforce loader constraints for interface method inheritance
- methodHandle selected_method = lookup_instance_method_in_klasses(recv_klass,
- resolved_method->name(),
- resolved_method->signature(), CHECK);
- if (selected_method.is_null() && !check_null_and_abstract) {
- // In theory this is a harmless placeholder value, but
- // in practice leaving in null affects the nsk default method tests.
- // This needs further study.
- selected_method = resolved_method;
- }
- // check if method exists
- if (selected_method.is_null()) {
- // Pass arguments for generating a verbose error message.
- throw_abstract_method_error(resolved_method, recv_klass, CHECK);
- }
- // check access
- // Throw Illegal Access Error if selected_method is not public.
- if (!selected_method->is_public()) {
- ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
- Method::name_and_sig_as_C_string(recv_klass,
- selected_method->name(),
- selected_method->signature()));
- }
- // check if abstract
- if (check_null_and_abstract && selected_method->is_abstract()) {
- throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);
+ methodHandle selected_method = resolved_method;
+
+ // resolve the method in the receiver class, unless it is private
+ if (!resolved_method()->is_private()) {
+ // do lookup based on receiver klass
+ // This search must match the linktime preparation search for itable initialization
+ // to correctly enforce loader constraints for interface method inheritance.
+ // Private methods are skipped as the resolved method was not private.
+ selected_method = lookup_instance_method_in_klasses(recv_klass,
+ resolved_method->name(),
+ resolved_method->signature(),
+ Klass::skip_private, CHECK);
+
+ if (selected_method.is_null() && !check_null_and_abstract) {
+ // In theory this is a harmless placeholder value, but
+ // in practice leaving in null affects the nsk default method tests.
+ // This needs further study.
+ selected_method = resolved_method;
+ }
+ // check if method exists
+ if (selected_method.is_null()) {
+ // Pass arguments for generating a verbose error message.
+ throw_abstract_method_error(resolved_method, recv_klass, CHECK);
+ }
+ // check access
+ // Throw Illegal Access Error if selected_method is not public.
+ if (!selected_method->is_public()) {
+ ResourceMark rm(THREAD);
+ THROW_MSG(vmSymbols::java_lang_IllegalAccessError(),
+ Method::name_and_sig_as_C_string(recv_klass,
+ selected_method->name(),
+ selected_method->signature()));
+ }
+ // check if abstract
+ if (check_null_and_abstract && selected_method->is_abstract()) {
+ throw_abstract_method_error(resolved_method, selected_method, recv_klass, CHECK);
+ }
}
if (log_develop_is_enabled(Trace, itables)) {
@@ -1466,13 +1495,25 @@
recv_klass, resolved_klass, selected_method, true);
}
// setup result
- if (!resolved_method->has_itable_index()) {
+ if (resolved_method->has_vtable_index()) {
int vtable_index = resolved_method->vtable_index();
+ log_develop_trace(itables)(" -- vtable index: %d", vtable_index);
assert(vtable_index == selected_method->vtable_index(), "sanity check");
result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK);
- } else {
+ } else if (resolved_method->has_itable_index()) {
int itable_index = resolved_method()->itable_index();
+ log_develop_trace(itables)(" -- itable index: %d", itable_index);
result.set_interface(resolved_klass, recv_klass, resolved_method, selected_method, itable_index, CHECK);
+ } else {
+ int index = resolved_method->vtable_index();
+ log_develop_trace(itables)(" -- non itable/vtable index: %d", index);
+ assert(index == Method::nonvirtual_vtable_index, "Oops hit another case!");
+ assert(resolved_method()->is_private() ||
+ (resolved_method()->is_final() && resolved_method->method_holder() == SystemDictionary::Object_klass()),
+ "Should only have non-virtual invokeinterface for private or final-Object methods!");
+ assert(resolved_method()->can_be_statically_bound(), "Should only have non-virtual invokeinterface for statically bound methods!");
+ // This sets up the nonvirtual form of "virtual" call (as needed for final and private methods)
+ result.set_virtual(resolved_klass, resolved_klass, resolved_method, resolved_method, index, CHECK);
}
}
--- a/src/hotspot/share/interpreter/linkResolver.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/interpreter/linkResolver.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -211,8 +211,8 @@
Handle *method_type_result, TRAPS);
JVMCI_ONLY(public:) // Needed for CompilerToVM.resolveMethod()
// Not Linktime so doesn't take LinkInfo
- static methodHandle lookup_instance_method_in_klasses (
- Klass* klass, Symbol* name, Symbol* signature, TRAPS);
+ static methodHandle lookup_instance_method_in_klasses (Klass* klass, Symbol* name, Symbol* signature,
+ Klass::PrivateLookupMode private_mode, TRAPS);
JVMCI_ONLY(private:)
// Similar loader constraint checking functions that throw
--- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -179,11 +179,19 @@
JfrDumpFlightRecordingDCmd::JfrDumpFlightRecordingDCmd(outputStream* output,
bool heap) : DCmdWithParser(output, heap),
- _name("name", "Recording name, e.g. \\\"My Recording\\\"", "STRING", true, NULL),
- _filename("filename", "Copy recording data to file, i.e \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", true),
+ _name("name", "Recording name, e.g. \\\"My Recording\\\"", "STRING", false, NULL),
+ _filename("filename", "Copy recording data to file, e.g. \\\"" JFR_FILENAME_EXAMPLE "\\\"", "STRING", false),
+ _maxage("maxage", "Maximum duration to dump, in (s)econds, (m)inutes, (h)ours, or (d)ays, e.g. 60m, or 0 for no limit", "NANOTIME", false, "0"),
+ _maxsize("maxsize", "Maximum amount of bytes to dump, in (M)B or (G)B, e.g. 500M, or 0 for no limit", "MEMORY SIZE", false, "0"),
+ _begin("begin", "Point in time to dump data from, e.g. 09:00, 21:35:00, 2018-06-03T18:12:56.827Z, 2018-06-03T20:13:46.832, -10m, -3h, or -1d", "STRING", false),
+ _end("end", "Point in time to dump data to, e.g. 09:00, 21:35:00, 2018-06-03T18:12:56.827Z, 2018-06-03T20:13:46.832, -10m, -3h, or -1d", "STRING", false),
_path_to_gc_roots("path-to-gc-roots", "Collect path to GC roots", "BOOLEAN", false, "false") {
_dcmdparser.add_dcmd_option(&_name);
_dcmdparser.add_dcmd_option(&_filename);
+ _dcmdparser.add_dcmd_option(&_maxage);
+ _dcmdparser.add_dcmd_option(&_maxsize);
+ _dcmdparser.add_dcmd_option(&_begin);
+ _dcmdparser.add_dcmd_option(&_end);
_dcmdparser.add_dcmd_option(&_path_to_gc_roots);
};
@@ -225,6 +233,26 @@
filepath = JfrJavaSupport::new_string(_filename.value(), CHECK);
}
+ jobject maxage = NULL;
+ if (_maxage.is_set()) {
+ maxage = JfrJavaSupport::new_java_lang_Long(_maxage.value()._nanotime, CHECK);
+ }
+
+ jobject maxsize = NULL;
+ if (_maxsize.is_set()) {
+ maxsize = JfrJavaSupport::new_java_lang_Long(_maxsize.value()._size, CHECK);
+ }
+
+ jstring begin = NULL;
+ if (_begin.is_set() && _begin.value() != NULL) {
+ begin = JfrJavaSupport::new_string(_begin.value(), CHECK);
+ }
+
+ jstring end = NULL;
+ if (_end.is_set() && _end.value() != NULL) {
+ end = JfrJavaSupport::new_string(_end.value(), CHECK);
+ }
+
jobject path_to_gc_roots = NULL;
if (_path_to_gc_roots.is_set()) {
path_to_gc_roots = JfrJavaSupport::new_java_lang_Boolean(_path_to_gc_roots.value(), CHECK);
@@ -232,7 +260,7 @@
static const char klass[] = "jdk/jfr/internal/dcmd/DCmdDump";
static const char method[] = "execute";
- static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";
+ static const char signature[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Boolean;)Ljava/lang/String;";
JfrJavaArguments execute_args(&result, klass, method, signature, CHECK);
execute_args.set_receiver(h_dcmd_instance);
@@ -240,6 +268,10 @@
// arguments
execute_args.push_jobject(name);
execute_args.push_jobject(filepath);
+ execute_args.push_jobject(maxage);
+ execute_args.push_jobject(maxsize);
+ execute_args.push_jobject(begin);
+ execute_args.push_jobject(end);
execute_args.push_jobject(path_to_gc_roots);
JfrJavaSupport::call_virtual(&execute_args, THREAD);
@@ -247,7 +279,7 @@
}
JfrCheckFlightRecordingDCmd::JfrCheckFlightRecordingDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap),
- _name("name","Recording text, e.g. \\\"My Recording\\\" or omit to see all recordings","STRING",false, NULL),
+ _name("name","Recording name, e.g. \\\"My Recording\\\" or omit to see all recordings","STRING",false, NULL),
_verbose("verbose","Print event settings for the recording(s)","BOOLEAN",
false, "false") {
_dcmdparser.add_dcmd_option(&_name);
--- a/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,10 @@
protected:
DCmdArgument<char*> _name;
DCmdArgument<char*> _filename;
+ DCmdArgument<NanoTimeArgument> _maxage;
+ DCmdArgument<MemorySizeArgument> _maxsize;
+ DCmdArgument<char*> _begin;
+ DCmdArgument<char*> _end;
DCmdArgument<bool> _path_to_gc_roots;
public:
--- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
#include "jfr/leakprofiler/utilities/granularTimer.hpp"
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "logging/log.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
--- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,7 @@
class EdgeQueue;
// Class responsible for iterating the heap breadth-first
-class BFSClosure : public ExtendedOopClosure {
+class BFSClosure : public BasicOopIterateClosure {
private:
EdgeQueue* _edge_queue;
EdgeStore* _edge_store;
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
#include "jfr/leakprofiler/utilities/rootType.hpp"
#include "jfr/leakprofiler/chains/rootSetClosure.hpp"
+#include "memory/iterator.inline.hpp"
#include "memory/resourceArea.hpp"
#include "oops/access.inline.hpp"
#include "oops/oop.inline.hpp"
--- a/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/dfsClosure.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,7 @@
class EdgeQueue;
// Class responsible for iterating the heap depth-first
-class DFSClosure: public ExtendedOopClosure {
+class DFSClosure: public BasicOopIterateClosure {
private:
static EdgeStore* _edge_store;
static BitSet* _mark_bits;
--- a/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/leakprofiler/chains/rootSetClosure.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -30,7 +30,7 @@
class EdgeQueue;
-class RootSetClosure: public ExtendedOopClosure {
+class RootSetClosure: public BasicOopIterateClosure {
private:
RootSetClosure(EdgeQueue* edge_queue);
EdgeQueue* _edge_queue;
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -59,9 +59,6 @@
#include "gc/g1/g1HeapRegionTraceType.hpp"
#include "gc/g1/g1YCTypes.hpp"
#endif
-#if INCLUDE_ZGC
-#include "gc/z/zStat.hpp"
-#endif
class JfrCheckpointThreadCountClosure : public ThreadClosure {
private:
@@ -343,23 +340,3 @@
writer.write(thread_group_id);
JfrThreadGroup::serialize(&writer, thread_group_id);
}
-
-void ZStatisticsCounterTypeConstant::serialize(JfrCheckpointWriter& writer) {
-#if INCLUDE_ZGC
- writer.write_count(ZStatCounter::count());
- for (ZStatCounter* counter = ZStatCounter::first(); counter != NULL; counter = counter->next()) {
- writer.write_key(counter->id());
- writer.write(counter->name());
- }
-#endif
-}
-
-void ZStatisticsSamplerTypeConstant::serialize(JfrCheckpointWriter& writer) {
-#if INCLUDE_ZGC
- writer.write_count(ZStatSampler::count());
- for (ZStatSampler* sampler = ZStatSampler::first(); sampler != NULL; sampler = sampler->next()) {
- writer.write_key(sampler->id());
- writer.write(sampler->name());
- }
-#endif
-}
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -135,14 +135,4 @@
void serialize(JfrCheckpointWriter& writer);
};
-class ZStatisticsCounterTypeConstant : public JfrSerializer {
- public:
- void serialize(JfrCheckpointWriter& writer);
-};
-
-class ZStatisticsSamplerTypeConstant : public JfrSerializer {
- public:
- void serialize(JfrCheckpointWriter& writer);
-};
-
#endif // SHARE_VM_JFR_CHECKPOINT_CONSTANT_JFRCONSTANT_HPP
--- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeManager.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -236,8 +236,6 @@
register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant());
register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant());
register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant());
- register_type(TYPE_ZSTATISTICSCOUNTERTYPE, false, true, new ZStatisticsCounterTypeConstant());
- register_type(TYPE_ZSTATISTICSSAMPLERTYPE, false, true, new ZStatisticsSamplerTypeConstant());
// register safepointing type serialization
register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant());
--- a/src/hotspot/share/jfr/utilities/jfrLogTagSets.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jfr/utilities/jfrLogTagSets.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -55,7 +55,8 @@
JFR_LOG_TAG(jfr, system, metadata) \
JFR_LOG_TAG(jfr, metadata) \
JFR_LOG_TAG(jfr, event) \
- JFR_LOG_TAG(jfr, setting)
+ JFR_LOG_TAG(jfr, setting) \
+ JFR_LOG_TAG(jfr, dcmd)
/* NEW TAGS, DONT FORGET TO UPDATE JAVA SIDE */
#endif // SHARE_VM_JFR_UTILITIES_JFRLOGTAGSETS_HPP
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -234,7 +234,7 @@
vmassert(index + 1 == newCount, "must be last");
- Klass* klass = NULL;
+ JVMCIKlassHandle klass(THREAD);
oop result = NULL;
if (h->is_klass()) {
klass = (Klass*) h;
@@ -1048,6 +1048,26 @@
record_scope(pc_offset, position, scope_mode, objectMapping, return_oop, CHECK);
}
+int CodeInstaller::map_jvmci_bci(int bci) {
+ if (bci < 0) {
+ if (bci == BytecodeFrame::BEFORE_BCI()) {
+ return BeforeBci;
+ } else if (bci == BytecodeFrame::AFTER_BCI()) {
+ return AfterBci;
+ } else if (bci == BytecodeFrame::UNWIND_BCI()) {
+ return UnwindBci;
+ } else if (bci == BytecodeFrame::AFTER_EXCEPTION_BCI()) {
+ return AfterExceptionBci;
+ } else if (bci == BytecodeFrame::UNKNOWN_BCI()) {
+ return UnknownBci;
+ } else if (bci == BytecodeFrame::INVALID_FRAMESTATE_BCI()) {
+ return InvalidFrameStateBci;
+ }
+ ShouldNotReachHere();
+ }
+ return bci;
+}
+
void CodeInstaller::record_scope(jint pc_offset, Handle position, ScopeMode scope_mode, GrowableArray<ScopeValue*>* objects, bool return_oop, TRAPS) {
Handle frame;
if (scope_mode == CodeInstaller::FullFrame) {
@@ -1063,16 +1083,13 @@
Handle hotspot_method (THREAD, BytecodePosition::method(position));
Method* method = getMethodFromHotSpotMethod(hotspot_method());
- jint bci = BytecodePosition::bci(position);
- if (bci == BytecodeFrame::BEFORE_BCI()) {
- bci = SynchronizationEntryBCI;
- }
+ jint bci = map_jvmci_bci(BytecodePosition::bci(position));
TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string());
bool reexecute = false;
if (frame.not_null()) {
- if (bci == SynchronizationEntryBCI){
+ if (bci < 0) {
reexecute = false;
} else {
Bytecodes::Code code = Bytecodes::java_code_at(method, method->bcp_from(bci));
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -255,6 +255,7 @@
FullFrame
};
+ int map_jvmci_bci(int bci);
void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, bool return_oop, TRAPS);
void record_scope(jint pc_offset, Handle debug_info, ScopeMode scope_mode, TRAPS) {
record_scope(pc_offset, debug_info, scope_mode, false /* return_oop */, THREAD);
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -44,6 +44,21 @@
#include "runtime/timerTrace.hpp"
#include "runtime/vframe_hp.hpp"
+JVMCIKlassHandle::JVMCIKlassHandle(Thread* thread, Klass* klass) {
+ _thread = thread;
+ _klass = klass;
+ if (klass != NULL) {
+ _holder = Handle(_thread, klass->holder_phantom());
+ }
+}
+
+JVMCIKlassHandle& JVMCIKlassHandle::operator=(Klass* klass) {
+ _klass = klass;
+ if (klass != NULL) {
+ _holder = Handle(_thread, klass->holder_phantom());
+ }
+ return *this;
+}
void JNIHandleMark::push_jni_handle_block() {
JavaThread* thread = JavaThread::current();
@@ -91,8 +106,8 @@
return NULL;
}
-oop CompilerToVM::get_jvmci_type(Klass* klass, TRAPS) {
- if (klass != NULL) {
+oop CompilerToVM::get_jvmci_type(JVMCIKlassHandle& klass, TRAPS) {
+ if (!klass.is_null()) {
JavaValue result(T_OBJECT);
JavaCallArguments args;
args.push_oop(Handle(THREAD, klass->java_mirror()));
@@ -311,7 +326,7 @@
}
C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
- Klass* klass = NULL;
+ JVMCIKlassHandle klass(THREAD);
oop base_object = JNIHandles::resolve(base);
jlong base_address = 0;
if (base_object != NULL && offset == oopDesc::klass_offset_in_bytes()) {
@@ -365,7 +380,8 @@
err_msg("Expected interface type, got %s", klass->external_name()));
}
InstanceKlass* iklass = InstanceKlass::cast(klass);
- oop implementor = CompilerToVM::get_jvmci_type(iklass->implementor(), CHECK_NULL);
+ JVMCIKlassHandle handle(THREAD, iklass->implementor());
+ oop implementor = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
return JNIHandles::make_local(THREAD, implementor);
C2V_END
@@ -400,7 +416,7 @@
THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Primitive type %s should be handled in Java code", class_name->as_C_string()));
}
- Klass* resolved_klass = NULL;
+ JVMCIKlassHandle resolved_klass(THREAD);
if (JNIHandles::resolve(accessing_class) == NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
@@ -433,12 +449,11 @@
class_loader,
protection_domain,
CHECK_0);
- if (resolved_klass != NULL) {
+ if (!resolved_klass.is_null()) {
resolved_klass = resolved_klass->array_klass(fd.dimension(), CHECK_0);
}
} else {
- resolved_klass = Universe::typeArrayKlassObj(t);
- resolved_klass = TypeArrayKlass::cast(resolved_klass)->array_klass(fd.dimension(), CHECK_0);
+ resolved_klass = TypeArrayKlass::cast(Universe::typeArrayKlassObj(t))->array_klass(fd.dimension(), CHECK_0);
}
}
}
@@ -482,25 +497,26 @@
C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index))
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
- Klass* resolved_klass = cp->klass_at(index, CHECK_NULL);
+ Klass* klass = cp->klass_at(index, CHECK_NULL);
+ JVMCIKlassHandle resolved_klass(THREAD, klass);
if (resolved_klass->is_instance_klass()) {
- InstanceKlass::cast(resolved_klass)->link_class_or_fail(THREAD);
+ InstanceKlass::cast(resolved_klass())->link_class_or_fail(THREAD);
}
- oop klass = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
- return JNIHandles::make_local(THREAD, klass);
+ oop jvmci_type = CompilerToVM::get_jvmci_type(resolved_klass, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, jvmci_type);
C2V_END
C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
Klass* loading_klass = cp->pool_holder();
bool is_accessible = false;
- Klass* klass = JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass);
+ JVMCIKlassHandle klass(THREAD, JVMCIEnv::get_klass_by_index(cp, index, is_accessible, loading_klass));
Symbol* symbol = NULL;
if (klass == NULL) {
symbol = cp->klass_name_at(index);
}
oop result_oop;
- if (klass != NULL) {
+ if (!klass.is_null()) {
result_oop = CompilerToVM::get_jvmci_type(klass, CHECK_NULL);
} else {
Handle result = java_lang_String::create_from_symbol(symbol, CHECK_NULL);
@@ -543,7 +559,8 @@
info->int_at_put(0, fd.access_flags().as_int());
info->int_at_put(1, fd.offset());
info->int_at_put(2, fd.index());
- oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
+ JVMCIKlassHandle handle(THREAD, fd.field_holder());
+ oop field_holder = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
return JNIHandles::make_local(THREAD, field_holder);
C2V_END
@@ -1413,7 +1430,8 @@
C2V_VMENTRY(jobject, getHostClass, (JNIEnv*, jobject, jobject jvmci_type))
InstanceKlass* k = InstanceKlass::cast(CompilerToVM::asKlass(jvmci_type));
InstanceKlass* host = k->host_klass();
- oop result = CompilerToVM::get_jvmci_type(host, CHECK_NULL);
+ JVMCIKlassHandle handle(THREAD, host);
+ oop result = CompilerToVM::get_jvmci_type(handle, CHECK_NULL);
return JNIHandles::make_local(THREAD, result);
C2V_END
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -28,6 +28,37 @@
#include "runtime/javaCalls.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
+// Helper class to ensure that references to Klass* are kept alive for G1
+class JVMCIKlassHandle : public StackObj {
+ private:
+ Klass* _klass;
+ Handle _holder;
+ Thread* _thread;
+
+ Klass* klass() const { return _klass; }
+ Klass* non_null_klass() const { assert(_klass != NULL, "resolving NULL _klass"); return _klass; }
+
+ public:
+ /* Constructors */
+ JVMCIKlassHandle (Thread* thread) : _klass(NULL), _thread(thread) {}
+ JVMCIKlassHandle (Thread* thread, Klass* klass);
+
+ JVMCIKlassHandle (const JVMCIKlassHandle &h): _klass(h._klass), _holder(h._holder), _thread(h._thread) {}
+ JVMCIKlassHandle& operator=(const JVMCIKlassHandle &s);
+ JVMCIKlassHandle& operator=(Klass* klass);
+
+ /* Operators for ease of use */
+ Klass* operator () () const { return klass(); }
+ Klass* operator -> () const { return non_null_klass(); }
+
+ bool operator == (Klass* o) const { return klass() == o; }
+ bool operator == (const JVMCIKlassHandle& h) const { return klass() == h.klass(); }
+
+ /* Null checks */
+ bool is_null() const { return _klass == NULL; }
+ bool not_null() const { return _klass != NULL; }
+};
+
class CompilerToVM {
public:
class Data {
@@ -161,7 +192,7 @@
static oop get_jvmci_method(const methodHandle& method, TRAPS);
- static oop get_jvmci_type(Klass* klass, TRAPS);
+ static oop get_jvmci_type(JVMCIKlassHandle& klass, TRAPS);
};
class JavaArgumentUnboxer : public SignatureIterator {
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -210,7 +210,12 @@
int_field(BytecodeFrame, numLocks) \
boolean_field(BytecodeFrame, rethrowException) \
boolean_field(BytecodeFrame, duringCall) \
+ static_int_field(BytecodeFrame, UNKNOWN_BCI) \
+ static_int_field(BytecodeFrame, UNWIND_BCI) \
static_int_field(BytecodeFrame, BEFORE_BCI) \
+ static_int_field(BytecodeFrame, AFTER_BCI) \
+ static_int_field(BytecodeFrame, AFTER_EXCEPTION_BCI) \
+ static_int_field(BytecodeFrame, INVALID_FRAMESTATE_BCI) \
end_class \
start_class(BytecodePosition) \
oop_field(BytecodePosition, caller, "Ljdk/vm/ci/code/BytecodePosition;") \
--- a/src/hotspot/share/logging/logTag.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/logging/logTag.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -44,6 +44,7 @@
LOG_TAG(blocks) \
LOG_TAG(bot) \
LOG_TAG(breakpoint) \
+ LOG_TAG(bytecode) \
LOG_TAG(cds) \
LOG_TAG(census) \
LOG_TAG(class) \
@@ -60,11 +61,13 @@
LOG_TAG(cset) \
LOG_TAG(data) \
LOG_TAG(datacreation) \
+ LOG_TAG(dcmd) \
LOG_TAG(decoder) \
LOG_TAG(defaultmethods) \
LOG_TAG(director) \
LOG_TAG(dump) \
LOG_TAG(ergo) \
+ LOG_TAG(event) \
LOG_TAG(exceptions) \
LOG_TAG(exit) \
LOG_TAG(fingerprint) \
@@ -81,6 +84,7 @@
LOG_TAG(inlining) \
LOG_TAG(interpreter) \
LOG_TAG(itables) \
+ LOG_TAG(jfr) \
LOG_TAG(jit) \
LOG_TAG(jni) \
LOG_TAG(jvmti) \
@@ -100,10 +104,12 @@
LOG_TAG(module) \
LOG_TAG(monitorinflation) \
LOG_TAG(monitormismatch) \
+ LOG_TAG(nestmates) \
LOG_TAG(nmethod) \
LOG_TAG(normalize) \
LOG_TAG(objecttagging) \
LOG_TAG(obsolete) \
+ LOG_TAG(oldobject) \
LOG_TAG(oom) \
LOG_TAG(oopmap) \
LOG_TAG(oops) \
@@ -125,10 +131,13 @@
LOG_TAG(region) \
LOG_TAG(reloc) \
LOG_TAG(remset) \
+ LOG_TAG(parser) \
LOG_TAG(purge) \
LOG_TAG(resolve) \
LOG_TAG(safepoint) \
+ LOG_TAG(sampling) \
LOG_TAG(scavenge) \
+ LOG_TAG(setting) \
LOG_TAG(smr) \
LOG_TAG(stacktrace) \
LOG_TAG(stackwalk) \
@@ -142,6 +151,7 @@
LOG_TAG(subclass) \
LOG_TAG(survivor) \
LOG_TAG(sweep) \
+ LOG_TAG(system) \
LOG_TAG(table) \
LOG_TAG(task) \
DEBUG_ONLY(LOG_TAG(test)) \
@@ -159,15 +169,7 @@
LOG_TAG(vmoperation) \
LOG_TAG(vmthread) \
LOG_TAG(vtables) \
- LOG_TAG(workgang) \
- LOG_TAG(jfr) \
- LOG_TAG(system) \
- LOG_TAG(parser) \
- LOG_TAG(bytecode) \
- LOG_TAG(setting) \
- LOG_TAG(oldobject) \
- LOG_TAG(sampling) \
- LOG_TAG(event)
+ LOG_TAG(workgang)
LOG_TAG_LIST_EXT
#define PREFIX_LOG_TAG(T) (LogTag::_##T)
--- a/src/hotspot/share/memory/heapInspection.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/memory/heapInspection.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -86,6 +86,8 @@
"Number of bytes used by the InstanceKlass::fields() array") \
f(inner_classes_bytes, IK_inner_classes, \
"Number of bytes used by the InstanceKlass::inner_classes() array") \
+ f(nest_members_bytes, IK_nest_members, \
+ "Number of bytes used by the InstanceKlass::nest_members() array") \
f(signers_bytes, IK_signers, \
"Number of bytes used by the InstanceKlass::singers() array") \
f(class_annotations_bytes, class_annotations, \
--- a/src/hotspot/share/memory/iterator.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/memory/iterator.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -63,12 +63,3 @@
do_nmethod(nm);
}
}
-
-// Generate the *Klass::oop_oop_iterate functions for the base class
-// of the oop closures. These versions use the virtual do_oop calls,
-// instead of the devirtualized do_oop_nv version.
-ALL_KLASS_OOP_OOP_ITERATE_DEFN(ExtendedOopClosure, _v)
-
-// Generate the *Klass::oop_oop_iterate functions
-// for the NoHeaderExtendedOopClosure helper class.
-ALL_KLASS_OOP_OOP_ITERATE_DEFN(NoHeaderExtendedOopClosure, _nv)
--- a/src/hotspot/share/memory/iterator.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/memory/iterator.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -55,17 +55,17 @@
};
extern DoNothingClosure do_nothing_cl;
-// ExtendedOopClosure adds extra code to be run during oop iterations.
+// OopIterateClosure adds extra code to be run during oop iterations.
// This is needed by the GC and is extracted to a separate type to not
// pollute the OopClosure interface.
-class ExtendedOopClosure : public OopClosure {
+class OopIterateClosure : public OopClosure {
private:
ReferenceDiscoverer* _ref_discoverer;
protected:
- ExtendedOopClosure(ReferenceDiscoverer* rd) : _ref_discoverer(rd) { }
- ExtendedOopClosure() : _ref_discoverer(NULL) { }
- ~ExtendedOopClosure() { }
+ OopIterateClosure(ReferenceDiscoverer* rd) : _ref_discoverer(rd) { }
+ OopIterateClosure() : _ref_discoverer(NULL) { }
+ ~OopIterateClosure() { }
void set_ref_discoverer_internal(ReferenceDiscoverer* rd) { _ref_discoverer = rd; }
@@ -89,23 +89,10 @@
// 1) do_klass on the header klass pointer.
// 2) do_klass on the klass pointer in the mirrors.
// 3) do_cld on the class loader data in class loaders.
- //
- // The virtual (without suffix) and the non-virtual (with _nv suffix) need
- // to be updated together, or else the devirtualization will break.
- //
- // Providing default implementations of the _nv functions unfortunately
- // removes the compile-time safeness, but reduces the clutter for the
- // ExtendedOopClosures that don't need to walk the metadata.
- // Currently, only CMS and G1 need these.
- bool do_metadata_nv() { return false; }
- virtual bool do_metadata() { return do_metadata_nv(); }
-
- void do_klass_nv(Klass* k) { ShouldNotReachHere(); }
- virtual void do_klass(Klass* k) { do_klass_nv(k); }
-
- void do_cld_nv(ClassLoaderData* cld) { ShouldNotReachHere(); }
- virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
+ virtual bool do_metadata() = 0;
+ virtual void do_klass(Klass* k) = 0;
+ virtual void do_cld(ClassLoaderData* cld) = 0;
// True iff this closure may be safely applied more than once to an oop
// location without an intervening "major reset" (like the end of a GC).
@@ -120,19 +107,24 @@
#endif
};
+// An OopIterateClosure that can be used when there's no need to visit the Metadata.
+class BasicOopIterateClosure : public OopIterateClosure {
+public:
+ BasicOopIterateClosure(ReferenceDiscoverer* rd = NULL) : OopIterateClosure(rd) {}
+
+ virtual bool do_metadata() { return false; }
+ virtual void do_klass(Klass* k) { ShouldNotReachHere(); }
+ virtual void do_cld(ClassLoaderData* cld) { ShouldNotReachHere(); }
+};
+
// Wrapper closure only used to implement oop_iterate_no_header().
-class NoHeaderExtendedOopClosure : public ExtendedOopClosure {
+class NoHeaderExtendedOopClosure : public BasicOopIterateClosure {
OopClosure* _wrapped_closure;
public:
NoHeaderExtendedOopClosure(OopClosure* cl) : _wrapped_closure(cl) {}
// Warning: this calls the virtual version do_oop in the the wrapped closure.
- void do_oop_nv(oop* p) { _wrapped_closure->do_oop(p); }
- void do_oop_nv(narrowOop* p) { _wrapped_closure->do_oop(p); }
-
- void do_oop(oop* p) { assert(false, "Only the _nv versions should be used");
- _wrapped_closure->do_oop(p); }
- void do_oop(narrowOop* p) { assert(false, "Only the _nv versions should be used");
- _wrapped_closure->do_oop(p);}
+ virtual void do_oop(oop* p) { _wrapped_closure->do_oop(p); }
+ virtual void do_oop(narrowOop* p) { _wrapped_closure->do_oop(p); }
};
class KlassClosure : public Closure {
@@ -161,20 +153,13 @@
// The base class for all concurrent marking closures,
// that participates in class unloading.
// It's used to proxy through the metadata to the oops defined in them.
-class MetadataAwareOopClosure: public ExtendedOopClosure {
-
+class MetadataVisitingOopIterateClosure: public OopIterateClosure {
public:
- MetadataAwareOopClosure() : ExtendedOopClosure() { }
- MetadataAwareOopClosure(ReferenceDiscoverer* rd) : ExtendedOopClosure(rd) { }
+ MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd = NULL) : OopIterateClosure(rd) { }
- bool do_metadata_nv() { return true; }
- virtual bool do_metadata() { return do_metadata_nv(); }
-
- void do_klass_nv(Klass* k);
- virtual void do_klass(Klass* k) { do_klass_nv(k); }
-
- void do_cld_nv(ClassLoaderData* cld);
- virtual void do_cld(ClassLoaderData* cld) { do_cld_nv(cld); }
+ virtual bool do_metadata() { return true; }
+ virtual void do_klass(Klass* k);
+ virtual void do_cld(ClassLoaderData* cld);
};
// ObjectClosure is used for iterating through an object space
@@ -204,10 +189,10 @@
// Applies an oop closure to all ref fields in objects iterated over in an
// object iteration.
class ObjectToOopClosure: public ObjectClosure {
- ExtendedOopClosure* _cl;
+ OopIterateClosure* _cl;
public:
void do_object(oop obj);
- ObjectToOopClosure(ExtendedOopClosure* cl) : _cl(cl) {}
+ ObjectToOopClosure(OopIterateClosure* cl) : _cl(cl) {}
};
// A version of ObjectClosure that is expected to be robust
@@ -371,30 +356,22 @@
}
};
-// The two class template specializations are used to dispatch calls
-// to the ExtendedOopClosure functions. If use_non_virtual_call is true,
-// the non-virtual versions are called (E.g. do_oop_nv), otherwise the
-// virtual versions are called (E.g. do_oop).
-
-template <bool use_non_virtual_call>
-class Devirtualizer {};
-
-// Dispatches to the non-virtual functions.
-template <> class Devirtualizer<true> {
+// Dispatches to the non-virtual functions if OopClosureType has
+// a concrete implementation, otherwise a virtual call is taken.
+class Devirtualizer {
public:
- template <class OopClosureType, typename T> static void do_oop(OopClosureType* closure, T* p);
- template <class OopClosureType> static void do_klass(OopClosureType* closure, Klass* k);
- template <class OopClosureType> static void do_cld(OopClosureType* closure, ClassLoaderData* cld);
- template <class OopClosureType> static bool do_metadata(OopClosureType* closure);
+ template <typename OopClosureType, typename T> static void do_oop_no_verify(OopClosureType* closure, T* p);
+ template <typename OopClosureType, typename T> static void do_oop(OopClosureType* closure, T* p);
+ template <typename OopClosureType> static void do_klass(OopClosureType* closure, Klass* k);
+ template <typename OopClosureType> static void do_cld(OopClosureType* closure, ClassLoaderData* cld);
+ template <typename OopClosureType> static bool do_metadata(OopClosureType* closure);
};
-// Dispatches to the virtual functions.
-template <> class Devirtualizer<false> {
+class OopIteratorClosureDispatch {
public:
- template <class OopClosureType, typename T> static void do_oop(OopClosureType* closure, T* p);
- template <class OopClosureType> static void do_klass(OopClosureType* closure, Klass* k);
- template <class OopClosureType> static void do_cld(OopClosureType* closure, ClassLoaderData* cld);
- template <class OopClosureType> static bool do_metadata(OopClosureType* closure);
+ template <typename OopClosureType> static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass);
+ template <typename OopClosureType> static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr);
+ template <typename OopClosureType> static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass);
};
#endif // SHARE_VM_MEMORY_ITERATOR_HPP
--- a/src/hotspot/share/memory/iterator.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/memory/iterator.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -38,21 +38,21 @@
#include "oops/typeArrayKlass.inline.hpp"
#include "utilities/debug.hpp"
-inline void MetadataAwareOopClosure::do_cld_nv(ClassLoaderData* cld) {
+inline void MetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
bool claim = true; // Must claim the class loader data before processing.
cld->oops_do(this, claim);
}
-inline void MetadataAwareOopClosure::do_klass_nv(Klass* k) {
+inline void MetadataVisitingOopIterateClosure::do_klass(Klass* k) {
ClassLoaderData* cld = k->class_loader_data();
- do_cld_nv(cld);
+ MetadataVisitingOopIterateClosure::do_cld(cld);
}
#ifdef ASSERT
// This verification is applied to all visited oops.
// The closures can turn is off by overriding should_verify_oops().
template <typename T>
-void ExtendedOopClosure::verify(T* p) {
+void OopIterateClosure::verify(T* p) {
if (should_verify_oops()) {
T heap_oop = RawAccess<>::oop_load(p);
if (!CompressedOops::is_null(heap_oop)) {
@@ -65,54 +65,360 @@
#endif
// Implementation of the non-virtual do_oop dispatch.
+//
+// The same implementation is used for do_metadata, do_klass, and do_cld.
+//
+// Preconditions:
+// - Base has a pure virtual do_oop
+// - Only one of the classes in the inheritance chain from OopClosureType to
+// Base implements do_oop.
+//
+// Given the preconditions:
+// - If &OopClosureType::do_oop is resolved to &Base::do_oop, then there is no
+// implementation of do_oop between Base and OopClosureType. However, there
+// must be one implementation in one of the subclasses of OopClosureType.
+// In this case we take the virtual call.
+//
+// - Conversely, if &OopClosureType::do_oop is not resolved to &Base::do_oop,
+// then we've found the one and only concrete implementation. In this case we
+// take a non-virtual call.
+//
+// Because of this it's clear when we should call the virtual call and
+// when the non-virtual call should be made.
+//
+// The way we find if &OopClosureType::do_oop is resolved to &Base::do_oop is to
+// check if the resulting type of the class of a member-function pointer to
+// &OopClosureType::do_oop is equal to the type of the class of a
+// &Base::do_oop member-function pointer. Template parameter deduction is used
+// to find these types, and then the IsSame trait is used to check if they are
+// equal. Finally, SFINAE is used to select the appropriate implementation.
+//
+// Template parameters:
+// T - narrowOop or oop
+// Receiver - the resolved type of the class of the
+// &OopClosureType::do_oop member-function pointer. That is,
+// the klass with the do_oop member function.
+// Base - klass with the pure virtual do_oop member function.
+// OopClosureType - The dynamic closure type
+//
+// Parameters:
+// closure - The closure to call
+// p - The oop (or narrowOop) field to pass to the closure
-template <class OopClosureType, typename T>
-inline void Devirtualizer<true>::do_oop(OopClosureType* closure, T* p) {
- debug_only(closure->verify(p));
- closure->do_oop_nv(p);
-}
-template <class OopClosureType>
-inline void Devirtualizer<true>::do_klass(OopClosureType* closure, Klass* k) {
- closure->do_klass_nv(k);
-}
-template <class OopClosureType>
-void Devirtualizer<true>::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
- closure->do_cld_nv(cld);
-}
-template <class OopClosureType>
-inline bool Devirtualizer<true>::do_metadata(OopClosureType* closure) {
- // Make sure the non-virtual and the virtual versions match.
- assert(closure->do_metadata_nv() == closure->do_metadata(), "Inconsistency in do_metadata");
- return closure->do_metadata_nv();
+template <typename T, typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
+call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
+ closure->do_oop(p);
}
-// Implementation of the virtual do_oop dispatch.
+template <typename T, typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
+call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
+ // Sanity check
+ STATIC_ASSERT((!IsSame<OopClosureType, OopIterateClosure>::value));
+ closure->OopClosureType::do_oop(p);
+}
-template <class OopClosureType, typename T>
-void Devirtualizer<false>::do_oop(OopClosureType* closure, T* p) {
- debug_only(closure->verify(p));
- closure->do_oop(p);
+template <typename OopClosureType, typename T>
+inline void Devirtualizer::do_oop_no_verify(OopClosureType* closure, T* p) {
+ call_do_oop<T>(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p);
}
-template <class OopClosureType>
-void Devirtualizer<false>::do_klass(OopClosureType* closure, Klass* k) {
- closure->do_klass(k);
+
+template <typename OopClosureType, typename T>
+inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) {
+ debug_only(closure->verify(p));
+
+ do_oop_no_verify(closure, p);
}
-template <class OopClosureType>
-void Devirtualizer<false>::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
- closure->do_cld(cld);
-}
-template <class OopClosureType>
-bool Devirtualizer<false>::do_metadata(OopClosureType* closure) {
+
+// Implementation of the non-virtual do_metadata dispatch.
+
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<IsSame<Receiver, Base>::value, bool>::type
+call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
return closure->do_metadata();
}
-// The list of all "specializable" oop_oop_iterate function definitions.
-#define ALL_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- ALL_INSTANCE_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \
- ALL_INSTANCE_REF_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \
- ALL_INSTANCE_MIRROR_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \
- ALL_INSTANCE_CLASS_LOADER_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- ALL_OBJ_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix) \
- ALL_TYPE_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN( OopClosureType, nv_suffix)
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<!IsSame<Receiver, Base>::value, bool>::type
+call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
+ return closure->OopClosureType::do_metadata();
+}
+
+template <typename OopClosureType>
+inline bool Devirtualizer::do_metadata(OopClosureType* closure) {
+ return call_do_metadata(&OopClosureType::do_metadata, &OopIterateClosure::do_metadata, closure);
+}
+
+// Implementation of the non-virtual do_klass dispatch.
+
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
+call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
+ closure->do_klass(k);
+}
+
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
+call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
+ closure->OopClosureType::do_klass(k);
+}
+
+template <typename OopClosureType>
+inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) {
+ call_do_klass(&OopClosureType::do_klass, &OopIterateClosure::do_klass, closure, k);
+}
+
+// Implementation of the non-virtual do_cld dispatch.
+
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
+call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
+ closure->do_cld(cld);
+}
+
+template <typename Receiver, typename Base, typename OopClosureType>
+static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
+call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
+ closure->OopClosureType::do_cld(cld);
+}
+
+template <typename OopClosureType>
+void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
+ call_do_cld(&OopClosureType::do_cld, &OopIterateClosure::do_cld, closure, cld);
+}
+
+// Dispatch table implementation for *Klass::oop_oop_iterate
+//
+// It allows for a single call to do a multi-dispatch to an optimized version
+// of oop_oop_iterate that statically know all these types:
+// - OopClosureType : static type give at call site
+// - Klass* : dynamic to static type through Klass::id() -> table index
+// - UseCompressedOops : dynamic to static value determined once
+//
+// when users call obj->oop_iterate(&cl).
+//
+// oopDesc::oop_iterate() calls OopOopIterateDispatch::function(klass)(cl, obj, klass),
+// which dispatches to an optimized version of
+// [Instance, ObjArry, etc]Klass::oop_oop_iterate(oop, OopClosureType)
+//
+// OopClosureType :
+// If OopClosureType has an implementation of do_oop (and do_metadata et.al.),
+// then the static type of OopClosureType will be used to allow inlining of
+// do_oop (even though do_oop is virtual). Otherwise, a virtual call will be
+// used when calling do_oop.
+//
+// Klass* :
+// A table mapping from *Klass::ID to function is setup. This happens once
+// when the program starts, when the static _table instance is initialized for
+// the OopOopIterateDispatch specialized with the OopClosureType.
+//
+// UseCompressedOops :
+// Initially the table is populated with an init function, and not the actual
+// oop_oop_iterate function. This is done, so that the first time we dispatch
+// through the init function we check what the value of UseCompressedOops
+// became, and use that to determine if we should install an optimized
+// narrowOop version or optimized oop version of oop_oop_iterate. The appropriate
+// oop_oop_iterate function replaces the init function in the table, and
+// succeeding calls will jump directly to oop_oop_iterate.
+
+
+template <typename OopClosureType>
+class OopOopIterateDispatch : public AllStatic {
+private:
+ class Table {
+ private:
+ template <typename KlassType, typename T>
+ static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* k) {
+ ((KlassType*)k)->KlassType::template oop_oop_iterate<T>(obj, cl);
+ }
+
+ template <typename KlassType>
+ static void init(OopClosureType* cl, oop obj, Klass* k) {
+ OopOopIterateDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
+ }
+
+ template <typename KlassType>
+ void set_init_function() {
+ _function[KlassType::ID] = &init<KlassType>;
+ }
+
+ template <typename KlassType>
+ void set_resolve_function() {
+ // Size requirement to prevent word tearing
+ // when functions pointers are updated.
+ STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*));
+ if (UseCompressedOops) {
+ _function[KlassType::ID] = &oop_oop_iterate<KlassType, narrowOop>;
+ } else {
+ _function[KlassType::ID] = &oop_oop_iterate<KlassType, oop>;
+ }
+ }
+
+ template <typename KlassType>
+ void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
+ set_resolve_function<KlassType>();
+ _function[KlassType::ID](cl, obj, k);
+ }
+
+ public:
+ void (*_function[KLASS_ID_COUNT])(OopClosureType*, oop, Klass*);
+
+ Table(){
+ set_init_function<InstanceKlass>();
+ set_init_function<InstanceRefKlass>();
+ set_init_function<InstanceMirrorKlass>();
+ set_init_function<InstanceClassLoaderKlass>();
+ set_init_function<ObjArrayKlass>();
+ set_init_function<TypeArrayKlass>();
+ }
+ };
+
+ static Table _table;
+public:
+
+ static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) {
+ return _table._function[klass->id()];
+ }
+};
+
+template <typename OopClosureType>
+typename OopOopIterateDispatch<OopClosureType>::Table OopOopIterateDispatch<OopClosureType>::_table;
+
+
+template <typename OopClosureType>
+class OopOopIterateBoundedDispatch {
+private:
+ class Table {
+ private:
+ template <typename KlassType, typename T>
+ static void oop_oop_iterate_bounded(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
+ ((KlassType*)k)->KlassType::template oop_oop_iterate_bounded<T>(obj, cl, mr);
+ }
+
+ template <typename KlassType>
+ static void init(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
+ OopOopIterateBoundedDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k, mr);
+ }
+
+ template <typename KlassType>
+ void set_init_function() {
+ _function[KlassType::ID] = &init<KlassType>;
+ }
+
+ template <typename KlassType>
+ void set_resolve_function() {
+ if (UseCompressedOops) {
+ _function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, narrowOop>;
+ } else {
+ _function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, oop>;
+ }
+ }
+
+ template <typename KlassType>
+ void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
+ set_resolve_function<KlassType>();
+ _function[KlassType::ID](cl, obj, k, mr);
+ }
+
+ public:
+ void (*_function[KLASS_ID_COUNT])(OopClosureType*, oop, Klass*, MemRegion);
+
+ Table(){
+ set_init_function<InstanceKlass>();
+ set_init_function<InstanceRefKlass>();
+ set_init_function<InstanceMirrorKlass>();
+ set_init_function<InstanceClassLoaderKlass>();
+ set_init_function<ObjArrayKlass>();
+ set_init_function<TypeArrayKlass>();
+ }
+ };
+
+ static Table _table;
+public:
+
+ static void (*function(Klass* klass))(OopClosureType*, oop, Klass*, MemRegion) {
+ return _table._function[klass->id()];
+ }
+};
+
+template <typename OopClosureType>
+typename OopOopIterateBoundedDispatch<OopClosureType>::Table OopOopIterateBoundedDispatch<OopClosureType>::_table;
+
+
+template <typename OopClosureType>
+class OopOopIterateBackwardsDispatch {
+private:
+ class Table {
+ private:
+ template <typename KlassType, typename T>
+ static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* k) {
+ ((KlassType*)k)->KlassType::template oop_oop_iterate_reverse<T>(obj, cl);
+ }
+
+ template <typename KlassType>
+ static void init(OopClosureType* cl, oop obj, Klass* k) {
+ OopOopIterateBackwardsDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
+ }
+
+ template <typename KlassType>
+ void set_init_function() {
+ _function[KlassType::ID] = &init<KlassType>;
+ }
+
+ template <typename KlassType>
+ void set_resolve_function() {
+ if (UseCompressedOops) {
+ _function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, narrowOop>;
+ } else {
+ _function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, oop>;
+ }
+ }
+
+ template <typename KlassType>
+ void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
+ set_resolve_function<KlassType>();
+ _function[KlassType::ID](cl, obj, k);
+ }
+
+ public:
+ void (*_function[KLASS_ID_COUNT])(OopClosureType*, oop, Klass*);
+
+ Table(){
+ set_init_function<InstanceKlass>();
+ set_init_function<InstanceRefKlass>();
+ set_init_function<InstanceMirrorKlass>();
+ set_init_function<InstanceClassLoaderKlass>();
+ set_init_function<ObjArrayKlass>();
+ set_init_function<TypeArrayKlass>();
+ }
+ };
+
+ static Table _table;
+public:
+
+ static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) {
+ return _table._function[klass->id()];
+ }
+};
+
+template <typename OopClosureType>
+typename OopOopIterateBackwardsDispatch<OopClosureType>::Table OopOopIterateBackwardsDispatch<OopClosureType>::_table;
+
+
+template <typename OopClosureType>
+void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) {
+ OopOopIterateDispatch<OopClosureType>::function(klass)(cl, obj, klass);
+}
+
+template <typename OopClosureType>
+void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) {
+ OopOopIterateBoundedDispatch<OopClosureType>::function(klass)(cl, obj, klass, mr);
+}
+
+template <typename OopClosureType>
+void OopIteratorClosureDispatch::oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass) {
+ OopOopIterateBackwardsDispatch<OopClosureType>::function(klass)(cl, obj, klass);
+}
#endif // SHARE_VM_MEMORY_ITERATOR_INLINE_HPP
--- a/src/hotspot/share/oops/access.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/access.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -104,8 +104,8 @@
template <DecoratorSet expected_mo_decorators>
static void verify_primitive_decorators() {
- const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE ^ AS_DEST_NOT_INITIALIZED) |
- IN_HEAP | IN_HEAP_ARRAY;
+ const DecoratorSet primitive_decorators = (AS_DECORATOR_MASK ^ AS_NO_KEEPALIVE) |
+ IN_HEAP | IS_ARRAY;
verify_decorators<expected_mo_decorators | primitive_decorators>();
}
@@ -113,15 +113,14 @@
static void verify_oop_decorators() {
const DecoratorSet oop_decorators = AS_DECORATOR_MASK | IN_DECORATOR_MASK |
(ON_DECORATOR_MASK ^ ON_UNKNOWN_OOP_REF) | // no unknown oop refs outside of the heap
- OOP_DECORATOR_MASK;
+ IS_ARRAY | IS_NOT_NULL | IS_DEST_UNINITIALIZED;
verify_decorators<expected_mo_decorators | oop_decorators>();
}
template <DecoratorSet expected_mo_decorators>
static void verify_heap_oop_decorators() {
const DecoratorSet heap_oop_decorators = AS_DECORATOR_MASK | ON_DECORATOR_MASK |
- OOP_DECORATOR_MASK | (IN_DECORATOR_MASK ^
- (IN_NATIVE | IN_CONCURRENT_ROOT)); // no root accesses in the heap
+ IN_HEAP | IS_ARRAY | IS_NOT_NULL;
verify_decorators<expected_mo_decorators | heap_oop_decorators>();
}
@@ -135,8 +134,8 @@
static inline bool oop_arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
size_t length) {
- verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
- AS_DECORATOR_MASK>();
+ verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP |
+ AS_DECORATOR_MASK | IS_ARRAY | IS_DEST_UNINITIALIZED>();
return AccessInternal::arraycopy<decorators | INTERNAL_VALUE_IS_OOP>(src_obj, src_offset_in_bytes, src_raw,
dst_obj, dst_offset_in_bytes, dst_raw,
length);
@@ -146,8 +145,8 @@
static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes, const T* src_raw,
arrayOop dst_obj, size_t dst_offset_in_bytes, T* dst_raw,
size_t length) {
- verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP | IN_HEAP_ARRAY |
- AS_DECORATOR_MASK>();
+ verify_decorators<ARRAYCOPY_DECORATOR_MASK | IN_HEAP |
+ AS_DECORATOR_MASK | IS_ARRAY>();
AccessInternal::arraycopy<decorators>(src_obj, src_offset_in_bytes, src_raw,
dst_obj, dst_offset_in_bytes, dst_raw,
length);
@@ -300,8 +299,8 @@
// Helper for array access.
template <DecoratorSet decorators = INTERNAL_EMPTY>
-class ArrayAccess: public HeapAccess<IN_HEAP_ARRAY | decorators> {
- typedef HeapAccess<IN_HEAP_ARRAY | decorators> AccessT;
+class ArrayAccess: public HeapAccess<IS_ARRAY | decorators> {
+ typedef HeapAccess<IS_ARRAY | decorators> AccessT;
public:
template <typename T>
static inline void arraycopy(arrayOop src_obj, size_t src_offset_in_bytes,
@@ -354,7 +353,6 @@
const DecoratorSet barrier_strength_decorators = decorators & AS_DECORATOR_MASK;
STATIC_ASSERT(barrier_strength_decorators == 0 || ( // make sure barrier strength decorators are disjoint if set
(barrier_strength_decorators ^ AS_NO_KEEPALIVE) == 0 ||
- (barrier_strength_decorators ^ AS_DEST_NOT_INITIALIZED) == 0 ||
(barrier_strength_decorators ^ AS_RAW) == 0 ||
(barrier_strength_decorators ^ AS_NORMAL) == 0
));
@@ -378,7 +376,6 @@
STATIC_ASSERT(location_decorators == 0 || ( // make sure location decorators are disjoint if set
(location_decorators ^ IN_NATIVE) == 0 ||
(location_decorators ^ IN_HEAP) == 0 ||
- (location_decorators ^ (IN_HEAP | IN_HEAP_ARRAY)) == 0 ||
(location_decorators ^ (IN_NATIVE | IN_CONCURRENT_ROOT)) == 0
));
}
--- a/src/hotspot/share/oops/accessBackend.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/accessBackend.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -181,7 +181,7 @@
// This mask specifies what decorators are relevant for raw accesses. When passing
// accesses to the raw layer, irrelevant decorators are removed.
const DecoratorSet RAW_DECORATOR_MASK = INTERNAL_DECORATOR_MASK | MO_DECORATOR_MASK |
- ARRAYCOPY_DECORATOR_MASK | OOP_DECORATOR_MASK;
+ ARRAYCOPY_DECORATOR_MASK | IS_NOT_NULL;
// The RawAccessBarrier performs raw accesses with additional knowledge of
// memory ordering, so that OrderAccess/Atomic is called when necessary.
@@ -1290,7 +1290,7 @@
(IsSame<T, void>::value || IsIntegral<T>::value) ||
IsFloatingPoint<T>::value)); // arraycopy allows type erased void elements
typedef typename Decay<T>::type DecayedT;
- const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IN_HEAP_ARRAY | IN_HEAP>::value;
+ const DecoratorSet expanded_decorators = DecoratorFixup<decorators | IS_ARRAY | IN_HEAP>::value;
return arraycopy_reduce_types<expanded_decorators>(src_obj, src_offset_in_bytes, const_cast<DecayedT*>(src_raw),
dst_obj, dst_offset_in_bytes, const_cast<DecayedT*>(dst_raw),
length);
--- a/src/hotspot/share/oops/accessBackend.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/accessBackend.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -35,7 +35,7 @@
inline typename EnableIf<
AccessInternal::MustConvertCompressedOop<idecorators, T>::value, T>::type
RawAccessBarrier<decorators>::decode_internal(typename HeapOopType<idecorators>::type value) {
- if (HasDecorator<decorators, OOP_NOT_NULL>::value) {
+ if (HasDecorator<decorators, IS_NOT_NULL>::value) {
return CompressedOops::decode_not_null(value);
} else {
return CompressedOops::decode(value);
@@ -48,7 +48,7 @@
AccessInternal::MustConvertCompressedOop<idecorators, T>::value,
typename HeapOopType<idecorators>::type>::type
RawAccessBarrier<decorators>::encode_internal(T value) {
- if (HasDecorator<decorators, OOP_NOT_NULL>::value) {
+ if (HasDecorator<decorators, IS_NOT_NULL>::value) {
return CompressedOops::encode_not_null(value);
} else {
return CompressedOops::encode(value);
--- a/src/hotspot/share/oops/accessDecorators.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/accessDecorators.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -143,8 +143,6 @@
// - Accesses on narrowOop* translate to encoded/decoded memory accesses without runtime checks
// - Accesses on HeapWord* translate to a runtime check choosing one of the above
// - Accesses on other types translate to raw memory accesses without runtime checks
-// * AS_DEST_NOT_INITIALIZED: This property can be important to e.g. SATB barriers by
-// marking that the previous value is uninitialized nonsense rather than a real value.
// * AS_NO_KEEPALIVE: The barrier is used only on oop references and will not keep any involved objects
// alive, regardless of the type of reference being accessed. It will however perform the memory access
// in a consistent way w.r.t. e.g. concurrent compaction, so that the right field is being accessed,
@@ -155,11 +153,9 @@
// Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time
// decorator for enabling primitive barriers is enabled for the build.
const DecoratorSet AS_RAW = UCONST64(1) << 12;
-const DecoratorSet AS_DEST_NOT_INITIALIZED = UCONST64(1) << 13;
const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 14;
const DecoratorSet AS_NORMAL = UCONST64(1) << 15;
-const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_DEST_NOT_INITIALIZED |
- AS_NO_KEEPALIVE | AS_NORMAL;
+const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMAL;
// === Reference Strength Decorators ===
// These decorators only apply to accesses on oop-like types (oop/narrowOop).
@@ -182,23 +178,24 @@
// The location is important to the GC as it may imply different actions. The following decorators are used:
// * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will
// be omitted if this decorator is not set.
-// * IN_HEAP_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case
-// for some GCs, and implies that it is an IN_HEAP.
// * IN_NATIVE: The access is performed in an off-heap data structure pointing into the Java heap.
// * IN_CONCURRENT_ROOT: The access is performed in an off-heap data structure pointing into the Java heap,
// but is notably not scanned during safepoints. This is sometimes a special case for some GCs and
// implies that it is also an IN_NATIVE.
const DecoratorSet IN_HEAP = UCONST64(1) << 20;
-const DecoratorSet IN_HEAP_ARRAY = UCONST64(1) << 21;
const DecoratorSet IN_NATIVE = UCONST64(1) << 22;
const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 23;
-const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_HEAP_ARRAY |
- IN_NATIVE | IN_CONCURRENT_ROOT;
+const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE | IN_CONCURRENT_ROOT;
-// == Value Decorators ==
-// * OOP_NOT_NULL: This property can make certain barriers faster such as compressing oops.
-const DecoratorSet OOP_NOT_NULL = UCONST64(1) << 25;
-const DecoratorSet OOP_DECORATOR_MASK = OOP_NOT_NULL;
+// == Boolean Flag Decorators ==
+// * IS_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case
+// for some GCs.
+// * IS_DEST_UNINITIALIZED: This property can be important to e.g. SATB barriers by
+// marking that the previous value is uninitialized nonsense rather than a real value.
+// * IS_NOT_NULL: This property can make certain barriers faster such as compressing oops.
+const DecoratorSet IS_ARRAY = UCONST64(1) << 21;
+const DecoratorSet IS_DEST_UNINITIALIZED = UCONST64(1) << 13;
+const DecoratorSet IS_NOT_NULL = UCONST64(1) << 25;
// == Arraycopy Decorators ==
// * ARRAYCOPY_CHECKCAST: This property means that the class of the objects in source
@@ -238,11 +235,8 @@
// If no barrier strength has been picked, normal will be used
static const DecoratorSet barrier_strength_default = memory_ordering_default |
((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
- // Heap array accesses imply it is a heap access
- static const DecoratorSet heap_array_is_in_heap = barrier_strength_default |
- ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
- static const DecoratorSet conc_root_is_root = heap_array_is_in_heap |
- ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
+ static const DecoratorSet conc_root_is_root = barrier_strength_default |
+ ((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
static const DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
};
@@ -259,11 +253,8 @@
// If no barrier strength has been picked, normal will be used
DecoratorSet barrier_strength_default = memory_ordering_default |
((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
- // Heap array accesses imply it is a heap access
- DecoratorSet heap_array_is_in_heap = barrier_strength_default |
- ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
- DecoratorSet conc_root_is_root = heap_array_is_in_heap |
- ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
+ DecoratorSet conc_root_is_root = barrier_strength_default |
+ ((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
return value;
}
--- a/src/hotspot/share/oops/arrayKlass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/arrayKlass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -71,16 +71,18 @@
Method* ArrayKlass::uncached_lookup_method(const Symbol* name,
const Symbol* signature,
- OverpassLookupMode overpass_mode) const {
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode private_mode) const {
// There are no methods in an array klass but the super class (Object) has some
assert(super(), "super klass must be present");
// Always ignore overpass methods in superclasses, although technically the
// super klass of an array, (j.l.Object) should not have
// any overpass methods present.
- return super()->uncached_lookup_method(name, signature, Klass::skip_overpass);
+ return super()->uncached_lookup_method(name, signature, Klass::skip_overpass, private_mode);
}
-ArrayKlass::ArrayKlass(Symbol* name) :
+ArrayKlass::ArrayKlass(Symbol* name, KlassID id) :
+ Klass(id),
_dimension(1),
_higher_dimension(NULL),
_lower_dimension(NULL) {
--- a/src/hotspot/share/oops/arrayKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/arrayKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -46,7 +46,7 @@
// Constructors
// The constructor with the Symbol argument does the real array
// initialization, the other is a dummy
- ArrayKlass(Symbol* name);
+ ArrayKlass(Symbol* name, KlassID id);
ArrayKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); }
public:
@@ -87,7 +87,8 @@
// Lookup operations
Method* uncached_lookup_method(const Symbol* name,
const Symbol* signature,
- OverpassLookupMode overpass_mode) const;
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode private_mode = find_private) const;
static ArrayKlass* cast(Klass* k) {
return const_cast<ArrayKlass*>(cast(const_cast<const Klass*>(k)));
@@ -146,36 +147,4 @@
void oop_verify_on(oop obj, outputStream* st);
};
-// Array oop iteration macros for declarations.
-// Used to generate the declarations in the *ArrayKlass header files.
-
-#define OOP_OOP_ITERATE_DECL_RANGE(OopClosureType, nv_suffix) \
- void oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end);
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-// Named NO_BACKWARDS because the definition used by *ArrayKlass isn't reversed, see below.
-#define OOP_OOP_ITERATE_DECL_NO_BACKWARDS(OopClosureType, nv_suffix) \
- void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
-#endif
-
-
-// Array oop iteration macros for definitions.
-// Used to generate the definitions in the *ArrayKlass.inline.hpp files.
-
-#define OOP_OOP_ITERATE_DEFN_RANGE(KlassType, OopClosureType, nv_suffix) \
- \
-void KlassType::oop_oop_iterate_range##nv_suffix(oop obj, OopClosureType* closure, int start, int end) { \
- oop_oop_iterate_range<nvs_to_bool(nv_suffix)>(obj, closure, start, end); \
-}
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-#define OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
-void KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
- /* No reverse implementation ATM. */ \
- oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
-}
-#else
-#define OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(KlassType, OopClosureType, nv_suffix)
-#endif
-
#endif // SHARE_VM_OOPS_ARRAYKLASS_HPP
--- a/src/hotspot/share/oops/cpCache.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/cpCache.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -174,17 +174,37 @@
int byte_no = -1;
bool change_to_virtual = false;
-
+ InstanceKlass* holder = NULL; // have to declare this outside the switch
switch (invoke_code) {
case Bytecodes::_invokeinterface:
- // We get here from InterpreterRuntime::resolve_invoke when an invokeinterface
- // instruction somehow links to a non-interface method (in Object).
- // In that case, the method has no itable index and must be invoked as a virtual.
- // Set a flag to keep track of this corner case.
- assert(method->is_public(), "Calling non-public method in Object with invokeinterface");
- change_to_virtual = true;
+ holder = method->method_holder();
+ // check for private interface method invocations
+ if (vtable_index == Method::nonvirtual_vtable_index && holder->is_interface() ) {
+ assert(method->is_private(), "unexpected non-private method");
+ assert(method->can_be_statically_bound(), "unexpected non-statically-bound method");
+ // set_f2_as_vfinal_method checks if is_vfinal flag is true.
+ set_method_flags(as_TosState(method->result_type()),
+ ( 1 << is_vfinal_shift) |
+ ((method->is_final_method() ? 1 : 0) << is_final_shift),
+ method()->size_of_parameters());
+ set_f2_as_vfinal_method(method());
+ byte_no = 2;
+ set_f1(holder); // interface klass*
+ break;
+ }
+ else {
+ // We get here from InterpreterRuntime::resolve_invoke when an invokeinterface
+ // instruction links to a non-interface method (in Object). This can happen when
+ // an interface redeclares an Object method (like CharSequence declaring toString())
+ // or when invokeinterface is used explicitly.
+ // In that case, the method has no itable index and must be invoked as a virtual.
+ // Set a flag to keep track of this corner case.
+ assert(holder->is_interface() || holder == SystemDictionary::Object_klass(), "unexpected holder class");
+ assert(method->is_public(), "Calling non-public method in Object with invokeinterface");
+ change_to_virtual = true;
- // ...and fall through as if we were handling invokevirtual:
+ // ...and fall through as if we were handling invokevirtual:
+ }
case Bytecodes::_invokevirtual:
{
if (!is_vtable_call) {
@@ -237,7 +257,7 @@
// is executed.
if (invoke_code != Bytecodes::_invokespecial || !sender_is_interface ||
method->name() == vmSymbols::object_initializer_name()) {
- set_bytecode_1(invoke_code);
+ set_bytecode_1(invoke_code);
}
} else if (byte_no == 2) {
if (change_to_virtual) {
@@ -257,7 +277,18 @@
// We set bytecode_2() to _invokevirtual.
// See also interpreterRuntime.cpp. (8/25/2000)
} else {
- assert(invoke_code == Bytecodes::_invokevirtual, "");
+ assert(invoke_code == Bytecodes::_invokevirtual ||
+ (invoke_code == Bytecodes::_invokeinterface &&
+ ((method->is_private() ||
+ (method->is_final() && method->method_holder() == SystemDictionary::Object_klass())))),
+ "unexpected invocation mode");
+ if (invoke_code == Bytecodes::_invokeinterface &&
+ (method->is_private() || method->is_final())) {
+ // We set bytecode_1() to _invokeinterface, because that is the
+ // bytecode # used by the interpreter to see if it is resolved.
+ // We set bytecode_2() to _invokevirtual.
+ set_bytecode_1(invoke_code);
+ }
}
// set up for invokevirtual, even if linking for invokeinterface also:
set_bytecode_2(Bytecodes::_invokevirtual);
--- a/src/hotspot/share/oops/instanceClassLoaderKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,6 @@
#ifndef SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
#define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/instanceKlass.hpp"
#include "utilities/macros.hpp"
@@ -40,8 +39,11 @@
class InstanceClassLoaderKlass: public InstanceKlass {
friend class VMStructs;
friend class InstanceKlass;
- private:
- InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_class_loader) {}
+public:
+ static const KlassID ID = InstanceClassLoaderKlassID;
+
+private:
+ InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_class_loader, ID) {}
public:
InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -57,39 +59,24 @@
#endif
// Oop fields (and metadata) iterators
- // [nv = true] Use non-virtual calls to do_oop_nv.
- // [nv = false] Use virtual calls to do_oop.
//
// The InstanceClassLoaderKlass iterators also visit the CLD pointer (or mirror of anonymous klasses.)
- private:
+ public:
// Forward iteration
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate(oop obj, OopClosureType* closure);
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
// Reverse iteration
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
-#endif
// Bounded range iteration
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
-
- public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
-#endif
-
};
#endif // SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
--- a/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceClassLoaderKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,7 @@
#define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_INLINE_HPP
#include "classfile/javaClasses.hpp"
-#include "memory/iterator.inline.hpp"
+#include "memory/iterator.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/oop.inline.hpp"
@@ -34,48 +34,40 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
inline void InstanceClassLoaderKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate<nv>(obj, closure);
+ InstanceKlass::oop_oop_iterate<T>(obj, closure);
- if (Devirtualizer<nv>::do_metadata(closure)) {
+ if (Devirtualizer::do_metadata(closure)) {
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
- Devirtualizer<nv>::do_cld(closure, cld);
+ Devirtualizer::do_cld(closure, cld);
}
}
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
inline void InstanceClassLoaderKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
+ InstanceKlass::oop_oop_iterate_reverse<T>(obj, closure);
- assert(!Devirtualizer<nv>::do_metadata(closure),
+ assert(!Devirtualizer::do_metadata(closure),
"Code to handle metadata is not implemented");
}
-#endif // INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
inline void InstanceClassLoaderKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
+ InstanceKlass::oop_oop_iterate_bounded<T>(obj, closure, mr);
- if (Devirtualizer<nv>::do_metadata(closure)) {
+ if (Devirtualizer::do_metadata(closure)) {
if (mr.contains(obj)) {
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
// cld can be null if we have a non-registered class loader.
if (cld != NULL) {
- Devirtualizer<nv>::do_cld(closure, cld);
+ Devirtualizer::do_cld(closure, cld);
}
}
}
}
-#define ALL_INSTANCE_CLASS_LOADER_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( InstanceClassLoaderKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( InstanceClassLoaderKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BACKWARDS(InstanceClassLoaderKlass, OopClosureType, nv_suffix)
-
#endif // SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/instanceKlass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -38,7 +38,6 @@
#include "code/dependencyContext.hpp"
#include "compiler/compileBroker.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "interpreter/oopMapCache.hpp"
#include "interpreter/rewriter.hpp"
#include "jvmtifiles/jvmti.h"
@@ -145,6 +144,198 @@
return false;
}
+// called to verify that k is a member of this nest
+bool InstanceKlass::has_nest_member(InstanceKlass* k, TRAPS) const {
+ if (_nest_members == NULL || _nest_members == Universe::the_empty_short_array()) {
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Checked nest membership of %s in non-nest-host class %s",
+ k->external_name(), this->external_name());
+ }
+ return false;
+ }
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Checking nest membership of %s in %s",
+ k->external_name(), this->external_name());
+ }
+
+ // Check names first and if they match then check actual klass. This avoids
+ // resolving anything unnecessarily.
+ for (int i = 0; i < _nest_members->length(); i++) {
+ int cp_index = _nest_members->at(i);
+ Symbol* name = _constants->klass_name_at(cp_index);
+ if (name == k->name()) {
+ log_trace(class, nestmates)("- Found it at nest_members[%d] => cp[%d]", i, cp_index);
+
+ // names match so check actual klass - this may trigger class loading if
+ // it doesn't match (but that should be impossible)
+ Klass* k2 = _constants->klass_at(cp_index, CHECK_false);
+ if (k2 == k) {
+ log_trace(class, nestmates)("- class is listed as a nest member");
+ return true;
+ } else {
+ // same name but different klass!
+ log_trace(class, nestmates)(" - klass comparison failed!");
+ // can't have different classes for the same name, so we're done
+ return false;
+ }
+ }
+ }
+ log_trace(class, nestmates)("- class is NOT a nest member!");
+ return false;
+}
+
+// Return nest-host class, resolving, validating and saving it if needed.
+// In cases where this is called from a thread that can not do classloading
+// (such as a native JIT thread) then we simply return NULL, which in turn
+// causes the access check to return false. Such code will retry the access
+// from a more suitable environment later.
+InstanceKlass* InstanceKlass::nest_host(Symbol* validationException, TRAPS) {
+ InstanceKlass* nest_host_k = _nest_host;
+ if (nest_host_k == NULL) {
+ // need to resolve and save our nest-host class. This could be attempted
+ // concurrently but as the result is idempotent and we don't use the class
+ // then we do not need any synchronization beyond what is implicitly used
+ // during class loading.
+ if (_nest_host_index != 0) { // we have a real nest_host
+ // Before trying to resolve check if we're in a suitable context
+ if (!THREAD->can_call_java() && !_constants->tag_at(_nest_host_index).is_klass()) {
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Rejected resolution of nest-host of %s in unsuitable thread",
+ this->external_name());
+ }
+ return NULL;
+ }
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Resolving nest-host of %s using cp entry for %s",
+ this->external_name(),
+ _constants->klass_name_at(_nest_host_index)->as_C_string());
+ }
+
+ Klass* k = _constants->klass_at(_nest_host_index, THREAD);
+ if (HAS_PENDING_EXCEPTION) {
+ Handle exc_h = Handle(THREAD, PENDING_EXCEPTION);
+ if (exc_h->is_a(SystemDictionary::NoClassDefFoundError_klass())) {
+ // throw a new CDNFE with the original as its cause, and a clear msg
+ ResourceMark rm(THREAD);
+ char buf[200];
+ CLEAR_PENDING_EXCEPTION;
+ jio_snprintf(buf, sizeof(buf),
+ "Unable to load nest-host class (%s) of %s",
+ _constants->klass_name_at(_nest_host_index)->as_C_string(),
+ this->external_name());
+ log_trace(class, nestmates)("%s - NoClassDefFoundError", buf);
+ THROW_MSG_CAUSE_NULL(vmSymbols::java_lang_NoClassDefFoundError(), buf, exc_h);
+ }
+ // All other exceptions pass through (OOME, StackOverflowError, LinkageErrors etc).
+ return NULL;
+ }
+
+ // A valid nest-host is an instance class in the current package that lists this
+ // class as a nest member. If any of these conditions are not met we post the
+ // requested exception type (if any) and return NULL
+
+ const char* error = NULL;
+
+ // JVMS 5.4.4 indicates package check comes first
+ if (is_same_class_package(k)) {
+
+ // Now check actual membership. We can't be a member if our "host" is
+ // not an instance class.
+ if (k->is_instance_klass()) {
+ nest_host_k = InstanceKlass::cast(k);
+
+ bool is_member = nest_host_k->has_nest_member(this, CHECK_NULL);
+ if (is_member) {
+ // save resolved nest-host value
+ _nest_host = nest_host_k;
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Resolved nest-host of %s to %s",
+ this->external_name(), k->external_name());
+ }
+ return nest_host_k;
+ }
+ }
+ error = "current type is not listed as a nest member";
+ } else {
+ error = "types are in different packages";
+ }
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Type %s is not a nest member of resolved type %s: %s",
+ this->external_name(),
+ k->external_name(),
+ error);
+ }
+
+ if (validationException != NULL) {
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(THREAD_AND_LOCATION,
+ validationException,
+ "Type %s is not a nest member of %s: %s",
+ this->external_name(),
+ k->external_name(),
+ error
+ );
+ }
+ return NULL;
+ } else {
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Type %s is not part of a nest: setting nest-host to self",
+ this->external_name());
+ }
+ // save resolved nest-host value
+ return (_nest_host = this);
+ }
+ }
+ return nest_host_k;
+}
+
+// check if 'this' and k are nestmates (same nest_host), or k is our nest_host,
+// or we are k's nest_host - all of which is covered by comparing the two
+// resolved_nest_hosts
+bool InstanceKlass::has_nestmate_access_to(InstanceKlass* k, TRAPS) {
+
+ assert(this != k, "this should be handled by higher-level code");
+
+ // Per JVMS 5.4.4 we first resolve and validate the current class, then
+ // the target class k. Resolution exceptions will be passed on by upper
+ // layers. IncompatibleClassChangeErrors from membership validation failures
+ // will also be passed through.
+
+ Symbol* icce = vmSymbols::java_lang_IncompatibleClassChangeError();
+ InstanceKlass* cur_host = nest_host(icce, CHECK_false);
+ if (cur_host == NULL) {
+ return false;
+ }
+
+ Klass* k_nest_host = k->nest_host(icce, CHECK_false);
+ if (k_nest_host == NULL) {
+ return false;
+ }
+
+ bool access = (cur_host == k_nest_host);
+
+ if (log_is_enabled(Trace, class, nestmates)) {
+ ResourceMark rm(THREAD);
+ log_trace(class, nestmates)("Class %s does %shave nestmate access to %s",
+ this->external_name(),
+ access ? "" : "NOT ",
+ k->external_name());
+ }
+
+ return access;
+}
+
InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& parser, TRAPS) {
const int size = InstanceKlass::size(parser.vtable_size(),
parser.itable_size(),
@@ -169,13 +360,11 @@
else if (is_class_loader(class_name, parser)) {
// class loader
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);
- }
- else {
+ } else {
// normal
ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_misc_kind_other);
}
- }
- else {
+ } else {
// reference
ik = new (loader_data, size, THREAD) InstanceRefKlass(parser);
}
@@ -211,11 +400,15 @@
return vtable_indices;
}
-InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind) :
+InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id) :
+ Klass(id),
_static_field_size(parser.static_field_size()),
_nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
_itable_len(parser.itable_size()),
- _reference_type(parser.reference_type()) {
+ _reference_type(parser.reference_type()),
+ _nest_members(NULL),
+ _nest_host_index(0),
+ _nest_host(NULL) {
set_vtable_length(parser.vtable_size());
set_kind(kind);
set_access_flags(parser.access_flags());
@@ -359,6 +552,13 @@
}
set_inner_classes(NULL);
+ if (nest_members() != NULL &&
+ nest_members() != Universe::the_empty_short_array() &&
+ !nest_members()->is_shared()) {
+ MetadataFactory::free_array<jushort>(loader_data, nest_members());
+ }
+ set_nest_members(NULL);
+
// We should deallocate the Annotations instance if it's not in shared spaces.
if (annotations() != NULL && !annotations()->is_shared()) {
MetadataFactory::free_metadata(loader_data, annotations());
@@ -643,7 +843,6 @@
return true;
}
-
// Rewrite the byte codes of all of the methods of a class.
// The rewriter must be called exactly once. Rewriting must happen after
// verification but before the first method of the class is executed.
@@ -1359,13 +1558,14 @@
// and skips over static methods
Method* InstanceKlass::find_instance_method(const Array<Method*>* methods,
const Symbol* name,
- const Symbol* signature) {
+ const Symbol* signature,
+ PrivateLookupMode private_mode) {
Method* const meth = InstanceKlass::find_method_impl(methods,
name,
signature,
find_overpass,
skip_static,
- find_private);
+ private_mode);
assert(((meth == NULL) || !meth->is_static()),
"find_instance_method should have skipped statics");
return meth;
@@ -1373,8 +1573,10 @@
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
-Method* InstanceKlass::find_instance_method(const Symbol* name, const Symbol* signature) const {
- return InstanceKlass::find_instance_method(methods(), name, signature);
+Method* InstanceKlass::find_instance_method(const Symbol* name,
+ const Symbol* signature,
+ PrivateLookupMode private_mode) const {
+ return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
}
// Find looks up the name/signature in the local methods array
@@ -1475,7 +1677,7 @@
// Do linear search to find matching signature. First, quick check
// for common case, ignoring overpasses if requested.
if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) {
- return hit;
+ return hit;
}
// search downwards through overloaded methods
@@ -1531,10 +1733,12 @@
}
// uncached_lookup_method searches both the local class methods array and all
-// superclasses methods arrays, skipping any overpass methods in superclasses.
+// superclasses methods arrays, skipping any overpass methods in superclasses,
+// and possibly skipping private methods.
Method* InstanceKlass::uncached_lookup_method(const Symbol* name,
const Symbol* signature,
- OverpassLookupMode overpass_mode) const {
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode private_mode) const {
OverpassLookupMode overpass_local_mode = overpass_mode;
const Klass* klass = this;
while (klass != NULL) {
@@ -1542,7 +1746,7 @@
signature,
overpass_local_mode,
find_static,
- find_private);
+ private_mode);
if (method != NULL) {
return method;
}
@@ -2044,6 +2248,8 @@
}
}
}
+
+ it->push(&_nest_members);
}
void InstanceKlass::remove_unshareable_info() {
@@ -2087,10 +2293,12 @@
guarantee(_previous_versions == NULL, "must be");
#endif
- _init_thread = NULL;
- _methods_jmethod_ids = NULL;
- _jni_ids = NULL;
- _oop_map_cache = NULL;
+ _init_thread = NULL;
+ _methods_jmethod_ids = NULL;
+ _jni_ids = NULL;
+ _oop_map_cache = NULL;
+ // clear _nest_host to ensure re-load at runtime
+ _nest_host = NULL;
}
void InstanceKlass::remove_java_mirror() {
@@ -2642,9 +2850,14 @@
if (cnt >= nof_interfaces) {
ResourceMark rm(THREAD);
stringStream ss;
+ bool same_module = (module() == holder->module());
ss.print("Receiver class %s does not implement "
- "the interface %s defining the method to be called",
- class_loader_and_module_name(), holder->class_loader_and_module_name());
+ "the interface %s defining the method to be called "
+ "(%s%s%s)",
+ external_name(), holder->external_name(),
+ (same_module) ? joint_in_module_of_loader(holder) : class_in_module_of_loader(),
+ (same_module) ? "" : "; ",
+ (same_module) ? "" : holder->class_in_module_of_loader());
THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), ss.as_string());
}
@@ -2946,6 +3159,7 @@
st->cr();
}
st->print(BULLET"inner classes: "); inner_classes()->print_value_on(st); st->cr();
+ st->print(BULLET"nest members: "); nest_members()->print_value_on(st); st->cr();
st->print(BULLET"java mirror: "); java_mirror()->print_value_on(st); st->cr();
st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", vtable_length(), p2i(start_of_vtable())); st->cr();
if (vtable_length() > 0 && (Verbose || WizardMode)) print_vtable(start_of_vtable(), vtable_length(), st);
@@ -3188,6 +3402,7 @@
n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces()));
n += (sz->_fields_bytes = sz->count_array(fields()));
n += (sz->_inner_classes_bytes = sz->count_array(inner_classes()));
+ n += (sz->_nest_members_bytes = sz->count_array(nest_members()));
sz->_ro_bytes += n;
const ConstantPool* cp = constants();
@@ -3415,10 +3630,6 @@
}
}
-oop InstanceKlass::holder_phantom() const {
- return class_loader_data()->holder_phantom();
-}
-
#ifdef ASSERT
void InstanceKlass::set_init_state(ClassState state) {
bool good_state = is_shared() ? (_init_state <= state)
--- a/src/hotspot/share/oops/instanceKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -29,7 +29,6 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/moduleEntry.hpp"
#include "classfile/packageEntry.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/referenceType.hpp"
#include "oops/annotations.hpp"
#include "oops/constMethod.hpp"
@@ -120,8 +119,11 @@
friend class ClassFileParser;
friend class CompileReplay;
+ public:
+ static const KlassID ID = InstanceKlassID;
+
protected:
- InstanceKlass(const ClassFileParser& parser, unsigned kind);
+ InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id = ID);
public:
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -165,6 +167,19 @@
// number_of_inner_classes * 4 + enclosing_method_attribute_size.
Array<jushort>* _inner_classes;
+ // The NestMembers attribute. An array of shorts, where each is a
+ // class info index for the class that is a nest member. This data
+ // has not been validated.
+ Array<jushort>* _nest_members;
+
+ // The NestHost attribute. The class info index for the class
+ // that is the nest-host of this class. This data has not been validated.
+ jushort _nest_host_index;
+
+ // Resolved nest-host klass: either true nest-host or self if we are not nested.
+ // By always being set it makes nest-member access checks simpler.
+ InstanceKlass* _nest_host;
+
// the source debug extension for this klass, NULL if not specified.
// Specified as UTF-8 string without terminating zero byte in the classfile,
// it is stored in the instanceklass as a NULL-terminated UTF-8 string
@@ -435,6 +450,24 @@
Array<u2>* inner_classes() const { return _inner_classes; }
void set_inner_classes(Array<u2>* f) { _inner_classes = f; }
+ // nest members
+ Array<u2>* nest_members() const { return _nest_members; }
+ void set_nest_members(Array<u2>* m) { _nest_members = m; }
+
+ // nest-host index
+ jushort nest_host_index() const { return _nest_host_index; }
+ void set_nest_host_index(u2 i) { _nest_host_index = i; }
+
+private:
+ // Called to verify that k is a member of this nest - does not look at k's nest-host
+ bool has_nest_member(InstanceKlass* k, TRAPS) const;
+public:
+ // Returns nest-host class, resolving and validating it if needed
+ // Returns NULL if an exception occurs during loading, or validation fails
+ InstanceKlass* nest_host(Symbol* validationException, TRAPS);
+ // Check if this klass is a nestmate of k - resolves this nest-host and k's
+ bool has_nestmate_access_to(InstanceKlass* k, TRAPS);
+
enum InnerClassAttributeOffset {
// From http://mirror.eng/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc10.html#18814
inner_class_inner_class_info_offset = 0,
@@ -554,10 +587,12 @@
const Symbol* signature);
// find a local method, but skip static methods
- Method* find_instance_method(const Symbol* name, const Symbol* signature) const;
+ Method* find_instance_method(const Symbol* name, const Symbol* signature,
+ PrivateLookupMode private_mode = find_private) const;
static Method* find_instance_method(const Array<Method*>* methods,
const Symbol* name,
- const Symbol* signature);
+ const Symbol* signature,
+ PrivateLookupMode private_mode = find_private);
// find a local method (returns NULL if not found)
Method* find_local_method(const Symbol* name,
@@ -585,7 +620,8 @@
// lookup operation (returns NULL if not found)
Method* uncached_lookup_method(const Symbol* name,
const Symbol* signature,
- OverpassLookupMode overpass_mode) const;
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode private_mode = find_private) const;
// lookup a method in all the interfaces that this class implements
// (returns NULL if not found)
@@ -653,11 +689,6 @@
return is_anonymous() ? java_mirror() : class_loader();
}
- // Load the klass's holder as a phantom. This is useful when a weak Klass
- // pointer has been "peeked" and then must be kept alive before it may
- // be used safely.
- oop holder_phantom() const;
-
bool is_contended() const {
return (_misc_flags & _misc_is_contended) != 0;
}
@@ -1196,89 +1227,56 @@
#endif
// Oop fields (and metadata) iterators
- // [nv = true] Use non-virtual calls to do_oop_nv.
- // [nv = false] Use virtual calls to do_oop.
//
// The InstanceKlass iterators also visits the Object's klass.
// Forward iteration
public:
// Iterate over all oop fields in the oop maps.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure);
- protected:
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline int oop_oop_iterate(oop obj, OopClosureType* closure);
- private:
- // Iterate over all oop fields in the oop maps.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_oop_maps_specialized(oop obj, OopClosureType* closure);
-
// Iterate over all oop fields in one oop map.
- template <bool nv, typename T, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_oop_map(OopMapBlock* map, oop obj, OopClosureType* closure);
// Reverse iteration
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- public:
- // Iterate over all oop fields in the oop maps.
- template <bool nv, class OopClosureType>
- inline void oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure);
-
- protected:
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline int oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
private:
// Iterate over all oop fields in the oop maps.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_oop_maps_specialized_reverse(oop obj, OopClosureType* closure);
+ template <typename T, class OopClosureType>
+ inline void oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure);
// Iterate over all oop fields in one oop map.
- template <bool nv, typename T, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_oop_map_reverse(OopMapBlock* map, oop obj, OopClosureType* closure);
-#endif // INCLUDE_OOP_OOP_ITERATE_BACKWARDS
// Bounded range iteration
public:
// Iterate over all oop fields in the oop maps.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr);
- protected:
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline int oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
private:
- // Iterate over all oop fields in the oop maps.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_oop_maps_specialized_bounded(oop obj, OopClosureType* closure, MemRegion mr);
-
// Iterate over all oop fields in one oop map.
- template <bool nv, typename T, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_oop_map_bounded(OopMapBlock* map, oop obj, OopClosureType* closure, MemRegion mr);
public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
-#endif
-
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
public:
--- a/src/hotspot/share/oops/instanceKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -54,30 +54,28 @@
// By force inlining the following functions, we get similar GC performance
// as the previous macro based implementation.
-template <bool nv, typename T, class OopClosureType>
+template <typename T, class OopClosureType>
ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map(OopMapBlock* map, oop obj, OopClosureType* closure) {
T* p = (T*)obj->obj_field_addr_raw<T>(map->offset());
T* const end = p + map->count();
for (; p < end; ++p) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, typename T, class OopClosureType>
+template <typename T, class OopClosureType>
ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map_reverse(OopMapBlock* map, oop obj, OopClosureType* closure) {
T* const start = (T*)obj->obj_field_addr_raw<T>(map->offset());
T* p = start + map->count();
while (start < p) {
--p;
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-#endif
-template <bool nv, typename T, class OopClosureType>
+template <typename T, class OopClosureType>
ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_map_bounded(OopMapBlock* map, oop obj, OopClosureType* closure, MemRegion mr) {
T* p = (T*)obj->obj_field_addr_raw<T>(map->offset());
T* end = p + map->count();
@@ -96,111 +94,73 @@
}
for (;p < end; ++p) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-template <bool nv, typename T, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized(oop obj, OopClosureType* closure) {
+template <typename T, class OopClosureType>
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure) {
OopMapBlock* map = start_of_nonstatic_oop_maps();
OopMapBlock* const end_map = map + nonstatic_oop_map_count();
for (; map < end_map; ++map) {
- oop_oop_iterate_oop_map<nv, T>(map, obj, closure);
+ oop_oop_iterate_oop_map<T>(map, obj, closure);
}
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, typename T, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_reverse(oop obj, OopClosureType* closure) {
+template <typename T, class OopClosureType>
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure) {
OopMapBlock* const start_map = start_of_nonstatic_oop_maps();
OopMapBlock* map = start_map + nonstatic_oop_map_count();
while (start_map < map) {
--map;
- oop_oop_iterate_oop_map_reverse<nv, T>(map, obj, closure);
+ oop_oop_iterate_oop_map_reverse<T>(map, obj, closure);
}
}
-#endif
-template <bool nv, typename T, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_specialized_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+template <typename T, class OopClosureType>
+ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
OopMapBlock* map = start_of_nonstatic_oop_maps();
OopMapBlock* const end_map = map + nonstatic_oop_map_count();
for (;map < end_map; ++map) {
- oop_oop_iterate_oop_map_bounded<nv, T>(map, obj, closure, mr);
- }
-}
-
-template <bool nv, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure) {
- if (UseCompressedOops) {
- oop_oop_iterate_oop_maps_specialized<nv, narrowOop>(obj, closure);
- } else {
- oop_oop_iterate_oop_maps_specialized<nv, oop>(obj, closure);
+ oop_oop_iterate_oop_map_bounded<T>(map, obj, closure, mr);
}
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure) {
- if (UseCompressedOops) {
- oop_oop_iterate_oop_maps_specialized_reverse<nv, narrowOop>(obj, closure);
- } else {
- oop_oop_iterate_oop_maps_specialized_reverse<nv, oop>(obj, closure);
- }
-}
-#endif
-
-template <bool nv, class OopClosureType>
-ALWAYSINLINE void InstanceKlass::oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- if (UseCompressedOops) {
- oop_oop_iterate_oop_maps_specialized_bounded<nv, narrowOop>(obj, closure, mr);
- } else {
- oop_oop_iterate_oop_maps_specialized_bounded<nv, oop>(obj, closure, mr);
- }
-}
-
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
ALWAYSINLINE int InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- if (Devirtualizer<nv>::do_metadata(closure)) {
- Devirtualizer<nv>::do_klass(closure, this);
+ if (Devirtualizer::do_metadata(closure)) {
+ Devirtualizer::do_klass(closure, this);
}
- oop_oop_iterate_oop_maps<nv>(obj, closure);
+ oop_oop_iterate_oop_maps<T>(obj, closure);
return size_helper();
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
ALWAYSINLINE int InstanceKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- assert(!Devirtualizer<nv>::do_metadata(closure),
+ assert(!Devirtualizer::do_metadata(closure),
"Code to handle metadata is not implemented");
- oop_oop_iterate_oop_maps_reverse<nv>(obj, closure);
-
- return size_helper();
-}
-#endif
-
-template <bool nv, class OopClosureType>
-ALWAYSINLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- if (Devirtualizer<nv>::do_metadata(closure)) {
- if (mr.contains(obj)) {
- Devirtualizer<nv>::do_klass(closure, this);
- }
- }
-
- oop_oop_iterate_oop_maps_bounded<nv>(obj, closure, mr);
+ oop_oop_iterate_oop_maps_reverse<T>(obj, closure);
return size_helper();
}
-#define ALL_INSTANCE_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( InstanceKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( InstanceKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BACKWARDS(InstanceKlass, OopClosureType, nv_suffix)
+template <typename T, class OopClosureType>
+ALWAYSINLINE int InstanceKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ if (Devirtualizer::do_metadata(closure)) {
+ if (mr.contains(obj)) {
+ Devirtualizer::do_klass(closure, this);
+ }
+ }
+
+ oop_oop_iterate_oop_maps_bounded<T>(obj, closure, mr);
+
+ return size_helper();
+}
#endif // SHARE_VM_OOPS_INSTANCEKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/instanceMirrorKlass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,6 @@
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/oopFactory.hpp"
#include "oops/instanceKlass.hpp"
--- a/src/hotspot/share/oops/instanceMirrorKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,6 @@
#define SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
#include "classfile/systemDictionary.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/handles.hpp"
#include "utilities/macros.hpp"
@@ -45,10 +44,13 @@
friend class VMStructs;
friend class InstanceKlass;
+ public:
+ static const KlassID ID = InstanceMirrorKlassID;
+
private:
static int _offset_of_static_fields;
- InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_mirror) {}
+ InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_mirror, ID) {}
public:
InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -98,60 +100,33 @@
#endif
// Oop fields (and metadata) iterators
- // [nv = true] Use non-virtual calls to do_oop_nv.
- // [nv = false] Use virtual calls to do_oop.
//
// The InstanceMirrorKlass iterators also visit the hidden Klass pointer.
- public:
// Iterate over the static fields.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_statics(oop obj, OopClosureType* closure);
- private:
- // Iterate over the static fields.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_statics_specialized(oop obj, OopClosureType* closure);
-
// Forward iteration
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate(oop obj, OopClosureType* closure);
-
// Reverse iteration
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
-#endif
-
// Bounded range iteration
// Iterate over the oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
- // Iterate over the static fields.
- template <bool nv, class OopClosureType>
- inline void oop_oop_iterate_statics_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ private:
// Iterate over the static fields.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_statics_specialized_bounded(oop obj, OopClosureType* closure, MemRegion mr);
-
-
- public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
-#endif
+ template <typename T, class OopClosureType>
+ inline void oop_oop_iterate_statics_bounded(oop obj, OopClosureType* closure, MemRegion mr);
};
#endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
--- a/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceMirrorKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -33,30 +33,21 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
-template <bool nv, typename T, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate_statics_specialized(oop obj, OopClosureType* closure) {
+template <typename T, class OopClosureType>
+void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closure) {
T* p = (T*)start_of_static_fields(obj);
T* const end = p + java_lang_Class::static_oop_field_count(obj);
for (; p < end; ++p) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-template <bool nv, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate_statics(oop obj, OopClosureType* closure) {
- if (UseCompressedOops) {
- oop_oop_iterate_statics_specialized<nv, narrowOop>(obj, closure);
- } else {
- oop_oop_iterate_statics_specialized<nv, oop>(obj, closure);
- }
-}
+template <typename T, class OopClosureType>
+void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate<T>(obj, closure);
-template <bool nv, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate<nv>(obj, closure);
-
- if (Devirtualizer<nv>::do_metadata(closure)) {
+ if (Devirtualizer::do_metadata(closure)) {
Klass* klass = java_lang_Class::as_Klass(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
@@ -66,9 +57,9 @@
// loader data is claimed, this is done by calling do_cld explicitly.
// For non-anonymous classes the call to do_cld is made when the class
// loader itself is handled.
- Devirtualizer<nv>::do_cld(closure, klass->class_loader_data());
+ Devirtualizer::do_cld(closure, klass->class_loader_data());
} else {
- Devirtualizer<nv>::do_klass(closure, klass);
+ Devirtualizer::do_klass(closure, klass);
}
} else {
// We would like to assert here (as below) that if klass has been NULL, then
@@ -83,22 +74,20 @@
}
}
- oop_oop_iterate_statics<nv>(obj, closure);
+ oop_oop_iterate_statics<T>(obj, closure);
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
void InstanceMirrorKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
+ InstanceKlass::oop_oop_iterate_reverse<T>(obj, closure);
- InstanceMirrorKlass::oop_oop_iterate_statics<nv>(obj, closure);
+ InstanceMirrorKlass::oop_oop_iterate_statics<T>(obj, closure);
}
-#endif // INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, typename T, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate_statics_specialized_bounded(oop obj,
- OopClosureType* closure,
- MemRegion mr) {
+template <typename T, class OopClosureType>
+void InstanceMirrorKlass::oop_oop_iterate_statics_bounded(oop obj,
+ OopClosureType* closure,
+ MemRegion mr) {
T* p = (T*)start_of_static_fields(obj);
T* end = p + java_lang_Class::static_oop_field_count(obj);
@@ -116,39 +105,25 @@
}
for (;p < end; ++p) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-template <bool nv, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate_statics_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- if (UseCompressedOops) {
- oop_oop_iterate_statics_specialized_bounded<nv, narrowOop>(obj, closure, mr);
- } else {
- oop_oop_iterate_statics_specialized_bounded<nv, oop>(obj, closure, mr);
- }
-}
+template <typename T, class OopClosureType>
+void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ InstanceKlass::oop_oop_iterate_bounded<T>(obj, closure, mr);
-template <bool nv, class OopClosureType>
-void InstanceMirrorKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
-
- if (Devirtualizer<nv>::do_metadata(closure)) {
+ if (Devirtualizer::do_metadata(closure)) {
if (mr.contains(obj)) {
Klass* klass = java_lang_Class::as_Klass(obj);
// We'll get NULL for primitive mirrors.
if (klass != NULL) {
- Devirtualizer<nv>::do_klass(closure, klass);
+ Devirtualizer::do_klass(closure, klass);
}
}
}
- oop_oop_iterate_statics_bounded<nv>(obj, closure, mr);
+ oop_oop_iterate_statics_bounded<T>(obj, closure, mr);
}
-#define ALL_INSTANCE_MIRROR_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( InstanceMirrorKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( InstanceMirrorKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BACKWARDS(InstanceMirrorKlass, OopClosureType, nv_suffix)
-
#endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/instanceRefKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceRefKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,6 @@
#ifndef SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/instanceKlass.hpp"
#include "utilities/macros.hpp"
@@ -50,8 +49,11 @@
class InstanceRefKlass: public InstanceKlass {
friend class InstanceKlass;
+ public:
+ static const KlassID ID = InstanceRefKlassID;
+
private:
- InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_reference) {}
+ InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_reference, ID) {}
public:
InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
@@ -67,52 +69,48 @@
#endif
// Oop fields (and metadata) iterators
- // [nv = true] Use non-virtual calls to do_oop_nv.
- // [nv = false] Use virtual calls to do_oop.
//
// The InstanceRefKlass iterators also support reference processing.
// Forward iteration
-private:
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Reverse iteration
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
-#endif
// Bounded range iteration
// Iterate over all oop fields and metadata.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
+ private:
+
// Reference processing part of the iterators.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType, class Contains>
- inline void oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains);
+ template <typename T, class OopClosureType, class Contains>
+ inline void oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure, Contains& contains);
// Only perform reference processing if the referent object is within mr.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_ref_processing_bounded(oop obj, OopClosureType* closure, MemRegion mr);
// Reference processing
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure);
// Building blocks for specialized handling.
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void do_referent(oop obj, OopClosureType* closure, Contains& contains);
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void do_next(oop obj, OopClosureType* closure, Contains& contains);
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void do_discovered(oop obj, OopClosureType* closure, Contains& contains);
template <typename T, class OopClosureType>
@@ -120,32 +118,23 @@
// Do discovery while handling InstanceRefKlasses. Reference discovery
// is only done if the closure provides a ReferenceProcessor.
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains);
// Used for a special case in G1 where the closure needs to be applied
// to the discovered field. Reference discovery is also done if the
// closure provides a ReferenceProcessor.
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void oop_oop_iterate_discovered_and_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains);
// Apply the closure to all fields. No reference discovery is done.
- template <bool nv, typename T, class OopClosureType, class Contains>
+ template <typename T, class OopClosureType, class Contains>
static void oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains);
template <typename T>
static void trace_reference_gc(const char *s, oop obj) NOT_DEBUG_RETURN;
public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_BACKWARDS)
-#endif
-
// Update non-static oop maps so 'referent', 'nextPending' and
// 'discovered' will look like non-oops
static void update_nonstatic_oop_maps(Klass* k);
--- a/src/hotspot/share/oops/instanceRefKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/instanceRefKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -37,19 +37,19 @@
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
-template <bool nv, typename T, class OopClosureType, class Contains>
+template <typename T, class OopClosureType, class Contains>
void InstanceRefKlass::do_referent(oop obj, OopClosureType* closure, Contains& contains) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr_raw(obj);
if (contains(referent_addr)) {
- Devirtualizer<nv>::do_oop(closure, referent_addr);
+ Devirtualizer::do_oop(closure, referent_addr);
}
}
-template <bool nv, typename T, class OopClosureType, class Contains>
+template <typename T, class OopClosureType, class Contains>
void InstanceRefKlass::do_discovered(oop obj, OopClosureType* closure, Contains& contains) {
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr_raw(obj);
if (contains(discovered_addr)) {
- Devirtualizer<nv>::do_oop(closure, discovered_addr);
+ Devirtualizer::do_oop(closure, discovered_addr);
}
}
@@ -76,7 +76,7 @@
return false;
}
-template <bool nv, typename T, class OopClosureType, class Contains>
+template <typename T, class OopClosureType, class Contains>
void InstanceRefKlass::oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains) {
// Try to discover reference and return if it succeeds.
if (try_discover<T>(obj, type, closure)) {
@@ -84,38 +84,38 @@
}
// Treat referent and discovered as normal oops.
- do_referent<nv, T>(obj, closure, contains);
- do_discovered<nv, T>(obj, closure, contains);
+ do_referent<T>(obj, closure, contains);
+ do_discovered<T>(obj, closure, contains);
}
-template <bool nv, typename T, class OopClosureType, class Contains>
+template <typename T, class OopClosureType, class Contains>
void InstanceRefKlass::oop_oop_iterate_fields(oop obj, OopClosureType* closure, Contains& contains) {
- do_referent<nv, T>(obj, closure, contains);
- do_discovered<nv, T>(obj, closure, contains);
+ do_referent<T>(obj, closure, contains);
+ do_discovered<T>(obj, closure, contains);
}
-template <bool nv, typename T, class OopClosureType, class Contains>
+template <typename T, class OopClosureType, class Contains>
void InstanceRefKlass::oop_oop_iterate_discovered_and_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains) {
// Explicitly apply closure to the discovered field.
- do_discovered<nv, T>(obj, closure, contains);
+ do_discovered<T>(obj, closure, contains);
// Then do normal reference processing with discovery.
- oop_oop_iterate_discovery<nv, T>(obj, type, closure, contains);
+ oop_oop_iterate_discovery<T>(obj, type, closure, contains);
}
-template <bool nv, typename T, class OopClosureType, class Contains>
-void InstanceRefKlass::oop_oop_iterate_ref_processing_specialized(oop obj, OopClosureType* closure, Contains& contains) {
+template <typename T, class OopClosureType, class Contains>
+void InstanceRefKlass::oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure, Contains& contains) {
switch (closure->reference_iteration_mode()) {
- case ExtendedOopClosure::DO_DISCOVERY:
+ case OopIterateClosure::DO_DISCOVERY:
trace_reference_gc<T>("do_discovery", obj);
- oop_oop_iterate_discovery<nv, T>(obj, reference_type(), closure, contains);
+ oop_oop_iterate_discovery<T>(obj, reference_type(), closure, contains);
break;
- case ExtendedOopClosure::DO_DISCOVERED_AND_DISCOVERY:
+ case OopIterateClosure::DO_DISCOVERED_AND_DISCOVERY:
trace_reference_gc<T>("do_discovered_and_discovery", obj);
- oop_oop_iterate_discovered_and_discovery<nv, T>(obj, reference_type(), closure, contains);
+ oop_oop_iterate_discovered_and_discovery<T>(obj, reference_type(), closure, contains);
break;
- case ExtendedOopClosure::DO_FIELDS:
+ case OopIterateClosure::DO_FIELDS:
trace_reference_gc<T>("do_fields", obj);
- oop_oop_iterate_fields<nv, T>(obj, closure, contains);
+ oop_oop_iterate_fields<T>(obj, closure, contains);
break;
default:
ShouldNotReachHere();
@@ -127,14 +127,10 @@
template <typename T> bool operator()(T* p) const { return true; }
};
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
void InstanceRefKlass::oop_oop_iterate_ref_processing(oop obj, OopClosureType* closure) {
AlwaysContains always_contains;
- if (UseCompressedOops) {
- oop_oop_iterate_ref_processing_specialized<nv, narrowOop>(obj, closure, always_contains);
- } else {
- oop_oop_iterate_ref_processing_specialized<nv, oop>(obj, closure, always_contains);
- }
+ oop_oop_iterate_ref_processing<T>(obj, closure, always_contains);
}
class MrContains {
@@ -144,38 +140,31 @@
template <typename T> bool operator()(T* p) const { return _mr.contains(p); }
};
-template <bool nv, class OopClosureType>
+template <typename T, class OopClosureType>
void InstanceRefKlass::oop_oop_iterate_ref_processing_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
const MrContains contains(mr);
- if (UseCompressedOops) {
- oop_oop_iterate_ref_processing_specialized<nv, narrowOop>(obj, closure, contains);
- } else {
- oop_oop_iterate_ref_processing_specialized<nv, oop>(obj, closure, contains);
- }
+ oop_oop_iterate_ref_processing<T>(obj, closure, contains);
+}
+
+template <typename T, class OopClosureType>
+void InstanceRefKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate<T>(obj, closure);
+
+ oop_oop_iterate_ref_processing<T>(obj, closure);
}
-template <bool nv, class OopClosureType>
-void InstanceRefKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate<nv>(obj, closure);
+template <typename T, class OopClosureType>
+void InstanceRefKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ InstanceKlass::oop_oop_iterate_reverse<T>(obj, closure);
- oop_oop_iterate_ref_processing<nv>(obj, closure);
+ oop_oop_iterate_ref_processing<T>(obj, closure);
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-template <bool nv, class OopClosureType>
-void InstanceRefKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
- InstanceKlass::oop_oop_iterate_reverse<nv>(obj, closure);
+template <typename T, class OopClosureType>
+void InstanceRefKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
+ InstanceKlass::oop_oop_iterate_bounded<T>(obj, closure, mr);
- oop_oop_iterate_ref_processing<nv>(obj, closure);
-}
-#endif // INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-
-
-template <bool nv, class OopClosureType>
-void InstanceRefKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
- InstanceKlass::oop_oop_iterate_bounded<nv>(obj, closure, mr);
-
- oop_oop_iterate_ref_processing_bounded<nv>(obj, closure, mr);
+ oop_oop_iterate_ref_processing_bounded<T>(obj, closure, mr);
}
#ifdef ASSERT
@@ -192,11 +181,4 @@
}
#endif
-// Macro to define InstanceRefKlass::oop_oop_iterate for virtual/nonvirtual for
-// all closures. Macros calling macros above for each oop size.
-#define ALL_INSTANCE_REF_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( InstanceRefKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( InstanceRefKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BACKWARDS(InstanceRefKlass, OopClosureType, nv_suffix)
-
#endif // SHARE_VM_OOPS_INSTANCEREFKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/klass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/klass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -168,7 +168,9 @@
return NULL;
}
-Method* Klass::uncached_lookup_method(const Symbol* name, const Symbol* signature, OverpassLookupMode overpass_mode) const {
+Method* Klass::uncached_lookup_method(const Symbol* name, const Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode private_mode) const {
#ifdef ASSERT
tty->print_cr("Error: uncached_lookup_method called on a klass oop."
" Likely error: reflection method does not correctly"
@@ -188,9 +190,10 @@
// which doesn't zero out the memory before calling the constructor.
// Need to set the _java_mirror field explicitly to not hit an assert that the field
// should be NULL before setting it.
-Klass::Klass() : _prototype_header(markOopDesc::prototype()),
- _shared_class_path_index(-1),
- _java_mirror(NULL) {
+Klass::Klass(KlassID id) : _id(id),
+ _prototype_header(markOopDesc::prototype()),
+ _shared_class_path_index(-1),
+ _java_mirror(NULL) {
CDS_ONLY(_shared_class_flags = 0;)
CDS_JAVA_HEAP_ONLY(_archived_mirror = 0;)
_primary_supers[0] = this;
@@ -386,6 +389,10 @@
debug_only(verify();)
}
+oop Klass::holder_phantom() const {
+ return class_loader_data()->holder_phantom();
+}
+
void Klass::clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses) {
if (!ClassUnloading || !unloading_occurred) {
return;
@@ -767,80 +774,124 @@
#endif // PRODUCT
-// The caller of class_loader_and_module_name() (or one of its callers)
-// must use a ResourceMark in order to correctly free the result.
-const char* Klass::class_loader_and_module_name() const {
- const char* delim = "/";
- size_t delim_len = strlen(delim);
-
- const char* fqn = external_name();
- // Length of message to return; always include FQN
- size_t msglen = strlen(fqn) + 1;
-
- bool has_cl_name = false;
- bool has_mod_name = false;
- bool has_version = false;
+// Caller needs ResourceMark
+// joint_in_module_of_loader provides an optimization if 2 classes are in
+// the same module to succinctly print out relevant information about their
+// module name and class loader's name_and_id for error messages.
+// Format:
+// <fully-qualified-external-class-name1> and <fully-qualified-external-class-name2>
+// are in module <module-name>[@<version>]
+// of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
+const char* Klass::joint_in_module_of_loader(const Klass* class2, bool include_parent_loader) const {
+ assert(module() == class2->module(), "classes do not have the same module");
+ const char* class1_name = external_name();
+ size_t len = strlen(class1_name) + 1;
- // Use class loader name, if exists and not builtin
- const char* class_loader_name = "";
- ClassLoaderData* cld = class_loader_data();
- assert(cld != NULL, "class_loader_data should not be NULL");
- if (!cld->is_builtin_class_loader_data()) {
- // If not builtin, look for name
- oop loader = class_loader();
- if (loader != NULL) {
- oop class_loader_name_oop = java_lang_ClassLoader::name(loader);
- if (class_loader_name_oop != NULL) {
- class_loader_name = java_lang_String::as_utf8_string(class_loader_name_oop);
- if (class_loader_name != NULL && class_loader_name[0] != '\0') {
- has_cl_name = true;
- msglen += strlen(class_loader_name) + delim_len;
- }
- }
- }
+ const char* class2_description = class2->class_in_module_of_loader(true, include_parent_loader);
+ len += strlen(class2_description);
+
+ len += strlen(" and ");
+
+ char* joint_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
+
+ // Just return the FQN if error when allocating string
+ if (joint_description == NULL) {
+ return class1_name;
}
+ jio_snprintf(joint_description, len, "%s and %s",
+ class1_name,
+ class2_description);
+
+ return joint_description;
+}
+
+// Caller needs ResourceMark
+// class_in_module_of_loader provides a standard way to include
+// relevant information about a class, such as its module name as
+// well as its class loader's name_and_id, in error messages and logging.
+// Format:
+// <fully-qualified-external-class-name> is in module <module-name>[@<version>]
+// of loader <loader-name_and_id>[, parent loader <parent-loader-name_and_id>]
+const char* Klass::class_in_module_of_loader(bool use_are, bool include_parent_loader) const {
+ // 1. fully qualified external name of class
+ const char* klass_name = external_name();
+ size_t len = strlen(klass_name) + 1;
+
+ // 2. module name + @version
const char* module_name = "";
const char* version = "";
+ bool has_version = false;
+ bool module_is_named = false;
+ const char* module_name_phrase = "";
const Klass* bottom_klass = is_objArray_klass() ?
- ObjArrayKlass::cast(this)->bottom_klass() : this;
+ ObjArrayKlass::cast(this)->bottom_klass() : this;
if (bottom_klass->is_instance_klass()) {
ModuleEntry* module = InstanceKlass::cast(bottom_klass)->module();
- // Use module name, if exists
if (module->is_named()) {
- has_mod_name = true;
+ module_is_named = true;
+ module_name_phrase = "module ";
module_name = module->name()->as_C_string();
- msglen += strlen(module_name);
+ len += strlen(module_name);
// Use version if exists and is not a jdk module
if (module->should_show_version()) {
has_version = true;
version = module->version()->as_C_string();
- msglen += strlen(version) + 1; // +1 for "@"
+ // Include stlen(version) + 1 for the "@"
+ len += strlen(version) + 1;
}
+ } else {
+ module_name = UNNAMED_MODULE;
+ len += UNNAMED_MODULE_LEN;
}
} else {
- // klass is an array of primitives, so its module is java.base
+ // klass is an array of primitives, module is java.base
+ module_is_named = true;
+ module_name_phrase = "module ";
module_name = JAVA_BASE_NAME;
- }
-
- if (has_cl_name || has_mod_name) {
- msglen += delim_len;
+ len += JAVA_BASE_NAME_LEN;
}
- char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
+ // 3. class loader's name_and_id
+ ClassLoaderData* cld = class_loader_data();
+ assert(cld != NULL, "class_loader_data should not be null");
+ const char* loader_name_and_id = cld->loader_name_and_id();
+ len += strlen(loader_name_and_id);
- // Just return the FQN if error in allocating string
- if (message == NULL) {
- return fqn;
+ // 4. include parent loader information
+ const char* parent_loader_phrase = "";
+ const char* parent_loader_name_and_id = "";
+ if (include_parent_loader &&
+ !cld->is_builtin_class_loader_data()) {
+ oop parent_loader = java_lang_ClassLoader::parent(class_loader());
+ ClassLoaderData *parent_cld = ClassLoaderData::class_loader_data(parent_loader);
+ assert(parent_cld != NULL, "parent's class loader data should not be null");
+ parent_loader_name_and_id = parent_cld->loader_name_and_id();
+ parent_loader_phrase = ", parent loader ";
+ len += strlen(parent_loader_phrase) + strlen(parent_loader_name_and_id);
}
- jio_snprintf(message, msglen, "%s%s%s%s%s%s%s",
- class_loader_name,
- (has_cl_name) ? delim : "",
- (has_mod_name) ? module_name : "",
+ // Start to construct final full class description string
+ len += ((use_are) ? strlen(" are in ") : strlen(" is in "));
+ len += strlen(module_name_phrase) + strlen(" of loader ");
+
+ char* class_description = NEW_RESOURCE_ARRAY_RETURN_NULL(char, len);
+
+ // Just return the FQN if error when allocating string
+ if (class_description == NULL) {
+ return klass_name;
+ }
+
+ jio_snprintf(class_description, len, "%s %s in %s%s%s%s of loader %s%s%s",
+ klass_name,
+ (use_are) ? "are" : "is",
+ module_name_phrase,
+ module_name,
(has_version) ? "@" : "",
(has_version) ? version : "",
- (has_cl_name || has_mod_name) ? delim : "",
- fqn);
- return message;
+ loader_name_and_id,
+ parent_loader_phrase,
+ parent_loader_name_and_id);
+
+ return class_description;
}
--- a/src/hotspot/share/oops/klass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/klass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,6 @@
#define SHARE_VM_OOPS_KLASS_HPP
#include "classfile/classLoaderData.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.hpp"
#include "memory/memRegion.hpp"
#include "oops/metadata.hpp"
@@ -38,6 +37,18 @@
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
+// Klass IDs for all subclasses of Klass
+enum KlassID {
+ InstanceKlassID,
+ InstanceRefKlassID,
+ InstanceMirrorKlassID,
+ InstanceClassLoaderKlassID,
+ TypeArrayKlassID,
+ ObjArrayKlassID
+};
+
+const uint KLASS_ID_COUNT = 6;
+
//
// A Klass provides:
// 1: language level class object (method dictionary etc.)
@@ -103,6 +114,9 @@
// because it is frequently queried.
jint _layout_helper;
+ // Klass identifier used to implement devirtualized oop closure dispatching.
+ const KlassID _id;
+
// The fields _super_check_offset, _secondary_super_cache, _secondary_supers
// and _primary_supers all help make fast subtype checks. See big discussion
// in doc/server_compiler/checktype.txt
@@ -173,11 +187,14 @@
protected:
// Constructor
- Klass();
+ Klass(KlassID id);
+ Klass() : _id(KlassID(-1)) { assert(DumpSharedSpaces || UseSharedSpaces, "only for cds"); }
void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw();
public:
+ int id() { return _id; }
+
enum DefaultsLookupMode { find_defaults, skip_defaults };
enum OverpassLookupMode { find_overpass, skip_overpass };
enum StaticLookupMode { find_static, skip_static };
@@ -467,7 +484,9 @@
// lookup operation for MethodLookupCache
friend class MethodLookupCache;
virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const;
- virtual Method* uncached_lookup_method(const Symbol* name, const Symbol* signature, OverpassLookupMode overpass_mode) const;
+ virtual Method* uncached_lookup_method(const Symbol* name, const Symbol* signature,
+ OverpassLookupMode overpass_mode,
+ PrivateLookupMode = find_private) const;
public:
Method* lookup_method(const Symbol* name, const Symbol* signature) const {
return uncached_lookup_method(name, signature, find_overpass);
@@ -541,7 +560,8 @@
// and the package separators as '/'.
virtual const char* signature_name() const;
- const char* class_loader_and_module_name() const;
+ const char* joint_in_module_of_loader(const Klass* class2, bool include_parent_loader = false) const;
+ const char* class_in_module_of_loader(bool use_are = false, bool include_parent_loader = false) const;
// Returns "interface", "abstract class" or "class".
const char* external_kind() const;
@@ -638,6 +658,11 @@
// Klass is considered alive. Has already been marked as unloading.
bool is_loader_alive() const { return !class_loader_data()->is_unloading(); }
+ // Load the klass's holder as a phantom. This is useful when a weak Klass
+ // pointer has been "peeked" and then must be kept alive before it may
+ // be used safely.
+ oop holder_phantom() const;
+
static void clean_weak_klass_links(bool unloading_occurred, bool clean_alive_klasses = true);
static void clean_subklass_tree() {
clean_weak_klass_links(/*unloading_occurred*/ true , /* clean_alive_klasses */ false);
@@ -653,24 +678,6 @@
virtual void oop_pc_update_pointers(oop obj, ParCompactionManager* cm) = 0;
#endif
- // Iterators specialized to particular subtypes
- // of ExtendedOopClosure, to avoid closure virtual calls.
-#define Klass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- virtual void oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) = 0; \
- /* Iterates "closure" over all the oops in "obj" (of type "this") within "mr". */ \
- virtual void oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) = 0;
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-#define Klass_OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
- virtual void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) = 0;
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL_BACKWARDS)
-#endif
-
virtual void array_klasses_do(void f(Klass* k)) {}
// Return self, except for abstract classes with exactly 1
@@ -718,44 +725,4 @@
static Klass* decode_klass(narrowKlass v);
};
-// Helper to convert the oop iterate macro suffixes into bool values that can be used by template functions.
-#define nvs_nv_to_bool true
-#define nvs_v_to_bool false
-#define nvs_to_bool(nv_suffix) nvs##nv_suffix##_to_bool
-
-// Oop iteration macros for declarations.
-// Used to generate declarations in the *Klass header files.
-
-#define OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- void oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure); \
- void oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr);
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-#define OOP_OOP_ITERATE_DECL_BACKWARDS(OopClosureType, nv_suffix) \
- void oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure);
-#endif
-
-
-// Oop iteration macros for definitions.
-// Used to generate definitions in the *Klass.inline.hpp files.
-
-#define OOP_OOP_ITERATE_DEFN(KlassType, OopClosureType, nv_suffix) \
-void KlassType::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
- oop_oop_iterate<nvs_to_bool(nv_suffix)>(obj, closure); \
-}
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-#define OOP_OOP_ITERATE_DEFN_BACKWARDS(KlassType, OopClosureType, nv_suffix) \
-void KlassType::oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
- oop_oop_iterate_reverse<nvs_to_bool(nv_suffix)>(obj, closure); \
-}
-#else
-#define OOP_OOP_ITERATE_DEFN_BACKWARDS(KlassType, OopClosureType, nv_suffix)
-#endif
-
-#define OOP_OOP_ITERATE_DEFN_BOUNDED(KlassType, OopClosureType, nv_suffix) \
-void KlassType::oop_oop_iterate_bounded##nv_suffix(oop obj, OopClosureType* closure, MemRegion mr) { \
- oop_oop_iterate_bounded<nvs_to_bool(nv_suffix)>(obj, closure, mr); \
-}
-
#endif // SHARE_VM_OOPS_KLASS_HPP
--- a/src/hotspot/share/oops/klassVtable.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/klassVtable.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1122,7 +1122,7 @@
inline bool interface_method_needs_itable_index(Method* m) {
if (m->is_static()) return false; // e.g., Stream.empty
if (m->is_initializer()) return false; // <init> or <clinit>
- if (m->is_private()) return false; // requires invokeSpecial
+ if (m->is_private()) return false; // uses direct call
// If an interface redeclares a method from java.lang.Object,
// it should already have a vtable index, don't touch it.
// e.g., CharSequence.toString (from initialize_vtable)
@@ -1211,8 +1211,13 @@
methodHandle target;
if (m->has_itable_index()) {
// This search must match the runtime resolution, i.e. selection search for invokeinterface
- // to correctly enforce loader constraints for interface method inheritance
- target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(), CHECK);
+ // to correctly enforce loader constraints for interface method inheritance.
+ // Private methods are skipped as a private class method can never be the implementation
+ // of an interface method.
+ // Invokespecial does not perform selection based on the receiver, so it does not use
+ // the cached itable.
+ target = LinkResolver::lookup_instance_method_in_klasses(_klass, m->name(), m->signature(),
+ Klass::skip_private, CHECK);
}
if (target == NULL || !target->is_public() || target->is_abstract() || target->is_overpass()) {
assert(target == NULL || !target->is_overpass() || target->is_public(),
--- a/src/hotspot/share/oops/method.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/method.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -690,12 +690,10 @@
int Method::line_number_from_bci(int bci) const {
- if (bci == SynchronizationEntryBCI) bci = 0;
- assert(bci == 0 || 0 <= bci && bci < code_size(), "illegal bci");
int best_bci = 0;
int best_line = -1;
-
- if (has_linenumber_table()) {
+ if (bci == SynchronizationEntryBCI) bci = 0;
+ if (0 <= bci && bci < code_size() && has_linenumber_table()) {
// The line numbers are a short array of 2-tuples [start_pc, line_number].
// Not necessarily sorted and not necessarily one-to-one.
CompressedLineNumberReadStream stream(compressed_linenumber_table());
--- a/src/hotspot/share/oops/objArrayKlass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayKlass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -29,7 +29,6 @@
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceClosure.hpp"
@@ -142,7 +141,7 @@
return oak;
}
-ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name) {
+ObjArrayKlass::ObjArrayKlass(int n, Klass* element_klass, Symbol* name) : ArrayKlass(name, ID) {
this->set_dimension(n);
this->set_element_klass(element_klass);
// decrement refcount because object arrays are not explicitly freed. The
--- a/src/hotspot/share/oops/objArrayKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -34,6 +34,10 @@
class ObjArrayKlass : public ArrayKlass {
friend class VMStructs;
friend class JVMCIVMStructs;
+
+ public:
+ static const KlassID ID = ObjArrayKlassID;
+
private:
// If you add a new field that points to any metaspace object, you
// must add this field to ObjArrayKlass::metaspace_pointers_do().
@@ -127,63 +131,39 @@
#endif
// Oop fields (and metadata) iterators
- // [nv = true] Use non-virtual calls to do_oop_nv.
- // [nv = false] Use virtual calls to do_oop.
//
// The ObjArrayKlass iterators also visits the Object's klass.
- private:
+ // Iterate over oop elements and metadata.
+ template <typename T, typename OopClosureType>
+ inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Iterate over oop elements and metadata.
- template <bool nv, typename OopClosureType>
- inline void oop_oop_iterate(oop obj, OopClosureType* closure);
+ template <typename T, typename OopClosureType>
+ inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
// Iterate over oop elements within mr, and metadata.
- template <bool nv, typename OopClosureType>
+ template <typename T, typename OopClosureType>
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
- // Iterate over oop elements with indices within [start, end), and metadata.
- template <bool nv, class OopClosureType>
- inline void oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end);
-
// Iterate over oop elements within [start, end), and metadata.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_range_specialized(objArrayOop a, OopClosureType* closure, int start, int end);
+ template <typename T, class OopClosureType>
+ inline void oop_oop_iterate_range(objArrayOop a, OopClosureType* closure, int start, int end);
public:
// Iterate over all oop elements.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_elements(objArrayOop a, OopClosureType* closure);
private:
- // Iterate over all oop elements.
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_elements_specialized(objArrayOop a, OopClosureType* closure);
+ // Iterate over all oop elements with indices within mr.
+ template <typename T, class OopClosureType>
+ inline void oop_oop_iterate_elements_bounded(objArrayOop a, OopClosureType* closure, void* low, void* high);
- // Iterate over all oop elements with indices within mr.
- template <bool nv, class OopClosureType>
+ template <typename T, class OopClosureType>
inline void oop_oop_iterate_elements_bounded(objArrayOop a, OopClosureType* closure, MemRegion mr);
- // Iterate over oop elements within [low, high)..
- // Specialized for [T = oop] or [T = narrowOop].
- template <bool nv, typename T, class OopClosureType>
- inline void oop_oop_iterate_elements_specialized_bounded(objArrayOop a, OopClosureType* closure, void* low, void* high);
-
-
public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_RANGE)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_RANGE)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_NO_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_NO_BACKWARDS)
-#endif
-
// JVM support
jint compute_modifier_flags(TRAPS) const;
--- a/src/hotspot/share/oops/objArrayKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -26,7 +26,7 @@
#define SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP
#include "memory/memRegion.hpp"
-#include "memory/iterator.inline.hpp"
+#include "memory/iterator.hpp"
#include "oops/arrayOop.inline.hpp"
#include "oops/arrayKlass.hpp"
#include "oops/klass.hpp"
@@ -35,18 +35,18 @@
#include "oops/oop.inline.hpp"
#include "utilities/macros.hpp"
-template <bool nv, typename T, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_elements_specialized(objArrayOop a, OopClosureType* closure) {
+template <typename T, class OopClosureType>
+void ObjArrayKlass::oop_oop_iterate_elements(objArrayOop a, OopClosureType* closure) {
T* p = (T*)a->base_raw();
T* const end = p + a->length();
for (;p < end; p++) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-template <bool nv, typename T, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_elements_specialized_bounded(
+template <typename T, class OopClosureType>
+void ObjArrayKlass::oop_oop_iterate_elements_bounded(
objArrayOop a, OopClosureType* closure, void* low, void* high) {
T* const l = (T*)low;
@@ -63,78 +63,58 @@
}
for (;p < end; ++p) {
- Devirtualizer<nv>::do_oop(closure, p);
+ Devirtualizer::do_oop(closure, p);
}
}
-template <bool nv, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_elements(objArrayOop a, OopClosureType* closure) {
- if (UseCompressedOops) {
- oop_oop_iterate_elements_specialized<nv, narrowOop>(a, closure);
- } else {
- oop_oop_iterate_elements_specialized<nv, oop>(a, closure);
- }
-}
-
-template <bool nv, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_elements_bounded(objArrayOop a, OopClosureType* closure, MemRegion mr) {
- if (UseCompressedOops) {
- oop_oop_iterate_elements_specialized_bounded<nv, narrowOop>(a, closure, mr.start(), mr.end());
- } else {
- oop_oop_iterate_elements_specialized_bounded<nv, oop>(a, closure, mr.start(), mr.end());
- }
-}
-
-template <bool nv, typename OopClosureType>
+template <typename T, typename OopClosureType>
void ObjArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
assert (obj->is_array(), "obj must be array");
objArrayOop a = objArrayOop(obj);
- if (Devirtualizer<nv>::do_metadata(closure)) {
- Devirtualizer<nv>::do_klass(closure, obj->klass());
+ if (Devirtualizer::do_metadata(closure)) {
+ Devirtualizer::do_klass(closure, obj->klass());
}
- oop_oop_iterate_elements<nv>(a, closure);
+ oop_oop_iterate_elements<T>(a, closure);
}
-template <bool nv, typename OopClosureType>
+template <typename T, typename OopClosureType>
+void ObjArrayKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ // No reverse implementation ATM.
+ oop_oop_iterate<T>(obj, closure);
+}
+
+template <typename T, typename OopClosureType>
void ObjArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
assert(obj->is_array(), "obj must be array");
objArrayOop a = objArrayOop(obj);
- if (Devirtualizer<nv>::do_metadata(closure)) {
- Devirtualizer<nv>::do_klass(closure, a->klass());
+ if (Devirtualizer::do_metadata(closure)) {
+ Devirtualizer::do_klass(closure, a->klass());
}
- oop_oop_iterate_elements_bounded<nv>(a, closure, mr);
-}
-
-template <bool nv, typename T, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_range_specialized(objArrayOop a, OopClosureType* closure, int start, int end) {
- T* low = start == 0 ? cast_from_oop<T*>(a) : a->obj_at_addr_raw<T>(start);
- T* high = (T*)a->base_raw() + end;
-
- oop_oop_iterate_elements_specialized_bounded<nv, T>(a, closure, low, high);
+ oop_oop_iterate_elements_bounded<T>(a, closure, mr.start(), mr.end());
}
// Like oop_oop_iterate but only iterates over a specified range and only used
// for objArrayOops.
-template <bool nv, class OopClosureType>
-void ObjArrayKlass::oop_oop_iterate_range(oop obj, OopClosureType* closure, int start, int end) {
- assert(obj->is_array(), "obj must be array");
- objArrayOop a = objArrayOop(obj);
+template <typename T, class OopClosureType>
+void ObjArrayKlass::oop_oop_iterate_range(objArrayOop a, OopClosureType* closure, int start, int end) {
+ T* low = start == 0 ? cast_from_oop<T*>(a) : a->obj_at_addr_raw<T>(start);
+ T* high = (T*)a->base_raw() + end;
+
+ oop_oop_iterate_elements_bounded<T>(a, closure, low, high);
+}
+// Placed here to resolve include cycle between objArrayKlass.inline.hpp and objArrayOop.inline.hpp
+template <typename OopClosureType>
+void objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) {
if (UseCompressedOops) {
- oop_oop_iterate_range_specialized<nv, narrowOop>(a, closure, start, end);
+ ((ObjArrayKlass*)klass())->oop_oop_iterate_range<narrowOop>(this, blk, start, end);
} else {
- oop_oop_iterate_range_specialized<nv, oop>(a, closure, start, end);
+ ((ObjArrayKlass*)klass())->oop_oop_iterate_range<oop>(this, blk, start, end);
}
}
-#define ALL_OBJ_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( ObjArrayKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( ObjArrayKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_RANGE( ObjArrayKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(ObjArrayKlass, OopClosureType, nv_suffix)
-
#endif // SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/objArrayOop.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayOop.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -23,7 +23,6 @@
*/
#include "precompiled.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/access.inline.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/objArrayOop.inline.hpp"
@@ -37,18 +36,9 @@
} else {
offs = objArrayOopDesc::obj_at_offset<oop>(index);
}
- return HeapAccess<IN_HEAP_ARRAY>::oop_atomic_cmpxchg_at(exchange_value, as_oop(), offs, compare_value);
+ return HeapAccess<IS_ARRAY>::oop_atomic_cmpxchg_at(exchange_value, as_oop(), offs, compare_value);
}
Klass* objArrayOopDesc::element_klass() {
return ObjArrayKlass::cast(klass())->element_klass();
}
-
-#define ObjArrayOop_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- \
-void objArrayOopDesc::oop_iterate_range(OopClosureType* blk, int start, int end) { \
- ((ObjArrayKlass*)klass())->oop_oop_iterate_range##nv_suffix(this, blk, start, end); \
-}
-
-ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DEFN)
-ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayOop_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/oops/objArrayOop.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayOop.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,6 @@
#ifndef SHARE_VM_OOPS_OBJARRAYOOP_HPP
#define SHARE_VM_OOPS_OBJARRAYOOP_HPP
-#include "gc/shared/specialized_oop_closures.hpp"
#include "oops/arrayOop.hpp"
#include "utilities/align.hpp"
@@ -107,12 +106,10 @@
Klass* element_klass();
+public:
// special iterators for index ranges, returns size of object
-#define ObjArrayOop_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
+ template <typename OopClosureType>
void oop_iterate_range(OopClosureType* blk, int start, int end);
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(ObjArrayOop_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(ObjArrayOop_OOP_ITERATE_DECL)
};
#endif // SHARE_VM_OOPS_OBJARRAYOOP_HPP
--- a/src/hotspot/share/oops/objArrayOop.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/objArrayOop.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -46,12 +46,12 @@
inline oop objArrayOopDesc::obj_at(int index) const {
ptrdiff_t offset = UseCompressedOops ? obj_at_offset<narrowOop>(index) : obj_at_offset<oop>(index);
- return HeapAccess<IN_HEAP_ARRAY>::oop_load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::oop_load_at(as_oop(), offset);
}
inline void objArrayOopDesc::obj_at_put(int index, oop value) {
ptrdiff_t offset = UseCompressedOops ? obj_at_offset<narrowOop>(index) : obj_at_offset<oop>(index);
- HeapAccess<IN_HEAP_ARRAY>::oop_store_at(as_oop(), offset, value);
+ HeapAccess<IS_ARRAY>::oop_store_at(as_oop(), offset, value);
}
#endif // SHARE_VM_OOPS_OBJARRAYOOP_INLINE_HPP
--- a/src/hotspot/share/oops/oop.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/oop.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,6 @@
#ifndef SHARE_VM_OOPS_OOP_HPP
#define SHARE_VM_OOPS_OOP_HPP
-#include "gc/shared/specialized_oop_closures.hpp"
#include "memory/iterator.hpp"
#include "memory/memRegion.hpp"
#include "oops/access.hpp"
@@ -266,7 +265,7 @@
// Exactly one thread succeeds in inserting the forwarding pointer, and
// this call returns "NULL" for that thread; any other thread has the
// value of the forwarding pointer returned and does not modify "this".
- inline oop forward_to_atomic(oop p);
+ inline oop forward_to_atomic(oop p, atomic_memory_order order = memory_order_conservative);
inline oop forwardee() const;
inline oop forwardee_acquire() const;
@@ -288,32 +287,20 @@
inline void ps_push_contents(PSPromotionManager* pm);
#endif
-
- // iterators, returns size of object
-#define OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
- inline void oop_iterate(OopClosureType* blk); \
- inline void oop_iterate(OopClosureType* blk, MemRegion mr); // Only in mr.
+ template <typename OopClosureType>
+ inline void oop_iterate(OopClosureType* cl);
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL)
-
-#define OOP_ITERATE_SIZE_DECL(OopClosureType, nv_suffix) \
- inline int oop_iterate_size(OopClosureType* blk); \
- inline int oop_iterate_size(OopClosureType* blk, MemRegion mr); // Only in mr.
+ template <typename OopClosureType>
+ inline void oop_iterate(OopClosureType* cl, MemRegion mr);
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_SIZE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_SIZE_DECL)
-
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
+ template <typename OopClosureType>
+ inline int oop_iterate_size(OopClosureType* cl);
-#define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
- inline void oop_iterate_backwards(OopClosureType* blk);
+ template <typename OopClosureType>
+ inline int oop_iterate_size(OopClosureType* cl, MemRegion mr);
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DECL)
-
-#endif // INCLUDE_OOP_OOP_ITERATE_BACKWARDS
+ template <typename OopClosureType>
+ inline void oop_iterate_backwards(OopClosureType* cl);
inline int oop_iterate_no_header(OopClosure* bk);
inline int oop_iterate_no_header(OopClosure* bk, MemRegion mr);
--- a/src/hotspot/share/oops/oop.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/oop.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -352,7 +352,7 @@
return cas_set_mark_raw(m, compare, order) == compare;
}
-oop oopDesc::forward_to_atomic(oop p) {
+oop oopDesc::forward_to_atomic(oop p, atomic_memory_order order) {
markOop oldMark = mark_raw();
markOop forwardPtrMark = markOopDesc::encode_pointer_as_mark(p);
markOop curMark;
@@ -361,7 +361,7 @@
assert(sizeof(markOop) == sizeof(intptr_t), "CAS below requires this.");
while (!oldMark->is_marked()) {
- curMark = cas_set_mark_raw(forwardPtrMark, oldMark);
+ curMark = cas_set_mark_raw(forwardPtrMark, oldMark, order);
assert(is_forwarded(), "object should have been forwarded");
if (curMark == oldMark) {
return NULL;
@@ -432,35 +432,40 @@
}
#endif // INCLUDE_PARALLELGC
-#define OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- \
-void oopDesc::oop_iterate(OopClosureType* blk) { \
- klass()->oop_oop_iterate##nv_suffix(this, blk); \
-} \
- \
-void oopDesc::oop_iterate(OopClosureType* blk, MemRegion mr) { \
- klass()->oop_oop_iterate_bounded##nv_suffix(this, blk, mr); \
+template <typename OopClosureType>
+void oopDesc::oop_iterate(OopClosureType* cl) {
+ OopIteratorClosureDispatch::oop_oop_iterate(cl, this, klass());
+}
+
+template <typename OopClosureType>
+void oopDesc::oop_iterate(OopClosureType* cl, MemRegion mr) {
+ OopIteratorClosureDispatch::oop_oop_iterate(cl, this, klass(), mr);
}
-#define OOP_ITERATE_SIZE_DEFN(OopClosureType, nv_suffix) \
- \
-int oopDesc::oop_iterate_size(OopClosureType* blk) { \
- Klass* k = klass(); \
- int size = size_given_klass(k); \
- k->oop_oop_iterate##nv_suffix(this, blk); \
- return size; \
-} \
- \
-int oopDesc::oop_iterate_size(OopClosureType* blk, MemRegion mr) { \
- Klass* k = klass(); \
- int size = size_given_klass(k); \
- k->oop_oop_iterate_bounded##nv_suffix(this, blk, mr); \
- return size; \
+template <typename OopClosureType>
+int oopDesc::oop_iterate_size(OopClosureType* cl) {
+ Klass* k = klass();
+ int size = size_given_klass(k);
+ OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k);
+ return size;
+}
+
+template <typename OopClosureType>
+int oopDesc::oop_iterate_size(OopClosureType* cl, MemRegion mr) {
+ Klass* k = klass();
+ int size = size_given_klass(k);
+ OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
+ return size;
+}
+
+template <typename OopClosureType>
+void oopDesc::oop_iterate_backwards(OopClosureType* cl) {
+ OopIteratorClosureDispatch::oop_oop_iterate_backwards(cl, this, klass());
}
int oopDesc::oop_iterate_no_header(OopClosure* blk) {
// The NoHeaderExtendedOopClosure wraps the OopClosure and proxies all
- // the do_oop calls, but turns off all other features in ExtendedOopClosure.
+ // the do_oop calls, but turns off all other features in OopIterateClosure.
NoHeaderExtendedOopClosure cl(blk);
return oop_iterate_size(&cl);
}
@@ -470,24 +475,6 @@
return oop_iterate_size(&cl, mr);
}
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
-#define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
- \
-inline void oopDesc::oop_iterate_backwards(OopClosureType* blk) { \
- klass()->oop_oop_iterate_backwards##nv_suffix(this, blk); \
-}
-#else
-#define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)
-#endif
-
-#define ALL_OOPDESC_OOP_ITERATE(OopClosureType, nv_suffix) \
- OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_ITERATE_SIZE_DEFN(OopClosureType, nv_suffix) \
- OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix)
-
-ALL_OOP_OOP_ITERATE_CLOSURES_1(ALL_OOPDESC_OOP_ITERATE)
-ALL_OOP_OOP_ITERATE_CLOSURES_2(ALL_OOPDESC_OOP_ITERATE)
-
bool oopDesc::is_instanceof_or_null(oop obj, Klass* klass) {
return obj == NULL || obj->klass()->is_subtype_of(klass);
}
--- a/src/hotspot/share/oops/typeArrayKlass.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/typeArrayKlass.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -86,7 +86,7 @@
return new (loader_data, size, THREAD) TypeArrayKlass(type, name);
}
-TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name) {
+TypeArrayKlass::TypeArrayKlass(BasicType type, Symbol* name) : ArrayKlass(name, ID) {
set_layout_helper(array_layout_helper(type));
assert(is_array_klass(), "sanity");
assert(is_typeArray_klass(), "sanity");
--- a/src/hotspot/share/oops/typeArrayKlass.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/typeArrayKlass.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -33,6 +33,10 @@
class TypeArrayKlass : public ArrayKlass {
friend class VMStructs;
+
+ public:
+ static const KlassID ID = TypeArrayKlassID;
+
private:
jint _max_length; // maximum number of elements allowed in an array
@@ -87,28 +91,20 @@
private:
// The implementation used by all oop_oop_iterate functions in TypeArrayKlasses.
- inline void oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure);
+ inline void oop_oop_iterate_impl(oop obj, OopIterateClosure* closure);
+ public:
// Wraps oop_oop_iterate_impl to conform to macros.
- template <bool nv, typename OopClosureType>
+ template <typename T, typename OopClosureType>
inline void oop_oop_iterate(oop obj, OopClosureType* closure);
// Wraps oop_oop_iterate_impl to conform to macros.
- template <bool nv, typename OopClosureType>
+ template <typename T, typename OopClosureType>
inline void oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
- public:
-
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL)
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_RANGE)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_RANGE)
-
-#if INCLUDE_OOP_OOP_ITERATE_BACKWARDS
- ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_OOP_ITERATE_DECL_NO_BACKWARDS)
- ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_OOP_ITERATE_DECL_NO_BACKWARDS)
-#endif
-
+ // Wraps oop_oop_iterate_impl to conform to macros.
+ template <typename T, typename OopClosureType>
+ inline void oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
protected:
// Find n'th dimensional array
--- a/src/hotspot/share/oops/typeArrayKlass.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/typeArrayKlass.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -31,27 +31,27 @@
#include "oops/typeArrayKlass.hpp"
#include "oops/typeArrayOop.hpp"
-class ExtendedOopClosure;
+class OopIterateClosure;
-inline void TypeArrayKlass::oop_oop_iterate_impl(oop obj, ExtendedOopClosure* closure) {
+inline void TypeArrayKlass::oop_oop_iterate_impl(oop obj, OopIterateClosure* closure) {
assert(obj->is_typeArray(),"must be a type array");
- // Performance tweak: We skip iterating over the klass pointer since we
- // know that Universe::TypeArrayKlass never moves.
+ // Performance tweak: We skip processing the klass pointer since all
+ // TypeArrayKlasses are guaranteed processed via the null class loader.
}
-template <bool nv, typename OopClosureType>
+template <typename T, typename OopClosureType>
void TypeArrayKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
oop_oop_iterate_impl(obj, closure);
}
-template <bool nv, typename OopClosureType>
+template <typename T, typename OopClosureType>
void TypeArrayKlass::oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr) {
oop_oop_iterate_impl(obj, closure);
}
-#define ALL_TYPE_ARRAY_KLASS_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN( TypeArrayKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_BOUNDED( TypeArrayKlass, OopClosureType, nv_suffix) \
- OOP_OOP_ITERATE_DEFN_NO_BACKWARDS(TypeArrayKlass, OopClosureType, nv_suffix)
+template <typename T, typename OopClosureType>
+void TypeArrayKlass::oop_oop_iterate_reverse(oop obj, OopClosureType* closure) {
+ oop_oop_iterate_impl(obj, closure);
+}
#endif // SHARE_VM_OOPS_TYPEARRAYKLASS_INLINE_HPP
--- a/src/hotspot/share/oops/typeArrayOop.inline.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/oops/typeArrayOop.inline.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -91,92 +91,92 @@
inline jbyte typeArrayOopDesc::byte_at(int which) const {
ptrdiff_t offset = element_offset<jbyte>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::byte_at_put(int which, jbyte contents) {
ptrdiff_t offset = element_offset<jbyte>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jboolean typeArrayOopDesc::bool_at(int which) const {
ptrdiff_t offset = element_offset<jboolean>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::bool_at_put(int which, jboolean contents) {
ptrdiff_t offset = element_offset<jboolean>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, jboolean(contents & 1));
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, jboolean(contents & 1));
}
inline jchar typeArrayOopDesc::char_at(int which) const {
ptrdiff_t offset = element_offset<jchar>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::char_at_put(int which, jchar contents) {
ptrdiff_t offset = element_offset<jchar>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jint typeArrayOopDesc::int_at(int which) const {
ptrdiff_t offset = element_offset<jint>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::int_at_put(int which, jint contents) {
ptrdiff_t offset = element_offset<jint>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jshort typeArrayOopDesc::short_at(int which) const {
ptrdiff_t offset = element_offset<jshort>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::short_at_put(int which, jshort contents) {
ptrdiff_t offset = element_offset<jshort>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jushort typeArrayOopDesc::ushort_at(int which) const {
ptrdiff_t offset = element_offset<jushort>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::ushort_at_put(int which, jushort contents) {
ptrdiff_t offset = element_offset<jushort>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jlong typeArrayOopDesc::long_at(int which) const {
ptrdiff_t offset = element_offset<jlong>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::long_at_put(int which, jlong contents) {
ptrdiff_t offset = element_offset<jlong>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jfloat typeArrayOopDesc::float_at(int which) const {
ptrdiff_t offset = element_offset<jfloat>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::float_at_put(int which, jfloat contents) {
ptrdiff_t offset = element_offset<jfloat>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jdouble typeArrayOopDesc::double_at(int which) const {
ptrdiff_t offset = element_offset<jdouble>(which);
- return HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::double_at_put(int which, jdouble contents) {
ptrdiff_t offset = element_offset<jdouble>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, contents);
}
inline jbyte typeArrayOopDesc::byte_at_acquire(int which) const {
ptrdiff_t offset = element_offset<jbyte>(which);
- return HeapAccess<MO_ACQUIRE | IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return HeapAccess<MO_ACQUIRE | IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::release_byte_at_put(int which, jbyte contents) {
ptrdiff_t offset = element_offset<jbyte>(which);
- HeapAccess<MO_RELEASE | IN_HEAP_ARRAY>::store_at(as_oop(), offset, contents);
+ HeapAccess<MO_RELEASE | IS_ARRAY>::store_at(as_oop(), offset, contents);
}
// Java thinks Symbol arrays are just arrays of either long or int, since
@@ -185,20 +185,20 @@
#ifdef _LP64
inline Symbol* typeArrayOopDesc::symbol_at(int which) const {
ptrdiff_t offset = element_offset<jlong>(which);
- return (Symbol*)(jlong) HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return (Symbol*)(jlong) HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::symbol_at_put(int which, Symbol* contents) {
ptrdiff_t offset = element_offset<jlong>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, (jlong)contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, (jlong)contents);
}
#else
inline Symbol* typeArrayOopDesc::symbol_at(int which) const {
ptrdiff_t offset = element_offset<jint>(which);
- return (Symbol*)(jint) HeapAccess<IN_HEAP_ARRAY>::load_at(as_oop(), offset);
+ return (Symbol*)(jint) HeapAccess<IS_ARRAY>::load_at(as_oop(), offset);
}
inline void typeArrayOopDesc::symbol_at_put(int which, Symbol* contents) {
ptrdiff_t offset = element_offset<jint>(which);
- HeapAccess<IN_HEAP_ARRAY>::store_at(as_oop(), offset, (jint)contents);
+ HeapAccess<IS_ARRAY>::store_at(as_oop(), offset, (jint)contents);
}
#endif // _LP64
--- a/src/hotspot/share/opto/doCall.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/opto/doCall.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -505,28 +505,36 @@
speculative_receiver_type = receiver_type != NULL ? receiver_type->speculative_type() : NULL;
}
- // invoke-super-special
+ // Additional receiver subtype checks for interface calls via invokespecial or invokeinterface.
+ ciKlass* receiver_constraint = NULL;
if (iter().cur_bc_raw() == Bytecodes::_invokespecial && !orig_callee->is_object_initializer()) {
ciInstanceKlass* calling_klass = method()->holder();
ciInstanceKlass* sender_klass =
calling_klass->is_anonymous() ? calling_klass->host_klass() :
calling_klass;
if (sender_klass->is_interface()) {
- Node* receiver_node = stack(sp() - nargs);
- Node* cls_node = makecon(TypeKlassPtr::make(sender_klass));
- Node* bad_type_ctrl = NULL;
- Node* casted_receiver = gen_checkcast(receiver_node, cls_node, &bad_type_ctrl);
- if (bad_type_ctrl != NULL) {
- PreserveJVMState pjvms(this);
- set_control(bad_type_ctrl);
- uncommon_trap(Deoptimization::Reason_class_check,
- Deoptimization::Action_none);
- }
- if (stopped()) {
- return; // MUST uncommon-trap?
- }
- set_stack(sp() - nargs, casted_receiver);
+ receiver_constraint = sender_klass;
}
+ } else if (iter().cur_bc_raw() == Bytecodes::_invokeinterface && orig_callee->is_private()) {
+ assert(holder->is_interface(), "How did we get a non-interface method here!");
+ receiver_constraint = holder;
+ }
+
+ if (receiver_constraint != NULL) {
+ Node* receiver_node = stack(sp() - nargs);
+ Node* cls_node = makecon(TypeKlassPtr::make(receiver_constraint));
+ Node* bad_type_ctrl = NULL;
+ Node* casted_receiver = gen_checkcast(receiver_node, cls_node, &bad_type_ctrl);
+ if (bad_type_ctrl != NULL) {
+ PreserveJVMState pjvms(this);
+ set_control(bad_type_ctrl);
+ uncommon_trap(Deoptimization::Reason_class_check,
+ Deoptimization::Action_none);
+ }
+ if (stopped()) {
+ return; // MUST uncommon-trap?
+ }
+ set_stack(sp() - nargs, casted_receiver);
}
// Note: It's OK to try to inline a virtual call.
--- a/src/hotspot/share/opto/parse2.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/opto/parse2.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -69,7 +69,7 @@
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
Node* ld = access_load_at(array, adr, adr_type, elemtype, bt,
- IN_HEAP | IN_HEAP_ARRAY | C2_CONTROL_DEPENDENT_LOAD);
+ IN_HEAP | IS_ARRAY | C2_CONTROL_DEPENDENT_LOAD);
if (big_val) {
push_pair(ld);
} else {
@@ -104,7 +104,7 @@
const TypeAryPtr* adr_type = TypeAryPtr::get_array_body_type(bt);
- access_store_at(control(), array, adr, adr_type, val, elemtype, bt, MO_UNORDERED | IN_HEAP | IN_HEAP_ARRAY);
+ access_store_at(control(), array, adr, adr_type, val, elemtype, bt, MO_UNORDERED | IN_HEAP | IS_ARRAY);
}
--- a/src/hotspot/share/opto/parse3.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/opto/parse3.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -351,7 +351,7 @@
Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs);
intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop);
Node* eaddr = basic_plus_adr(array, offset);
- access_store_at(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, IN_HEAP | IN_HEAP_ARRAY);
+ access_store_at(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT, IN_HEAP | IS_ARRAY);
}
}
return array;
--- a/src/hotspot/share/prims/jvm.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvm.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1892,6 +1892,98 @@
}
JVM_END
+JVM_ENTRY(jboolean, JVM_AreNestMates(JNIEnv *env, jclass current, jclass member))
+{
+ JVMWrapper("JVM_AreNestMates");
+ Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current));
+ assert(c->is_instance_klass(), "must be");
+ InstanceKlass* ck = InstanceKlass::cast(c);
+ Klass* m = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(member));
+ assert(m->is_instance_klass(), "must be");
+ InstanceKlass* mk = InstanceKlass::cast(m);
+ return ck->has_nestmate_access_to(mk, THREAD);
+}
+JVM_END
+
+JVM_ENTRY(jclass, JVM_GetNestHost(JNIEnv* env, jclass current))
+{
+ // current is not a primitive or array class
+ JVMWrapper("JVM_GetNestHost");
+ Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current));
+ assert(c->is_instance_klass(), "must be");
+ InstanceKlass* ck = InstanceKlass::cast(c);
+ // Don't post exceptions if validation fails
+ InstanceKlass* host = ck->nest_host(NULL, THREAD);
+ return (jclass) (host == NULL ? NULL :
+ JNIHandles::make_local(THREAD, host->java_mirror()));
+}
+JVM_END
+
+JVM_ENTRY(jobjectArray, JVM_GetNestMembers(JNIEnv* env, jclass current))
+{
+ // current is not a primitive or array class
+ JVMWrapper("JVM_GetNestMembers");
+ Klass* c = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(current));
+ assert(c->is_instance_klass(), "must be");
+ InstanceKlass* ck = InstanceKlass::cast(c);
+ // Get the nest host for this nest - throw ICCE if validation fails
+ Symbol* icce = vmSymbols::java_lang_IncompatibleClassChangeError();
+ InstanceKlass* host = ck->nest_host(icce, CHECK_NULL);
+
+ {
+ JvmtiVMObjectAllocEventCollector oam;
+ Array<u2>* members = host->nest_members();
+ int length = members == NULL ? 0 : members->length();
+ // nest host is first in the array so make it one bigger
+ objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(),
+ length + 1, CHECK_NULL);
+ objArrayHandle result (THREAD, r);
+ result->obj_at_put(0, host->java_mirror());
+ if (length != 0) {
+ int i;
+ for (i = 0; i < length; i++) {
+ int cp_index = members->at(i);
+ Klass* k = host->constants()->klass_at(cp_index, CHECK_NULL);
+ if (k->is_instance_klass()) {
+ InstanceKlass* nest_host_k =
+ InstanceKlass::cast(k)->nest_host(icce, CHECK_NULL);
+ if (nest_host_k == host) {
+ result->obj_at_put(i+1, k->java_mirror());
+ }
+ else {
+ // k's nest host is legal but it isn't our host so
+ // throw ICCE
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(THREAD_AND_LOCATION,
+ icce,
+ "Nest member %s in %s declares a different nest host of %s",
+ k->external_name(),
+ host->external_name(),
+ nest_host_k->external_name()
+ );
+ return NULL;
+ }
+ }
+ else {
+ // we have a bad nest member entry - throw ICCE
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(THREAD_AND_LOCATION,
+ icce,
+ "Class %s can not be a nest member of %s",
+ k->external_name(),
+ host->external_name()
+ );
+ return NULL;
+ }
+ }
+ }
+ else {
+ assert(host == ck, "must be singleton nest");
+ }
+ return (jobjectArray)JNIHandles::make_local(THREAD, result());
+ }
+}
+JVM_END
// Constant pool access //////////////////////////////////////////////////////////
--- a/src/hotspot/share/prims/jvmti.xml Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmti.xml Mon Jun 25 09:48:06 2018 -0700
@@ -358,7 +358,7 @@
]>
<specification label="JVM(TM) Tool Interface"
- majorversion="9"
+ majorversion="11"
minorversion="0"
microversion="0">
<title subtitle="Version">
@@ -778,7 +778,7 @@
<intro id="bci" label="Bytecode Instrumentation">
This interface does not include some events that one might expect in an interface with
- profiling support. Some examples include object allocation events and full speed
+ profiling support. Some examples include full speed
method enter and exit events. The interface instead provides support for
<i>bytecode instrumentation</i>, the ability to alter the Java virtual machine
bytecode instructions which comprise the target program. Typically, these alterations
@@ -3454,7 +3454,7 @@
<jint/>
<description>
For <datalink id="JVMTI_HEAP_REFERENCE_FIELD"/>, the
- referrer object is not a class or an inteface.
+ referrer object is not a class or an interface.
In this case, <code>index</code> is the index of the field
in the class of the referrer object.
This class is referred to below as <i>C</i>.
@@ -7631,9 +7631,12 @@
<eventlink id="ClassFileLoadHook"/> event
will be sent.
<p/>
- The retransformation may change method bodies, the constant pool and attributes.
+ The retransformation may change method bodies, the constant pool and attributes
+ (unless explicitly prohibited).
The retransformation must not add, remove or rename fields or methods, change the
signatures of methods, change modifiers, or change inheritance.
+ The retransformation must not change the <code>NestHost</code> or
+ <code>NestMembers</code> attributes.
These restrictions may be lifted in future versions.
See the error return description below for information on error codes
returned if an unsupported retransformation is attempted.
@@ -7704,6 +7707,9 @@
A retransformed class file does not declare a method
declared in the old class version.
</error>
+ <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED">
+ A retransformed class file has unsupported differences in class attributes.
+ </error>
<error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED">
A retransformed class file has different class modifiers.
</error>
@@ -7778,9 +7784,12 @@
<eventlink id="ClassFileLoadHook">Class File Load Hook</eventlink>
will be sent (if enabled), but no other <jvmti/> events will be sent.
<p/>
- The redefinition may change method bodies, the constant pool and attributes.
+ The redefinition may change method bodies, the constant pool and attributes
+ (unless explicitly prohibited).
The redefinition must not add, remove or rename fields or methods, change the
signatures of methods, change modifiers, or change inheritance.
+ The retransformation must not change the <code>NestHost</code> or
+ <code>NestMembers</code> attributes.
These restrictions may be lifted in future versions.
See the error return description below for information on error codes
returned if an unsupported redefinition is attempted.
@@ -7855,6 +7864,9 @@
A new class version does not declare a method
declared in the old class version.
</error>
+ <error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED">
+ A new class version has unsupported differences in class attributes.
+ </error>
<error id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED">
A new class version has different modifiers.
</error>
@@ -8513,10 +8525,10 @@
For the method indicated by <code>method</code>,
return the beginning and ending addresses through
<code>start_location_ptr</code> and <code>end_location_ptr</code>. In a
- conventional byte code indexing scheme,
+ conventional bytecode indexing scheme,
<code>start_location_ptr</code> will always point to zero
and <code>end_location_ptr</code>
- will always point to the byte code count minus one.
+ will always point to the bytecode count minus one.
</description>
<origin>jvmdi</origin>
<capabilities>
@@ -8649,8 +8661,8 @@
<synopsis>Get Bytecodes</synopsis>
<description>
For the method indicated by <code>method</code>,
- return the byte codes that implement the method. The number of
- bytecodes is returned via <code>bytecode_count_ptr</code>. The byte codes
+ return the bytecodes that implement the method. The number of
+ bytecodes is returned via <code>bytecode_count_ptr</code>. The bytecodes
themselves are returned via <code>bytecodes_ptr</code>.
</description>
<origin>jvmdi</origin>
@@ -8673,13 +8685,13 @@
<param id="bytecode_count_ptr">
<outptr><jint/></outptr>
<description>
- On return, points to the length of the byte code array
+ On return, points to the length of the bytecode array
</description>
</param>
<param id="bytecodes_ptr">
<allocbuf outcount="bytecode_count_ptr"><uchar/></allocbuf>
<description>
- On return, points to the pointer to the byte code array
+ On return, points to the pointer to the bytecode array
</description>
</param>
</parameters>
@@ -8923,7 +8935,7 @@
layer of agents) this function allows each transformation
to have its own prefix.
The prefixes are applied in the order supplied and are
- processed in the same manor as described for the
+ processed in the same manner as described for the
application of prefixes from multiple <jvmti/> environments
in <functionlink id="SetNativeMethodPrefix"/>.
<p/>
@@ -11788,6 +11800,9 @@
A method in the new class version has different modifiers
than its counterpart in the old class version.
</errorid>
+ <errorid id="JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED" num="72">
+ A new class version has unsupported differences in class attributes.
+ </errorid>
</errorcategory>
</errorsection>
@@ -12996,7 +13011,7 @@
Agents that create more than one JVM TI environment, where the
capability is added to some but not all environments, may observe the
start phase beginning earlier in the JVM TI environments that possess
- the capabilty.
+ the capability.
<p/>
In the case of VM start-up failure, this event will not be sent.
</description>
@@ -13492,9 +13507,8 @@
<event label="VM Object Allocation"
id="VMObjectAlloc" const="JVMTI_EVENT_VM_OBJECT_ALLOC" num="84">
<description>
- Sent when a method causes the virtual machine to allocate an
- Object visible to Java programming language code and the
- allocation is not detectable by other intrumentation mechanisms.
+ Sent when a method causes the virtual machine to directly allocate an
+ Object visible to Java programming language code.
Generally object allocation should be detected by instrumenting
the bytecodes of allocating methods.
Object allocation generated in native code by JNI function
@@ -13505,6 +13519,12 @@
VM. These methods should send this event.
Virtual machines which are incapable of bytecode instrumentation
for some or all of their methods can send this event.
+
+ Note that the <internallink
+ id="SampledObjectAlloc">SampledObjectAlloc</internallink>
+ event is triggered on all Java object allocations, including those
+ caused by bytecode method execution, JNI method execution, and
+ directly by VM methods.
<p/>
Typical examples where this event might be sent:
<ul>
@@ -14927,6 +14947,13 @@
- The function may return NULL in the start phase if the
can_generate_early_vmstart capability is enabled.
</change>
+ <change date="7 February 2018" version="11.0.0">
+ Minor update for new class file NestHost and NestMembers attributes:
+ - Specify that RedefineClasses and RetransformClasses are not allowed
+ to change the class file NestHost and NestMembers attributes.
+ - Add new error JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED
+ that can be returned by RedefineClasses and RetransformClasses.
+ </change>
</changehistory>
</specification>
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -388,6 +388,40 @@
}
}
+// NestHost_attribute {
+// u2 attribute_name_index;
+// u4 attribute_length;
+// u2 host_class_index;
+// }
+void JvmtiClassFileReconstituter::write_nest_host_attribute() {
+ int length = sizeof(u2);
+ int host_class_index = ik()->nest_host_index();
+
+ write_attribute_name_index("NestHost");
+ write_u4(length);
+ write_u2(host_class_index);
+}
+
+// NestMembers_attribute {
+// u2 attribute_name_index;
+// u4 attribute_length;
+// u2 number_of_classes;
+// u2 classes[number_of_classes];
+// }
+void JvmtiClassFileReconstituter::write_nest_members_attribute() {
+ Array<u2>* nest_members = ik()->nest_members();
+ int number_of_classes = nest_members->length();
+ int length = sizeof(u2) * (1 + number_of_classes);
+
+ write_attribute_name_index("NestMembers");
+ write_u4(length);
+ write_u2(number_of_classes);
+ for (int i = 0; i < number_of_classes; i++) {
+ u2 class_cp_index = nest_members->at(i);
+ write_u2(class_cp_index);
+ }
+}
+
// Write InnerClasses attribute
// JVMSpec| InnerClasses_attribute {
@@ -658,6 +692,12 @@
if (cpool()->operands() != NULL) {
++attr_count;
}
+ if (ik()->nest_host_index() != 0) {
+ ++attr_count;
+ }
+ if (ik()->nest_members() != Universe::the_empty_short_array()) {
+ ++attr_count;
+ }
write_u2(attr_count);
@@ -682,6 +722,12 @@
if (cpool()->operands() != NULL) {
write_bootstrapmethod_attribute();
}
+ if (ik()->nest_host_index() != 0) {
+ write_nest_host_attribute();
+ }
+ if (ik()->nest_members() != Universe::the_empty_short_array()) {
+ write_nest_members_attribute();
+ }
}
// Write the method information portion of ClassFile structure
--- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -116,6 +116,8 @@
void write_attribute_name_index(const char* name);
void write_annotations_attribute(const char* attr_name, AnnotationArray* annos);
void write_bootstrapmethod_attribute();
+ void write_nest_host_attribute();
+ void write_nest_members_attribute();
address writeable_address(size_t size);
void write_u1(u1 x);
--- a/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiCodeBlobEvents.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -269,7 +269,7 @@
ScopeDesc *sd = &sc0;
while( !sd->is_top() ) { sd = sd->sender(); }
int bci = sd->bci();
- if (bci != InvocationEntryBci) {
+ if (bci >= 0) {
assert(map_length < pcds_in_method, "checking");
map[map_length].start_address = (const void*)pcd->real_pc(nm);
map[map_length].location = bci;
--- a/src/hotspot/share/prims/jvmtiExport.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiExport.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -370,6 +370,14 @@
return JNI_EVERSION; // unsupported minor version number
}
break;
+ case 11:
+ switch (minor) {
+ case 0: // version 11.0.<micro> is recognized
+ break;
+ default:
+ return JNI_EVERSION; // unsupported minor version number
+ }
+ break;
default:
return JNI_EVERSION; // unsupported major version number
}
--- a/src/hotspot/share/prims/jvmtiH.xsl Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiH.xsl Mon Jun 25 09:48:06 2018 -0700
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2018, 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
@@ -20,7 +20,7 @@
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.
-
+
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
@@ -47,7 +47,7 @@
/* Constants */
</xsl:text>
<xsl:apply-templates select="//constants"/>
-
+
<xsl:text>
/* Errors */
@@ -91,7 +91,7 @@
<xsl:apply-templates select="functionsection"/>
<xsl:call-template name="outro"/>
-
+
</xsl:template>
<xsl:template name="intro">
@@ -114,6 +114,7 @@
JVMTI_VERSION_1_1 = 0x30010100,
JVMTI_VERSION_1_2 = 0x30010200,
JVMTI_VERSION_9 = 0x30090000,
+ JVMTI_VERSION_11 = 0x300B0000,
JVMTI_VERSION = 0x30000000 + (</xsl:text>
<xsl:value-of select="//specification/@majorversion"/>
@@ -298,7 +299,7 @@
</xsl:when>
<xsl:otherwise>
<xsl:text> RESERVED */
- void *reserved</xsl:text>
+ void *reserved</xsl:text>
<xsl:value-of select="$index"/>
</xsl:otherwise>
</xsl:choose>
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -683,6 +683,95 @@
_operands_index_map_count = 0;
} // end finalize_operands_merge()
+// Symbol* comparator for qsort
+// The caller must have an active ResourceMark.
+static int symcmp(const void* a, const void* b) {
+ char* astr = (*(Symbol**)a)->as_C_string();
+ char* bstr = (*(Symbol**)b)->as_C_string();
+ return strcmp(astr, bstr);
+}
+
+static jvmtiError check_nest_attributes(InstanceKlass* the_class,
+ InstanceKlass* scratch_class) {
+ // Check whether the class NestHost attribute has been changed.
+ Thread* thread = Thread::current();
+ ResourceMark rm(thread);
+ JvmtiThreadState *state = JvmtiThreadState::state_for((JavaThread*)thread);
+ u2 the_nest_host_idx = the_class->nest_host_index();
+ u2 scr_nest_host_idx = scratch_class->nest_host_index();
+
+ if (the_nest_host_idx != 0 && scr_nest_host_idx != 0) {
+ Symbol* the_sym = the_class->constants()->klass_name_at(the_nest_host_idx);
+ Symbol* scr_sym = scratch_class->constants()->klass_name_at(scr_nest_host_idx);
+ if (the_sym != scr_sym) {
+ log_trace(redefine, class, nestmates)
+ ("redefined class %s attribute change error: NestHost class: %s replaced with: %s",
+ the_class->external_name(), the_sym->as_C_string(), scr_sym->as_C_string());
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+ }
+ } else if ((the_nest_host_idx == 0) ^ (scr_nest_host_idx == 0)) {
+ const char* action_str = (the_nest_host_idx != 0) ? "removed" : "added";
+ log_trace(redefine, class, nestmates)
+ ("redefined class %s attribute change error: NestHost attribute %s",
+ the_class->external_name(), action_str);
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+ }
+
+ // Check whether the class NestMembers attribute has been changed.
+ Array<u2>* the_nest_members = the_class->nest_members();
+ Array<u2>* scr_nest_members = scratch_class->nest_members();
+ bool the_members_exists = the_nest_members != Universe::the_empty_short_array();
+ bool scr_members_exists = scr_nest_members != Universe::the_empty_short_array();
+
+ int members_len = the_nest_members->length();
+ if (the_members_exists && scr_members_exists) {
+ if (members_len != scr_nest_members->length()) {
+ log_trace(redefine, class, nestmates)
+ ("redefined class %s attribute change error: NestMember len=%d changed to len=%d",
+ the_class->external_name(), members_len, scr_nest_members->length());
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+ }
+
+ // The order of entries in the NestMembers array is not specified so we
+ // have to explicitly check for the same contents. We do this by copying
+ // the referenced symbols into their own arrays, sorting them and then
+ // comparing each element pair.
+
+ Symbol** the_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
+ Symbol** scr_syms = NEW_RESOURCE_ARRAY_RETURN_NULL(Symbol*, members_len);
+
+ if (the_syms == NULL || scr_syms == NULL) {
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
+ for (int i = 0; i < members_len; i++) {
+ int the_cp_index = the_nest_members->at(i);
+ int scr_cp_index = scr_nest_members->at(i);
+ the_syms[i] = the_class->constants()->klass_name_at(the_cp_index);
+ scr_syms[i] = scratch_class->constants()->klass_name_at(scr_cp_index);
+ }
+
+ qsort(the_syms, members_len, sizeof(Symbol*), symcmp);
+ qsort(scr_syms, members_len, sizeof(Symbol*), symcmp);
+
+ for (int i = 0; i < members_len; i++) {
+ if (the_syms[i] != scr_syms[i]) {
+ log_trace(redefine, class, nestmates)
+ ("redefined class %s attribute change error: NestMembers[%d]: %s changed to %s",
+ the_class->external_name(), i, the_syms[i]->as_C_string(), scr_syms[i]->as_C_string());
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+ }
+ }
+ } else if (the_members_exists ^ scr_members_exists) {
+ const char* action_str = (the_members_exists) ? "removed" : "added";
+ log_trace(redefine, class, nestmates)
+ ("redefined class %s attribute change error: NestMembers attribute %s",
+ the_class->external_name(), action_str);
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
+ }
+
+ return JVMTI_ERROR_NONE;
+}
jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions(
InstanceKlass* the_class,
@@ -725,6 +814,12 @@
return JVMTI_ERROR_INVALID_CLASS;
}
+ // Check whether the nest-related attributes have been changed.
+ jvmtiError err = check_nest_attributes(the_class, scratch_class);
+ if (err != JVMTI_ERROR_NONE) {
+ return err;
+ }
+
// Check whether class modifiers are the same.
jushort old_flags = (jushort) the_class->access_flags().get_flags();
jushort new_flags = (jushort) scratch_class->access_flags().get_flags();
@@ -1598,6 +1693,12 @@
bool VM_RedefineClasses::rewrite_cp_refs(InstanceKlass* scratch_class,
TRAPS) {
+ // rewrite constant pool references in the nest attributes:
+ if (!rewrite_cp_refs_in_nest_attributes(scratch_class)) {
+ // propagate failure back to caller
+ return false;
+ }
+
// rewrite constant pool references in the methods:
if (!rewrite_cp_refs_in_methods(scratch_class, THREAD)) {
// propagate failure back to caller
@@ -1680,6 +1781,22 @@
return true;
} // end rewrite_cp_refs()
+// Rewrite constant pool references in the NestHost and NestMembers attributes.
+bool VM_RedefineClasses::rewrite_cp_refs_in_nest_attributes(
+ InstanceKlass* scratch_class) {
+
+ u2 cp_index = scratch_class->nest_host_index();
+ if (cp_index != 0) {
+ scratch_class->set_nest_host_index(find_new_index(cp_index));
+ }
+ Array<u2>* nest_members = scratch_class->nest_members();
+ for (int i = 0; i < nest_members->length(); i++) {
+ u2 cp_index = nest_members->at(i);
+ nest_members->at_put(i, find_new_index(cp_index));
+ }
+ return true;
+}
+
// Rewrite constant pool references in the methods.
bool VM_RedefineClasses::rewrite_cp_refs_in_methods(
InstanceKlass* scratch_class, TRAPS) {
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -469,6 +469,7 @@
AnnotationArray* type_annotations_typeArray, int &byte_i_ref, TRAPS);
bool rewrite_cp_refs_in_fields_annotations(
InstanceKlass* scratch_class, TRAPS);
+ bool rewrite_cp_refs_in_nest_attributes(InstanceKlass* scratch_class);
void rewrite_cp_refs_in_method(methodHandle method,
methodHandle * new_method_p, TRAPS);
bool rewrite_cp_refs_in_methods(InstanceKlass* scratch_class, TRAPS);
--- a/src/hotspot/share/prims/methodHandles.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/prims/methodHandles.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -238,7 +238,12 @@
vmindex);
m->access_flags().print_on(tty);
if (!m->is_abstract()) {
- tty->print("default");
+ if (!m->is_private()) {
+ tty->print("default");
+ }
+ else {
+ tty->print("private-intf");
+ }
}
tty->cr();
}
@@ -292,6 +297,9 @@
} else if (m->is_initializer()) {
flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
} else {
+ // "special" reflects that this is a direct call, not that it
+ // necessarily originates from an invokespecial. We can also do
+ // direct calls for private and/or final non-static methods.
flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
}
break;
--- a/src/hotspot/share/runtime/jniHandles.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/jniHandles.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -517,7 +517,7 @@
// Try last block
if (_last->_top < block_size_in_oops) {
oop* handle = &(_last->_handles)[_last->_top++];
- NativeAccess<AS_DEST_NOT_INITIALIZED>::oop_store(handle, obj);
+ NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj);
return (jobject) handle;
}
@@ -525,7 +525,7 @@
if (_free_list != NULL) {
oop* handle = _free_list;
_free_list = (oop*) *_free_list;
- NativeAccess<AS_DEST_NOT_INITIALIZED>::oop_store(handle, obj);
+ NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj);
return (jobject) handle;
}
// Check if unused block follow last
--- a/src/hotspot/share/runtime/reflection.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/reflection.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -650,26 +650,27 @@
return msg;
}
-bool Reflection::verify_field_access(const Klass* current_class,
- const Klass* resolved_class,
- const Klass* field_class,
- AccessFlags access,
- bool classloader_only,
- bool protected_restriction) {
- // Verify that current_class can access a field of field_class, where that
+bool Reflection::verify_member_access(const Klass* current_class,
+ const Klass* resolved_class,
+ const Klass* member_class,
+ AccessFlags access,
+ bool classloader_only,
+ bool protected_restriction,
+ TRAPS) {
+ // Verify that current_class can access a member of member_class, where that
// field's access bits are "access". We assume that we've already verified
- // that current_class can access field_class.
+ // that current_class can access member_class.
//
// If the classloader_only flag is set, we automatically allow any accesses
// in which current_class doesn't have a classloader.
//
- // "resolved_class" is the runtime type of "field_class". Sometimes we don't
+ // "resolved_class" is the runtime type of "member_class". Sometimes we don't
// need this distinction (e.g. if all we have is the runtime type, or during
// class file parsing when we only care about the static type); in that case
- // callers should ensure that resolved_class == field_class.
+ // callers should ensure that resolved_class == member_class.
//
if ((current_class == NULL) ||
- (current_class == field_class) ||
+ (current_class == member_class) ||
access.is_public()) {
return true;
}
@@ -683,18 +684,18 @@
InstanceKlass::cast(host_class)->is_anonymous()),
"host_class should not be anonymous");
}
- if (host_class == field_class) {
+ if (host_class == member_class) {
return true;
}
if (access.is_protected()) {
if (!protected_restriction) {
- // See if current_class (or outermost host class) is a subclass of field_class
+ // See if current_class (or outermost host class) is a subclass of member_class
// An interface may not access protected members of j.l.Object
- if (!host_class->is_interface() && host_class->is_subclass_of(field_class)) {
+ if (!host_class->is_interface() && host_class->is_subclass_of(member_class)) {
if (access.is_static() || // static fields are ok, see 6622385
current_class == resolved_class ||
- field_class == resolved_class ||
+ member_class == resolved_class ||
host_class->is_subclass_of(resolved_class) ||
resolved_class->is_subclass_of(host_class)) {
return true;
@@ -703,18 +704,35 @@
}
}
- if (!access.is_private() && is_same_class_package(current_class, field_class)) {
+ // package access
+ if (!access.is_private() && is_same_class_package(current_class, member_class)) {
return true;
}
+ // private access between different classes needs a nestmate check, but
+ // not for anonymous classes - so check host_class
+ if (access.is_private() && host_class == current_class) {
+ if (current_class->is_instance_klass() && member_class->is_instance_klass() ) {
+ InstanceKlass* cur_ik = const_cast<InstanceKlass*>(InstanceKlass::cast(current_class));
+ InstanceKlass* field_ik = const_cast<InstanceKlass*>(InstanceKlass::cast(member_class));
+ // Nestmate access checks may require resolution and validation of the nest-host.
+ // It is up to the caller to check for pending exceptions and handle appropriately.
+ bool access = cur_ik->has_nestmate_access_to(field_ik, CHECK_false);
+ if (access) {
+ guarantee(resolved_class->is_subclass_of(member_class), "must be!");
+ return true;
+ }
+ }
+ }
+
// Allow all accesses from jdk/internal/reflect/MagicAccessorImpl subclasses to
// succeed trivially.
if (current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
return true;
}
- return can_relax_access_check_for(
- current_class, field_class, classloader_only);
+ // Check for special relaxations
+ return can_relax_access_check_for(current_class, member_class, classloader_only);
}
bool Reflection::is_same_class_package(const Klass* class1, const Klass* class2) {
--- a/src/hotspot/share/runtime/reflection.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/reflection.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -90,12 +90,13 @@
const InstanceKlass* new_class,
const VerifyClassAccessResults result);
- static bool verify_field_access(const Klass* current_class,
- const Klass* resolved_class,
- const Klass* field_class,
- AccessFlags access,
- bool classloader_only,
- bool protected_restriction = false);
+ static bool verify_member_access(const Klass* current_class,
+ const Klass* resolved_class,
+ const Klass* member_class,
+ AccessFlags access,
+ bool classloader_only,
+ bool protected_restriction,
+ TRAPS);
static bool is_same_class_package(const Klass* class1, const Klass* class2);
// inner class reflection
--- a/src/hotspot/share/runtime/sharedRuntime.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1959,14 +1959,27 @@
// must use a ResourceMark in order to correctly free the result.
char* SharedRuntime::generate_class_cast_message(
Klass* caster_klass, Klass* target_klass, Symbol* target_klass_name) {
-
- const char* caster_name = caster_klass->class_loader_and_module_name();
+ const char* caster_name = caster_klass->external_name();
assert(target_klass != NULL || target_klass_name != NULL, "one must be provided");
const char* target_name = target_klass == NULL ? target_klass_name->as_C_string() :
- target_klass->class_loader_and_module_name();
-
- size_t msglen = strlen(caster_name) + strlen(" cannot be cast to ") + strlen(target_name) + 1;
+ target_klass->external_name();
+
+ size_t msglen = strlen(caster_name) + strlen("class ") + strlen(" cannot be cast to class ") + strlen(target_name) + 1;
+
+ const char* caster_klass_description = "";
+ const char* target_klass_description = "";
+ const char* klass_separator = "";
+ if (target_klass != NULL && caster_klass->module() == target_klass->module()) {
+ caster_klass_description = caster_klass->joint_in_module_of_loader(target_klass);
+ } else {
+ caster_klass_description = caster_klass->class_in_module_of_loader();
+ target_klass_description = (target_klass != NULL) ? target_klass->class_in_module_of_loader() : "";
+ klass_separator = (target_klass != NULL) ? "; " : "";
+ }
+
+ // add 3 for parenthesis and preceeding space
+ msglen += strlen(caster_klass_description) + strlen(target_klass_description) + strlen(klass_separator) + 3;
char* message = NEW_RESOURCE_ARRAY_RETURN_NULL(char, msglen);
if (message == NULL) {
@@ -1975,9 +1988,13 @@
} else {
jio_snprintf(message,
msglen,
- "%s cannot be cast to %s",
+ "class %s cannot be cast to class %s (%s%s%s)",
caster_name,
- target_name);
+ target_name,
+ caster_klass_description,
+ klass_separator,
+ target_klass_description
+ );
}
return message;
}
--- a/src/hotspot/share/runtime/stubRoutines.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/stubRoutines.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -418,7 +418,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
- ArrayAccess<AS_DEST_NOT_INITIALIZED>::oop_arraycopy_raw((HeapWord*)src, (HeapWord*)dest, count);
+ ArrayAccess<IS_DEST_UNINITIALIZED>::oop_arraycopy_raw((HeapWord*)src, (HeapWord*)dest, count);
JRT_END
JRT_LEAF(void, StubRoutines::arrayof_jbyte_copy(HeapWord* src, HeapWord* dest, size_t count))
@@ -462,7 +462,7 @@
SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy
#endif // !PRODUCT
assert(count != 0, "count should be non-zero");
- ArrayAccess<ARRAYCOPY_ARRAYOF | AS_DEST_NOT_INITIALIZED>::oop_arraycopy_raw(src, dest, count);
+ ArrayAccess<ARRAYCOPY_ARRAYOF | IS_DEST_UNINITIALIZED>::oop_arraycopy_raw(src, dest, count);
JRT_END
address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {
--- a/src/hotspot/share/runtime/threadSMR.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/runtime/threadSMR.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1067,8 +1067,15 @@
// Print Threads class SMR info.
void ThreadsSMRSupport::print_info_on(outputStream* st) {
- // Only grab the Threads_lock if we don't already own it
- // and if we are not reporting an error.
+ // Only grab the Threads_lock if we don't already own it and if we
+ // are not reporting an error.
+ // Note: Not grabbing the Threads_lock during error reporting is
+ // dangerous because the data structures we want to print can be
+ // freed concurrently. However, grabbing the Threads_lock during
+ // error reporting can be equally dangerous since this thread might
+ // block during error reporting or a nested error could leave the
+ // Threads_lock held. The classic no win scenario.
+ //
MutexLockerEx ml((Threads_lock->owned_by_self() || VMError::is_error_reported()) ? NULL : Threads_lock);
st->print_cr("Threads class SMR info:");
--- a/src/hotspot/share/utilities/debug.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/utilities/debug.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -714,16 +714,13 @@
}
}
-static bool store_context(const void* context) {
- if (memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t)) == false) {
- return false;
- }
+static void store_context(const void* context) {
+ memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
#if defined(__linux) && defined(PPC64)
// on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up
// after copying the context (see comment in sys/ucontext.h):
*((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs);
#endif
- return true;
}
bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
@@ -734,9 +731,8 @@
if (ucVoid) {
const intx my_tid = os::current_thread_id();
if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) {
- if (store_context(ucVoid)) {
- g_assertion_context = &g_stored_assertion_context;
- }
+ store_context(ucVoid);
+ g_assertion_context = &g_stored_assertion_context;
}
}
return true;
--- a/src/hotspot/share/utilities/macros.hpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/utilities/macros.hpp Mon Jun 25 09:48:06 2018 -0700
@@ -239,14 +239,6 @@
#define NOT_ZGC_RETURN_(code) { return code; }
#endif // INCLUDE_ZGC
-#if INCLUDE_CMSGC || INCLUDE_EPSILONGC || INCLUDE_G1GC || INCLUDE_PARALLELGC || INCLUDE_ZGC
-#define INCLUDE_NOT_ONLY_SERIALGC 1
-#else
-#define INCLUDE_NOT_ONLY_SERIALGC 0
-#endif
-
-#define INCLUDE_OOP_OOP_ITERATE_BACKWARDS INCLUDE_NOT_ONLY_SERIALGC
-
#ifndef INCLUDE_NMT
#define INCLUDE_NMT 1
#endif // INCLUDE_NMT
--- a/src/hotspot/share/utilities/vmError.cpp Mon Jun 25 08:14:11 2018 -0700
+++ b/src/hotspot/share/utilities/vmError.cpp Mon Jun 25 09:48:06 2018 -0700
@@ -1698,6 +1698,13 @@
// Case 15 is tested by test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java.
// Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
// Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
+
+ // We grab Threads_lock to keep ThreadsSMRSupport::print_info_on()
+ // from racing with Threads::add() or Threads::remove() as we
+ // generate the hs_err_pid file. This makes our ErrorHandling tests
+ // more stable.
+ MutexLockerEx ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+
switch (how) {
case 1: vmassert(str == NULL, "expected null"); break;
case 2: vmassert(num == 1023 && *str == 'X',
--- a/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/com/sun/java/util/jar/pack/intrinsic.properties Mon Jun 25 09:48:06 2018 -0700
@@ -13,6 +13,8 @@
pack.code.attribute.CharacterRangeTable = NH[PHPOHIIH]
pack.class.attribute.SourceID = RUH
pack.class.attribute.CompilationID = RUH
+pack.class.attribute.NestHost = RCH
+pack.class.attribute.NestMembers = NH[RCH]
# Note: Zero-length ("marker") attributes do not need to be specified here.
# They are automatically defined to have an empty layout.
--- a/src/java.base/share/classes/java/lang/Class.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Class.java Mon Jun 25 09:48:06 2018 -0700
@@ -82,9 +82,9 @@
import sun.reflect.misc.ReflectUtil;
/**
- * Instances of the class {@code Class} represent classes and
- * interfaces in a running Java application. An enum is a kind of
- * class and an annotation is a kind of interface. Every array also
+ * Instances of the class {@code Class} represent classes and interfaces
+ * in a running Java application. An enum type is a kind of class and an
+ * annotation type is a kind of interface. Every array also
* belongs to a class that is reflected as a {@code Class} object
* that is shared by all arrays with the same element type and number
* of dimensions. The primitive Java types ({@code boolean},
@@ -93,10 +93,34 @@
* {@code double}), and the keyword {@code void} are also
* represented as {@code Class} objects.
*
- * <p> {@code Class} has no public constructor. Instead {@code Class}
- * objects are constructed automatically by the Java Virtual Machine as classes
- * are loaded and by calls to the {@code defineClass} method in the class
- * loader.
+ * <p> {@code Class} has no public constructor. Instead a {@code Class}
+ * object is constructed automatically by the Java Virtual Machine
+ * when a class loader invokes one of the
+ * {@link ClassLoader#defineClass(String,byte[], int,int) defineClass} methods
+ * and passes the bytes of a {@code class} file.
+ *
+ * <p> The methods of class {@code Class} expose many characteristics of a
+ * class or interface. Most characteristics are derived from the {@code class}
+ * file that the class loader passed to the Java Virtual Machine. A few
+ * characteristics are determined by the class loading environment at run time,
+ * such as the module returned by {@link #getModule() getModule()}.
+ *
+ * <p> Some methods of class {@code Class} expose whether the declaration of
+ * a class or interface in Java source code was <em>enclosed</em> within
+ * another declaration. Other methods describe how a class or interface
+ * is situated in a <em>nest</em>. A <a id="nest">nest</a> is a set of
+ * classes and interfaces, in the same run-time package, that
+ * allow mutual access to their {@code private} members.
+ * The classes and interfaces are known as <em>nestmates</em>.
+ * One nestmate acts as the
+ * <em>nest host</em>, and enumerates the other nestmates which
+ * belong to the nest; each of them in turn records it as the nest host.
+ * The classes and interfaces which belong to a nest, including its host, are
+ * determined when
+ * {@code class} files are generated, for example, a Java compiler
+ * will typically record a top-level class as the host of a nest where the
+ * other members are the classes and interfaces whose declarations are
+ * enclosed within the top-level class declaration.
*
* <p> The following example uses a {@code Class} object to print the
* class name of an object:
@@ -3848,4 +3872,161 @@
public AnnotatedType[] getAnnotatedInterfaces() {
return TypeAnnotationParser.buildAnnotatedInterfaces(getRawTypeAnnotations(), getConstantPool(), this);
}
+
+ private native Class<?> getNestHost0();
+
+ /**
+ * Returns the nest host of the <a href=#nest>nest</a> to which the class
+ * or interface represented by this {@code Class} object belongs.
+ * Every class and interface is a member of exactly one nest.
+ * A class or interface that is not recorded as belonging to a nest
+ * belongs to the nest consisting only of itself, and is the nest
+ * host.
+ *
+ * <p>Each of the {@code Class} objects representing array types,
+ * primitive types, and {@code void} returns {@code this} to indicate
+ * that the represented entity belongs to the nest consisting only of
+ * itself, and is the nest host.
+ *
+ * <p>If there is a {@linkplain LinkageError linkage error} accessing
+ * the nest host, or if this class or interface is not enumerated as
+ * a member of the nest by the nest host, then it is considered to belong
+ * to its own nest and {@code this} is returned as the host.
+ *
+ * @apiNote A {@code class} file of version 55.0 or greater may record the
+ * host of the nest to which it belongs by using the {@code NestHost}
+ * attribute (JVMS 4.7.28). Alternatively, a {@code class} file of
+ * version 55.0 or greater may act as a nest host by enumerating the nest's
+ * other members with the
+ * {@code NestMembers} attribute (JVMS 4.7.29).
+ * A {@code class} file of version 54.0 or lower does not use these
+ * attributes.
+ *
+ * @return the nest host of this class or interface
+ *
+ * @throws SecurityException
+ * If the returned class is not the current class, and
+ * if a security manager, <i>s</i>, is present and the caller's
+ * class loader is not the same as or an ancestor of the class
+ * loader for the returned class and invocation of {@link
+ * SecurityManager#checkPackageAccess s.checkPackageAccess()}
+ * denies access to the package of the returned class
+ * @since 11
+ * @jvms 4.7.28 and 4.7.29 NestHost and NestMembers attributes
+ * @jvms 5.4.4 Access Control
+ */
+ @CallerSensitive
+ public Class<?> getNestHost() {
+ if (isPrimitive() || isArray()) {
+ return this;
+ }
+ Class<?> host;
+ try {
+ host = getNestHost0();
+ } catch (LinkageError e) {
+ // if we couldn't load our nest-host then we
+ // act as-if we have no nest-host attribute
+ return this;
+ }
+ // if null then nest membership validation failed, so we
+ // act as-if we have no nest-host attribute
+ if (host == null || host == this) {
+ return this;
+ }
+ // returning a different class requires a security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkPackageAccess(sm,
+ ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ return host;
+ }
+
+ /**
+ * Determines if the given {@code Class} is a nestmate of the
+ * class or interface represented by this {@code Class} object.
+ * Two classes or interfaces are nestmates
+ * if they have the same {@linkplain #getNestHost() nest host}.
+ *
+ * @param c the class to check
+ * @return {@code true} if this class and {@code c} are members of
+ * the same nest; and {@code false} otherwise.
+ *
+ * @since 11
+ */
+ public boolean isNestmateOf(Class<?> c) {
+ if (this == c) {
+ return true;
+ }
+ if (isPrimitive() || isArray() ||
+ c.isPrimitive() || c.isArray()) {
+ return false;
+ }
+ try {
+ return getNestHost0() == c.getNestHost0();
+ } catch (LinkageError e) {
+ return false;
+ }
+ }
+
+ private native Class<?>[] getNestMembers0();
+
+ /**
+ * Returns an array containing {@code Class} objects representing all the
+ * classes and interfaces that are members of the nest to which the class
+ * or interface represented by this {@code Class} object belongs.
+ * The {@linkplain #getNestHost() nest host} of that nest is the zeroth
+ * element of the array. Subsequent elements represent any classes or
+ * interfaces that are recorded by the nest host as being members of
+ * the nest; the order of such elements is unspecified. Duplicates are
+ * permitted.
+ * If the nest host of that nest does not enumerate any members, then the
+ * array has a single element containing {@code this}.
+ *
+ * <p>Each of the {@code Class} objects representing array types,
+ * primitive types, and {@code void} returns an array containing only
+ * {@code this}.
+ *
+ * <p>This method validates that, for each class or interface which is
+ * recorded as a member of the nest by the nest host, that class or
+ * interface records itself as a member of that same nest. Any exceptions
+ * that occur during this validation are rethrown by this method.
+ *
+ * @return an array of all classes and interfaces in the same nest as
+ * this class
+ *
+ * @throws LinkageError
+ * If there is any problem loading or validating a nest member or
+ * its nest host
+ * @throws SecurityException
+ * If any returned class is not the current class, and
+ * if a security manager, <i>s</i>, is present and the caller's
+ * class loader is not the same as or an ancestor of the class
+ * loader for that returned class and invocation of {@link
+ * SecurityManager#checkPackageAccess s.checkPackageAccess()}
+ * denies access to the package of that returned class
+ *
+ * @since 11
+ * @see #getNestHost()
+ */
+ @CallerSensitive
+ public Class<?>[] getNestMembers() {
+ if (isPrimitive() || isArray()) {
+ return new Class<?>[] { this };
+ }
+ Class<?>[] members = getNestMembers0();
+ // Can't actually enable this due to bootstrapping issues
+ // assert(members.length != 1 || members[0] == this); // expected invariant from VM
+
+ if (members.length > 1) {
+ // If we return anything other than the current class we need
+ // a security check
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ checkPackageAccess(sm,
+ ClassLoader.getClassLoader(Reflection.getCallerClass()), true);
+ }
+ }
+ return members;
+ }
}
--- a/src/java.base/share/classes/java/lang/Thread.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/Thread.java Mon Jun 25 09:48:06 2018 -0700
@@ -36,6 +36,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.LockSupport;
+
+import jdk.internal.misc.TerminatingThreadLocal;
import sun.nio.ch.Interruptible;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
@@ -838,6 +840,9 @@
* a chance to clean up before it actually exits.
*/
private void exit() {
+ if (threadLocals != null && TerminatingThreadLocal.REGISTRY.isPresent()) {
+ TerminatingThreadLocal.threadTerminated();
+ }
if (group != null) {
group.threadTerminated(this);
group = null;
--- a/src/java.base/share/classes/java/lang/ThreadLocal.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/ThreadLocal.java Mon Jun 25 09:48:06 2018 -0700
@@ -24,6 +24,8 @@
*/
package java.lang;
+import jdk.internal.misc.TerminatingThreadLocal;
+
import java.lang.ref.*;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@@ -171,6 +173,19 @@
}
/**
+ * Returns {@code true} if there is a value in the current thread's copy of
+ * this thread-local variable, even if that values is {@code null}.
+ *
+ * @return {@code true} if current thread has associated value in this
+ * thread-local variable; {@code false} if not
+ */
+ boolean isPresent() {
+ Thread t = Thread.currentThread();
+ ThreadLocalMap map = getMap(t);
+ return map != null && map.getEntry(this) != null;
+ }
+
+ /**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method.
*
@@ -180,10 +195,14 @@
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
- if (map != null)
+ if (map != null) {
map.set(this, value);
- else
+ } else {
createMap(t, value);
+ }
+ if (this instanceof TerminatingThreadLocal) {
+ TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
+ }
return value;
}
@@ -199,10 +218,11 @@
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
- if (map != null)
+ if (map != null) {
map.set(this, value);
- else
+ } else {
createMap(t, value);
+ }
}
/**
@@ -218,8 +238,9 @@
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
- if (m != null)
+ if (m != null) {
m.remove(this);
+ }
}
/**
--- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java Mon Jun 25 09:48:06 2018 -0700
@@ -58,7 +58,8 @@
if (!member.isResolved()) throw new InternalError();
if (member.getDeclaringClass().isInterface() &&
- member.isMethod() && !member.isAbstract()) {
+ member.getReferenceKind() == REF_invokeInterface &&
+ member.isMethod() && !member.isAbstract()) {
// Check for corner case: invokeinterface of Object method
MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
@@ -80,22 +81,28 @@
mtype = mtype.insertParameterTypes(0, refc);
}
if (!member.isField()) {
+ // refKind reflects the original type of lookup via findSpecial or
+ // findVirtual etc.
switch (refKind) {
case REF_invokeSpecial: {
member = member.asSpecial();
- LambdaForm lform = preparedLambdaForm(member, callerClass);
- Class<?> checkClass = refc; // Class to use for receiver type check
- if (callerClass != null) {
- checkClass = callerClass; // potentially strengthen to caller class
+ // if caller is an interface we need to adapt to get the
+ // receiver check inserted
+ if (callerClass == null) {
+ throw new InternalError("callerClass must not be null for REF_invokeSpecial");
}
- return new Special(mtype, lform, member, checkClass);
+ LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
+ return new Special(mtype, lform, member, callerClass);
}
case REF_invokeInterface: {
- LambdaForm lform = preparedLambdaForm(member, callerClass);
+ // for interfaces we always need the receiver typecheck,
+ // so we always pass 'true' to ensure we adapt if needed
+ // to include the REF_invokeSpecial case
+ LambdaForm lform = preparedLambdaForm(member, true);
return new Interface(mtype, lform, member, refc);
}
default: {
- LambdaForm lform = preparedLambdaForm(member, callerClass);
+ LambdaForm lform = preparedLambdaForm(member);
return new DirectMethodHandle(mtype, lform, member);
}
}
@@ -165,11 +172,16 @@
* Cache and share this structure among all methods with
* the same basicType and refKind.
*/
- private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
+ private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
MethodType mtype = m.getInvocationType().basicType();
assert(!m.isMethodHandleInvoke()) : m;
int which;
+ // MemberName.getReferenceKind represents the JVM optimized form of the call
+ // as distinct from the "kind" passed to DMH.make which represents the original
+ // bytecode-equivalent request. Specifically private/final methods that use a direct
+ // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
+ // invocation mode may be invokevirtual or invokeinterface.
switch (m.getReferenceKind()) {
case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
case REF_invokeStatic: which = LF_INVSTATIC; break;
@@ -183,7 +195,7 @@
preparedLambdaForm(mtype, which);
which = LF_INVSTATIC_INIT;
}
- if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
+ if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
which = LF_INVSPECIAL_IFC;
}
LambdaForm lform = preparedLambdaForm(mtype, which);
@@ -195,7 +207,7 @@
}
private static LambdaForm preparedLambdaForm(MemberName m) {
- return preparedLambdaForm(m, null);
+ return preparedLambdaForm(m, false);
}
private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
--- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java Mon Jun 25 09:48:06 2018 -0700
@@ -61,7 +61,13 @@
* parameters</em>, which must be provided as arguments to the
* {@code CallSite} target, and which may be early-bound to the behavior
* {@code MethodHandle}. The number of captured parameters and their types
- * are determined during linkage.</li>
+ * are determined during linkage.
+ * The identity of a function object produced by invoking the
+ * {@code CallSite}'s target is unpredictable, and therefore
+ * identity-sensitive operations (such as reference equality, object
+ * locking, and {@code System.identityHashCode()} may produce different
+ * results in different implementations, or even upon different invocations
+ * in the same implementation.</li>
*
* <li><em>Invocation</em> occurs when an implemented interface method
* is invoked on a function object. This may occur many times for a single
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -250,6 +250,9 @@
* can also be created. These do not perform virtual lookup based on
* receiver type. Such a method handle simulates the effect of
* an {@code invokespecial} instruction to the same method.
+ * A non-virtual method handle can also be created to simulate the effect
+ * of an {@code invokevirtual} or {@code invokeinterface} instruction on
+ * a private method (as applicable).
*
* <h1>Usage examples</h1>
* Here are some examples of usage:
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -469,15 +469,20 @@
* methods as if they were normal methods, but the JVM bytecode verifier rejects them.
* A lookup of such an internal method will produce a {@code NoSuchMethodException}.
* <p>
- * In some cases, access between nested classes is obtained by the Java compiler by creating
- * an wrapper method to access a private method of another class
- * in the same top-level declaration.
+ * If the relationship between nested types is expressed directly through the
+ * {@code NestHost} and {@code NestMembers} attributes
+ * (see the Java Virtual Machine Specification, sections 4.7.28 and 4.7.29),
+ * then the associated {@code Lookup} object provides direct access to
+ * the lookup class and all of its nestmates
+ * (see {@link java.lang.Class#getNestHost Class.getNestHost}).
+ * Otherwise, access between nested classes is obtained by the Java compiler creating
+ * a wrapper method to access a private method of another class in the same nest.
* For example, a nested class {@code C.D}
* can access private members within other related classes such as
* {@code C}, {@code C.D.E}, or {@code C.B},
* but the Java compiler may need to generate wrapper methods in
* those related classes. In such cases, a {@code Lookup} object on
- * {@code C.E} would be unable to those private members.
+ * {@code C.E} would be unable to access those private members.
* A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
* which can transform a lookup on {@code C.E} into one on any of those other
* classes, without special elevation of privilege.
@@ -499,11 +504,12 @@
* <em>Discussion of private access:</em>
* We say that a lookup has <em>private access</em>
* if its {@linkplain #lookupModes lookup modes}
- * include the possibility of accessing {@code private} members.
+ * include the possibility of accessing {@code private} members
+ * (which includes the private members of nestmates).
* As documented in the relevant methods elsewhere,
* only lookups with private access possess the following capabilities:
* <ul style="font-size:smaller;">
- * <li>access private fields, methods, and constructors of the lookup class
+ * <li>access private fields, methods, and constructors of the lookup class and its nestmates
* <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
* such as {@code Class.forName}
* <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
@@ -728,9 +734,7 @@
* <p>
* A freshly-created lookup object
* on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has
- * all possible bits set, except {@code UNCONDITIONAL}. The lookup can be used to
- * access all members of the caller's class, all public types in the caller's module,
- * and all public types in packages exported by other modules to the caller's module.
+ * all possible bits set, except {@code UNCONDITIONAL}.
* A lookup object on a new lookup class
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
@@ -1106,8 +1110,9 @@
* The method and all its argument types must be accessible to the lookup object.
* <p>
* When called, the handle will treat the first argument as a receiver
- * and dispatch on the receiver's type to determine which method
+ * and, for non-private methods, dispatch on the receiver's type to determine which method
* implementation to enter.
+ * For private methods the named method in {@code refc} will be invoked on the receiver.
* (The dispatching action is identical with that performed by an
* {@code invokevirtual} or {@code invokeinterface} instruction.)
* <p>
@@ -1171,7 +1176,6 @@
* @throws NoSuchMethodException if the method does not exist
* @throws IllegalAccessException if access checking fails,
* or if the method is {@code static},
- * or if the method is {@code private} method of interface,
* or if the method's variable arity modifier bit
* is set and {@code asVarargsCollector} fails
* @exception SecurityException if a security manager is present and it
@@ -2225,17 +2229,13 @@
return "member is private to package";
}
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
-
private void checkSpecialCaller(Class<?> specialCaller, Class<?> refc) throws IllegalAccessException {
int allowedModes = this.allowedModes;
if (allowedModes == TRUSTED) return;
if (!hasPrivateAccess()
|| (specialCaller != lookupClass()
// ensure non-abstract methods in superinterfaces can be special-invoked
- && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))
- && !(ALLOW_NESTMATE_ACCESS &&
- VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
+ && !(refc != null && refc.isInterface() && refc.isAssignableFrom(specialCaller))))
throw new MemberName(specialCaller).
makeAccessException("no private access for invokespecial", this);
}
@@ -2246,9 +2246,7 @@
if (!method.isProtected() || method.isStatic()
|| allowedModes == TRUSTED
|| method.getDeclaringClass() == lookupClass()
- || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
- || (ALLOW_NESTMATE_ACCESS &&
- VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
+ || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass()))
return false;
return true;
}
@@ -2288,6 +2286,7 @@
private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
boolean checkSecurity,
boolean doRestrict, Class<?> boundCallerClass) throws IllegalAccessException {
+
checkMethod(refKind, refc, method);
// Optionally check with the security manager; this isn't needed for unreflect* calls.
if (checkSecurity)
@@ -2300,6 +2299,7 @@
refc != lookupClass().getSuperclass() &&
refc.isAssignableFrom(lookupClass())) {
assert(!method.getName().equals("<init>")); // not this code path
+
// Per JVMS 6.5, desc. of invokespecial instruction:
// If the method is in a superclass of the LC,
// and if our original search was above LC.super,
--- a/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/invoke/SerializedLambda.java Mon Jun 25 09:48:06 2018 -0700
@@ -53,6 +53,12 @@
* that the properties of the {@code SerializedLambda} are consistent with a
* lambda actually captured by that class.
*
+ * <p>The identity of a function object produced by deserializing the serialized
+ * form is unpredictable, and therefore identity-sensitive operations (such as
+ * reference equality, object locking, and {@code System.identityHashCode()} may
+ * produce different results in different implementations, or even upon
+ * different deserializations in the same implementation.
+ *
* @see LambdaMetafactory
* @since 1.8
*/
--- a/src/java.base/share/classes/java/lang/module/package-info.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/module/package-info.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -154,8 +154,9 @@
* application module specified to the 'java' launcher. When compiling code in
* the unnamed module, or at run-time when the main application class is loaded
* from the class path, then the default set of root modules is implementation
- * specific (In the JDK implementation it is the module "java.se", if observable,
- * and every observable module that exports an API). </p>
+ * specific. In the JDK the default set of root modules contains every module
+ * that is observable on the upgrade module path or among the system modules,
+ * and that exports at least one package without qualification. </p>
*
* <h2> Observable modules </h2>
*
--- a/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java Mon Jun 25 09:48:06 2018 -0700
@@ -47,7 +47,7 @@
* in a manner that would normally be prohibited.
*
* <p> Java language access control prevents use of private members outside
- * their class; package access members outside their package; protected members
+ * their top-level class; package access members outside their package; protected members
* outside their package or subclasses; and public members outside their
* module unless they are declared in an {@link Module#isExported(String,Module)
* exported} package and the user {@link Module#canRead reads} their module. By
--- a/src/java.base/share/classes/java/lang/reflect/Method.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/lang/reflect/Method.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -505,8 +505,8 @@
*
* <p>If the underlying method is an instance method, it is invoked
* using dynamic method lookup as documented in The Java Language
- * Specification, Second Edition, section 15.12.4.4; in particular,
- * overriding based on the runtime type of the target object will occur.
+ * Specification, section 15.12.4.4; in particular,
+ * overriding based on the runtime type of the target object may occur.
*
* <p>If the underlying method is static, the class that declared
* the method is initialized if it has not already been initialized.
--- a/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -37,6 +37,7 @@
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ResourceManager;
+import sun.net.util.SocketExceptions;
/**
* Default Socket Implementation. This implementation does
@@ -415,7 +416,7 @@
}
} catch (IOException e) {
close();
- throw e;
+ throw SocketExceptions.of(e, new InetSocketAddress(address, port));
}
}
--- a/src/java.base/share/classes/java/nio/BufferMismatch.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/java/nio/BufferMismatch.java Mon Jun 25 09:48:06 2018 -0700
@@ -34,6 +34,8 @@
static int mismatch(ByteBuffer a, int aOff, ByteBuffer b, int bOff, int length) {
int i = 0;
if (length > 7) {
+ if (a.get(aOff) != b.get(bOff))
+ return 0;
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + aOff,
b.base(), b.address + bOff,
@@ -56,6 +58,8 @@
// (order is null) then the slow path is taken
if (length > 3 && a.charRegionOrder() == b.charRegionOrder()
&& a.charRegionOrder() != null && b.charRegionOrder() != null) {
+ if (a.get(aOff) != b.get(bOff))
+ return 0;
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_CHAR_INDEX_SCALE),
@@ -74,6 +78,8 @@
static int mismatch(ShortBuffer a, int aOff, ShortBuffer b, int bOff, int length) {
int i = 0;
if (length > 3 && a.order() == b.order()) {
+ if (a.get(aOff) != b.get(bOff))
+ return 0;
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_SHORT_INDEX_SCALE),
@@ -92,6 +98,8 @@
static int mismatch(IntBuffer a, int aOff, IntBuffer b, int bOff, int length) {
int i = 0;
if (length > 1 && a.order() == b.order()) {
+ if (a.get(aOff) != b.get(bOff))
+ return 0;
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_INT_INDEX_SCALE),
@@ -110,11 +118,13 @@
static int mismatch(FloatBuffer a, int aOff, FloatBuffer b, int bOff, int length) {
int i = 0;
if (length > 1 && a.order() == b.order()) {
- i = ArraysSupport.vectorizedMismatch(
- a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
- b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
- length,
- ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ if (Float.floatToRawIntBits(a.get(aOff)) == Float.floatToRawIntBits(b.get(bOff))) {
+ i = ArraysSupport.vectorizedMismatch(
+ a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
+ b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE),
+ length,
+ ArraysSupport.LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ }
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values; and
@@ -146,6 +156,8 @@
static int mismatch(LongBuffer a, int aOff, LongBuffer b, int bOff, int length) {
int i = 0;
if (length > 0 && a.order() == b.order()) {
+ if (a.get(aOff) != b.get(bOff))
+ return 0;
i = ArraysSupport.vectorizedMismatch(
a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_LONG_INDEX_SCALE),
@@ -163,11 +175,13 @@
static int mismatch(DoubleBuffer a, int aOff, DoubleBuffer b, int bOff, int length) {
int i = 0;
if (length > 0 && a.order() == b.order()) {
- i = ArraysSupport.vectorizedMismatch(
- a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
- b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
- length,
- ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ if (Double.doubleToRawLongBits(a.get(aOff)) == Double.doubleToRawLongBits(b.get(bOff))) {
+ i = ArraysSupport.vectorizedMismatch(
+ a.base(), a.address + (aOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
+ b.base(), b.address + (bOff << ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE),
+ length,
+ ArraysSupport.LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ }
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values; and
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Mon Jun 25 09:48:06 2018 -0700
@@ -44,6 +44,7 @@
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.Modules;
import jdk.internal.module.ServicesCatalog;
/**
@@ -249,15 +250,16 @@
}
}
+ // return the Module object for the module name. The Module may
+ // in the boot layer or a child layer for the case that the module
+ // is loaded into a running VM
if (mn != null) {
- // named module from runtime image or exploded module
- Optional<Module> om = ModuleLayer.boot().findModule(mn);
- if (!om.isPresent())
- throw new InternalError(mn + " not in boot layer");
- return om.get();
+ String name = mn;
+ return Modules.findLoadedModule(mn)
+ .orElseThrow(() -> new InternalError(name + " not loaded"));
+ } else {
+ return null;
}
-
- return null;
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/TerminatingThreadLocal.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018, 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.misc;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+
+/**
+ * A thread-local variable that is notified when a thread terminates and
+ * it has been initialized in the terminating thread (even if it was
+ * initialized with a null value).
+ */
+public class TerminatingThreadLocal<T> extends ThreadLocal<T> {
+
+ @Override
+ public void set(T value) {
+ super.set(value);
+ register(this);
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+ unregister(this);
+ }
+
+ /**
+ * Invoked by a thread when terminating and this thread-local has an associated
+ * value for the terminating thread (even if that value is null), so that any
+ * native resources maintained by the value can be released.
+ *
+ * @param value current thread's value of this thread-local variable
+ * (may be null but only if null value was explicitly initialized)
+ */
+ protected void threadTerminated(T value) {
+ }
+
+ // following methods and field are implementation details and should only be
+ // called from the corresponding code int Thread/ThreadLocal class.
+
+ /**
+ * Invokes the TerminatingThreadLocal's {@link #threadTerminated()} method
+ * on all instances registered in current thread.
+ */
+ public static void threadTerminated() {
+ for (TerminatingThreadLocal<?> ttl : REGISTRY.get()) {
+ ttl._threadTerminated();
+ }
+ }
+
+ private void _threadTerminated() { threadTerminated(get()); }
+
+ /**
+ * Register given TerminatingThreadLocal
+ *
+ * @param tl the ThreadLocal to register
+ */
+ public static void register(TerminatingThreadLocal<?> tl) {
+ REGISTRY.get().add(tl);
+ }
+
+ /**
+ * Unregister given TerminatingThreadLocal
+ *
+ * @param tl the ThreadLocal to unregister
+ */
+ private static void unregister(TerminatingThreadLocal<?> tl) {
+ REGISTRY.get().remove(tl);
+ }
+
+ /**
+ * a per-thread registry of TerminatingThreadLocal(s) that have been registered
+ * but later not unregistered in a particular thread.
+ */
+ public static final ThreadLocal<Collection<TerminatingThreadLocal<?>>> REGISTRY =
+ new ThreadLocal<>() {
+ @Override
+ protected Collection<TerminatingThreadLocal<?>> initialValue() {
+ return Collections.newSetFromMap(new IdentityHashMap<>(4));
+ }
+ };
+}
--- a/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -22,13 +22,14 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.internal.module;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
-import java.util.HashSet;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Defines methods to compute the default set of root modules for the unnamed
@@ -36,58 +37,45 @@
*/
public final class DefaultRoots {
- private static final String JAVA_SE = "java.se";
-
private DefaultRoots() { }
/**
- * Returns the default set of root modules for the unnamed module computed from
- * the system modules observable with the given module finder.
+ * Returns the default set of root modules for the unnamed module from the
+ * modules observable with the intersection of two module finders.
+ *
+ * The first module finder should be the module finder that finds modules on
+ * the upgrade module path or among the system modules. The second module
+ * finder should be the module finder that finds all modules on the module
+ * path, or a subset of when using --limit-modules.
*/
- static Set<String> compute(ModuleFinder systemModuleFinder, ModuleFinder finder) {
- Set<String> roots = new HashSet<>();
-
- boolean hasJava = false;
- if (systemModuleFinder.find(JAVA_SE).isPresent()) {
- if (finder == systemModuleFinder || finder.find(JAVA_SE).isPresent()) {
- // java.se is a system module
- hasJava = true;
- roots.add(JAVA_SE);
- }
- }
-
- for (ModuleReference mref : systemModuleFinder.findAll()) {
- String mn = mref.descriptor().name();
- if (hasJava && mn.startsWith("java.")) {
- // not a root
- continue;
- }
-
- if (ModuleResolution.doNotResolveByDefault(mref)) {
- // not a root
- continue;
- }
-
- if ((finder == systemModuleFinder || finder.find(mn).isPresent())) {
- // add as root if exports at least one package to all modules
- ModuleDescriptor descriptor = mref.descriptor();
- for (ModuleDescriptor.Exports e : descriptor.exports()) {
- if (!e.isQualified()) {
- roots.add(mn);
- break;
- }
- }
- }
- }
-
- return roots;
+ static Set<String> compute(ModuleFinder finder1, ModuleFinder finder2) {
+ return finder1.findAll().stream()
+ .filter(mref -> !ModuleResolution.doNotResolveByDefault(mref))
+ .map(ModuleReference::descriptor)
+ .filter(descriptor -> finder2.find(descriptor.name()).isPresent()
+ && exportsAPI(descriptor))
+ .map(ModuleDescriptor::name)
+ .collect(Collectors.toSet());
}
/**
* Returns the default set of root modules for the unnamed module from the
* modules observable with the given module finder.
+ *
+ * This method is used by the jlink system modules plugin.
*/
public static Set<String> compute(ModuleFinder finder) {
return compute(finder, finder);
}
+
+ /**
+ * Returns true if the given module exports a package to all modules
+ */
+ private static boolean exportsAPI(ModuleDescriptor descriptor) {
+ return descriptor.exports()
+ .stream()
+ .filter(e -> !e.isQualified())
+ .findAny()
+ .isPresent();
+ }
}
--- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Mon Jun 25 09:48:06 2018 -0700
@@ -280,11 +280,10 @@
// If there is no initial module specified then assume that the initial
// module is the unnamed module of the application class loader. This
- // is implemented by resolving "java.se" and all (non-java.*) modules
- // that export an API. If "java.se" is not observable then all java.*
- // modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
- // bit set in their ModuleResolution attribute flags are excluded from
- // the default set of roots.
+ // is implemented by resolving all observable modules that export an
+ // API. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT bit set in
+ // their ModuleResolution attribute flags are excluded from the
+ // default set of roots.
if (mainModule == null || addAllDefaultModules) {
roots.addAll(DefaultRoots.compute(systemModuleFinder, finder));
}
--- a/src/java.base/share/classes/jdk/internal/module/Modules.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/Modules.java Mon Jun 25 09:48:06 2018 -0700
@@ -35,6 +35,7 @@
import java.security.PrivilegedAction;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -249,7 +250,19 @@
}
- // the top-most system layer
- private static ModuleLayer topLayer;
+ /**
+ * Finds the module with the given name in the boot layer or any child
+ * layers created to load the "java.instrument" or "jdk.management.agent"
+ * modules into a running VM.
+ */
+ public static Optional<Module> findLoadedModule(String name) {
+ ModuleLayer top = topLayer;
+ if (top == null)
+ top = ModuleLayer.boot();
+ return top.findModule(name);
+ }
+
+ // the top-most layer
+ private static volatile ModuleLayer topLayer;
}
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Attribute.java Mon Jun 25 09:48:06 2018 -0700
@@ -58,6 +58,8 @@
*/
package jdk.internal.org.objectweb.asm;
+import java.util.Arrays;
+
/**
* A non standard class, field, method or code attribute.
*
@@ -281,4 +283,72 @@
attr = attr.next;
}
}
+
+ //The stuff below is temporary - once proper support for nestmate attribute has been added, it can be safely removed.
+ //see also changes in ClassReader.accept.
+
+ public static class NestMembers extends Attribute {
+ public NestMembers() {
+ super("NestMembers");
+ }
+
+ byte[] bytes;
+ String[] classes;
+
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
+ int offset = off;
+ NestMembers a = new NestMembers();
+ int size = cr.readShort(off);
+ a.classes = new String[size];
+ off += 2;
+ for (int i = 0; i < size ; i++) {
+ a.classes[i] = cr.readClass(off, buf);
+ off += 2;
+ }
+ a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
+ return a;
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
+ ByteVector v = new ByteVector(bytes.length);
+ v.putShort(classes.length);
+ for (String s : classes) {
+ v.putShort(cw.newClass(s));
+ }
+ return v;
+ }
+ }
+
+ public static class NestHost extends Attribute {
+
+ byte[] bytes;
+ String clazz;
+
+ public NestHost() {
+ super("NestHost");
+ }
+
+ @Override
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf, int codeOff, Label[] labels) {
+ int offset = off;
+ NestHost a = new NestHost();
+ a.clazz = cr.readClass(off, buf);
+ a.bytes = Arrays.copyOfRange(cr.b, offset, offset + len);
+ return a;
+ }
+
+ @Override
+ protected ByteVector write(ClassWriter cw, byte[] code, int len, int maxStack, int maxLocals) {
+ ByteVector v = new ByteVector(bytes.length);
+ v.putShort(cw.newClass(clazz));
+ return v;
+ }
+ }
+
+ static final Attribute[] DEFAULT_ATTRIBUTE_PROTOS = new Attribute[] {
+ new NestMembers(),
+ new NestHost()
+ };
}
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java Mon Jun 25 09:48:06 2018 -0700
@@ -530,7 +530,7 @@
* , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
*/
public void accept(final ClassVisitor classVisitor, final int flags) {
- accept(classVisitor, new Attribute[0], flags);
+ accept(classVisitor, Attribute.DEFAULT_ATTRIBUTE_PROTOS, flags);
}
/**
--- a/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -629,14 +629,10 @@
typeSizeInStackSlots(returnType));
} else {
if (isInterface()) {
- if (isPrivate()) {
- cb.opc_invokespecial(targetMethodRef, count, 0);
- } else {
- cb.opc_invokeinterface(targetMethodRef,
- count,
- count,
- typeSizeInStackSlots(returnType));
- }
+ cb.opc_invokeinterface(targetMethodRef,
+ count,
+ count,
+ typeSizeInStackSlots(returnType));
} else {
cb.opc_invokevirtual(targetMethodRef,
count,
--- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -143,6 +143,15 @@
return true;
}
+ // Check for nestmate access if member is private
+ if (Modifier.isPrivate(modifiers)) {
+ // Note: targetClass may be outside the nest, but that is okay
+ // as long as memberClass is in the nest.
+ if (areNestMates(currentClass, memberClass)) {
+ return true;
+ }
+ }
+
boolean successSoFar = false;
if (Modifier.isProtected(modifiers)) {
@@ -351,4 +360,12 @@
return new IllegalAccessException(msg);
}
+
+ /**
+ * Returns true if {@code currentClass} and {@code memberClass}
+ * are nestmates - that is, if they have the same nesthost as
+ * determined by the VM.
+ */
+ public static native boolean areNestMates(Class<?> currentClass,
+ Class<?> memberClass);
}
--- a/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/util/ArraysSupport.java Mon Jun 25 09:48:06 2018 -0700
@@ -166,6 +166,8 @@
int length) {
int i = 0;
if (length > 7) {
+ if (a[0] != b[0])
+ return 0;
i = vectorizedMismatch(
a, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
b, Unsafe.ARRAY_BOOLEAN_BASE_OFFSET,
@@ -186,6 +188,8 @@
int length) {
int i = 0;
if (length > 7) {
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BOOLEAN_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
@@ -228,6 +232,8 @@
int i = 0;
if (length > 7) {
+ if (a[0] != b[0])
+ return 0;
i = vectorizedMismatch(
a, Unsafe.ARRAY_BYTE_BASE_OFFSET,
b, Unsafe.ARRAY_BYTE_BASE_OFFSET,
@@ -275,6 +281,8 @@
int i = 0;
if (length > 7) {
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + aFromIndex;
int bOffset = Unsafe.ARRAY_BYTE_BASE_OFFSET + bFromIndex;
i = vectorizedMismatch(
@@ -300,6 +308,8 @@
int length) {
int i = 0;
if (length > 3) {
+ if (a[0] != b[0])
+ return 0;
i = vectorizedMismatch(
a, Unsafe.ARRAY_CHAR_BASE_OFFSET,
b, Unsafe.ARRAY_CHAR_BASE_OFFSET,
@@ -320,6 +330,8 @@
int length) {
int i = 0;
if (length > 3) {
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_CHAR_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_CHAR_INDEX_SCALE);
i = vectorizedMismatch(
@@ -345,6 +357,8 @@
int length) {
int i = 0;
if (length > 3) {
+ if (a[0] != b[0])
+ return 0;
i = vectorizedMismatch(
a, Unsafe.ARRAY_SHORT_BASE_OFFSET,
b, Unsafe.ARRAY_SHORT_BASE_OFFSET,
@@ -365,6 +379,8 @@
int length) {
int i = 0;
if (length > 3) {
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_SHORT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_SHORT_INDEX_SCALE);
i = vectorizedMismatch(
@@ -390,6 +406,8 @@
int length) {
int i = 0;
if (length > 1) {
+ if (a[0] != b[0])
+ return 0;
i = vectorizedMismatch(
a, Unsafe.ARRAY_INT_BASE_OFFSET,
b, Unsafe.ARRAY_INT_BASE_OFFSET,
@@ -410,6 +428,8 @@
int length) {
int i = 0;
if (length > 1) {
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_INT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_INT_INDEX_SCALE);
i = vectorizedMismatch(
@@ -441,12 +461,14 @@
int length) {
int i = 0;
if (length > 1) {
- int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
- int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
- i = vectorizedMismatch(
- a, aOffset,
- b, bOffset,
- length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ if (Float.floatToRawIntBits(a[aFromIndex]) == Float.floatToRawIntBits(b[bFromIndex])) {
+ int aOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_FLOAT_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_FLOAT_INDEX_SCALE);
+ }
// Mismatched
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
@@ -481,6 +503,8 @@
if (length == 0) {
return -1;
}
+ if (a[0] != b[0])
+ return 0;
int i = vectorizedMismatch(
a, Unsafe.ARRAY_LONG_BASE_OFFSET,
b, Unsafe.ARRAY_LONG_BASE_OFFSET,
@@ -494,6 +518,8 @@
if (length == 0) {
return -1;
}
+ if (a[aFromIndex] != b[bFromIndex])
+ return 0;
int aOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int bOffset = Unsafe.ARRAY_LONG_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_LONG_INDEX_SCALE);
int i = vectorizedMismatch(
@@ -518,12 +544,15 @@
if (length == 0) {
return -1;
}
- int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
- int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
- int i = vectorizedMismatch(
- a, aOffset,
- b, bOffset,
- length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ int i = 0;
+ if (Double.doubleToRawLongBits(a[aFromIndex]) == Double.doubleToRawLongBits(b[bFromIndex])) {
+ int aOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (aFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ int bOffset = Unsafe.ARRAY_DOUBLE_BASE_OFFSET + (bFromIndex << LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ i = vectorizedMismatch(
+ a, aOffset,
+ b, bOffset,
+ length, LOG2_ARRAY_DOUBLE_INDEX_SCALE);
+ }
if (i >= 0) {
// Check if mismatch is not associated with two NaN values
if (!Double.isNaN(a[aFromIndex + i]) || !Double.isNaN(b[bFromIndex + i]))
--- a/src/java.base/share/classes/module-info.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/module-info.java Mon Jun 25 09:48:06 2018 -0700
@@ -242,6 +242,7 @@
exports sun.nio.ch to
java.management,
jdk.crypto.cryptoki,
+ jdk.net,
jdk.sctp,
jdk.unsupported;
exports sun.nio.cs to
--- a/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -44,7 +44,6 @@
private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
- private static final boolean ALLOW_NESTMATE_ACCESS = false;
/**
* Evaluate the JVM linkage rules for access to the given method
@@ -62,23 +61,29 @@
* the defining class should be passed for both arguments ({@code defc == refc}).
* <h3>JVM Specification, 5.4.4 "Access Control"</h3>
* A field or method R is accessible to a class or interface D if
- * and only if any of the following conditions is true:<ul>
- * <li>R is public.
+ * and only if any of the following is true:
+ * <ul>
+ * <li>R is public.</li>
* <li>R is protected and is declared in a class C, and D is either
- * a subclass of C or C itself. Furthermore, if R is not
- * static, then the symbolic reference to R must contain a
- * symbolic reference to a class T, such that T is either a
- * subclass of D, a superclass of D or D itself.
- * <li>R is either protected or has default access (that is,
- * neither public nor protected nor private), and is declared
- * by a class in the same runtime package as D.
- * <li>R is private and is declared in D.
+ * a subclass of C or C itself. Furthermore, if R is not static,
+ * then the symbolic reference to R must contain a symbolic
+ * reference to a class T, such that T is either a subclass of D,
+ * a superclass of D, or D itself.
+ * <p>During verification, it was also required that, even if T is
+ * a superclass of D, the target reference of a protected instance
+ * field access or method invocation must be an instance of D or a
+ * subclass of D (4.10.1.8).</p></li>
+ * <li>R is either protected or has default access (that is, neither
+ * public nor protected nor private), and is declared by a class
+ * in the same run-time package as D.</li>
+ * <li>R is private and is declared in D by a class or interface
+ * belonging to the same nest as D.</li>
* </ul>
- * This discussion of access control omits a related restriction
- * on the target of a protected field access or method invocation
- * (the target must be of class D or a subtype of D). That
- * requirement is checked as part of the verification process
- * (5.4.1); it is not part of link-time access control.
+ * If a referenced field or method is not accessible, access checking
+ * throws an IllegalAccessError. If an exception is thrown while
+ * attempting to determine the nest host of a class or interface,
+ * access checking fails for the same reason.
+ *
* @param refc the class used in the symbolic reference to the proposed member
* @param defc the class in which the proposed member is actually defined
* @param mods modifier flags for the proposed member
@@ -98,9 +103,10 @@
return false;
}
// Usually refc and defc are the same, but verify defc also in case they differ.
- if (defc == lookupClass &&
+ if (defc == lookupClass &&
(allowedModes & PRIVATE) != 0)
- return true; // easy check; all self-access is OK
+ return true; // easy check; all self-access is OK with a private lookup
+
switch (mods & ALL_ACCESS_MODES) {
case PUBLIC:
return true; // already checked above
@@ -126,10 +132,13 @@
return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
isSamePackage(defc, lookupClass));
case PRIVATE:
- // Loosened rules for privates follows access rules for inner classes.
- return (ALLOW_NESTMATE_ACCESS &&
- (allowedModes & PRIVATE) != 0 &&
- isSamePackageMember(defc, lookupClass));
+ // Rules for privates follows access rules for nestmates.
+ boolean canAccess = ((allowedModes & PRIVATE) != 0 &&
+ Reflection.areNestMates(defc, lookupClass));
+ // for private methods the selected method equals the
+ // resolved method - so refc == defc
+ assert (canAccess && refc == defc) || !canAccess;
+ return canAccess;
default:
throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/net/util/SocketExceptions.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018, 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 sun.net.util;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.InetSocketAddress;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+
+public final class SocketExceptions {
+ private SocketExceptions() {}
+
+ /**
+ * Security or system property which specifies categories of
+ * (potentially sensitive) information that may be included
+ * in exception text. This class only defines one category:
+ * "hostInfo" which represents the hostname and port number
+ * of the remote peer relating to a socket exception.
+ * The property value is a comma separated list of
+ * case insignificant category names.
+ */
+ private static final String enhancedTextPropname = "jdk.net.includeInExceptions";
+
+ private static final boolean enhancedExceptionText = initTextProp();
+
+ private static boolean initTextProp() {
+ return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ String val = System.getProperty(enhancedTextPropname);
+ if (val == null) {
+ val = Security.getProperty(enhancedTextPropname);
+ if (val == null)
+ return false;
+ }
+ String[] tokens = val.split(",");
+ for (String token : tokens) {
+ if (token.equalsIgnoreCase("hostinfo"))
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+
+ /**
+ * Utility which takes an exception and returns either the same exception
+ * or a new exception of the same type with the same stack trace
+ * and detail message enhanced with addressing information from the
+ * given InetSocketAddress.
+ *
+ * If the system/security property "jdk.net.enhanceExceptionText" is not
+ * set or is false, then the original exception is returned.
+ *
+ * Only specific IOException subtypes are supported.
+ */
+ public static IOException of(IOException e, InetSocketAddress address) {
+ if (!enhancedExceptionText || address == null)
+ return e;
+ int port = address.getPort();
+ String host = address.getHostString();
+ StringBuilder sb = new StringBuilder();
+ sb.append(e.getMessage());
+ sb.append(": ");
+ sb.append(host);
+ sb.append(':');
+ sb.append(Integer.toString(port));
+ String enhancedMsg = sb.toString();
+ return create(e, enhancedMsg);
+ }
+
+ // return a new instance of the same type with the given detail
+ // msg, or if the type doesn't support detail msgs, return given
+ // instance.
+
+ private static IOException create(IOException e, String msg) {
+ return AccessController.doPrivileged(new PrivilegedAction<IOException>() {
+ public IOException run() {
+ try {
+ Class<?> clazz = e.getClass();
+ Constructor<?> ctor = clazz.getConstructor(String.class);
+ IOException e1 = (IOException)(ctor.newInstance(msg));
+ e1.setStackTrace(e.getStackTrace());
+ return e1;
+ } catch (Exception e0) {
+ // Some eg AsynchronousCloseException have no detail msg
+ return e;
+ }
+ }
+ });
+ }
+}
--- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -54,6 +54,7 @@
import sun.net.NetHooks;
import sun.net.ext.ExtendedSocketOptions;
+import sun.net.util.SocketExceptions;
import static sun.net.ext.ExtendedSocketOptions.SOCK_STREAM;
/**
@@ -706,7 +707,7 @@
} catch (IOException ioe) {
// connect failed, close the channel
close();
- throw ioe;
+ throw SocketExceptions.of(ioe, isa);
}
}
@@ -792,7 +793,7 @@
} catch (IOException ioe) {
// connect failed, close the channel
close();
- throw ioe;
+ throw SocketExceptions.of(ioe, remoteAddress);
}
}
--- a/src/java.base/share/classes/sun/nio/ch/Util.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/ch/Util.java Mon Jun 25 09:48:06 2018 -0700
@@ -26,6 +26,7 @@
package sun.nio.ch;
import java.io.FileDescriptor;
+import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.nio.ByteBuffer;
@@ -35,9 +36,10 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
+
+import jdk.internal.misc.TerminatingThreadLocal;
import jdk.internal.misc.Unsafe;
import sun.security.action.GetPropertyAction;
-import java.io.IOException;
public class Util {
@@ -50,13 +52,18 @@
private static final long MAX_CACHED_BUFFER_SIZE = getMaxCachedBufferSize();
// Per-thread cache of temporary direct buffers
- private static ThreadLocal<BufferCache> bufferCache =
- new ThreadLocal<BufferCache>()
- {
+ private static ThreadLocal<BufferCache> bufferCache = new TerminatingThreadLocal<>() {
@Override
protected BufferCache initialValue() {
return new BufferCache();
}
+ @Override
+ protected void threadTerminated(BufferCache cache) { // will never be null
+ while (!cache.isEmpty()) {
+ ByteBuffer bb = cache.removeFirst();
+ free(bb);
+ }
+ }
};
/**
--- a/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,7 @@
package sun.nio.fs;
+import jdk.internal.misc.TerminatingThreadLocal;
import jdk.internal.misc.Unsafe;
/**
@@ -37,8 +38,21 @@
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int TEMP_BUF_POOL_SIZE = 3;
- private static ThreadLocal<NativeBuffer[]> threadLocal =
- new ThreadLocal<NativeBuffer[]>();
+ private static ThreadLocal<NativeBuffer[]> threadLocal = new TerminatingThreadLocal<>() {
+ @Override
+ protected void threadTerminated(NativeBuffer[] buffers) {
+ // threadLocal may be initialized but with initialValue of null
+ if (buffers != null) {
+ for (int i = 0; i < TEMP_BUF_POOL_SIZE; i++) {
+ NativeBuffer buffer = buffers[i];
+ if (buffer != null) {
+ buffer.free();
+ buffers[i] = null;
+ }
+ }
+ }
+ }
+ };
/**
* Allocates a native buffer, of at least the given size, from the heap.
--- a/src/java.base/share/conf/security/java.security Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/conf/security/java.security Mon Jun 25 09:48:06 2018 -0700
@@ -1027,10 +1027,10 @@
#
# An IOR type check filter, if configured, is used by an ORB during
# an ORB::string_to_object invocation to check the veracity of the type encoded
-# in the ior string.
+# in the ior string.
#
# The filter pattern consists of a semi-colon separated list of class names.
-# The configured list contains the binary class names of the IDL interface types
+# The configured list contains the binary class names of the IDL interface types
# corresponding to the IDL stub class to be instantiated.
# As such, a filter specifies a list of IDL stub classes that will be
# allowed by an ORB when an ORB::string_to_object is invoked.
@@ -1059,3 +1059,16 @@
# and javax.crypto.spec.SecretKeySpec and rejects all the others.
jceks.key.serialFilter = java.base/java.lang.Enum;java.base/java.security.KeyRep;\
java.base/java.security.KeyRep$Type;java.base/javax.crypto.spec.SecretKeySpec;!*
+
+#
+# Enhanced exception message text
+#
+# By default, socket exception messages do not include potentially sensitive
+# information such as hostnames or port numbers. This property may be set to one
+# or more values, separated by commas, and with no white-space. Each value
+# represents a category of enhanced information. Currently, the only category defined
+# is "hostInfo" which enables more detailed information in the IOExceptions
+# thrown by java.net.Socket and also the socket types in the java.nio.channels package.
+# The setting in this file can be overridden by a system property of the same name
+# and with the same syntax and possible values.
+#jdk.net.includeInExceptions=hostInfo
--- a/src/java.base/share/legal/cldr.md Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/legal/cldr.md Mon Jun 25 09:48:06 2018 -0700
@@ -1,12 +1,38 @@
-## Unicode Common Local Data Repository (CLDR) v29
+## Unicode Common Local Data Repository (CLDR) v33
### CLDR License
-<pre>
+
+```
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
+
+Unicode Data Files do not include PDF online code charts under the
+directory http://www.unicode.org/Public/.
-Copyright © 1991-2016 Unicode, Inc. All rights reserved.
+Software includes any source code published in the Unicode Standard
+or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
-Distributed under the Terms of Use in
-http://www.unicode.org/copyright.html.
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2018 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
@@ -15,28 +41,26 @@
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
-or Software are furnished to do so, provided that
+or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
-of the Data Files or Software,
+of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
-documentation, and
-(c) there is clear notice in each modified Data File or in the Software
-as well as in the documentation associated with the Data File(s) or
-Software that the data or software has been modified.
+Documentation.
-THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
-NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
-OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
-Except as contained in this notice, the name of a copyright holder shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in these Data Files or Software without prior written authorization of
-the copyright holder.
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
-</pre>
+```
--- a/src/java.base/share/legal/icu.md Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/legal/icu.md Mon Jun 25 09:48:06 2018 -0700
@@ -1,12 +1,14 @@
-## International Components for Unicode (ICU4J) v56.1
+## International Components for Unicode (ICU4J) v60.2
### ICU4J License
-<pre>
+
+```
UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
Unicode Data Files include all data files under the directories
http://www.unicode.org/Public/, http://www.unicode.org/reports/,
-http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
http://www.unicode.org/utility/trac/browser/.
Unicode Data Files do not include PDF online code charts under the
@@ -15,7 +17,8 @@
Software includes any source code published in the Unicode Standard
or under the directories
http://www.unicode.org/Public/, http://www.unicode.org/reports/,
-http://www.unicode.org/cldr/data/, http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
http://www.unicode.org/utility/trac/browser/.
NOTICE TO USER: Carefully read the following legal agreement.
@@ -28,7 +31,7 @@
COPYRIGHT AND PERMISSION NOTICE
-Copyright © 1991-2016 Unicode, Inc. All rights reserved.
+Copyright © 1991-2018 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
@@ -60,4 +63,4 @@
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
-</pre>
+```
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/legal/unicode.md Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,66 @@
+## The Unicode Standard, Unicode Character Database, Version 10.0.0
+
+### Unicode Character Database
+
+```
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
+
+Unicode Data Files do not include PDF online code charts under the
+directory http://www.unicode.org/Public/.
+
+Software includes any source code published in the Unicode Standard
+or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2018 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+```
--- a/src/java.base/share/native/libjava/Class.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/native/libjava/Class.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2018, 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
@@ -65,15 +65,17 @@
{"getDeclaredMethods0","(Z)[" MHD, (void *)&JVM_GetClassDeclaredMethods},
{"getDeclaredConstructors0","(Z)[" CTR, (void *)&JVM_GetClassDeclaredConstructors},
{"getProtectionDomain0", "()" PD, (void *)&JVM_GetProtectionDomain},
- {"getDeclaredClasses0", "()[" CLS, (void *)&JVM_GetDeclaredClasses},
+ {"getDeclaredClasses0", "()[" CLS, (void *)&JVM_GetDeclaredClasses},
{"getDeclaringClass0", "()" CLS, (void *)&JVM_GetDeclaringClass},
{"getSimpleBinaryName0", "()" STR, (void *)&JVM_GetSimpleBinaryName},
{"getGenericSignature0", "()" STR, (void *)&JVM_GetClassSignature},
- {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
+ {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
- {"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
+ {"desiredAssertionStatus0","("CLS")Z", (void *)&JVM_DesiredAssertionStatus},
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
{"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
+ {"getNestHost0", "()" CLS, (void *)&JVM_GetNestHost},
+ {"getNestMembers0", "()[" CLS, (void *)&JVM_GetNestMembers},
};
#undef OBJ
--- a/src/java.base/share/native/libjava/Reflection.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/share/native/libjava/Reflection.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -38,3 +38,9 @@
{
return JVM_GetClassAccessFlags(env, cls);
}
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_internal_reflect_Reflection_areNestMates(JNIEnv *env, jclass unused, jclass current, jclass member)
+{
+ return JVM_AreNestMates(env, current, member);
+}
--- a/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/unix/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.io.FileDescriptor;
import sun.net.NetHooks;
+import sun.net.util.SocketExceptions;
import sun.security.action.GetPropertyAction;
/**
@@ -258,6 +259,10 @@
end();
}
if (e != null) {
+ if (e instanceof IOException) {
+ var isa = (InetSocketAddress)pendingRemote;
+ e = SocketExceptions.of((IOException)e, isa);
+ }
// close channel if connection cannot be established
try {
close();
@@ -350,6 +355,9 @@
// close channel if connect fails
if (e != null) {
+ if (e instanceof IOException) {
+ e = SocketExceptions.of((IOException)e, isa);
+ }
try {
close();
} catch (Throwable suppressed) {
--- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -35,6 +35,7 @@
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import jdk.internal.misc.Unsafe;
+import sun.net.util.SocketExceptions;
/**
* Windows implementation of AsynchronousSocketChannel using overlapped I/O.
@@ -253,7 +254,8 @@
if (exc != null) {
closeChannel();
- result.setFailure(toIOException(exc));
+ exc = SocketExceptions.of(toIOException(exc), remote);
+ result.setFailure(exc);
}
Invoker.invoke(result);
}
@@ -278,7 +280,9 @@
// can't close channel while in begin/end block
if (exc != null) {
closeChannel();
- result.setFailure(toIOException(exc));
+ IOException ee = toIOException(exc);
+ ee = SocketExceptions.of(ee, remote);
+ result.setFailure(ee);
}
if (canInvokeDirect) {
@@ -293,11 +297,13 @@
*/
@Override
public void failed(int error, IOException x) {
+ x = SocketExceptions.of(x, remote);
if (isOpen()) {
closeChannel();
result.setFailure(x);
} else {
- result.setFailure(new AsynchronousCloseException());
+ x = SocketExceptions.of(new AsynchronousCloseException(), remote);
+ result.setFailure(x);
}
Invoker.invoke(result);
}
--- a/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.instrument/share/classes/java/lang/instrument/Instrumentation.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -219,10 +219,14 @@
* Instances of the retransformed class are not affected.
*
* <P>
- * The retransformation may change method bodies, the constant pool and attributes.
+ * The retransformation may change method bodies, the constant pool and
+ * attributes (unless explicitly prohibited).
* The retransformation must not add, remove or rename fields or methods, change the
- * signatures of methods, or change inheritance. These restrictions maybe be
- * lifted in future versions. The class file bytes are not checked, verified and installed
+ * signatures of methods, or change inheritance.
+ * The retransformation must not change the <code>NestHost</code> or
+ * <code>NestMembers</code> attributes.
+ * These restrictions may be lifted in future versions.
+ * The class file bytes are not checked, verified and installed
* until after the transformations have been applied, if the resultant bytes are in
* error this method will throw an exception.
*
@@ -306,10 +310,14 @@
* Instances of the redefined class are not affected.
*
* <P>
- * The redefinition may change method bodies, the constant pool and attributes.
+ * The redefinition may change method bodies, the constant pool and attributes
+ * (unless explicitly prohibited).
* The redefinition must not add, remove or rename fields or methods, change the
- * signatures of methods, or change inheritance. These restrictions maybe be
- * lifted in future versions. The class file bytes are not checked, verified and installed
+ * signatures of methods, or change inheritance.
+ * The redefinition must not change the <code>NestHost</code> or
+ * <code>NestMembers</code> attributes.
+ * These restrictions may be lifted in future versions.
+ * The class file bytes are not checked, verified and installed
* until after the transformations have been applied, if the resultant bytes are in
* error this method will throw an exception.
*
--- a/src/java.instrument/share/native/libinstrument/JavaExceptions.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.instrument/share/native/libinstrument/JavaExceptions.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -214,6 +214,11 @@
message = "class redefinition failed: attempted to change the class modifiers";
break;
+ case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED:
+ throwableClassName = "java/lang/UnsupportedOperationException";
+ message = "class redefinition failed: attempted to change the class NestHost or NestMembers attribute";
+ break;
+
case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
throwableClassName = "java/lang/UnsupportedOperationException";
message = "class redefinition failed: attempted to change method modifiers";
--- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -234,14 +234,12 @@
* @exception GSSException may be thrown
*/
public int getInitLifetime() throws GSSException {
- int retVal = 0;
Date d = getEndTime();
if (d == null) {
return 0;
}
- retVal = (int)(d.getTime() - (new Date().getTime()));
-
- return retVal/1000;
+ long retVal = d.getTime() - System.currentTimeMillis();
+ return (int)(retVal/1000);
}
/**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Mon Jun 25 09:48:06 2018 -0700
@@ -94,6 +94,7 @@
private final Name dollarCloseResource;
private final Types types;
private final boolean debugLower;
+ private final boolean disableProtectedAccessors; // experimental
private final PkgInfo pkginfoOpt;
protected Lower(Context context) {
@@ -122,6 +123,7 @@
Options options = Options.instance(context);
debugLower = options.isSet("debuglower");
pkginfoOpt = PkgInfo.get(options);
+ disableProtectedAccessors = options.isSet("disableProtectedAccessors");
}
/** The currently enclosing class.
@@ -1031,6 +1033,9 @@
/** Do we need an access method to reference private symbol?
*/
boolean needsPrivateAccess(Symbol sym) {
+ if (target.hasNestmateAccess()) {
+ return false;
+ }
if ((sym.flags() & PRIVATE) == 0 || sym.owner == currentClass) {
return false;
} else if (sym.name == names.init && sym.owner.isLocal()) {
@@ -1045,6 +1050,7 @@
/** Do we need an access method to reference symbol in other package?
*/
boolean needsProtectedAccess(Symbol sym, JCTree tree) {
+ if (disableProtectedAccessors) return false;
if ((sym.flags() & PROTECTED) == 0 ||
sym.owner.owner == currentClass.owner || // fast special case
sym.packge() == currentClass.packge())
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Mon Jun 25 09:48:06 2018 -0700
@@ -81,6 +81,7 @@
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.jvm.ClassWriter;
import com.sun.tools.javac.jvm.JNIWriter;
+import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
@@ -144,6 +145,7 @@
private final JavaFileManager fileManager;
private final ModuleFinder moduleFinder;
private final Source source;
+ private final Target target;
private final boolean allowModules;
private final boolean allowAccessIntoSystem;
@@ -191,6 +193,7 @@
types = Types.instance(context);
fileManager = context.get(JavaFileManager.class);
source = Source.instance(context);
+ target = Target.instance(context);
allowModules = Feature.MODULES.allowedInSource(source);
Options options = Options.instance(context);
@@ -1234,18 +1237,24 @@
Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>();
if (rootModules.contains(syms.unnamedModule)) {
- ModuleSymbol javaSE = syms.getModule(java_se);
Predicate<ModuleSymbol> jdkModulePred;
-
- if (javaSE != null && (observable == null || observable.contains(javaSE))) {
+ if (target.allApiModulesAreRoots()) {
jdkModulePred = sym -> {
sym.complete();
- return !sym.name.startsWith(java_)
- && sym.exports.stream().anyMatch(e -> e.modules == null);
+ return sym.exports.stream().anyMatch(e -> e.modules == null);
};
- enabledRoot.add(javaSE);
} else {
- jdkModulePred = sym -> true;
+ ModuleSymbol javaSE = syms.getModule(java_se);
+ if (javaSE != null && (observable == null || observable.contains(javaSE))) {
+ jdkModulePred = sym -> {
+ sym.complete();
+ return !sym.name.startsWith(java_)
+ && sym.exports.stream().anyMatch(e -> e.modules == null);
+ };
+ enabledRoot.add(javaSE);
+ } else {
+ jdkModulePred = sym -> true;
+ }
}
Predicate<ModuleSymbol> noIncubatorPred = sym -> {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
import java.util.Set;
import java.util.HashSet;
import java.util.LinkedHashSet;
+import java.util.stream.Collectors;
import javax.tools.JavaFileManager;
import javax.tools.FileObject;
@@ -1106,6 +1107,56 @@
endAttr(alenIdx);
}
+ /**
+ * Write NestMembers attribute (if needed)
+ */
+ int writeNestMembersIfNeeded(ClassSymbol csym) {
+ ListBuffer<Symbol> nested = new ListBuffer<>();
+ listNested(csym, nested);
+ Set<Symbol> nestedUnique = new LinkedHashSet<>(nested);
+ if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
+ int alenIdx = writeAttr(names.NestMembers);
+ databuf.appendChar(nestedUnique.size());
+ for (Symbol s : nestedUnique) {
+ databuf.appendChar(pool.put(s));
+ }
+ endAttr(alenIdx);
+ return 1;
+ }
+ return 0;
+ }
+
+ /**
+ * Write NestHost attribute (if needed)
+ */
+ int writeNestHostIfNeeded(ClassSymbol csym) {
+ if (csym.owner.kind != PCK) {
+ int alenIdx = writeAttr(names.NestHost);
+ databuf.appendChar(pool.put(csym.outermostClass()));
+ endAttr(alenIdx);
+ return 1;
+ }
+ return 0;
+ }
+
+ private void listNested(Symbol sym, ListBuffer<Symbol> seen) {
+ if (sym.kind != TYP) return;
+ ClassSymbol csym = (ClassSymbol)sym;
+ if (csym.owner.kind != PCK) {
+ seen.add(csym);
+ }
+ if (csym.members() != null) {
+ for (Symbol s : sym.members().getSymbols()) {
+ listNested(s, seen);
+ }
+ }
+ if (csym.trans_local != null) {
+ for (Symbol s : csym.trans_local) {
+ listNested(s, seen);
+ }
+ }
+ }
+
/** Write "bootstrapMethods" attribute.
*/
void writeBootstrapMethods() {
@@ -1835,6 +1886,13 @@
}
poolbuf.appendChar(target.majorVersion);
+ if (c.owner.kind != MDL) {
+ if (target.hasNestmateAccess()) {
+ acount += writeNestMembersIfNeeded(c);
+ acount += writeNestHostIfNeeded(c);
+ }
+ }
+
writePool(c.pool);
if (innerClasses != null) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -126,6 +126,7 @@
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debug.code");
allowBetterNullChecks = target.hasObjects();
+ disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
pool = new Pool(types);
// ignore cldc because we cannot have both stackmap formats
@@ -140,6 +141,7 @@
private final boolean genCrt;
private final boolean debugCode;
private final boolean allowBetterNullChecks;
+ private boolean disableVirtualizedPrivateInvoke;
/** Code buffer, set by genMethod.
*/
@@ -2064,10 +2066,17 @@
} else {
items.makeThisItem().load();
sym = binaryQualifier(sym, env.enclClass.type);
- result = items.makeMemberItem(sym, (sym.flags() & PRIVATE) != 0);
+ result = items.makeMemberItem(sym, nonVirtualForPrivateAccess(sym));
}
}
+ //where
+ private boolean nonVirtualForPrivateAccess(Symbol sym) {
+ boolean useVirtual = target.hasVirtualPrivateInvoke() &&
+ !disableVirtualizedPrivateInvoke;
+ return !useVirtual && ((sym.flags() & PRIVATE) != 0);
+ }
+
public void visitSelect(JCFieldAccess tree) {
Symbol sym = tree.sym;
@@ -2124,7 +2133,7 @@
} else {
result = items.
makeMemberItem(sym,
- (sym.flags() & PRIVATE) != 0 ||
+ nonVirtualForPrivateAccess(sym) ||
selectSuper || accessSuper);
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java Mon Jun 25 09:48:06 2018 -0700
@@ -160,4 +160,24 @@
public String multiReleaseValue() {
return Integer.toString(this.ordinal() - Target.JDK1_1.ordinal() + 1);
}
+
+ /** All modules that export an API are roots when compiling code in the unnamed
+ * module and targeting 11 or newer.
+ */
+ public boolean allApiModulesAreRoots() {
+ return compareTo(JDK1_11) >= 0;
+ }
+
+ /** Does the target VM support nestmate access?
+ */
+ public boolean hasNestmateAccess() {
+ return compareTo(JDK1_11) >= 0;
+ }
+
+ /** Does the target VM support virtual private invocations?
+ */
+ public boolean hasVirtualPrivateInvoke() {
+ return compareTo(JDK1_11) >= 0;
+ }
+
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -152,6 +152,8 @@
public final Name MethodParameters;
public final Name Module;
public final Name ModuleResolution;
+ public final Name NestHost;
+ public final Name NestMembers;
public final Name RuntimeInvisibleAnnotations;
public final Name RuntimeInvisibleParameterAnnotations;
public final Name RuntimeInvisibleTypeAnnotations;
@@ -315,6 +317,8 @@
MethodParameters = fromString("MethodParameters");
Module = fromString("Module");
ModuleResolution = fromString("ModuleResolution");
+ NestHost = fromString("NestHost");
+ NestMembers = fromString("NestMembers");
RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.h Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.h Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -47,5 +47,6 @@
#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
#define SECG_CURVE_OID_TOTAL_LEN 7
+#define BRAINPOOL_CURVE_OID_TOTAL_LEN 11
#endif /* __ec_h_ */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecdecode.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -172,7 +172,8 @@
#endif
if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
- (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
+ (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN) &&
+ (encodedParams->len != BRAINPOOL_CURVE_OID_TOTAL_LEN)) {
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
};
@@ -565,6 +566,30 @@
params, kmflag) );
break;
+ case ECCurve_BrainpoolP256r1:
+ /* Populate params for brainpoolP256r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP256r1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_BrainpoolP320r1:
+ /* Populate params for brainpoolP320r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP320r1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_BrainpoolP384r1:
+ /* Populate params for brainpoolP384r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP384r1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_BrainpoolP512r1:
+ /* Populate params for brainpoolP512r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_BrainpoolP512r1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
default:
break;
};
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-curve.h Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -623,6 +623,46 @@
"0100000000000000000001CDC98AE0E2DE574ABF33", 1
};
+static const ECCurveParams ecCurve_BrainpoolP256r1 = {
+ "brainpoolP256r1", ECField_GFp, 256,
+ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
+ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
+ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
+ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
+ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
+ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP320r1 = {
+ "brainpoolP320r1", ECField_GFp, 320,
+ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
+ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
+ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
+ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
+ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
+ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP384r1 = {
+ "brainpoolP384r1", ECField_GFp, 384,
+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
+ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
+ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
+ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
+ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
+ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 1
+};
+
+static const ECCurveParams ecCurve_BrainpoolP512r1 = {
+ "brainpoolP512r1", ECField_GFp, 512,
+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
+ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
+ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
+ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
+ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
+ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 1
+};
+
/* mapping between ECCurveName enum and pointers to ECCurveParams */
static const ECCurveParams *ecCurve_map[] = {
NULL, /* ECCurve_noName */
@@ -683,6 +723,10 @@
&ecCurve_WTLS_1, /* ECCurve_WTLS_1 */
&ecCurve_WTLS_8, /* ECCurve_WTLS_8 */
&ecCurve_WTLS_9, /* ECCurve_WTLS_9 */
+ &ecCurve_BrainpoolP256r1, /* ECCurve_BrainpoolP256r1 */
+ &ecCurve_BrainpoolP320r1, /* ECCurve_BrainpoolP320r1 */
+ &ecCurve_BrainpoolP384r1, /* ECCurve_brainpoolP384r1 */
+ &ecCurve_BrainpoolP512r1, /* ECCurve_brainpoolP512r1 */
NULL /* ECCurve_pastLastCurve */
};
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-exp.h Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-exp.h Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -161,6 +161,12 @@
/* ECCurve_WTLS_11 == ECCurve_NIST_B233 */
/* ECCurve_WTLS_12 == ECCurve_NIST_P224 */
+ /* ECC Brainpool prime curves in RFC 5639*/
+ ECCurve_BrainpoolP256r1,
+ ECCurve_BrainpoolP320r1,
+ ECCurve_BrainpoolP384r1,
+ ECCurve_BrainpoolP512r1,
+
ECCurve_pastLastCurve
} ECCurveName;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_gf.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_gf.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -833,6 +833,7 @@
MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
+ MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
}
MP_CHECKOK(s_mp_pad(r, 5));
MP_DIGIT(r, 4) = r4;
@@ -908,6 +909,7 @@
MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
+ MP_ADD_CARRY(b5, r5, r5, borrow, borrow);
}
MP_CHECKOK(s_mp_pad(r, 6));
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/oid.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -63,6 +63,10 @@
#define ANSI_X962_GF2m_OID ANSI_X962_CURVE_OID, 0x00
#define ANSI_X962_GFp_OID ANSI_X962_CURVE_OID, 0x01
+#define TELETRUST_ALGO_OID 0x2b, 0x24, 0x03
+#define ECC_BRAINPOOL TELETRUST_ALGO_OID, 0x03, 0x02, 0x08
+#define ECC_BRAINPOOL_EC_V1 ECC_BRAINPOOL, 0x01, 0x01
+
#define CONST_OID static const unsigned char
/* ANSI X9.62 prime curve OIDs */
@@ -134,6 +138,22 @@
CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 };
CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 };
+/* TeleTrusT ECC Brainpool prime curve OIDs */
+CONST_OID brainpoolP160r1[] = { ECC_BRAINPOOL_EC_V1, 0x01 };
+CONST_OID brainpoolP160t1[] = { ECC_BRAINPOOL_EC_V1, 0x02 };
+CONST_OID brainpoolP192r1[] = { ECC_BRAINPOOL_EC_V1, 0x03 };
+CONST_OID brainpoolP192t1[] = { ECC_BRAINPOOL_EC_V1, 0x04 };
+CONST_OID brainpoolP224r1[] = { ECC_BRAINPOOL_EC_V1, 0x05 };
+CONST_OID brainpoolP224t1[] = { ECC_BRAINPOOL_EC_V1, 0x06 };
+CONST_OID brainpoolP256r1[] = { ECC_BRAINPOOL_EC_V1, 0x07 };
+CONST_OID brainpoolP256t1[] = { ECC_BRAINPOOL_EC_V1, 0x08 };
+CONST_OID brainpoolP320r1[] = { ECC_BRAINPOOL_EC_V1, 0x09 };
+CONST_OID brainpoolP320t1[] = { ECC_BRAINPOOL_EC_V1, 0x0a };
+CONST_OID brainpoolP384r1[] = { ECC_BRAINPOOL_EC_V1, 0x0b };
+CONST_OID brainpoolP384t1[] = { ECC_BRAINPOOL_EC_V1, 0x0c };
+CONST_OID brainpoolP512r1[] = { ECC_BRAINPOOL_EC_V1, 0x0d };
+CONST_OID brainpoolP512t1[] = { ECC_BRAINPOOL_EC_V1, 0x0e };
+
#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
#ifndef SECOID_NO_STRINGS
#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
@@ -409,30 +429,98 @@
INVALID_CERT_EXTENSION )
};
+static SECOidData BRAINPOOL_oids[] = {
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+
+ /* RFC 5639 Brainpool named elliptic curves */
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ OD( brainpoolP256r1, ECCurve_BrainpoolP256r1,
+ "brainpoolP256r1 domain parameter set",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION ),
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ OD( brainpoolP320r1, ECCurve_BrainpoolP320r1,
+ "brainpoolP320r1 domain parameter set",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION ),
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ OD( brainpoolP384r1, ECCurve_BrainpoolP384r1,
+ "brainpoolP384r1 domain parameter set",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION ),
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+ OD( brainpoolP512r1, ECCurve_BrainpoolP512r1,
+ "brainpoolP512r1 domain parameter set",
+ CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION ),
+ { { siDEROID, NULL, 0 }, ECCurve_noName,
+ "Unknown OID", CKM_INVALID_MECHANISM,
+ INVALID_CERT_EXTENSION }
+};
+
+int
+oideql(unsigned char *reqoid, unsigned char *foundoid, size_t reqlen, size_t foundlen)
+{
+ if (!reqoid || !foundoid) {
+ return 0;
+ }
+
+ if (reqlen != foundlen) {
+ return 0;
+ }
+
+ return memcmp(reqoid, foundoid, reqlen) == 0;
+}
+
SECOidData *
SECOID_FindOID(const SECItem *oid)
{
SECOidData *po;
SECOidData *ret = NULL;
+ int reqlen = oid->len;
- if (oid->len == 8) {
+ if (reqlen == 8) {
if (oid->data[6] == 0x00) {
- /* XXX bounds check */
- po = &ANSI_oids[oid->data[7]];
- if (memcmp(oid->data, po->oid.data, 8) == 0)
- ret = po;
+ /* XXX bounds check */
+ po = &ANSI_oids[oid->data[7]];
+ if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+ ret = po;
+ }
}
if (oid->data[6] == 0x01) {
- /* XXX bounds check */
- po = &ANSI_prime_oids[oid->data[7]];
- if (memcmp(oid->data, po->oid.data, 8) == 0)
- ret = po;
+ /* XXX bounds check */
+ po = &ANSI_prime_oids[oid->data[7]];
+ if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+ ret = po;
+ }
}
- } else if (oid->len == 5) {
+ } else if (reqlen == 5) {
/* XXX bounds check */
po = &SECG_oids[oid->data[4]];
- if (memcmp(oid->data, po->oid.data, 5) == 0)
- ret = po;
+ if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+ ret = po;
+ }
+ } else if (reqlen == 9) {
+ /* XXX bounds check */
+ po = &BRAINPOOL_oids[oid->data[8]];
+ if (oideql(oid->data, po->oid.data, reqlen, po->oid.len)) {
+ ret = po;
+ }
}
return(ret);
}
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Attribute.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -58,6 +58,8 @@
public static final String ModulePackages = "ModulePackages";
public static final String ModuleResolution = "ModuleResolution";
public static final String ModuleTarget = "ModuleTarget";
+ public static final String NestHost = "NestHost";
+ public static final String NestMembers = "NestMembers";
public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@@ -130,6 +132,8 @@
standardAttributes.put(ModulePackages, ModulePackages_attribute.class);
standardAttributes.put(ModuleResolution, ModuleResolution_attribute.class);
standardAttributes.put(ModuleTarget, ModuleTarget_attribute.class);
+ standardAttributes.put(NestHost, NestHost_attribute.class);
+ standardAttributes.put(NestMembers, NestMembers_attribute.class);
standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
@@ -193,6 +197,8 @@
R visitModulePackages(ModulePackages_attribute attr, P p);
R visitModuleResolution(ModuleResolution_attribute attr, P p);
R visitModuleTarget(ModuleTarget_attribute attr, P p);
+ R visitNestHost(NestHost_attribute attr, P p);
+ R visitNestMembers(NestMembers_attribute attr, P p);
R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -529,6 +529,12 @@
}
@Override
+ public Void visitNestHost(NestHost_attribute attr, ClassOutputStream out) {
+ out.writeShort(attr.top_index);
+ return null;
+ }
+
+ @Override
public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
out.writeByte(attr.method_parameter_table.length);
for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
@@ -627,6 +633,15 @@
}
@Override
+ public Void visitNestMembers(NestMembers_attribute attr, ClassOutputStream out) {
+ out.writeShort(attr.members_indexes.length);
+ for (int i : attr.members_indexes) {
+ out.writeShort(i);
+ }
+ return null;
+ }
+
+ @Override
public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, ClassOutputStream out) {
annotationWriter.write(attr.annotations, out);
return null;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestHost_attribute.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, 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 com.sun.tools.classfile;
+
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+
+import java.io.IOException;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class NestHost_attribute extends Attribute {
+ NestHost_attribute(ClassReader cr, int name_index, int length) throws IOException {
+ super(name_index, length);
+ top_index = cr.readUnsignedShort();
+ }
+
+ public NestHost_attribute(ConstantPool constant_pool, int signature_index)
+ throws ConstantPoolException {
+ this(constant_pool.getUTF8Index(Attribute.Signature), signature_index);
+ }
+
+ public NestHost_attribute(int name_index, int top_index) {
+ super(name_index, 2);
+ this.top_index = top_index;
+ }
+
+ public CONSTANT_Class_info getNestTop(ConstantPool constant_pool) throws ConstantPoolException {
+ return constant_pool.getClassInfo(top_index);
+ }
+
+ public <R, D> R accept(Visitor<R, D> visitor, D data) {
+ return visitor.visitNestHost(this, data);
+ }
+
+ public final int top_index;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/NestMembers_attribute.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, 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 com.sun.tools.classfile;
+
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+
+import java.io.IOException;
+import java.util.stream.IntStream;
+
+/**
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class NestMembers_attribute extends Attribute {
+ NestMembers_attribute(ClassReader cr, int name_index, int length) throws IOException {
+ super(name_index, length);
+ int len = cr.readUnsignedShort();
+ members_indexes = new int[len];
+ for (int i = 0 ; i < len ; i++) {
+ members_indexes[i] = cr.readUnsignedShort();
+ }
+ }
+
+ public NestMembers_attribute(int name_index, int[] members_indexes) {
+ super(name_index, 2);
+ this.members_indexes = members_indexes;
+ }
+
+ public CONSTANT_Class_info[] getChildren(ConstantPool constant_pool) throws ConstantPoolException {
+ return IntStream.of(members_indexes)
+ .mapToObj(i -> {
+ try {
+ return constant_pool.getClassInfo(i);
+ } catch (ConstantPoolException ex) {
+ throw new AssertionError(ex);
+ }
+ }).toArray(CONSTANT_Class_info[]::new);
+ }
+
+ public <R, D> R accept(Visitor<R, D> visitor, D data) {
+ return visitor.visitNestMembers(this, data);
+ }
+
+ public final int[] members_indexes;
+}
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -35,6 +35,7 @@
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.CompilationID_attribute;
import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.ConstantValue_attribute;
import com.sun.tools.classfile.DefaultAttribute;
@@ -53,6 +54,8 @@
import com.sun.tools.classfile.ModulePackages_attribute;
import com.sun.tools.classfile.ModuleResolution_attribute;
import com.sun.tools.classfile.ModuleTarget_attribute;
+import com.sun.tools.classfile.NestHost_attribute;
+import com.sun.tools.classfile.NestMembers_attribute;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
@@ -397,6 +400,14 @@
return null;
}
+ @Override
+ public Void visitNestHost(NestHost_attribute attr, Void aVoid) {
+ print("NestHost: ");
+ constantWriter.write(attr.top_index);
+ println();
+ return null;
+ }
+
private String getJavaClassName(ModuleMainClass_attribute a) {
try {
return getJavaName(a.getMainClassName(constant_pool));
@@ -687,6 +698,22 @@
}
@Override
+ public Void visitNestMembers(NestMembers_attribute attr, Void aVoid) {
+ println("NestMembers:");
+ indent(+1);
+ try {
+ CONSTANT_Class_info[] children = attr.getChildren(constant_pool);
+ for (int i = 0; i < attr.members_indexes.length; i++) {
+ println(constantWriter.stringValue(children[i]));
+ }
+ indent(-1);
+ } catch (ConstantPoolException ex) {
+ throw new AssertionError(ex);
+ }
+ return null;
+ }
+
+ @Override
public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
println("RuntimeVisibleAnnotations:");
indent(+1);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -62,6 +62,7 @@
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public class JdepsConfiguration implements AutoCloseable {
@@ -319,7 +320,6 @@
static class SystemModuleFinder implements ModuleFinder {
private static final String JAVA_HOME = System.getProperty("java.home");
- private static final String JAVA_SE = "java.se";
private final FileSystem fileSystem;
private final Path root;
@@ -444,29 +444,15 @@
}
public Set<String> defaultSystemRoots() {
- Set<String> roots = new HashSet<>();
- boolean hasJava = false;
- if (systemModules.containsKey(JAVA_SE)) {
- // java.se is a system module
- hasJava = true;
- roots.add(JAVA_SE);
- }
-
- for (ModuleReference mref : systemModules.values()) {
- String mn = mref.descriptor().name();
- if (hasJava && mn.startsWith("java."))
- continue;
-
- // add as root if observable and exports at least one package
- ModuleDescriptor descriptor = mref.descriptor();
- for (ModuleDescriptor.Exports e : descriptor.exports()) {
- if (!e.isQualified()) {
- roots.add(mn);
- break;
- }
- }
- }
- return roots;
+ return systemModules.values().stream()
+ .map(ModuleReference::descriptor)
+ .filter(descriptor -> descriptor.exports()
+ .stream()
+ .filter(e -> !e.isQualified())
+ .findAny()
+ .isPresent())
+ .map(ModuleDescriptor::name)
+ .collect(Collectors.toSet());
}
}
--- a/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdi/share/classes/com/sun/jdi/VirtualMachine.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -219,10 +219,11 @@
* this exception
* <UL>
* <LI>changing the schema (the fields)
- * <LI>changing the hierarchy (subclasses, interfaces)
+ * <LI>changing the hierarchy (superclasses, interfaces)
* <LI>deleting a method
* <LI>changing class modifiers
* <LI>changing method modifiers
+ * <LI>changing the {@code NestHost} or {@code NestMembers} class attributes
* </UL>
* </UL>
*
@@ -595,8 +596,9 @@
boolean canAddMethod();
/**
- * Determines if the target VM supports unrestricted
- * changes when performing class redefinition.
+ * Determines if the target VM supports
+ * changes when performing class redefinition that are
+ * otherwise restricted by {@link #redefineClasses}.
* @see #redefineClasses
*
* @return <code>true</code> if the feature is supported,
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -395,6 +395,9 @@
case JDWP.Error.METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED :
throw new UnsupportedOperationException(
"changes to method modifiers not implemented");
+ case JDWP.Error.CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED :
+ throw new UnsupportedOperationException(
+ "changes to class attribute not implemented");
case JDWP.Error.NAMES_DONT_MATCH :
throw new NoClassDefFoundError(
"class names do not match");
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -52,7 +52,7 @@
private final ThreadGroup mainGroupForJDI;
private ResourceBundle messages = null;
private int vmSequenceNumber = 0;
- private static final int majorVersion = 9;
+ private static final int majorVersion = 11;
private static final int minorVersion = 0;
private static final Object lock = new Object();
--- a/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/VirtualMachineImpl.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -35,7 +35,7 @@
#include "FrameID.h"
static char *versionName = "Java Debug Wire Protocol (Reference Implementation)";
-static int majorVersion = 9; /* JDWP major version */
+static int majorVersion = 11; /* JDWP major version */
static int minorVersion = 0; /* JDWP minor version */
static jboolean
--- a/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/error_messages.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -285,6 +285,7 @@
CASE_RETURN_JDWP_ERROR_TEXT(NAMES_DONT_MATCH)
CASE_RETURN_JDWP_ERROR_TEXT(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
CASE_RETURN_JDWP_ERROR_TEXT(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED)
+ CASE_RETURN_JDWP_ERROR_TEXT(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED)
CASE_RETURN_JDWP_ERROR_TEXT(NOT_IMPLEMENTED)
CASE_RETURN_JDWP_ERROR_TEXT(NULL_POINTER)
CASE_RETURN_JDWP_ERROR_TEXT(ABSENT_INFORMATION)
--- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -1888,6 +1888,8 @@
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED;
case JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED):
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED;
+ case JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED):
+ return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED;
case JDWP_ERROR(NOT_IMPLEMENTED):
return JVMTI_ERROR_NOT_AVAILABLE;
case JDWP_ERROR(NULL_POINTER):
@@ -2220,6 +2222,8 @@
return JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED);
case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED:
return JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED);
+ case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED:
+ return JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED);
case AGENT_ERROR_NOT_CURRENT_FRAME:
return JDWP_ERROR(NOT_CURRENT_FRAME);
case AGENT_ERROR_INVALID_TAG:
--- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorder.java Mon Jun 25 09:48:06 2018 -0700
@@ -34,7 +34,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import jdk.jfr.internal.JVM;
@@ -77,8 +76,8 @@
*/
public List<Recording> getRecordings() {
List<Recording> recs = new ArrayList<>();
- for (PlatformRecording internal : internal.getRecordings()) {
- recs.add(internal.getRecording());
+ for (PlatformRecording r : internal.getRecordings()) {
+ recs.add(r.getRecording());
}
return Collections.unmodifiableList(recs);
}
@@ -112,7 +111,10 @@
* @return a snapshot of all available recording data, not {@code null}
*/
public Recording takeSnapshot() {
- return internal.newSnapshot();
+ Recording snapshot = new Recording();
+ snapshot.setName("Snapshot");
+ internal.fillWithRecordedData(snapshot.getInternal(), null);
+ return snapshot;
}
/**
@@ -345,9 +347,7 @@
return initialized;
}
- // package private
- PlatformRecording newInternalRecording(Map<String, String> settings) {
- return internal.newRecording(settings);
+ PlatformRecorder getInternal() {
+ return internal;
}
-
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/FlightRecorderPermission.java Mon Jun 25 09:48:06 2018 -0700
@@ -31,6 +31,7 @@
import java.util.Objects;
import jdk.jfr.internal.PlatformEventType;
+import jdk.jfr.internal.PlatformRecorder;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.Type;
@@ -185,6 +186,11 @@
public boolean isUnsigned(ValueDescriptor v) {
return v.isUnsigned();
}
+
+ @Override
+ public PlatformRecorder getPlatformRecorder() {
+ return FlightRecorder.getFlightRecorder().getInternal();
+ }
}
/**
--- a/src/jdk.jfr/share/classes/jdk/jfr/Recording.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/Recording.java Mon Jun 25 09:48:06 2018 -0700
@@ -31,11 +31,11 @@
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
+import jdk.jfr.internal.PlatformRecorder;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.Utils;
@@ -93,11 +93,14 @@
private final PlatformRecording internal;
- private Recording(PlatformRecording internal) {
- this.internal = internal;
- this.internal.setRecording(this);
- if (internal.getRecording() != this) {
- throw new InternalError("Internal recording not properly setup");
+ public Recording(Map<String, String> settings) {
+ PlatformRecorder r = FlightRecorder.getFlightRecorder().getInternal();
+ synchronized (r) {
+ this.internal = r.newRecording(settings);
+ this.internal.setRecording(this);
+ if (internal.getRecording() != this) {
+ throw new InternalError("Internal recording not properly setup");
+ }
}
}
@@ -115,8 +118,8 @@
* FlightRecorderPermission "accessFlightRecorder" is not set.
*/
public Recording() {
- this(FlightRecorder.getFlightRecorder().newInternalRecording(new HashMap<String, String>()));
- }
+ this(new HashMap<String, String>());
+ }
/**
* Creates a recording with settings from a configuration.
@@ -145,7 +148,7 @@
* @see Configuration
*/
public Recording(Configuration configuration) {
- this(FlightRecorder.getFlightRecorder().newInternalRecording(configuration.getSettings()));
+ this(configuration.getSettings());
}
/**
@@ -370,7 +373,8 @@
*/
public void dump(Path destination) throws IOException {
Objects.requireNonNull(destination);
- internal.copyTo(new WriteableUserPath(destination), "Dumped by user", Collections.emptyMap());
+ internal.dump(new WriteableUserPath(destination));
+
}
/**
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/LogTag.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/LogTag.java Mon Jun 25 09:48:06 2018 -0700
@@ -73,7 +73,12 @@
/**
* Covers setting (for users of the JDK)
*/
- JFR_SETTING(9);
+ JFR_SETTING(9),
+ /**
+ * Covers usage of jcmd with JFR
+ */
+ JFR_DCMD(10);
+
/* set from native side */
private volatile int tagSetLevel = 100; // prevent logging if JVM log system has not been initialized
@@ -86,4 +91,8 @@
public boolean shouldLog(int level) {
return level >= tagSetLevel;
}
+
+ public boolean shouldLog(LogLevel logLevel) {
+ return shouldLog(logLevel.level);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/OldObjectSample.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,73 @@
+package jdk.jfr.internal;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.jfr.Enabled;
+import jdk.jfr.RecordingState;
+import jdk.jfr.internal.settings.CutoffSetting;
+import jdk.jfr.internal.test.WhiteBox;
+
+// The Old Object event could have been implemented as a periodic event, but
+// due to chunk rotations and how settings are calculated when multiple recordings
+// are running at the same time, it would lead to unacceptable overhead.
+//
+// Instead, the event is only emitted before a recording stops and
+// if that recording has the event enabled.
+//
+// This requires special handling and the purpose of this class is to provide that
+//
+public final class OldObjectSample {
+
+ private static final String EVENT_NAME = Type.EVENT_NAME_PREFIX + "OldObjectSample";
+ private static final String OLD_OBJECT_CUTOFF = EVENT_NAME + "#" + Cutoff.NAME;
+ private static final String OLD_OBJECT_ENABLED = EVENT_NAME + "#" + Enabled.NAME;
+
+ // Emit if old object is enabled in recoding with cutoff for that recording
+ public static void emit(PlatformRecording recording) {
+ if (isEnabled(recording)) {
+ long nanos = CutoffSetting.parseValueSafe(recording.getSettings().get(OLD_OBJECT_CUTOFF));
+ long ticks = Utils.nanosToTicks(nanos);
+ JVM.getJVM().emitOldObjectSamples(ticks, WhiteBox.getWriteAllObjectSamples());
+ }
+ }
+
+ // Emit if old object is enabled for at least one recording, and use the largest
+ // cutoff for an enabled recoding
+ public static void emit(List<PlatformRecording> recordings, Boolean pathToGcRoots) {
+ boolean enabled = false;
+ long cutoffNanos = Boolean.TRUE.equals(pathToGcRoots) ? Long.MAX_VALUE : 0L;
+ for (PlatformRecording r : recordings) {
+ if (r.getState() == RecordingState.RUNNING) {
+ if (isEnabled(r)) {
+ enabled = true;
+ long c = CutoffSetting.parseValueSafe(r.getSettings().get(OLD_OBJECT_CUTOFF));
+ cutoffNanos = Math.max(c, cutoffNanos);
+ }
+ }
+ }
+ if (enabled) {
+ long ticks = Utils.nanosToTicks(cutoffNanos);
+ JVM.getJVM().emitOldObjectSamples(ticks, WhiteBox.getWriteAllObjectSamples());
+ }
+ }
+
+ public static void updateSettingPathToGcRoots(Map<String, String> s, Boolean pathToGcRoots) {
+ if (pathToGcRoots != null) {
+ s.put(OLD_OBJECT_CUTOFF, pathToGcRoots ? "infinity" : "0 ns");
+ }
+ }
+
+ public static Map<String, String> createSettingsForSnapshot(PlatformRecording recording, Boolean pathToGcRoots) {
+ Map<String, String> settings = new HashMap<>(recording.getSettings());
+ updateSettingPathToGcRoots(settings, pathToGcRoots);
+ return settings;
+ }
+
+ private static boolean isEnabled(PlatformRecording r) {
+ Map<String, String> settings = r.getSettings();
+ String s = settings.get(OLD_OBJECT_ENABLED);
+ return "true".equals(s);
+ }
+}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecorder.java Mon Jun 25 09:48:06 2018 -0700
@@ -38,6 +38,7 @@
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -46,7 +47,6 @@
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
-import jdk.jfr.Enabled;
import jdk.jfr.EventType;
import jdk.jfr.FlightRecorder;
import jdk.jfr.FlightRecorderListener;
@@ -56,8 +56,6 @@
import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.internal.SecuritySupport.SecureRecorderListener;
import jdk.jfr.internal.instrument.JDKEvents;
-import jdk.jfr.internal.settings.CutoffSetting;
-import jdk.jfr.internal.test.WhiteBox;
public final class PlatformRecorder {
@@ -111,7 +109,16 @@
return newRecording(settings, ++recordingCounter);
}
- public synchronized PlatformRecording newRecording(Map<String, String> settings, long id) {
+ // To be used internally when doing dumps.
+ // Caller must have recorder lock and close recording before releasing lock
+ public PlatformRecording newTemporaryRecording() {
+ if(!Thread.holdsLock(this)) {
+ throw new InternalError("Caller must have recorder lock");
+ }
+ return newRecording(new HashMap<>(), 0);
+ }
+
+ private synchronized PlatformRecording newRecording(Map<String, String> settings, long id) {
PlatformRecording recording = new PlatformRecording(this, id);
if (!settings.isEmpty()) {
recording.setSettings(settings);
@@ -249,7 +256,7 @@
RequestEngine.doChunkBegin();
}
- synchronized void stop(PlatformRecording recording, WriteableUserPath alternativePath) {
+ synchronized void stop(PlatformRecording recording) {
RecordingState state = recording.getState();
if (Utils.isAfter(state, RecordingState.RUNNING)) {
@@ -270,7 +277,7 @@
}
}
}
- emitOldObjectSamples(recording);
+ OldObjectSample.emit(recording);
if (endPhysical) {
RequestEngine.doChunkEnd();
@@ -282,7 +289,7 @@
}
} else {
// last memory
- dumpMemoryToDestination(recording, alternativePath);
+ dumpMemoryToDestination(recording);
}
jvm.endRecording_();
disableEvents();
@@ -306,26 +313,13 @@
recording.setState(RecordingState.STOPPED);
}
- // Only dump event if the recording that is being stopped
- // has OldObjectSample enabled + cutoff from recording, not global value
- private void emitOldObjectSamples(PlatformRecording recording) {
- Map<String, String> settings = recording.getSettings();
- String s = settings.get(Type.EVENT_NAME_PREFIX + "OldObjectSample#" + Enabled.NAME);
- if ("true".equals(s)) {
- long nanos = CutoffSetting.parseValueSafe(settings.get(Type.EVENT_NAME_PREFIX + "OldObjectSample#" + Cutoff.NAME));
- long ticks = Utils.nanosToTicks(nanos);
- JVM.getJVM().emitOldObjectSamples(ticks, WhiteBox.getWriteAllObjectSamples());
- }
- }
-
- private void dumpMemoryToDestination(PlatformRecording recording, WriteableUserPath alternativePath) {
- WriteableUserPath dest = alternativePath != null ? alternativePath : recording.getDestination();
+ private void dumpMemoryToDestination(PlatformRecording recording) {
+ WriteableUserPath dest = recording.getDestination();
if (dest != null) {
MetadataRepository.getInstance().setOutput(dest.getText());
recording.clearDestination();
}
}
-
private void disableEvents() {
MetadataRepository.getInstance().disableEvents();
}
@@ -504,47 +498,47 @@
return newRec;
}
- public synchronized Recording newSnapshot() {
+ public synchronized void fillWithRecordedData(PlatformRecording target, Boolean pathToGcRoots) {
boolean running = false;
boolean toDisk = false;
+
for (PlatformRecording r : recordings) {
if (r.getState() == RecordingState.RUNNING) {
running = true;
+ if (r.isToDisk()) {
+ toDisk = true;
+ }
}
- if (r.isToDisk()) {
- toDisk = true;
- }
-
}
// If needed, flush data from memory
if (running) {
if (toDisk) {
+ OldObjectSample.emit(recordings, pathToGcRoots);
rotateDisk();
} else {
- try (Recording snapshot = new Recording()) {
- PlatformRecording internal = PrivateAccess.getInstance().getPlatformRecording(snapshot);
- internal.setShouldWriteActiveRecordingEvent(false);
+ try (PlatformRecording snapshot = newTemporaryRecording()) {
+ snapshot.setToDisk(true);
+ snapshot.setShouldWriteActiveRecordingEvent(false);
snapshot.start();
- snapshot.stop();
- return makeRecordingWithDiskChunks();
+ OldObjectSample.emit(recordings, pathToGcRoots);
+ snapshot.stop("Snapshot dump");
+ fillWithDiskChunks(target);
}
+ return;
}
}
- return makeRecordingWithDiskChunks();
+ fillWithDiskChunks(target);
}
- private Recording makeRecordingWithDiskChunks() {
- Recording snapshot = new Recording();
- snapshot.setName("Snapshot");
- PlatformRecording internal = PrivateAccess.getInstance().getPlatformRecording(snapshot);
+ private void fillWithDiskChunks(PlatformRecording target) {
for (RepositoryChunk c : makeChunkList(null, null)) {
- internal.add(c);
+ target.add(c);
}
- internal.setState(RecordingState.STOPPED);
+ target.setState(RecordingState.STOPPED);
Instant startTime = null;
Instant endTime = null;
- for (RepositoryChunk c : makeChunkList(null, null)) {
+ for (RepositoryChunk c : target.getChunks()) {
if (startTime == null || c.getStartTime().isBefore(startTime)) {
startTime = c.getStartTime();
}
@@ -559,9 +553,8 @@
if (endTime == null) {
endTime = now;
}
- internal.setStartTime(startTime);
- internal.setStopTime(endTime);
- internal.setInternalDuration(Duration.between(startTime, endTime));
- return snapshot;
+ target.setStartTime(startTime);
+ target.setStopTime(endTime);
+ target.setInternalDuration(Duration.between(startTime, endTime));
}
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java Mon Jun 25 09:48:06 2018 -0700
@@ -41,7 +41,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -54,6 +53,7 @@
import jdk.jfr.FlightRecorderListener;
import jdk.jfr.Recording;
import jdk.jfr.RecordingState;
+import jdk.jfr.internal.SecuritySupport.SafePath;
public final class PlatformRecording implements AutoCloseable {
@@ -70,6 +70,7 @@
private boolean toDisk = true;
private String name;
private boolean dumpOnExit;
+ private SafePath dumpOnExitDirectory = new SafePath(".");
// Timestamp information
private Instant stopTime;
private Instant startTime;
@@ -89,7 +90,7 @@
// when you call dump(Path) or setDdestination(Path),
// but if no destination is set and dumponexit=true
// the control context of the recording is taken when the
- // Recording object is constructed. This works well for
+ // Recording object is constructed. This works well for
// -XX:StartFlightRecording and JFR.dump
this.noDestinationDumpOnExitAccessControlContext = AccessController.getContext();
this.id = id;
@@ -114,45 +115,37 @@
Logger.log(LogTag.JFR, LogLevel.INFO, () -> {
// Only print non-default values so it easy to see
// which options were added
- StringJoiner options = new StringJoiner(", ");
- if (!toDisk) {
- options.add("disk=false");
- }
- if (maxAge != null) {
- options.add("maxage=" + Utils.formatTimespan(maxAge, ""));
- }
- if (maxSize != 0) {
- options.add("maxsize=" + Utils.formatBytes(maxSize, ""));
- }
- if (dumpOnExit) {
- options.add("dumponexit=true");
- }
- if (duration != null) {
- options.add("duration=" + Utils.formatTimespan(duration, ""));
- }
- if (destination != null) {
- options.add("filename=" + destination.getText());
- }
- String optionText = options.toString();
- if (optionText.length() != 0) {
- optionText = "{" + optionText + "}";
- }
- return "Started recording \"" + getName() + "\" (" + getId() + ") " + optionText;
- });
+ StringJoiner options = new StringJoiner(", ");
+ if (!toDisk) {
+ options.add("disk=false");
+ }
+ if (maxAge != null) {
+ options.add("maxage=" + Utils.formatTimespan(maxAge, ""));
+ }
+ if (maxSize != 0) {
+ options.add("maxsize=" + Utils.formatBytes(maxSize, ""));
+ }
+ if (dumpOnExit) {
+ options.add("dumponexit=true");
+ }
+ if (duration != null) {
+ options.add("duration=" + Utils.formatTimespan(duration, ""));
+ }
+ if (destination != null) {
+ options.add("filename=" + destination.getText());
+ }
+ String optionText = options.toString();
+ if (optionText.length() != 0) {
+ optionText = "{" + optionText + "}";
+ }
+ return "Started recording \"" + getName() + "\" (" + getId() + ") " + optionText;
+ });
newState = getState();
}
notifyIfStateChanged(oldState, newState);
}
public boolean stop(String reason) {
- return stop(reason, null);
- }
-
- public boolean stop(String reason, WriteableUserPath alternativePath) {
- return stop(reason, alternativePath, Collections.emptyMap());
- }
-
- boolean stop(String reason, WriteableUserPath alternativePath, Map<String, String> overlaySettings) {
RecordingState oldState;
RecordingState newState;
synchronized (recorder) {
@@ -161,23 +154,21 @@
stopTask.cancel();
stopTask = null;
}
- recorder.stop(this, alternativePath);
+ recorder.stop(this);
String endText = reason == null ? "" : ". Reason \"" + reason + "\".";
- Logger.log(LogTag.JFR, LogLevel.INFO, "Stopped recording \"" + getName() + "\" (" + getId()+ ")" + endText);
+ Logger.log(LogTag.JFR, LogLevel.INFO, "Stopped recording \"" + getName() + "\" (" + getId() + ")" + endText);
this.stopTime = Instant.now();
newState = getState();
}
WriteableUserPath dest = getDestination();
- if (dest == null && alternativePath != null) {
- dest = alternativePath;
- }
+
if (dest != null) {
try {
- copyTo(dest, reason, overlaySettings);
- Logger.log(LogTag.JFR, LogLevel.INFO, "Wrote recording \"" + getName() + "\" (" + getId()+ ") to " + dest.getText());
+ dumpStopped(dest);
+ Logger.log(LogTag.JFR, LogLevel.INFO, "Wrote recording \"" + getName() + "\" (" + getId() + ") to " + dest.getText());
notifyIfStateChanged(newState, oldState);
close(); // remove if copied out
- } catch (IOException e) {
+ } catch(IOException e) {
// throw e; // BUG8925030
}
} else {
@@ -195,7 +186,7 @@
setState(RecordingState.DELAYED);
startTask = createStartTask();
recorder.getTimer().schedule(startTask, delay.toMillis());
- Logger.log(LogTag.JFR, LogLevel.INFO, "Scheduled recording \"" + getName() + "\" (" + getId()+ ") to start at " + now);
+ Logger.log(LogTag.JFR, LogLevel.INFO, "Scheduled recording \"" + getName() + "\" (" + getId() + ") to start at " + now);
}
}
@@ -271,7 +262,6 @@
}
}
-
public RecordingState getState() {
synchronized (recorder) {
return state;
@@ -296,79 +286,67 @@
}
chunks.clear();
setState(RecordingState.CLOSED);
- Logger.log(LogTag.JFR, LogLevel.INFO, "Closed recording \"" + getName() + "\" (" + getId()+ ")");
+ Logger.log(LogTag.JFR, LogLevel.INFO, "Closed recording \"" + getName() + "\" (" + getId() + ")");
}
newState = getState();
}
notifyIfStateChanged(newState, oldState);
}
- public void copyTo(WriteableUserPath path, String reason, Map<String, String> dumpSettings) throws IOException {
- synchronized (recorder) {
- RecordingState state = getState();
- if (state == RecordingState.CLOSED) {
- throw new IOException("Recording \"" + name + "\" (id=" + id + ") has been closed, no contents to write");
+ // To be used internally when doing dumps.
+ // Caller must have recorder lock and close recording before releasing lock
+ public PlatformRecording newSnapshotClone(String reason, Boolean pathToGcRoots) throws IOException {
+ if(!Thread.holdsLock(recorder)) {
+ throw new InternalError("Caller must have recorder lock");
+ }
+ RecordingState state = getState();
+ if (state == RecordingState.CLOSED) {
+ throw new IOException("Recording \"" + name + "\" (id=" + id + ") has been closed, no contents to write");
+ }
+ if (state == RecordingState.DELAYED || state == RecordingState.NEW) {
+ throw new IOException("Recording \"" + name + "\" (id=" + id + ") has not started, no contents to write");
+ }
+ if (state == RecordingState.STOPPED) {
+ PlatformRecording clone = recorder.newTemporaryRecording();
+ for (RepositoryChunk r : chunks) {
+ clone.add(r);
}
- if (state == RecordingState.DELAYED || state == RecordingState.NEW) {
- throw new IOException("Recording \"" + name + "\" (id=" + id + ") has not started, no contents to write");
- }
- if (state == RecordingState.STOPPED) {
- // have all we need, just write it
- dumpToFile(path, reason, getId());
- return;
- }
+ return clone;
+ }
- // Recording is RUNNING, create a clone
- try(PlatformRecording clone = recorder.newRecording(Collections.emptyMap(), 0)) {
- clone.setShouldWriteActiveRecordingEvent(false);
- clone.setName(getName());
- clone.setDestination(path);
- clone.setToDisk(true);
- // We purposely don't clone settings, since
- // a union a == a
- if (!isToDisk()) {
- // force memory contents to disk
- clone.start();
- } else {
- // using existing chunks on disk
- for (RepositoryChunk c : chunks) {
- clone.add(c);
- }
- clone.setState(RecordingState.RUNNING);
- clone.setStartTime(getStartTime());
- }
- if (dumpSettings.isEmpty()) {
- clone.setSettings(getSettings());
- clone.stop(reason); // dumps to destination path here
- } else {
- // Risk of violating lock order here, since
- // clone.stop() will take recorder lock inside
- // metadata lock, but OK if we already
- // have recorder lock when we entered metadata lock
- Thread.holdsLock(recorder);
- synchronized(MetadataRepository.getInstance()) {
- Thread.holdsLock(recorder);
- Map<String, String> oldSettings = getSettings();
- Map<String, String> newSettings = new HashMap<>(oldSettings);
- // replace with dump settings
- newSettings.putAll(dumpSettings);
- clone.setSettings(newSettings);
- clone.stop(reason);
- }
- }
+ // Recording is RUNNING, create a clone
+ PlatformRecording clone = recorder.newTemporaryRecording();
+ clone.setShouldWriteActiveRecordingEvent(false);
+ clone.setName(getName());
+ clone.setDestination(this.destination);
+ clone.setToDisk(true);
+ // We purposely don't clone settings here, since
+ // a union a == a
+ if (!isToDisk()) {
+ // force memory contents to disk
+ clone.start();
+ } else {
+ // using existing chunks on disk
+ for (RepositoryChunk c : chunks) {
+ clone.add(c);
}
- return;
+ clone.setState(RecordingState.RUNNING);
+ clone.setStartTime(getStartTime());
}
- }
-
- private void dumpToFile(WriteableUserPath userPath, String reason, long id) throws IOException {
- userPath.doPriviligedIO(() -> {
- try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(userPath.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
- cc.transferTo(fc);
- fc.force(true);
+ if (pathToGcRoots == null) {
+ clone.setSettings(getSettings()); // needed for old object sample
+ clone.stop(reason); // dumps to destination path here
+ } else {
+ // Risk of violating lock order here, since
+ // clone.stop() will take recorder lock inside
+ // metadata lock, but OK if we already
+ // have recorder lock when we entered metadata lock
+ synchronized (MetadataRepository.getInstance()) {
+ clone.setSettings(OldObjectSample.createSettingsForSnapshot(this, pathToGcRoots));
+ clone.stop(reason);
}
- return null;
- });
+ }
+ return clone;
}
public boolean isToDisk() {
@@ -387,7 +365,7 @@
}
}
- public void setDestination(WriteableUserPath userSuppliedPath) throws IOException {
+ public void setDestination(WriteableUserPath userSuppliedPath) throws IOException {
synchronized (recorder) {
if (Utils.isState(getState(), RecordingState.STOPPED, RecordingState.CLOSED)) {
throw new IllegalStateException("Destination can't be set on a recording that has been stopped/closed");
@@ -479,7 +457,7 @@
TreeMap<String, String> ordered = new TreeMap<>(settings);
Logger.log(LogTag.JFR_SETTING, LogLevel.INFO, "New settings for recording \"" + getName() + "\" (" + getId() + ")");
for (Map.Entry<String, String> entry : ordered.entrySet()) {
- String text = entry.getKey() + "=\"" + entry.getValue() + "\"";
+ String text = entry.getKey() + "=\"" + entry.getValue() + "\"";
Logger.log(LogTag.JFR_SETTING, LogLevel.INFO, text);
}
}
@@ -491,7 +469,6 @@
}
}
-
private void notifyIfStateChanged(RecordingState newState, RecordingState oldState) {
if (oldState == newState) {
return;
@@ -580,12 +557,12 @@
private void added(RepositoryChunk c) {
c.use();
size += c.getSize();
- Logger.log(JFR, DEBUG, ()-> "Recording \"" + name + "\" (" + id + ") added chunk " + c.toString() + ", current size=" + size);
+ Logger.log(JFR, DEBUG, () -> "Recording \"" + name + "\" (" + id + ") added chunk " + c.toString() + ", current size=" + size);
}
private void removed(RepositoryChunk c) {
size -= c.getSize();
- Logger.log(JFR, DEBUG, ()-> "Recording \"" + name + "\" (" + id + ") removed chunk " + c.toString() + ", current size=" + size);
+ Logger.log(JFR, DEBUG, () -> "Recording \"" + name + "\" (" + id + ") removed chunk " + c.toString() + ", current size=" + size);
c.release();
}
@@ -661,7 +638,7 @@
stop("End of duration reached");
} catch (Throwable t) {
// Prevent malicious user to propagate exception callback in the wrong context
- Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not stop recording. " + t.getMessage());
+ Logger.log(LogTag.JFR, LogLevel.ERROR, "Could not stop recording.");
}
}
};
@@ -678,7 +655,7 @@
}
void clearDestination() {
- destination = null;
+ destination = null;
}
public AccessControlContext getNoDestinationDumpOnExitAccessControlContext() {
@@ -686,10 +663,116 @@
}
void setShouldWriteActiveRecordingEvent(boolean shouldWrite) {
- this.shuoldWriteActiveRecordingEvent = shouldWrite;
+ this.shuoldWriteActiveRecordingEvent = shouldWrite;
}
boolean shouldWriteMetadataEvent() {
return shuoldWriteActiveRecordingEvent;
}
+
+ // Dump running and stopped recordings
+ public void dump(WriteableUserPath writeableUserPath) throws IOException {
+ synchronized (recorder) {
+ try(PlatformRecording p = newSnapshotClone("Dumped by user", null)) {
+ p.dumpStopped(writeableUserPath);
+ }
+ }
+ }
+
+ public void dumpStopped(WriteableUserPath userPath) throws IOException {
+ synchronized (recorder) {
+ userPath.doPriviligedIO(() -> {
+ try (ChunksChannel cc = new ChunksChannel(chunks); FileChannel fc = FileChannel.open(userPath.getReal(), StandardOpenOption.WRITE, StandardOpenOption.APPEND)) {
+ cc.transferTo(fc);
+ fc.force(true);
+ }
+ return null;
+ });
+ }
+ }
+
+ public void filter(Instant begin, Instant end, Long maxSize) {
+ synchronized (recorder) {
+ List<RepositoryChunk> result = removeAfter(end, removeBefore(begin, new ArrayList<>(chunks)));
+ if (maxSize != null) {
+ if (begin != null && end == null) {
+ result = reduceFromBeginning(maxSize, result);
+ } else {
+ result = reduceFromEnd(maxSize, result);
+ }
+ }
+ int size = 0;
+ for (RepositoryChunk r : result) {
+ size += r.getSize();
+ r.use();
+ }
+ this.size = size;
+ for (RepositoryChunk r : chunks) {
+ r.release();
+ }
+ chunks.clear();
+ chunks.addAll(result);
+ }
+ }
+
+ private static List<RepositoryChunk> removeBefore(Instant time, List<RepositoryChunk> input) {
+ if (time == null) {
+ return input;
+ }
+ List<RepositoryChunk> result = new ArrayList<>(input.size());
+ for (RepositoryChunk r : input) {
+ if (!r.getEndTime().isBefore(time)) {
+ result.add(r);
+ }
+ }
+ return result;
+ }
+
+ private static List<RepositoryChunk> removeAfter(Instant time, List<RepositoryChunk> input) {
+ if (time == null) {
+ return input;
+ }
+ List<RepositoryChunk> result = new ArrayList<>(input.size());
+ for (RepositoryChunk r : input) {
+ if (!r.getStartTime().isAfter(time)) {
+ result.add(r);
+ }
+ }
+ return result;
+ }
+
+ private static List<RepositoryChunk> reduceFromBeginning(Long maxSize, List<RepositoryChunk> input) {
+ if (maxSize == null || input.isEmpty()) {
+ return input;
+ }
+ List<RepositoryChunk> result = new ArrayList<>(input.size());
+ long total = 0;
+ for (RepositoryChunk r : input) {
+ total += r.getSize();
+ if (total > maxSize) {
+ break;
+ }
+ result.add(r);
+ }
+ // always keep at least one chunk
+ if (result.isEmpty()) {
+ result.add(input.get(0));
+ }
+ return result;
+ }
+
+ private static List<RepositoryChunk> reduceFromEnd(Long maxSize, List<RepositoryChunk> input) {
+ Collections.reverse(input);
+ List<RepositoryChunk> result = reduceFromBeginning(maxSize, input);
+ Collections.reverse(result);
+ return result;
+ }
+
+ public void setDumpOnExitDirectory(SafePath directory) {
+ this.dumpOnExitDirectory = directory;
+ }
+
+ public SafePath getDumpOnExitDirectory() {
+ return this.dumpOnExitDirectory;
+ }
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PrivateAccess.java Mon Jun 25 09:48:06 2018 -0700
@@ -92,4 +92,6 @@
public abstract void setAnnotations(SettingDescriptor s, List<AnnotationElement> a);
public abstract boolean isUnsigned(ValueDescriptor v);
+
+ public abstract PlatformRecorder getPlatformRecorder();
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java Mon Jun 25 09:48:06 2018 -0700
@@ -41,7 +41,7 @@
private static final JVM jvm = JVM.getJVM();
private static final Repository instance = new Repository();
- static DateTimeFormatter REPO_DATE_FORMAT = DateTimeFormatter
+ public final static DateTimeFormatter REPO_DATE_FORMAT = DateTimeFormatter
.ofPattern("yyyy_MM_dd_HH_mm_ss");
private final Set<SafePath> cleanupDirectories = new HashSet<>();
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ShutdownHook.java Mon Jun 25 09:48:06 2018 -0700
@@ -26,12 +26,10 @@
package jdk.jfr.internal;
import java.io.IOException;
-import java.nio.file.Paths;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.time.LocalDateTime;
import jdk.jfr.RecordingState;
@@ -67,9 +65,10 @@
WriteableUserPath dest = recording.getDestination();
if (dest == null) {
dest = makeDumpOnExitPath(recording);
+ recording.setDestination(dest);
}
if (dest != null) {
- recording.stop("Dump on exit", dest);
+ recording.stop("Dump on exit");
}
} catch (Exception e) {
Logger.log(LogTag.JFR, LogLevel.DEBUG, () -> "Could not dump recording " + recording.getName() + " on exit.");
@@ -78,23 +77,21 @@
private WriteableUserPath makeDumpOnExitPath(PlatformRecording recording) {
try {
- String pid = JVM.getJVM().getPid();
- String dfText = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now());
- String name = "hotspot-" + "pid-" + pid + "-id-" + recording.getId() + "-" + dfText + ".jfr";
+ String name = Utils.makeFilename(recording.getRecording());
AccessControlContext acc = recording.getNoDestinationDumpOnExitAccessControlContext();
return AccessController.doPrivileged(new PrivilegedExceptionAction<WriteableUserPath>() {
@Override
public WriteableUserPath run() throws Exception {
- return new WriteableUserPath(Paths.get(".", name));
+ return new WriteableUserPath(recording.getDumpOnExitDirectory().toPath().resolve(name));
}
}, acc);
} catch (PrivilegedActionException e) {
Throwable t = e.getCause();
if (t instanceof SecurityException) {
- Logger.log(LogTag.JFR, LogLevel.WARN, "Not allowed to create dump path for recording " + recording.getId() + " on exit. " + e.getMessage());
+ Logger.log(LogTag.JFR, LogLevel.WARN, "Not allowed to create dump path for recording " + recording.getId() + " on exit.");
}
if (t instanceof IOException) {
- Logger.log(LogTag.JFR, LogLevel.WARN, "Could not dump " + recording.getId() + " on exit. " + e.getMessage());
+ Logger.log(LogTag.JFR, LogLevel.WARN, "Could not dump " + recording.getId() + " on exit.");
}
return null;
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java Mon Jun 25 09:48:06 2018 -0700
@@ -43,6 +43,7 @@
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.time.Duration;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -55,6 +56,7 @@
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.jfr.Event;
import jdk.jfr.FlightRecorderPermission;
+import jdk.jfr.Recording;
import jdk.jfr.RecordingState;
import jdk.jfr.internal.handlers.EventHandler;
import jdk.jfr.internal.settings.PeriodSetting;
@@ -484,13 +486,6 @@
return Collections.unmodifiableList(list);
}
- public static void updateSettingPathToGcRoots(Map<String, String> settings, Boolean pathToGcRoots) {
- if (pathToGcRoots != null) {
- settings.put(Type.EVENT_NAME_PREFIX + "OldObjectSample#cutoff", pathToGcRoots ? "infinity" : "0 ns" );
- }
- }
-
-
public static String upgradeLegacyJDKEvent(String eventName) {
if (eventName.length() <= LEGACY_EVENT_NAME_PREFIX.length()) {
return eventName;
@@ -503,4 +498,11 @@
}
return eventName;
}
+
+ public static String makeFilename(Recording recording) {
+ String pid = JVM.getJVM().getPid();
+ String date = Repository.REPO_DATE_FORMAT.format(LocalDateTime.now());
+ String idText = recording == null ? "" : "-id-" + Long.toString(recording.getId());
+ return "hotspot-" + "pid-" + pid + idText + "-" + date + ".jfr";
+ }
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/AbstractDCmd.java Mon Jun 25 09:48:06 2018 -0700
@@ -27,8 +27,10 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
@@ -63,15 +65,19 @@
return result.toString();
}
- protected final SafePath resolvePath(String path, String errorMsg) throws DCmdException {
- if (path == null) {
- return null;
+ protected final SafePath resolvePath(Recording recording, String filename) throws InvalidPathException {
+ if (filename == null) {
+ return makeGenerated(recording, Paths.get("."));
}
- try {
- return new SafePath(path);
- } catch (InvalidPathException e) {
- throw new DCmdException(e, errorMsg, ", invalid path \"" + path + "\".");
+ Path path = Paths.get(filename);
+ if (Files.isDirectory(path)) {
+ return makeGenerated(recording, path);
}
+ return new SafePath(path.toAbsolutePath().normalize());
+ }
+
+ private SafePath makeGenerated(Recording recording, Path directory) {
+ return new SafePath(directory.toAbsolutePath().resolve(Utils.makeFilename(recording)).normalize());
}
protected final Recording findRecording(String name) throws DCmdException {
@@ -83,10 +89,12 @@
}
}
- protected final void reportOperationComplete(String actionPrefix, Recording r, SafePath file) {
+ protected final void reportOperationComplete(String actionPrefix, String name, SafePath file) {
print(actionPrefix);
- print(" recording ");
- print("\"" + r.getName() + "\"");
+ print(" recording");
+ if (name != null) {
+ print(" \"" + name + "\"");
+ }
if (file != null) {
print(",");
try {
@@ -136,7 +144,7 @@
}
protected final void printBytes(long bytes, String separation) {
- print(Utils.formatBytes(bytes, separation));
+ print(Utils.formatBytes(bytes, separation));
}
protected final void printTimespan(Duration timespan, String separator) {
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdCheck.java Mon Jun 25 09:48:06 2018 -0700
@@ -36,6 +36,9 @@
import jdk.jfr.EventType;
import jdk.jfr.Recording;
import jdk.jfr.SettingDescriptor;
+import jdk.jfr.internal.LogLevel;
+import jdk.jfr.internal.LogTag;
+import jdk.jfr.internal.Logger;
/**
* JFR.check - invoked from native
@@ -59,13 +62,17 @@
return getResult();
}
- private void executeInternal(String recordingText, Boolean verbose) throws DCmdException {
+ private void executeInternal(String name, Boolean verbose) throws DCmdException {
+ if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
+ Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdCheck: name=" + name + ", verbose=" + verbose);
+ }
+
if (verbose == null) {
verbose = Boolean.FALSE;
}
- if (recordingText != null) {
- printRecording(findRecording(recordingText), verbose);
+ if (name != null) {
+ printRecording(findRecording(name), verbose);
return;
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdConfigure.java Mon Jun 25 09:48:06 2018 -0700
@@ -70,6 +70,19 @@
Boolean sampleThreads
) throws DCmdException {
+ if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
+ Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdConfigure: repositorypath=" + repositoryPath +
+ ", dumppath=" + dumpPath +
+ ", stackdepth=" + stackDepth +
+ ", globalbuffercount=" + globalBufferCount +
+ ", globalbuffersize=" + globalBufferSize +
+ ", thread_buffer_size" + threadBufferSize +
+ ", memorysize" + memorySize +
+ ", maxchunksize=" + maxChunkSize +
+ ", samplethreads" + sampleThreads);
+ }
+
+
boolean updated = false;
if (repositoryPath != null) {
try {
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdDump.java Mon Jun 25 09:48:06 2018 -0700
@@ -26,10 +26,21 @@
import java.io.IOException;
import java.nio.file.InvalidPathException;
-import java.util.HashMap;
-import java.util.Map;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeParseException;
+import jdk.jfr.FlightRecorder;
import jdk.jfr.Recording;
+import jdk.jfr.internal.LogLevel;
+import jdk.jfr.internal.LogTag;
+import jdk.jfr.internal.Logger;
+import jdk.jfr.internal.PlatformRecorder;
import jdk.jfr.internal.PlatformRecording;
import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.SecuritySupport.SafePath;
@@ -40,41 +51,155 @@
* JFR.dump
*
*/
-//Instantiated by native
+// Instantiated by native
final class DCmdDump extends AbstractDCmd {
/**
* Execute JFR.dump.
*
- * @param recordingText name or id of the recording to dump, or
- * <code>null</code>
+ * @param name name or id of the recording to dump, or <code>null</code> to dump everything
*
- * @param textPath file path where recording should be written.
+ * @param filename file path where recording should be written, not null
+ * @param maxAge how far back in time to dump, may be null
+ * @param maxSize how far back in size to dump data from, may be null
+ * @param begin point in time to dump data from, may be null
+ * @param end point in time to dump data to, may be null
+ * @param pathToGcRoots if Java heap should be swept for reference chains
*
* @return result output
*
* @throws DCmdException if the dump could not be completed
*/
- public String execute(String recordingText, String textPath, Boolean pathToGcRoots) throws DCmdException {
- if (textPath == null) {
- throw new DCmdException("Failed to dump %s, missing filename.", recordingText);
+ public String execute(String name, String filename, Long maxAge, Long maxSize, String begin, String end, Boolean pathToGcRoots) throws DCmdException {
+ if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
+ Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG,
+ "Executing DCmdDump: name=" + name +
+ ", filename=" + filename +
+ ", maxage=" + maxAge +
+ ", maxsize=" + maxSize +
+ ", begin=" + begin +
+ ", end" + end +
+ ", path-to-gc-roots=" + pathToGcRoots);
+ }
+
+ if (FlightRecorder.getFlightRecorder().getRecordings().isEmpty()) {
+ throw new DCmdException("No recordings to dump from. Use JFR.start to start a recording.");
+ }
+
+ if (maxAge != null) {
+ if (end != null || begin != null) {
+ throw new DCmdException("Dump failed, maxage can't be combined with begin or end.");
+ }
+
+ if (maxAge < 0) {
+ throw new DCmdException("Dump failed, maxage can't be negative.");
+ }
+ if (maxAge == 0) {
+ maxAge = Long.MAX_VALUE / 2; // a high value that won't overflow
+ }
}
- Recording recording = findRecording(recordingText);
- try {
- SafePath dumpFile = resolvePath(textPath, "Failed to dump %s");
- // create file for JVM
- Utils.touch(dumpFile.toPath());
- PlatformRecording r = PrivateAccess.getInstance().getPlatformRecording(recording);
- WriteableUserPath wup = new WriteableUserPath(dumpFile.toPath());
+
+ if (maxSize!= null) {
+ if (maxSize < 0) {
+ throw new DCmdException("Dump failed, maxsize can't be negative.");
+ }
+ if (maxSize == 0) {
+ maxSize = Long.MAX_VALUE / 2; // a high value that won't overflow
+ }
+ }
+
+ Instant beginTime = parseTime(begin, "begin");
+ Instant endTime = parseTime(end, "end");
- Map<String, String> overlay = new HashMap<>();
- Utils.updateSettingPathToGcRoots(overlay, pathToGcRoots);
+ if (beginTime != null && endTime != null) {
+ if (endTime.isBefore(beginTime)) {
+ throw new DCmdException("Dump failed, begin must preceed end.");
+ }
+ }
- r.copyTo(wup, "Dumped by user", overlay);
- reportOperationComplete("Dumped", recording, dumpFile);
- } catch (IOException | InvalidPathException e) {
- throw new DCmdException("Failed to dump %s. Could not copy recording for dump. %s", recordingText, e.getMessage());
+ Duration duration = null;
+ if (maxAge != null) {
+ duration = Duration.ofNanos(maxAge);
+ beginTime = Instant.now().minus(duration);
+ }
+ Recording recording = null;
+ if (name != null) {
+ recording = findRecording(name);
+ }
+ PlatformRecorder recorder = PrivateAccess.getInstance().getPlatformRecorder();
+ synchronized (recorder) {
+ dump(recorder, recording, name, filename, maxSize, pathToGcRoots, beginTime, endTime);
}
return getResult();
}
+ public void dump(PlatformRecorder recorder, Recording recording, String name, String filename, Long maxSize, Boolean pathToGcRoots, Instant beginTime, Instant endTime) throws DCmdException {
+ try (PlatformRecording r = newSnapShot(recorder, recording, pathToGcRoots)) {
+ r.filter(beginTime, endTime, maxSize);
+ if (r.getChunks().isEmpty()) {
+ throw new DCmdException("Dump failed. No data found in the specified interval.");
+ }
+ SafePath dumpFile = resolvePath(recording, filename);
+
+ // Needed for JVM
+ Utils.touch(dumpFile.toPath());
+ r.dumpStopped(new WriteableUserPath(dumpFile.toPath()));
+ reportOperationComplete("Dumped", name, dumpFile);
+ } catch (IOException | InvalidPathException e) {
+ throw new DCmdException("Dump failed. Could not copy recording data. %s", e.getMessage());
+ }
+ }
+
+ private Instant parseTime(String time, String parameter) throws DCmdException {
+ if (time == null) {
+ return null;
+ }
+ try {
+ return Instant.parse(time);
+ } catch (DateTimeParseException dtp) {
+ // fall through
+ }
+ try {
+ LocalDateTime ldt = LocalDateTime.parse(time);
+ return ZonedDateTime.of(ldt, ZoneId.systemDefault()).toInstant();
+ } catch (DateTimeParseException dtp) {
+ // fall through
+ }
+ try {
+ LocalTime lt = LocalTime.parse(time);
+ LocalDate ld = LocalDate.now();
+ Instant instant = ZonedDateTime.of(ld, lt, ZoneId.systemDefault()).toInstant();
+ Instant now = Instant.now();
+ if (instant.isAfter(now) && !instant.isBefore(now.plusSeconds(3600))) {
+ // User must have meant previous day
+ ld = ld.minusDays(1);
+ }
+ return ZonedDateTime.of(ld, lt, ZoneId.systemDefault()).toInstant();
+ } catch (DateTimeParseException dtp) {
+ // fall through
+ }
+
+ if (time.startsWith("-")) {
+ try {
+ long durationNanos = Utils.parseTimespan(time.substring(1));
+ Duration duration = Duration.ofNanos(durationNanos);
+ return Instant.now().minus(duration);
+ } catch (NumberFormatException nfe) {
+ // fall through
+ }
+ }
+ throw new DCmdException("Dump failed, not a valid %s time.", parameter);
+ }
+
+ private PlatformRecording newSnapShot(PlatformRecorder recorder, Recording recording, Boolean pathToGcRoots) throws DCmdException, IOException {
+ if (recording == null) {
+ // Operate on all recordings
+ PlatformRecording snapshot = recorder.newTemporaryRecording();
+ recorder.fillWithRecordedData(snapshot, pathToGcRoots);
+ return snapshot;
+ }
+
+ PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording);
+ return pr.newSnapshotClone("Dumped by user", pathToGcRoots);
+ }
+
}
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java Mon Jun 25 09:48:06 2018 -0700
@@ -25,19 +25,26 @@
package jdk.jfr.internal.dcmd;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.time.Duration;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import jdk.jfr.FlightRecorder;
import jdk.jfr.Recording;
import jdk.jfr.internal.JVM;
+import jdk.jfr.internal.LogLevel;
+import jdk.jfr.internal.LogTag;
+import jdk.jfr.internal.Logger;
+import jdk.jfr.internal.OldObjectSample;
+import jdk.jfr.internal.PrivateAccess;
import jdk.jfr.internal.SecuritySupport.SafePath;
import jdk.jfr.internal.Type;
-import jdk.jfr.internal.Utils;
import jdk.jfr.internal.jfc.JFC;
/**
@@ -51,7 +58,7 @@
* Execute JFR.start.
*
* @param name optional name that can be used to identify recording.
- * @param configurations names of settings files to use, i.e. "default" or
+ * @param settings names of settings files to use, i.e. "default" or
* "default.jfc".
* @param delay delay before recording is started, in nanoseconds. Must be
* at least 1 second.
@@ -73,7 +80,19 @@
* @throws DCmdException if recording could not be started
*/
@SuppressWarnings("resource")
- public String execute(String name, String[] configurations, Long delay, Long duration, Boolean disk, String path, Long maxAge, Long maxSize, Boolean dumpOnExit, Boolean pathToGcRoots) throws DCmdException {
+ public String execute(String name, String[] settings, Long delay, Long duration, Boolean disk, String path, Long maxAge, Long maxSize, Boolean dumpOnExit, Boolean pathToGcRoots) throws DCmdException {
+ if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
+ Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdStart: name=" + name +
+ ", settings=" + Arrays.asList(settings) +
+ ", delay=" + delay +
+ ", duration=" + duration +
+ ", disk=" + disk+
+ ", filename=" + path +
+ ", maxage=" + maxAge +
+ ", maxsize=" + maxSize +
+ ", dumponexit =" + dumpOnExit +
+ ", path-to-gc-roots=" + pathToGcRoots);
+ }
if (name != null) {
try {
Integer.parseInt(name);
@@ -86,25 +105,23 @@
if (duration == null && Boolean.FALSE.equals(dumpOnExit) && path != null) {
throw new DCmdException("Filename can only be set for a time bound recording or if dumponexit=true. Set duration/dumponexit or omit filename.");
}
- if (dumpOnExit == null && path != null) {
- dumpOnExit = Boolean.TRUE;
- }
+
Map<String, String> s = new HashMap<>();
- if (configurations == null || configurations.length == 0) {
- configurations = new String[] { "default" };
+ if (settings == null || settings.length == 0) {
+ settings = new String[] { "default" };
}
- for (String configName : configurations) {
+ for (String configName : settings) {
try {
s.putAll(JFC.createKnown(configName).getSettings());
} catch (IOException | ParseException e) {
- throw new DCmdException("Could not parse setting " + configurations[0], e);
+ throw new DCmdException("Could not parse setting " + settings[0], e);
}
}
- Utils.updateSettingPathToGcRoots(s, pathToGcRoots);
+ OldObjectSample.updateSettingPathToGcRoots(s, pathToGcRoots);
if (duration != null) {
if (duration < 1000L * 1000L * 1000L) {
@@ -133,10 +150,24 @@
recording.setToDisk(disk.booleanValue());
}
recording.setSettings(s);
+ SafePath safePath = null;
if (path != null) {
try {
- recording.setDestination(Paths.get(path));
+ if (dumpOnExit == null) {
+ // default to dumponexit=true if user specified filename
+ dumpOnExit = Boolean.TRUE;
+ }
+ Path p = Paths.get(path);
+ if (Files.isDirectory(p) && Boolean.TRUE.equals(dumpOnExit)) {
+ // Decide destination filename at dump time
+ // Purposely avoid generating filename in Recording#setDestination due to
+ // security concerns
+ PrivateAccess.getInstance().getPlatformRecording(recording).setDumpOnExitDirectory(new SafePath(p));
+ } else {
+ safePath = resolvePath(recording, path);
+ recording.setDestination(safePath.toPath());
+ }
} catch (IOException | InvalidPathException e) {
recording.close();
throw new DCmdException("Could not start recording, not able to write to file %s. %s ", path, e.getMessage());
@@ -175,10 +206,10 @@
recording.setMaxSize(250*1024L*1024L);
}
- if (path != null && duration != null) {
+ if (safePath != null && duration != null) {
println(" The result will be written to:");
println();
- printPath(new SafePath(path));
+ printPath(safePath);
} else {
println();
println();
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStop.java Mon Jun 25 09:48:06 2018 -0700
@@ -29,13 +29,16 @@
import java.nio.file.Paths;
import jdk.jfr.Recording;
+import jdk.jfr.internal.LogLevel;
+import jdk.jfr.internal.LogTag;
+import jdk.jfr.internal.Logger;
import jdk.jfr.internal.SecuritySupport.SafePath;
/**
* JFR.stop
*
*/
-//Instantiated by native
+// Instantiated by native
final class DCmdStop extends AbstractDCmd {
/**
@@ -43,35 +46,42 @@
*
* Requires that either <code>name or <code>id</code> is set.
*
- * @param recordingText name or id of the recording to stop.
+ * @param name name or id of the recording to stop.
*
- * @param textPath file path where data should be written after recording
- * has been stopped, or <code>null</code> if recording shouldn't be
- * written to disk.
+ * @param filename file path where data should be written after recording has
+ * been stopped, or <code>null</code> if recording shouldn't be written
+ * to disk.
* @return result text
*
* @throws DCmdException if recording could not be stopped
*/
- public String execute(String recordingText, String textPath) throws DCmdException {
+ public String execute(String name, String filename) throws DCmdException {
+ if (LogTag.JFR_DCMD.shouldLog(LogLevel.DEBUG)) {
+ Logger.log(LogTag.JFR_DCMD, LogLevel.DEBUG, "Executing DCmdStart: name=" + name + ", filename=" + filename);
+ }
+
try {
- SafePath path = resolvePath(textPath, "Failed to stop %s");
- Recording recording = findRecording(recordingText);
- if (textPath != null) {
+ SafePath safePath = null;
+ Recording recording = findRecording(name);
+ if (filename != null) {
try {
- recording.setDestination(Paths.get(textPath));
- } catch (IOException e) {
- throw new DCmdException("Failed to stop %s. Could not set destination for \"%s\" to file %s", recording.getName(), textPath, e.getMessage());
+ // Ensure path is valid. Don't generate safePath if filename == null, as a user may
+ // want to stop recording without a dump
+ safePath = resolvePath(null, filename);
+ recording.setDestination(Paths.get(filename));
+ } catch (IOException | InvalidPathException e) {
+ throw new DCmdException("Failed to stop %s. Could not set destination for \"%s\" to file %s", recording.getName(), filename, e.getMessage());
}
}
recording.stop();
- reportOperationComplete("Stopped", recording, path);
+ reportOperationComplete("Stopped", recording.getName(), safePath);
recording.close();
return getResult();
} catch (InvalidPathException | DCmdException e) {
- if (textPath != null) {
- throw new DCmdException("Could not write recording \"%s\" to file. %s", recordingText, e.getMessage());
+ if (filename != null) {
+ throw new DCmdException("Could not write recording \"%s\" to file. %s", name, e.getMessage());
}
- throw new DCmdException(e, "Could not stop recording \"%s\".", recordingText, e.getMessage());
+ throw new DCmdException(e, "Could not stop recording \"%s\".", name, e.getMessage());
}
}
}
--- a/src/jdk.localedata/share/legal/cldr.md Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.localedata/share/legal/cldr.md Mon Jun 25 09:48:06 2018 -0700
@@ -1,12 +1,38 @@
-## Unicode Common Local Data Repository (CLDR) v29
+## Unicode Common Local Data Repository (CLDR) v33
### CLDR License
-<pre>
+
+```
+
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+Unicode Data Files include all data files under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
+
+Unicode Data Files do not include PDF online code charts under the
+directory http://www.unicode.org/Public/.
-Copyright © 1991-2016 Unicode, Inc. All rights reserved.
+Software includes any source code published in the Unicode Standard
+or under the directories
+http://www.unicode.org/Public/, http://www.unicode.org/reports/,
+http://www.unicode.org/cldr/data/,
+http://source.icu-project.org/repos/icu/, and
+http://www.unicode.org/utility/trac/browser/.
-Distributed under the Terms of Use in
-http://www.unicode.org/copyright.html.
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2018 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Unicode data files and any associated documentation
@@ -15,28 +41,26 @@
without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, and/or sell copies of
the Data Files or Software, and to permit persons to whom the Data Files
-or Software are furnished to do so, provided that
+or Software are furnished to do so, provided that either
(a) this copyright and permission notice appear with all copies
-of the Data Files or Software,
+of the Data Files or Software, or
(b) this copyright and permission notice appear in associated
-documentation, and
-(c) there is clear notice in each modified Data File or in the Software
-as well as in the documentation associated with the Data File(s) or
-Software that the data or software has been modified.
+Documentation.
-THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
-NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
-OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
-Except as contained in this notice, the name of a copyright holder shall not
-be used in advertising or otherwise to promote the sale, use or other dealings
-in these Data Files or Software without prior written authorization of
-the copyright holder.
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
-</pre>
+```
--- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/MBeanUtils.java Mon Jun 25 09:48:06 2018 -0700
@@ -122,7 +122,7 @@
}
int size = Integer.parseInt(string);
if (size <1) {
- throw new IllegalArgumentException("Block size msut be at least 1 byte");
+ throw new IllegalArgumentException("Block size must be at least 1 byte");
}
return size;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/nio/Channels.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2018, 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.nio;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Objects;
+
+import sun.nio.ch.IOUtil;
+import sun.nio.ch.Net;
+import sun.nio.ch.SelChImpl;
+import sun.nio.ch.SelectionKeyImpl;
+import sun.nio.ch.SelectorProviderImpl;
+
+/**
+ * Defines static methods to create {@link java.nio.channels.Channel channels}.
+ *
+ * <p> Unless otherwise specified, passing a {@code null} argument to any of the
+ * methods defined here will cause a {@code NullPointerException} to be thrown.
+ *
+ * @since 11
+ */
+
+public final class Channels {
+ private Channels() { }
+
+ /**
+ * An object used to coordinate the closing of a selectable channel created
+ * by {@link Channels#readWriteSelectableChannel readWriteSelectableChannel}.
+ *
+ * @since 11
+ */
+ public interface SelectableChannelCloser {
+
+ /**
+ * Closes a selectable channel.
+ *
+ * <p> This method is invoked by the channel's close method in order to
+ * perform the actual work of closing the channel. This method is only
+ * invoked if the channel has not yet been closed, and it is never
+ * invoked more than once by the channel's close implementation.
+ *
+ * <p> An implementation of this method must arrange for any other
+ * thread that is blocked in an I/O operation upon the channel to return
+ * immediately, either by throwing an exception or by returning normally.
+ * If the channel is {@link SelectableChannel#isRegistered registered}
+ * with one or more {@link java.nio.channels.Selector Selector}s then
+ * the file descriptor should not be released until the {@link
+ * #implReleaseChannel implReleaseChannel} method is invoked. </p>
+ *
+ * @param sc
+ * The selectable channel
+ *
+ * @throws IOException
+ * If an I/O error occurs while closing the file descriptor
+ *
+ * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel
+ */
+ void implCloseChannel(SelectableChannel sc) throws IOException;
+
+ /**
+ * Release the file descriptor and any resources for a selectable
+ * channel that closed while registered with one or more {@link
+ * java.nio.channels.Selector Selector}s.
+ *
+ * <p> This method is for cases where a channel is closed when
+ * {@link java.nio.channels.SelectableChannel#isRegistered registered}
+ * with one or more {@code Selector}s. A channel may remain registered
+ * for some time after it is closed. This method is invoked when the
+ * channel is eventually deregistered from the last {@code Selector}
+ * that it was registered with. It is invoked at most once.
+ *
+ * @apiNote This method is invoked while synchronized on the selector
+ * and its selected-key set. Great care must be taken to avoid deadlocks
+ * with other threads that also synchronize on these objects.
+ *
+ * @param sc
+ * The closed selectable channel
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ *
+ * @see java.nio.channels.spi.AbstractSelector#deregister
+ */
+ void implReleaseChannel(SelectableChannel sc) throws IOException;
+ }
+
+ /**
+ * Creates a selectable channel to a file descriptor that supports an
+ * {@link SelectableChannel#validOps() operation-set} of
+ * {@link SelectionKey#OP_READ OP_READ} and
+ * {@link SelectionKey#OP_WRITE OP_WRITE}. The selectable channel will be
+ * created by the default {@link SelectorProvider}.
+ *
+ * <p> The given file descriptor is a socket or resource that can be
+ * multiplexed by a {@link java.nio.channels.Selector} for read and write
+ * readiness. Great care is required to coordinate direct use of the file
+ * descriptor with the use of the selectable channel. In particular,
+ * changing the blocking mode or closing the file descriptor without careful
+ * coordination will result in unspecified and unsafe side effects. The
+ * given {@link SelectableChannelCloser SelectableChannelCloser} is invoked to
+ * close the file descriptor and to coordinate the closing when the channel
+ * is registered with a {@code Selector}. </p>
+ *
+ * <p> If there is a security manager set then its
+ * {@link SecurityManager#checkRead(FileDescriptor) checkRead} and
+ * {@link SecurityManager#checkWrite(FileDescriptor) checkWrite} methods
+ * are invoked to check that the caller has permission to both read from and
+ * write to the file descriptor. </p>
+ *
+ * @implNote This method throws {@code UnsupportedOperationException} if
+ * the default {@code SelectorProvider} is not the JDK built-in implementation.
+ *
+ * @param fd
+ * The file descriptor
+ * @param closer
+ * The object to close the channel
+ *
+ * @return The selectable channel
+ *
+ * @throws IllegalArgumentException
+ * If the file descriptor is not {@link FileDescriptor#valid() valid}
+ * @throws SecurityException
+ * If denied by the security manager
+ */
+ public static SelectableChannel readWriteSelectableChannel(FileDescriptor fd,
+ SelectableChannelCloser closer) {
+ Objects.requireNonNull(closer);
+ if (!fd.valid())
+ throw new IllegalArgumentException("file descriptor is not valid");
+
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkRead(fd);
+ sm.checkWrite(fd);
+ }
+
+ SelectorProvider provider = SelectorProvider.provider();
+ if (!(provider instanceof SelectorProviderImpl))
+ throw new UnsupportedOperationException("custom SelectorProvider");
+
+ return new ReadWriteChannelImpl((SelectorProviderImpl)provider, fd, closer);
+ }
+
+ private static final class ReadWriteChannelImpl
+ extends AbstractSelectableChannel implements SelChImpl
+ {
+ private final FileDescriptor fd;
+ private final int fdVal;
+ private final SelectableChannelCloser closer;
+
+ ReadWriteChannelImpl(SelectorProviderImpl provider,
+ FileDescriptor fd,
+ SelectableChannelCloser closer) {
+ super(provider);
+ this.fd = fd;
+ this.fdVal = IOUtil.fdVal(fd);
+ this.closer = closer;
+ }
+
+ @Override
+ public FileDescriptor getFD() {
+ return fd;
+ }
+
+ @Override
+ public int getFDVal() {
+ return fdVal;
+ }
+
+ @Override
+ public int validOps() {
+ return (SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ }
+
+ private boolean translateReadyOps(int ops,
+ int initialOps,
+ SelectionKeyImpl ski) {
+ int intOps = ski.nioInterestOps();
+ int oldOps = ski.nioReadyOps();
+ int newOps = initialOps;
+
+ if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
+ newOps = intOps;
+ ski.nioReadyOps(newOps);
+ return (newOps & ~oldOps) != 0;
+ }
+
+ if (((ops & Net.POLLIN) != 0) &&
+ ((intOps & SelectionKey.OP_READ) != 0))
+ newOps |= SelectionKey.OP_READ;
+
+ if (((ops & Net.POLLOUT) != 0) &&
+ ((intOps & SelectionKey.OP_WRITE) != 0))
+ newOps |= SelectionKey.OP_WRITE;
+
+ ski.nioReadyOps(newOps);
+ return (newOps & ~oldOps) != 0;
+ }
+
+ @Override
+ public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
+ return translateReadyOps(ops, ski.nioReadyOps(), ski);
+ }
+
+ @Override
+ public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
+ return translateReadyOps(ops, 0, ski);
+ }
+
+ @Override
+ public int translateInterestOps(int ops) {
+ int newOps = 0;
+ if ((ops & SelectionKey.OP_READ) != 0)
+ newOps |= Net.POLLIN;
+ if ((ops & SelectionKey.OP_WRITE) != 0)
+ newOps |= Net.POLLOUT;
+ return newOps;
+ }
+
+ @Override
+ protected void implConfigureBlocking(boolean block) throws IOException {
+ IOUtil.configureBlocking(fd, block);
+ }
+
+ @Override
+ protected void implCloseSelectableChannel() throws IOException {
+ closer.implCloseChannel(this);
+ }
+
+ @Override
+ public void kill() throws IOException {
+ closer.implReleaseChannel(this);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.net/share/classes/jdk/nio/package-info.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * Defines JDK-specific {@link java.nio.channels.Channel channel} APIs.
+ *
+ * @since 11
+ */
+
+package jdk.nio;
--- a/src/jdk.net/share/classes/module-info.java Mon Jun 25 08:14:11 2018 -0700
+++ b/src/jdk.net/share/classes/module-info.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -31,5 +31,6 @@
*/
module jdk.net {
exports jdk.net;
+ exports jdk.nio;
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/SHAOptionsBase.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/SHAOptionsBase.java Mon Jun 25 09:48:06 2018 -0700
@@ -74,8 +74,8 @@
* instructions required by the option are not supported.
*/
public static String getWarningForUnsupportedCPU(String optionName) {
- if (Platform.isAArch64() || Platform.isS390x() || Platform.isSparc() ||
- Platform.isX64() || Platform.isX86()) {
+ if (Platform.isAArch64() || Platform.isS390x() || Platform.isSparc()
+ || Platform.isX64() || Platform.isX86() || Platform.isPPC()) {
switch (optionName) {
case SHAOptionsBase.USE_SHA_OPTION:
return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE;
@@ -89,8 +89,8 @@
throw new Error("Unexpected option " + optionName);
}
} else {
- throw new Error("Support for CPUs different fromn AARCH64, S390x, SPARC, and X86 "
- + "is not implemented");
+ throw new Error("Support for CPUs different from AARCH64, S390x,"
+ + " SPARC, X86, and PPC is not implemented");
}
}
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -31,8 +31,8 @@
import jdk.test.lib.cli.predicate.OrPredicate;
/**
- * Generic test case for SHA-related options targeted to non-x86 and
- * non-SPARC CPUs.
+ * Generic test case for SHA-related options targeted to any CPU except
+ * AArch64, S390x, SPARC and X86.
*/
public class GenericTestCaseForOtherCPU extends
SHAOptionsBase.TestCase {
@@ -43,7 +43,8 @@
new OrPredicate(Platform::isS390x,
new OrPredicate(Platform::isSparc,
new OrPredicate(Platform::isPPC,
- new OrPredicate(Platform::isX64, Platform::isX86)))))));
+ new OrPredicate(Platform::isX64,
+ Platform::isX86)))))));
}
@Override
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -37,10 +37,7 @@
public class GenericTestCaseForSupportedCPU extends
SHAOptionsBase.TestCase {
public GenericTestCaseForSupportedCPU(String optionName) {
- super(optionName,
- new AndPredicate(
- new OrPredicate(Platform::isSparc, Platform::isAArch64),
- SHAOptionsBase.getPredicateForOption(optionName)));
+ super(optionName, SHAOptionsBase.getPredicateForOption(optionName));
}
@Override
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -33,25 +33,22 @@
import jdk.test.lib.cli.predicate.OrPredicate;
/**
- * Test case specific to UseSHA*Intrinsics options targeted to SPARC and AArch64
- * CPUs which don't support required instruction, but support other SHA-related
+ * Test case specific to UseSHA*Intrinsics options targeted to CPUs
+ * which don't support required instruction, but support other SHA-related
* instructions.
*
- * For example, CPU support sha1 instruction, but don't support sha256 or
+ * For example, CPU supports sha1 instruction, but doesn't support sha256 or
* sha512.
*/
public class UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU
extends SHAOptionsBase.TestCase {
public UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU(
String optionName) {
- // execute test case on SPARC CPU that support any sha* instructions,
+ // execute test case on CPU that supports any sha* instructions,
// but does not support sha* instruction required by the tested option.
super(optionName, new AndPredicate(
- new OrPredicate(Platform::isSparc, Platform::isAArch64),
- new AndPredicate(
- IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE,
- new NotPredicate(SHAOptionsBase.getPredicateForOption(
- optionName)))));
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE,
+ new NotPredicate(SHAOptionsBase.getPredicateForOption(optionName))));
}
@Override
protected void verifyWarnings() throws Throwable {
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedCPU.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedCPU.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -33,15 +33,13 @@
import jdk.test.lib.cli.predicate.OrPredicate;
/**
- * UseSHA specific test case targeted to SPARC and AArch64 CPUs which
- * support any sha* instruction.
+ * UseSHA specific test case targeted to CPUs which support any sha* instruction.
*/
public class UseSHASpecificTestCaseForSupportedCPU
extends SHAOptionsBase.TestCase {
public UseSHASpecificTestCaseForSupportedCPU(String optionName) {
- super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(
- new OrPredicate(Platform::isSparc, Platform::isAArch64),
- IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE));
+ super(SHAOptionsBase.USE_SHA_OPTION,
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE);
Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
String.format("Test case should be used for '%s' option only.",
--- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedCPU.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedCPU.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -34,16 +34,14 @@
import jdk.test.lib.cli.predicate.OrPredicate;
/**
- * UseSHA specific test case targeted to SPARC and AArch64 CPUs which don't
- * support all sha* instructions./
+ * UseSHA specific test case targeted to CPUs which don't support all
+ * sha* instructions.
*/
public class UseSHASpecificTestCaseForUnsupportedCPU
extends SHAOptionsBase.TestCase {
public UseSHASpecificTestCaseForUnsupportedCPU(String optionName) {
- super(SHAOptionsBase.USE_SHA_OPTION, new AndPredicate(
- new OrPredicate(Platform::isSparc, Platform::isAArch64),
- new NotPredicate(
- IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE)));
+ super(SHAOptionsBase.USE_SHA_OPTION, new NotPredicate(
+ IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE));
Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION,
"Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION
--- a/test/hotspot/jtreg/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/jsr292/methodHandleExceptions/TestAMEnotNPE.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -23,8 +23,8 @@
/**
* @test
- * @bug 8025260 8016839
- * @summary Ensure that AbstractMethodError and IllegalAccessError are thrown appropriately, not NullPointerException
+ * @bug 8025260 8016839 8046171
+ * @summary Ensure that correct exceptions are thrown, not NullPointerException
* @modules java.base/jdk.internal.org.objectweb.asm
* @library / .
*
@@ -34,6 +34,13 @@
* @run main/othervm -Xcomp compiler.jsr292.methodHandleExceptions.TestAMEnotNPE
*/
+// Since this test was written the specification for interface method selection has been
+// revised (JEP 181 - Nestmates) so that private methods are never selected, as they never
+// override any inherited method. So where a private method was previously selected
+// and then resulted in IllegalAccessError, the private method is skipped and the invocation
+// will either succeed or fail based on what other implementations are found in the inheritance
+// hierarchy. This is explained for each test below.
+
package compiler.jsr292.methodHandleExceptions;
import p.Dok;
@@ -91,43 +98,41 @@
}
}
- try {
- System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL");
- tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"),
- "p.D extends p.F (p.F implements p.I, FINAL public m), private m",
- IllegalAccessError.class, "pD_ext_pF");
- // We'll take either a VerifyError (pre 2013-11-30)
- // or an IllegalAccessError (post 2013-11-22)
- } catch (VerifyError ve) {
- System.out.println("Saw expected VerifyError " + ve);
- }
+ System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.F, p.F.m FINAL");
+ System.out.println(" - should invoke p.F.m as private p.D.m is skipped for selection");
+ tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/F"),
+ "p.D extends p.F (p.F implements p.I, FINAL public m), private m",
+ null /* should succeed */, "pD_ext_pF");
System.out.println();
System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m, p.D extends p.E");
+ System.out.println(" - should invoke p.E.m as private p.D.m is skipped for selection");
tryAndCheckThrown(lt, bytesForDprivateSubWhat("p/E"),
- "p.D extends p.E (p.E implements p.I, public m), private m",
- IllegalAccessError.class, "pD_ext_pE");
+ "p.D extends p.E (p.E implements p.I, public m), private m",
+ null /* should succeed */, "pD_ext_pE");
System.out.println("TRYING p.D.m ABSTRACT interface-invoked as p.I.m");
tryAndCheckThrown(lt, bytesForD(),
- "D extends abstract C, no m",
- AbstractMethodError.class, "pD_ext_pC");
+ "D extends abstract C, no m",
+ AbstractMethodError.class, "pD_ext_pC");
System.out.println("TRYING q.D.m PACKAGE interface-invoked as p.I.m");
tryAndCheckThrown(lt, "q.D", bytesForDsomeAccess("q/D", 0),
- "q.D implements p.I, protected m", IllegalAccessError.class,
- "qD_m_pp_imp_pI");
+ "q.D implements p.I, protected m",
+ IllegalAccessError.class, "qD_m_pp_imp_pI");
// Note jar file name is used in the plural-arg case.
System.out.println("TRYING p.D.m PRIVATE interface-invoked as p.I.m");
+ System.out.println(" - should invoke p.I.m as private p.D.m is skipped for selection");
tryAndCheckThrown(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
- "p.D implements p.I, private m",
- IllegalAccessError.class, "pD_m_pri_imp_pI");
+ "p.D implements p.I, private m",
+ null /* should succeed */, "pD_m_pri_imp_pI");
// Plural-arg test.
System.out.println("TRYING p.D.m PRIVATE MANY ARG interface-invoked as p.I.m");
+ System.out.println(" - should invoke p.I.m as private p.D.m is skipped for selection");
tryAndCheckThrownMany(lt, bytesForDsomeAccess("p/D", ACC_PRIVATE),
- "p.D implements p.I, private m", IllegalAccessError.class);
+ "p.D implements p.I, private m", null /* should succeed */);
if (lt.size() > 0) {
System.out.flush();
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
public class ResolvedJavaTypeResolveConcreteMethodTest {
public final MetaAccessProvider metaAccess;
@@ -117,8 +118,9 @@
ResolvedJavaType c = getType(C.class);
ResolvedJavaMethod priv = getMethod(a, "priv");
- assertNull(a.resolveConcreteMethod(priv, c));
- assertNull(b.resolveConcreteMethod(priv, c));
+ // nestmates have access to private methods
+ assertNotNull(a.resolveConcreteMethod(priv, c));
+ assertNotNull(b.resolveConcreteMethod(priv, c));
}
@Test
--- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertNotNull;
public class ResolvedJavaTypeResolveMethodTest {
public final MetaAccessProvider metaAccess;
@@ -117,8 +118,9 @@
ResolvedJavaType c = getType(C.class);
ResolvedJavaMethod priv = getMethod(a, "priv");
- assertNull(a.resolveMethod(priv, c));
- assertNull(b.resolveMethod(priv, c));
+ // nestmates have access to private methods
+ assertNotNull(a.resolveMethod(priv, c));
+ assertNotNull(b.resolveMethod(priv, c));
}
@Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/NestmatesJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * Utility class for invoking methods and constructors and accessing fields
+ * via JNI.
+ */
+public class NestmatesJNI {
+
+ static {
+ System.loadLibrary("NestmatesJNI");
+ }
+
+ public static native void callVoidVoid(Object target, String definingClassName, String methodName, boolean virtual);
+
+ public static native String callStringVoid(Object target, String definingClassName, String methodName, boolean virtual);
+
+ public static native void callStaticVoidVoid(String definingClassName, String methodName);
+
+ public static Object newInstance(String definingClassName, String sig, Object outerThis) {
+ return newInstance0(definingClassName, "<init>", sig, outerThis);
+ }
+
+ private static native Object newInstance0(String definingClassName, String method_name, String sig, Object outerThis);
+
+ public static native int getIntField(Object target, String definingClassName, String fieldName);
+
+ public static native void setIntField(Object target, String definingClassName, String fieldName, int newVal);
+
+ public static native int getStaticIntField(String definingClassName, String fieldName);
+
+ public static native void setStaticIntField(String definingClassName, String fieldName, int newVal);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/BadNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// NestHost attribute does not refer to a class
+
+class NestmateAttributeHolder$BadNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "NestmateAttributeHolder.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "NestmateAttributeHolder$BadNestHost"; // #13
+ Utf8 "BadNestHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "NestmateAttributeHolder"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 2;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x000A; // not a class index
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class NestmateAttributeHolder$BadNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/BadNestHostLength.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class BadNestHostLength {
+ }
+}
+*/
+
+// Declare NestHost attribute as variable-length > 2
+class NestmateAttributeHolder$BadNestHostLength {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "NestmateAttributeHolder.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "NestmateAttributeHolder$BadNestHostLength"; // #13
+ Utf8 "BadNestHostLength"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "NestmateAttributeHolder"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 2;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ [] {
+ #11 #11 #11 #11;
+ }
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class NestmateAttributeHolder$BadNestHostLength
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/BadNestMembersEntry.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// NestMembers attribute refers to non-class entry
+
+class BadNestMembersEntry {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ class #17; // #4
+ Utf8 "TwoNestHost"; // #5
+ Utf8 "InnerClasses"; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "BadNestMembersEntry.java"; // #12
+ Utf8 "NestMembers"; // #13
+ NameAndType #7 #8; // #14
+ Utf8 "BadNestMembersEntry"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "BadNestMembersEntry$TwoNestHost"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestMembers
+ 0x00010009; // not a class index
+ } // end NestMembers
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class BadNestMembersEntry
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/BadNestMembersLength.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// NestMembers attribute has wrong count for number of nestmates
+
+class BadNestMembersLength {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ class #17; // #4
+ Utf8 "TwoNestHost"; // #5
+ Utf8 "InnerClasses"; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "BadNestMembersLength.java"; // #12
+ Utf8 "NestMembers"; // #13
+ NameAndType #7 #8; // #14
+ Utf8 "BadNestMembersLength"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "BadNestMembersLength$TwoNestHost"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestMembers
+ 0x00000004; // bad length
+ } // end NestMembers
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class BadNestMembersLength
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/ConflictingAttributesInNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// Add NestHost attribute to nest-host class - conflicting attributes
+
+class ConflictingAttributesInNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ class #17; // #4
+ Utf8 "TwoNestHost"; // #5
+ Utf8 "InnerClasses"; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "ConflictingAttributesInNestHost.java"; // #12
+ Utf8 "NestMembers"; // #13
+ NameAndType #7 #8; // #14
+ Utf8 "ConflictingAttributesInNestHost"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "ConflictingAttributesInNestHost$TwoNestHost"; // #17
+ Utf8 "NestHost"; // #18
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestMembers
+ 0x00010004;
+ } // end NestMembers
+ ;
+ // conflict - can't be a member of a nest and have nest members
+ Attr(#18) { // NestHost
+ 0x0003; // #3 is Object
+ } // end NestHost
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class ConflictingAttributesInNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/ConflictingAttributesInNestMember.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+class NestmateAttributeHolder$ConflictingAttributesInNestMember {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "NestmateAttributeHolder.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "NestmateAttributeHolder$ConflictingAttributesInNestMember"; // #13
+ Utf8 "ConflictingAttributesInNestMember"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "NestmateAttributeHolder"; // #17
+ Utf8 "NestMembers"; // #18
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 2;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x000B;
+ } // end NestHost
+ ;
+ // conflict: can't have nest members when you are a member of a nest
+ Attr(#18) { // NestMembers
+ 0x00010004;
+ } // end NestMembers
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class NestmateAttributeHolder$ConflictingAttributesInNestMember
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/TestFinalMethodOverride.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test nestmate checks are no longer used when check_final_method_override is executed during parsing
+ * @run main TestFinalMethodOverride
+ */
+
+// The check_final_method_override function in ClassfileParser uses an
+// accessability check to see if the subclass method overrides a same-named
+// superclass method. This would result in a nestmate access check if the
+// super class method is private, which in turn could lead to classloading
+// and possibly exceptions and cause havoc in the classfile parsing process.
+// To fix that we added a check for whether the super class method is private,
+// and if so, we skip the override check as by definition you can't override
+// a private method.
+//
+// This test simply sets up the case where a public subclass method has the
+// same signature as a private superclass method - the case we now skip when
+// doing check_final_method_override. The test should trivially complete
+// normally.
+
+public class TestFinalMethodOverride {
+
+ public static class Super {
+ private final void theMethod() {}
+ }
+
+ public static class Inner extends Super {
+ // define our own theMethod
+ public void theMethod() {}
+ }
+
+ public static void main(String[] args) {
+ Inner i = new Inner();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/TestNestmateAttributes.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @bug 8046171
+ * @summary Test incorrect use of Nestmate related attributes
+ * @compile TwoNestHost.jcod
+ * TwoNestMembers.jcod
+ * ConflictingAttributesInNestHost.jcod
+ * ConflictingAttributesInNestMember.jcod
+ * BadNestMembersLength.jcod
+ * BadNestMembersEntry.jcod
+ * BadNestHost.jcod
+ * BadNestHostLength.jcod
+ * @run main TestNestmateAttributes
+ */
+
+public class TestNestmateAttributes {
+ public static void main(String args[]) throws Throwable {
+ String[] badClasses = new String[] {
+ "NestmateAttributeHolder$TwoNestHost",
+ "NestmateAttributeHolder",
+ "ConflictingAttributesInNestHost",
+ "NestmateAttributeHolder$ConflictingAttributesInNestMember",
+ "BadNestMembersLength",
+ "BadNestMembersEntry",
+ "NestmateAttributeHolder$BadNestHost",
+ "NestmateAttributeHolder$BadNestHostLength",
+ };
+
+ String[] messages = new String[] {
+ "Multiple NestHost attributes in class file",
+ "Multiple NestMembers attributes in class file",
+ "Conflicting NestMembers and NestHost attributes",
+ "Conflicting NestHost and NestMembers attributes",
+ "Wrong NestMembers attribute length",
+ "Nest member class_info_index 9 has bad constant type",
+ "Nest-host class_info_index 10 has bad constant type",
+ "Wrong NestHost attribute length",
+ };
+
+ for (int i = 0; i < badClasses.length; i++ ) {
+ try {
+ Class c = Class.forName(badClasses[i]);
+ throw new Error("Missing ClassFormatError: " + messages[i]);
+ }
+ catch (ClassFormatError expected) {
+ if (!expected.getMessage().contains(messages[i]))
+ throw new Error("Wrong ClassFormatError message: \"" +
+ expected.getMessage() + "\" does not contain \"" +
+ messages[i] + "\"");
+ System.out.println("OK - got expected exception: " + expected);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/TwoNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// Add second NestHost attribute - should fail parsing
+class NestmateAttributeHolder$TwoNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "NestmateAttributeHolder.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "NestmateAttributeHolder$TwoNestHost"; // #13
+ Utf8 "TwoNestHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "NestmateAttributeHolder"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 2;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x000B;
+ } // end NestHost
+ ;
+ Attr(#10) { // NestHost
+ 0x000B;
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class NestmateAttributeHolder$TwoNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/classFileParsing/TwoNestMembers.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Source: NestmateAttributeHolder.java
+
+public class NestmateAttributeHolder {
+ public static class TwoNestHost {
+ }
+}
+*/
+
+// Add second NestMembers attribute - should fail parsing
+
+class NestmateAttributeHolder {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ class #17; // #4
+ Utf8 "TwoNestHost"; // #5
+ Utf8 "InnerClasses"; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "NestmateAttributeHolder.java"; // #12
+ Utf8 "NestMembers"; // #13
+ NameAndType #7 #8; // #14
+ Utf8 "NestmateAttributeHolder"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "NestmateAttributeHolder$TwoNestHost"; // #17
+ } // Constant Pool
+
+ 0x0021; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 1;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestMembers
+ 0x00010004;
+ } // end NestMembers
+ ;
+ Attr(#13) { // NestMembers
+ 0x00010004;
+ } // end NestMembers
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class NestmateAttributeHolder
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/legacy/TestPrivateLookup.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test that private Lookup works for both nestmate-enabled classes
+ * and legacy classes
+ * @compile TestPrivateLookup.java
+ * @run main TestPrivateLookup
+ * @compile -source 10 -target 10 TestPrivateLookup.java
+ * @run main TestPrivateLookup noNestmates
+ */
+
+// Need the explicit first @compile above so that jtreg forces recompilation
+// with latest version. Otherwise compile-on-demand sees the JDK 10 version
+// and assumes it is up to date and then runs the test using that version -
+// which fails.
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestPrivateLookup {
+
+ static boolean compiledForNestmates;
+
+ static class C {
+ static class D {
+ private void m() { }
+ }
+
+ static void test() throws Throwable {
+ MethodType M_T = MethodType.methodType(void.class);
+ // Direct lookup from C
+ Lookup l = lookup();
+ try {
+ MethodHandle mh = l.findVirtual(D.class, "m", M_T);
+ if (compiledForNestmates) {
+ System.out.println("Lookup of D.m from C succeeded as expected with nestmates");
+ }
+ else {
+ throw new Error("Unexpected success when not compiled for nestmates!");
+ }
+ }
+ catch (IllegalAccessException iae) {
+ if (!compiledForNestmates) {
+ System.out.println("Lookup of D.m from C failed as expected without nestmates");
+ }
+ else {
+ throw new Error("Unexpected failure with nestmates", iae);
+ }
+ }
+ // switch lookup class to D
+ l = l.in(D.class);
+ try {
+ MethodHandle mh = l.findVirtual(D.class, "m", M_T);
+ System.out.println("Lookup of D.m from D succeeded as expected" +
+ " with" + (compiledForNestmates ? "" : "out") +
+ " nestmates");
+ }
+ catch (IllegalAccessException iae) {
+ throw new Error("Lookup of D.m from D failed", iae);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+
+ // If there's no nesthost attribute A.getNestHost() == A
+ compiledForNestmates = C.D.class.getNestHost() == TestPrivateLookup.class;
+ // sanity check
+ boolean expectingNestmates = args.length == 0;
+
+ if (compiledForNestmates && !expectingNestmates) {
+ throw new Error("Test is being run incorrectly: " +
+ "nestmates are being used but not expected");
+ }
+ if (expectingNestmates && !compiledForNestmates) {
+ throw new Error("Test is being run incorrectly: " +
+ "nestmates are expected but not being used");
+ }
+ System.out.println("Testing with" + (expectingNestmates ? "" : "out") +
+ " nestmates");
+
+ C.test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/libNestmatesJNI.c Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+#include <jni.h>
+
+// boolean flag for static versus non-static
+#define STATIC 1
+#define NON_STATIC 0
+
+// Helper methods to get class/method/field IDs
+
+static void getClassID(JNIEnv *env,
+ jstring defining_class_name,
+ jclass* clazz) {
+ const char* name = (*env)->GetStringUTFChars(env, defining_class_name, NULL);
+ if (name != NULL) {
+ *clazz = (*env)->FindClass(env, name);
+ (*env)->ReleaseStringUTFChars(env, defining_class_name, name);
+ }
+}
+
+static void getClassAndMethodID(JNIEnv *env,
+ int is_static,
+ jstring defining_class_name,
+ jstring method_name,
+ const char* sig,
+ jmethodID* m_id, jclass* clazz) {
+ getClassID(env, defining_class_name, clazz);
+ if (*clazz != NULL) {
+ const char* name = (*env)->GetStringUTFChars(env, method_name, NULL);
+ if (name != NULL) {
+ if (is_static) {
+ *m_id = (*env)->GetStaticMethodID(env, *clazz, name, sig);
+ } else {
+ *m_id = (*env)->GetMethodID(env, *clazz, name, sig);
+ }
+ (*env)->ReleaseStringUTFChars(env, method_name, name);
+ }
+ }
+}
+
+static void getClassAndFieldID(JNIEnv *env,
+ int is_static,
+ jstring defining_class_name,
+ jstring field_name,
+ const char* sig,
+ jfieldID* m_id, jclass* clazz) {
+ getClassID(env, defining_class_name, clazz);
+ if (*clazz != NULL) {
+ const char* name = (*env)->GetStringUTFChars(env, field_name, NULL);
+ if (name != NULL) {
+ if (is_static) {
+ *m_id = (*env)->GetStaticFieldID(env, *clazz, name, sig);
+ } else {
+ *m_id = (*env)->GetFieldID(env, *clazz, name, sig);
+ }
+ (*env)->ReleaseStringUTFChars(env, field_name, name);
+ }
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_NestmatesJNI_callVoidVoid(JNIEnv *env, jclass unused,
+ jobject target,
+ jstring defining_class_name,
+ jstring method_name,
+ jboolean virtual) {
+
+ // Lookup "void method_name()" in defining_class_name, and if it exists
+ // call target.method_name() using a virtual or non-virtual invocation
+
+ jmethodID m_id = NULL;
+ jclass clazz = NULL;
+ getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name,
+ "()V", &m_id, &clazz);
+ if (m_id != NULL && clazz != NULL) {
+ if (!virtual) {
+ (*env)->CallNonvirtualVoidMethod(env, target, clazz, m_id);
+ } else {
+ (*env)->CallVoidMethod(env, target, m_id);
+ }
+ }
+}
+
+JNIEXPORT jobject JNICALL
+Java_NestmatesJNI_callStringVoid(JNIEnv *env, jclass unused,
+ jobject target,
+ jstring defining_class_name,
+ jstring method_name,
+ jboolean virtual) {
+
+ // Lookup "String method_name()" in defining_class_name, and if it exists
+ // call target.method_name() using a virtual or non-virtual invocation
+
+ jmethodID m_id = NULL;
+ jclass clazz = NULL;
+ getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name,
+ "()Ljava/lang/String;", &m_id, &clazz);
+ if (m_id != NULL && clazz != NULL) {
+ if (!virtual) {
+ return (*env)->CallNonvirtualObjectMethod(env, target, clazz, m_id);
+ } else {
+ return (*env)->CallObjectMethod(env, target, m_id);
+ }
+ }
+ return NULL;
+}
+
+JNIEXPORT jobject JNICALL
+Java_NestmatesJNI_newInstance0(JNIEnv *env, jclass unused,
+ jstring defining_class_name,
+ jstring method_name,
+ jstring sig,
+ jobject outerThis) {
+
+ // Lookup the no-user-arg constructor in defining_class_name using sig,
+ // and use it to create an instance of the class, and return it. For
+ // inner classes we need an outerThis reference to pass to the constructor.
+
+ jmethodID m_id = NULL;
+ jclass clazz = NULL;
+ const char* _sig = (*env)->GetStringUTFChars(env, sig, NULL);
+ getClassAndMethodID(env, NON_STATIC, defining_class_name, method_name,
+ _sig, &m_id, &clazz);
+ (*env)->ReleaseStringUTFChars(env, sig, _sig);
+ if (m_id != NULL && clazz != NULL) {
+ return (*env)->NewObject(env, clazz, m_id, outerThis);
+ }
+ return NULL;
+}
+
+JNIEXPORT void JNICALL
+Java_NestmatesJNI_callStaticVoidVoid(JNIEnv *env, jclass unused,
+ jstring defining_class_name,
+ jstring method_name) {
+
+ // Lookup "static void method_name()" in defining_class_name, and if it exists
+ // invoke it.
+
+ jmethodID m_id = NULL;
+ jclass clazz = NULL;
+ getClassAndMethodID(env, STATIC, defining_class_name, method_name,
+ "()V", &m_id, &clazz);
+ if (m_id != NULL && clazz != NULL) {
+ (*env)->CallStaticVoidMethod(env, clazz, m_id);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_NestmatesJNI_getIntField(JNIEnv *env, jclass unused,
+ jobject target,
+ jstring defining_class_name,
+ jstring field_name) {
+
+ // Lookup field field_name in defining_class_name, and if it exists
+ // return its value.
+
+ jfieldID f_id = NULL;
+ jclass clazz = NULL;
+ getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name,
+ "I", &f_id, &clazz);
+ if (f_id != NULL && clazz != NULL) {
+ return (*env)->GetIntField(env, target, f_id);
+ }
+ return -1;
+}
+
+JNIEXPORT void JNICALL
+Java_NestmatesJNI_setIntField(JNIEnv *env, jclass unused,
+ jobject target,
+ jstring defining_class_name,
+ jstring field_name,
+ jint newVal) {
+
+ // Lookup field field_name in defining_class_name, and if it exists
+ // set it to newVal.
+
+ jfieldID f_id = NULL;
+ jclass clazz = NULL;
+ getClassAndFieldID(env, NON_STATIC, defining_class_name, field_name,
+ "I", &f_id, &clazz);
+ if (f_id != NULL && clazz != NULL) {
+ (*env)->SetIntField(env, target, f_id, newVal);
+ }
+}
+
+JNIEXPORT jint JNICALL
+Java_NestmatesJNI_getStaticIntField(JNIEnv *env, jclass unused,
+ jstring defining_class_name,
+ jstring field_name) {
+
+ // Lookup field field_name in defining_class_name, and if it exists
+ // return its value.
+
+ jfieldID f_id = NULL;
+ jclass clazz = NULL;
+ getClassAndFieldID(env, STATIC, defining_class_name, field_name,
+ "I", &f_id, &clazz);
+ if (f_id != NULL && clazz != NULL) {
+ return (*env)->GetStaticIntField(env, clazz, f_id);
+ }
+ return -1;
+}
+
+JNIEXPORT void JNICALL
+Java_NestmatesJNI_setStaticIntField(JNIEnv *env, jclass unused,
+ jstring defining_class_name,
+ jstring field_name,
+ jint newVal) {
+
+ // Lookup field field_name in defining_class_name, and if it exists
+ // set it to newVal.
+
+ jfieldID f_id = NULL;
+ jclass clazz = NULL;
+ getClassAndFieldID(env, STATIC, defining_class_name, field_name,
+ "I", &f_id, &clazz);
+ if (f_id != NULL && clazz != NULL) {
+ (*env)->SetStaticIntField(env, clazz, f_id, newVal);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/CallerMissingHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-existent class
+
+class TestNestmateMembership$CallerMissingHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Field #38 #39; // #1
+ String #40; // #2
+ Method #41 #42; // #3
+ Method #9 #43; // #4
+ Method #11 #43; // #5
+ Method #16 #44; // #6
+ String #45; // #7
+ Field #15 #46; // #8
+ class #47; // #9
+ Method #9 #44; // #10
+ class #50; // #11
+ Method #11 #44; // #12
+ Field #9 #52; // #13
+ Field #11 #52; // #14
+ class #53; // #15
+ class #55; // #16
+ Utf8 "msg"; // #17
+ Utf8 "Ljava/lang/String;"; // #18
+ Utf8 "f"; // #19
+ Utf8 "I"; // #20
+ Utf8 "m"; // #21
+ Utf8 "()V"; // #22
+ Utf8 "Code"; // #23
+ Utf8 "LineNumberTable"; // #24
+ Utf8 "invokeTarget"; // #25
+ Utf8 "invokeTargetMissingHost"; // #26
+ Utf8 "<init>"; // #27
+ Utf8 "newTarget"; // #28
+ Utf8 "newTargetMissingHost"; // #29
+ Utf8 "getFieldTarget"; // #30
+ Utf8 "getFieldTargetMissingHost"; // #31
+ Utf8 "putFieldTarget"; // #32
+ Utf8 "putFieldTargetMissingHost"; // #33
+ Utf8 "SourceFile"; // #34
+ Utf8 "TestNestmateMembership.java"; // #35
+ Utf8 "NestHost"; // #36
+ class #56; // #37
+ class #57; // #38
+ NameAndType #58 #59; // #39
+ Utf8 "CallerMissingHost.m() - java version"; // #40
+ class #60; // #41
+ NameAndType #61 #62; // #42
+ NameAndType #21 #22; // #43
+ NameAndType #27 #22; // #44
+ Utf8 "NoCallerMissingHost"; // #45
+ NameAndType #17 #18; // #46
+ Utf8 "TestNestmateMembership$Target"; // #47
+ Utf8 "Target"; // #48
+ Utf8 "InnerClasses"; // #49
+ Utf8 "TestNestmateMembership$TargetMissingHost"; // #50
+ Utf8 "TargetMissingHost"; // #51
+ NameAndType #19 #20; // #52
+ Utf8 "TestNestmateMembership$CallerMissingHost"; // #53
+ Utf8 "CallerMissingHost"; // #54
+ Utf8 "java/lang/Object"; // #55
+ Utf8 "TestNestmateMembership"; // #56
+ Utf8 "java/lang/System"; // #57
+ Utf8 "out"; // #58
+ Utf8 "Ljava/io/PrintStream;"; // #59
+ Utf8 "java/io/PrintStream"; // #60
+ Utf8 "println"; // #61
+ Utf8 "(Ljava/lang/String;)V"; // #62
+ class #45; // added - #63
+ } // Constant Pool
+
+ 0x0020; // access
+ #15;// this_cpx
+ #16;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #17; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x000A; // access
+ #21; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200011202B60003;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 209;
+ 8 210;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #25; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80004B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 212;
+ 3 213;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #26; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 215;
+ 3 216;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #27; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB700062A1207B5;
+ 0x0008B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 220;
+ 4 204;
+ 10 220;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000959B7000A4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 223;
+ 8 224;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #29; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000B59B7000C4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 226;
+ 8 227;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #30; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000D3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 234;
+ 4 235;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #31; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000E3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 237;
+ 4 238;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #32; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000DB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 240;
+ 5 241;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #33; // name_cpx
+ #22; // sig_cpx
+ [] { // Attributes
+ Attr(#23) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000EB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#24) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 243;
+ 5 244;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#34) { // SourceFile
+ #35;
+ } // end SourceFile
+ ;
+ Attr(#36) { // NestHost
+ 0x003F; // modified - #63
+ } // end NestHost
+ ;
+ Attr(#49) { // InnerClasses
+ [] { // InnerClasses
+ #9 #37 #48 8;
+ #11 #37 #51 8;
+ #15 #37 #54 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$CallerMissingHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/CallerNoHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute deleted
+
+class TestNestmateMembership$CallerNoHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Field #34 #35; // #1
+ String #36; // #2
+ Method #37 #38; // #3
+ Method #7 #39; // #4
+ Method #9 #39; // #5
+ Method #14 #40; // #6
+ class #41; // #7
+ Method #7 #40; // #8
+ class #44; // #9
+ Method #9 #40; // #10
+ Field #7 #46; // #11
+ Field #9 #46; // #12
+ class #47; // #13
+ class #49; // #14
+ Utf8 "f"; // #15
+ Utf8 "I"; // #16
+ Utf8 "m"; // #17
+ Utf8 "()V"; // #18
+ Utf8 "Code"; // #19
+ Utf8 "LineNumberTable"; // #20
+ Utf8 "invokeTarget"; // #21
+ Utf8 "invokeTargetNoHost"; // #22
+ Utf8 "<init>"; // #23
+ Utf8 "newTarget"; // #24
+ Utf8 "newTargetNoHost"; // #25
+ Utf8 "getFieldTarget"; // #26
+ Utf8 "getFieldTargetNoHost"; // #27
+ Utf8 "putFieldTarget"; // #28
+ Utf8 "putFieldTargetNoHost"; // #29
+ Utf8 "SourceFile"; // #30
+ Utf8 "TestNestmateMembership.java"; // #31
+ Utf8 "NestHost"; // #32
+ class #50; // #33
+ class #51; // #34
+ NameAndType #52 #53; // #35
+ Utf8 "CallerNoHost.m() - java version"; // #36
+ class #54; // #37
+ NameAndType #55 #56; // #38
+ NameAndType #17 #18; // #39
+ NameAndType #23 #18; // #40
+ Utf8 "TestNestmateMembership$Target"; // #41
+ Utf8 "Target"; // #42
+ Utf8 "InnerClasses"; // #43
+ Utf8 "TestNestmateMembership$TargetNoHost"; // #44
+ Utf8 "TargetNoHost"; // #45
+ NameAndType #15 #16; // #46
+ Utf8 "TestNestmateMembership$CallerNoHost"; // #47
+ Utf8 "CallerNoHost"; // #48
+ Utf8 "java/lang/Object"; // #49
+ Utf8 "TestNestmateMembership"; // #50
+ Utf8 "java/lang/System"; // #51
+ Utf8 "out"; // #52
+ Utf8 "Ljava/io/PrintStream;"; // #53
+ Utf8 "java/io/PrintStream"; // #54
+ Utf8 "println"; // #55
+ Utf8 "(Ljava/lang/String;)V"; // #56
+ } // Constant Pool
+
+ 0x0020; // access
+ #13;// this_cpx
+ #14;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #15; // name_cpx
+ #16; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x000A; // access
+ #17; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200011202B60003;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 163;
+ 8 164;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80004B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 166;
+ 3 167;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #22; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 169;
+ 3 170;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #23; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 174;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #24; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000759B700084B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 177;
+ 8 178;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #25; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000959B7000A4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 180;
+ 8 181;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #26; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000B3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 188;
+ 4 189;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #27; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000C3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 191;
+ 4 192;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 195;
+ 5 196;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #29; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000CB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 198;
+ 5 199;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#30) { // SourceFile
+ #31;
+ } // end SourceFile
+ ;
+ Attr(#43) { // InnerClasses
+ [] { // InnerClasses
+ #7 #33 #42 8;
+ #9 #33 #45 8;
+ #13 #33 #48 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$CallerNoHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/CallerNotInstanceHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-instance class
+
+class TestNestmateMembership$CallerNotInstanceHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Field #36 #37; // #1
+ String #38; // #2
+ Method #39 #40; // #3
+ Method #7 #41; // #4
+ Method #9 #41; // #5
+ Method #14 #42; // #6
+ class #43; // #7
+ Method #7 #42; // #8
+ class #46; // #9
+ Method #9 #42; // #10
+ Field #7 #48; // #11
+ Field #9 #48; // #12
+ class #49; // #13
+ class #51; // #14
+ Utf8 "oa"; // #15
+ Utf8 "[LInvalidNestHost;"; // #16
+ Utf8 "f"; // #17
+ Utf8 "I"; // #18
+ Utf8 "m"; // #19
+ Utf8 "()V"; // #20
+ Utf8 "Code"; // #21
+ Utf8 "LineNumberTable"; // #22
+ Utf8 "invokeTarget"; // #23
+ Utf8 "invokeTargetNotInstanceHost"; // #24
+ Utf8 "<init>"; // #25
+ Utf8 "newTarget"; // #26
+ Utf8 "newTargetNotInstanceHost"; // #27
+ Utf8 "getFieldTarget"; // #28
+ Utf8 "getFieldTargetNotInstanceHost"; // #29
+ Utf8 "putFieldTarget"; // #30
+ Utf8 "putFieldTargetNotInstanceHost"; // #31
+ Utf8 "SourceFile"; // #32
+ Utf8 "TestNestmateMembership.java"; // #33
+ Utf8 "NestHost"; // #34
+ class #52; // #35
+ class #53; // #36
+ NameAndType #54 #55; // #37
+ Utf8 "CallerNotInstanceHost.m() - java version"; // #38
+ class #56; // #39
+ NameAndType #57 #58; // #40
+ NameAndType #19 #20; // #41
+ NameAndType #25 #20; // #42
+ Utf8 "TestNestmateMembership$Target"; // #43
+ Utf8 "Target"; // #44
+ Utf8 "InnerClasses"; // #45
+ Utf8 "TestNestmateMembership$TargetNotInstanceHost"; // #46
+ Utf8 "TargetNotInstanceHost"; // #47
+ NameAndType #17 #18; // #48
+ Utf8 "TestNestmateMembership$CallerNotInstanceHost"; // #49
+ Utf8 "CallerNotInstanceHost"; // #50
+ Utf8 "java/lang/Object"; // #51
+ Utf8 "TestNestmateMembership"; // #52
+ Utf8 "java/lang/System"; // #53
+ Utf8 "out"; // #54
+ Utf8 "Ljava/io/PrintStream;"; // #55
+ Utf8 "java/io/PrintStream"; // #56
+ Utf8 "println"; // #57
+ Utf8 "(Ljava/lang/String;)V"; // #58
+ class #16; // Added - #59
+ } // Constant Pool
+
+ 0x0020; // access
+ #13;// this_cpx
+ #14;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #15; // name_cpx
+ #16; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #17; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x000A; // access
+ #19; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200011202B60003;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 254;
+ 8 255;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #23; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80004B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 257;
+ 3 258;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #24; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 260;
+ 3 261;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #25; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 265;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #26; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000759B700084B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 268;
+ 8 269;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #27; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000959B7000A4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 271;
+ 8 272;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000B3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 279;
+ 4 280;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #29; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000C3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 282;
+ 4 283;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #30; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 285;
+ 5 286;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #31; // name_cpx
+ #20; // sig_cpx
+ [] { // Attributes
+ Attr(#21) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000CB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#22) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 288;
+ 5 289;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#32) { // SourceFile
+ #33;
+ } // end SourceFile
+ ;
+ Attr(#34) { // NestHost
+ 0x003B; // modified #59
+ } // end NestHost
+ ;
+ Attr(#45) { // InnerClasses
+ [] { // InnerClasses
+ #7 #35 #44 8;
+ #9 #35 #47 8;
+ #13 #35 #50 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$CallerNotInstanceHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/CallerNotOurHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with no nest
+
+class TestNestmateMembership$CallerNotOurHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Field #34 #35; // #1
+ String #36; // #2
+ Method #37 #38; // #3
+ Method #7 #39; // #4
+ Method #9 #39; // #5
+ Method #14 #40; // #6
+ class #41; // #7
+ Method #7 #40; // #8
+ class #44; // #9
+ Method #9 #40; // #10
+ Field #7 #46; // #11
+ Field #9 #46; // #12
+ class #47; // #13
+ class #49; // #14
+ Utf8 "f"; // #15
+ Utf8 "I"; // #16
+ Utf8 "m"; // #17
+ Utf8 "()V"; // #18
+ Utf8 "Code"; // #19
+ Utf8 "LineNumberTable"; // #20
+ Utf8 "invokeTarget"; // #21
+ Utf8 "invokeTargetNotOurHost"; // #22
+ Utf8 "<init>"; // #23
+ Utf8 "newTarget"; // #24
+ Utf8 "newTargetNotOurHost"; // #25
+ Utf8 "getFieldTarget"; // #26
+ Utf8 "getFieldTargetNotOurHost"; // #27
+ Utf8 "putFieldTarget"; // #28
+ Utf8 "putFieldTargetNotOurHost"; // #29
+ Utf8 "SourceFile"; // #30
+ Utf8 "TestNestmateMembership.java"; // #31
+ Utf8 "NestHost"; // #32
+ class #50; // #33
+ class #51; // #34
+ NameAndType #52 #53; // #35
+ Utf8 "CallerNotOurHost.m() - java version"; // #36
+ class #54; // #37
+ NameAndType #55 #56; // #38
+ NameAndType #17 #18; // #39
+ NameAndType #23 #18; // #40
+ Utf8 "TestNestmateMembership$Target"; // #41
+ Utf8 "Target"; // #42
+ Utf8 "InnerClasses"; // #43
+ Utf8 "TestNestmateMembership$TargetNotOurHost"; // #44
+ Utf8 "TargetNotOurHost"; // #45
+ NameAndType #15 #16; // #46
+ Utf8 "TestNestmateMembership$CallerNotOurHost"; // #47
+ Utf8 "CallerNotOurHost"; // #48
+ Utf8 "java/lang/Object"; // #49
+ Utf8 "TestNestmateMembership"; // #50
+ Utf8 "java/lang/System"; // #51
+ Utf8 "out"; // #52
+ Utf8 "Ljava/io/PrintStream;"; // #53
+ Utf8 "java/io/PrintStream"; // #54
+ Utf8 "println"; // #55
+ Utf8 "(Ljava/lang/String;)V"; // #56
+ // Added
+ Utf8 "InvalidNestHost"; // #57
+ class #57; // #58
+ } // Constant Pool
+
+ 0x0020; // access
+ #13;// this_cpx
+ #14;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #15; // name_cpx
+ #16; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x000A; // access
+ #17; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200011202B60003;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 297;
+ 8 298;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80004B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 300;
+ 3 301;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #22; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 303;
+ 3 304;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #23; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 308;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #24; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000759B700084B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 311;
+ 8 312;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #25; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000959B7000A4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 314;
+ 8 315;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #26; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000B3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 322;
+ 4 323;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #27; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000C3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 325;
+ 4 326;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 328;
+ 5 329;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #29; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000CB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 331;
+ 5 332;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#30) { // SourceFile
+ #31;
+ } // end SourceFile
+ ;
+ Attr(#32) { // NestHost
+ 0x003A; // modified - #58
+ } // end NestHost
+ ;
+ Attr(#43) { // InnerClasses
+ [] { // InnerClasses
+ #7 #33 #42 8;
+ #9 #33 #45 8;
+ #13 #33 #48 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$CallerNotOurHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/CallerSelfHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// NestHost attribute refers to current class
+
+class TestNestmateMembership$CallerSelfHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Field #34 #35; // #1
+ String #36; // #2
+ Method #37 #38; // #3
+ Method #7 #39; // #4
+ Method #9 #39; // #5
+ Method #14 #40; // #6
+ class #41; // #7
+ Method #7 #40; // #8
+ class #44; // #9
+ Method #9 #40; // #10
+ Field #7 #46; // #11
+ Field #9 #46; // #12
+ class #47; // #13
+ class #49; // #14
+ Utf8 "f"; // #15
+ Utf8 "I"; // #16
+ Utf8 "m"; // #17
+ Utf8 "()V"; // #18
+ Utf8 "Code"; // #19
+ Utf8 "LineNumberTable"; // #20
+ Utf8 "invokeTarget"; // #21
+ Utf8 "invokeTargetSelfHost"; // #22
+ Utf8 "<init>"; // #23
+ Utf8 "newTarget"; // #24
+ Utf8 "newTargetSelfHost"; // #25
+ Utf8 "getFieldTarget"; // #26
+ Utf8 "getFieldTargetSelfHost"; // #27
+ Utf8 "putFieldTarget"; // #28
+ Utf8 "putFieldTargetSelfHost"; // #29
+ Utf8 "SourceFile"; // #30
+ Utf8 "TestNestmateMembership.java"; // #31
+ Utf8 "NestHost"; // #32
+ class #50; // #33
+ class #51; // #34
+ NameAndType #52 #53; // #35
+ Utf8 "CallerSelfHost.m() - java version"; // #36
+ class #54; // #37
+ NameAndType #55 #56; // #38
+ NameAndType #17 #18; // #39
+ NameAndType #23 #18; // #40
+ Utf8 "TestNestmateMembership$Target"; // #41
+ Utf8 "Target"; // #42
+ Utf8 "InnerClasses"; // #43
+ Utf8 "TestNestmateMembership$TargetSelfHost"; // #44
+ Utf8 "TargetSelfHost"; // #45
+ NameAndType #15 #16; // #46
+ Utf8 "TestNestmateMembership$CallerSelfHost"; // #47
+ Utf8 "CallerSelfHost"; // #48
+ Utf8 "java/lang/Object"; // #49
+ Utf8 "TestNestmateMembership"; // #50
+ Utf8 "java/lang/System"; // #51
+ Utf8 "out"; // #52
+ Utf8 "Ljava/io/PrintStream;"; // #53
+ Utf8 "java/io/PrintStream"; // #54
+ Utf8 "println"; // #55
+ Utf8 "(Ljava/lang/String;)V"; // #56
+ } // Constant Pool
+
+ 0x0020; // access
+ #13;// this_cpx
+ #14;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #15; // name_cpx
+ #16; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x000A; // access
+ #17; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200011202B60003;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 297;
+ 8 298;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80004B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 300;
+ 3 301;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #22; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 303;
+ 3 304;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #23; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70006B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 308;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #24; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000759B700084B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 311;
+ 8 312;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #25; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000959B7000A4B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 314;
+ 8 315;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #26; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000B3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 322;
+ 4 323;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #27; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB2000C3BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 325;
+ 4 326;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #28; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 328;
+ 5 329;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #29; // name_cpx
+ #18; // sig_cpx
+ [] { // Attributes
+ Attr(#19) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB3000CB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#20) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 331;
+ 5 332;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#30) { // SourceFile
+ #31;
+ } // end SourceFile
+ ;
+ Attr(#32) { // NestHost
+ 0x000D; // modified - #13
+ } // end NestHost
+ ;
+ Attr(#43) { // InnerClasses
+ [] { // InnerClasses
+ #7 #33 #42 8;
+ #9 #33 #45 8;
+ #13 #33 #48 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$CallerSelfHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/InvalidNestHost.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/* Empty class to use as an invalid nest-host class, in the same package as
+ * the test classes.
+ */
+public class InvalidNestHost {
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/PackagedNestHost.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 P1;
+
+/*
+ * This is used to produce a jcod file in which we modify the
+ * NestMembers attribute to claim that P2.PackagedNestHost.Member
+ * is a member of our nest.
+ */
+public class PackagedNestHost {
+ public static class Member {
+ // jcod file will change these to private
+ public Member() {}
+ public static int f;
+ public static void m() {
+ System.out.println("You should never see this!");
+ }
+ }
+
+ // Entry points for main test.
+ // These should fail at runtime as members will now be private
+ // and the nestmate access check should fail due to being in a
+ // different package.
+
+ public static void doInvoke() {
+ P2.PackagedNestHost2.Member.m();
+ }
+
+ public static void doConstruct() {
+ Object o = new P2.PackagedNestHost2.Member();
+ }
+
+ public static void doGetField() {
+ int x = P2.PackagedNestHost2.Member.f;
+ }
+
+ public static void doPutField() {
+ P2.PackagedNestHost2.Member.f = 42;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/PackagedNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestMembers attribute is modified to contain P2.PackagedNestHost2.Member
+
+class P1/PackagedNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #7 #22; // #1
+ Method #3 #23; // #2
+ class #25; // #3
+ Method #3 #22; // #4
+ Field #3 #26; // #5
+ class #27; // #6
+ class #28; // #7
+ class #29; // #8
+ Utf8 "Member"; // #9
+ Utf8 "InnerClasses"; // #10
+ Utf8 "<init>"; // #11
+ Utf8 "()V"; // #12
+ Utf8 "Code"; // #13
+ Utf8 "LineNumberTable"; // #14
+ Utf8 "doInvoke"; // #15
+ Utf8 "doConstruct"; // #16
+ Utf8 "doGetField"; // #17
+ Utf8 "doPutField"; // #18
+ Utf8 "SourceFile"; // #19
+ Utf8 "PackagedNestHost.java"; // #20
+ Utf8 "NestMembers"; // #21
+ NameAndType #11 #12; // #22
+ NameAndType #30 #12; // #23
+ class #31; // #24
+ Utf8 "P2/PackagedNestHost2$Member"; // #25
+ NameAndType #32 #33; // #26
+ Utf8 "P1/PackagedNestHost"; // #27
+ Utf8 "java/lang/Object"; // #28
+ Utf8 "P1/PackagedNestHost$Member"; // #29
+ Utf8 "m"; // #30
+ Utf8 "P2/PackagedNestHost2"; // #31
+ Utf8 "f"; // #32
+ Utf8 "I"; // #33
+ } // Constant Pool
+
+ 0x0021; // access
+ #6;// this_cpx
+ #7;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #11; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 31;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #15; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80002B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 47;
+ 3 48;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #16; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000359B700044B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 51;
+ 8 52;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #17; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB200053BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 55;
+ 4 56;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #18; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB30005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 59;
+ 5 60;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#19) { // SourceFile
+ #20;
+ } // end SourceFile
+ ;
+ Attr(#21) { // NestMembers
+ 0x00010003; // modified - #3
+ } // end NestMembers
+ ;
+ Attr(#10) { // InnerClasses
+ [] { // InnerClasses
+ #8 #6 #9 9;
+ #3 #24 #9 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P1/PackagedNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/PackagedNestHost2.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 P2;
+
+/*
+ * This is used to produce a jcod file in which we modify the
+ * NestHost attribute to claim that P2.PackagedNestHost.Member
+ * is a member of the nest of P1.PackagedNestHost.
+ */
+public class PackagedNestHost2 {
+ public static class Member {
+ // jcod file will change these to private
+ public Member() {}
+ public static int f;
+ public static void m() {
+ System.out.println("You should never see this!");
+ }
+
+ // Entry points for main test.
+ // These should fail at runtime as members will now be private
+ // and our nest-host won't resolve as it's in a different package.
+
+ public static void doInvoke() {
+ P1.PackagedNestHost.Member.m();
+ }
+
+ public static void doConstruct() {
+ Object o = new P1.PackagedNestHost.Member();
+ }
+
+ public static void doGetField() {
+ int x = P1.PackagedNestHost.Member.f;
+ }
+
+ public static void doPutField() {
+ P1.PackagedNestHost.Member.f = 42;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/PackagedNestHost2Member.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute is modified to contain P1.PackagedNestHost
+// Required members are declared private
+
+class P2/PackagedNestHost2$Member {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #10 #26; // #1
+ Field #27 #28; // #2
+ String #29; // #3
+ Method #30 #31; // #4
+ Method #6 #32; // #5
+ class #34; // #6
+ Method #6 #26; // #7
+ Field #6 #37; // #8
+ class #38; // #9
+ class #39; // #10
+ Utf8 "f"; // #11
+ Utf8 "I"; // #12
+ Utf8 "<init>"; // #13
+ Utf8 "()V"; // #14
+ Utf8 "Code"; // #15
+ Utf8 "LineNumberTable"; // #16
+ Utf8 "m"; // #17
+ Utf8 "doInvoke"; // #18
+ Utf8 "doConstruct"; // #19
+ Utf8 "doGetField"; // #20
+ Utf8 "doPutField"; // #21
+ Utf8 "SourceFile"; // #22
+ Utf8 "PackagedNestHost2.java"; // #23
+ Utf8 "NestHost"; // #24
+ class #40; // #25
+ NameAndType #13 #14; // #26
+ class #41; // #27
+ NameAndType #42 #43; // #28
+ Utf8 "You should never see this!"; // #29
+ class #44; // #30
+ NameAndType #45 #46; // #31
+ NameAndType #17 #14; // #32
+ class #47; // #33
+ Utf8 "P1/PackagedNestHost$Member"; // #34
+ Utf8 "Member"; // #35
+ Utf8 "InnerClasses"; // #36
+ NameAndType #11 #12; // #37
+ Utf8 "P2/PackagedNestHost2$Member"; // #38
+ Utf8 "java/lang/Object"; // #39
+ Utf8 "P2/PackagedNestHost2"; // #40
+ Utf8 "java/lang/System"; // #41
+ Utf8 "out"; // #42
+ Utf8 "Ljava/io/PrintStream;"; // #43
+ Utf8 "java/io/PrintStream"; // #44
+ Utf8 "println"; // #45
+ Utf8 "(Ljava/lang/String;)V"; // #46
+ Utf8 "P1/PackagedNestHost"; // #47
+ } // Constant Pool
+
+ 0x0021; // access
+ #9;// this_cpx
+ #10;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access - modified
+ #11; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access - modified
+ #13; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 34;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access - modified
+ #17; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 37;
+ 8 38;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #18; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 45;
+ 3 46;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #19; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xBB000659B700074B;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 49;
+ 8 50;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #20; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB200083BB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 53;
+ 4 54;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #21; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 1; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0x102AB30008B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 57;
+ 5 58;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#22) { // SourceFile
+ #23;
+ } // end SourceFile
+ ;
+ Attr(#24) { // NestHost
+ 0x0021; // modified - #33
+ } // end NestHost
+ ;
+ Attr(#36) { // InnerClasses
+ [] { // InnerClasses
+ #6 #33 #35 9;
+ #9 #25 #35 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P2/PackagedNestHost2$Member
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/PackagedNestHostMember.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// all members are declared private
+
+class P1/PackagedNestHost$Member {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #18; // #1
+ Field #19 #20; // #2
+ String #21; // #3
+ Method #22 #23; // #4
+ class #24; // #5
+ class #27; // #6
+ Utf8 "f"; // #7
+ Utf8 "I"; // #8
+ Utf8 "<init>"; // #9
+ Utf8 "()V"; // #10
+ Utf8 "Code"; // #11
+ Utf8 "LineNumberTable"; // #12
+ Utf8 "m"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "PackagedNestHost.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #28; // #17
+ NameAndType #9 #10; // #18
+ class #29; // #19
+ NameAndType #30 #31; // #20
+ Utf8 "You should never see this!"; // #21
+ class #32; // #22
+ NameAndType #33 #34; // #23
+ Utf8 "P1/PackagedNestHost$Member"; // #24
+ Utf8 "Member"; // #25
+ Utf8 "InnerClasses"; // #26
+ Utf8 "java/lang/Object"; // #27
+ Utf8 "P1/PackagedNestHost"; // #28
+ Utf8 "java/lang/System"; // #29
+ Utf8 "out"; // #30
+ Utf8 "Ljava/io/PrintStream;"; // #31
+ Utf8 "java/io/PrintStream"; // #32
+ Utf8 "println"; // #33
+ Utf8 "(Ljava/lang/String;)V"; // #34
+ } // Constant Pool
+
+ 0x0021; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access - modified
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 34;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access - modified
+ #13; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 37;
+ 8 38;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#16) { // NestHost
+ 0x0011;
+ } // end NestHost
+ ;
+ Attr(#26) { // InnerClasses
+ [] { // InnerClasses
+ #5 #17 #25 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P1/PackagedNestHost$Member
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TargetMissingHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-existent class
+
+class TestNestmateMembership$TargetMissingHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #8 #22; // #1
+ String #23; // #2
+ Field #7 #24; // #3
+ Field #25 #26; // #4
+ String #27; // #5
+ Method #28 #29; // #6
+ class #30; // #7
+ class #33; // #8
+ Utf8 "msg"; // #9
+ Utf8 "Ljava/lang/String;"; // #10
+ Utf8 "f"; // #11
+ Utf8 "I"; // #12
+ Utf8 "<init>"; // #13
+ Utf8 "()V"; // #14
+ Utf8 "Code"; // #15
+ Utf8 "LineNumberTable"; // #16
+ Utf8 "m"; // #17
+ Utf8 "SourceFile"; // #18
+ Utf8 "TestNestmateMembership.java"; // #19
+ Utf8 "NestHost"; // #20
+ class #34; // #21
+ NameAndType #13 #14; // #22
+ Utf8 "NoTargetMissingHost"; // #23
+ NameAndType #9 #10; // #24
+ class #35; // #25
+ NameAndType #36 #37; // #26
+ Utf8 "TargetMissingHost.m() - java version"; // #27
+ class #38; // #28
+ NameAndType #39 #40; // #29
+ Utf8 "TestNestmateMembership$TargetMissingHost"; // #30
+ Utf8 "TargetMissingHost"; // #31
+ Utf8 "InnerClasses"; // #32
+ Utf8 "java/lang/Object"; // #33
+ Utf8 "TestNestmateMembership"; // #34
+ Utf8 "java/lang/System"; // #35
+ Utf8 "out"; // #36
+ Utf8 "Ljava/io/PrintStream;"; // #37
+ Utf8 "java/io/PrintStream"; // #38
+ Utf8 "println"; // #39
+ Utf8 "(Ljava/lang/String;)V"; // #40
+ class #23; // #41 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #7;// this_cpx
+ #8;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #11; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access
+ #13; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB700012A1202B5;
+ 0x0003B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 354;
+ 4 353;
+ 10 354;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #17; // name_cpx
+ #14; // sig_cpx
+ [] { // Attributes
+ Attr(#15) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200041205B60006;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#16) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 357;
+ 8 358;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#18) { // SourceFile
+ #19;
+ } // end SourceFile
+ ;
+ Attr(#20) { // NestHost
+ 0x0029; // modified #41
+ } // end NestHost
+ ;
+ Attr(#32) { // InnerClasses
+ [] { // InnerClasses
+ #7 #21 #31 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$TargetMissingHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TargetNoHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute deleted
+
+class TestNestmateMembership$TargetNoHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #18; // #1
+ Field #19 #20; // #2
+ String #21; // #3
+ Method #22 #23; // #4
+ class #24; // #5
+ class #27; // #6
+ Utf8 "f"; // #7
+ Utf8 "I"; // #8
+ Utf8 "<init>"; // #9
+ Utf8 "()V"; // #10
+ Utf8 "Code"; // #11
+ Utf8 "LineNumberTable"; // #12
+ Utf8 "m"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestNestmateMembership.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #28; // #17
+ NameAndType #9 #10; // #18
+ class #29; // #19
+ NameAndType #30 #31; // #20
+ Utf8 "TargetNoHost.m() - java version"; // #21
+ class #32; // #22
+ NameAndType #33 #34; // #23
+ Utf8 "TestNestmateMembership$TargetNoHost"; // #24
+ Utf8 "TargetNoHost"; // #25
+ Utf8 "InnerClasses"; // #26
+ Utf8 "java/lang/Object"; // #27
+ Utf8 "TestNestmateMembership"; // #28
+ Utf8 "java/lang/System"; // #29
+ Utf8 "out"; // #30
+ Utf8 "Ljava/io/PrintStream;"; // #31
+ Utf8 "java/io/PrintStream"; // #32
+ Utf8 "println"; // #33
+ Utf8 "(Ljava/lang/String;)V"; // #34
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 345;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #13; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 348;
+ 8 349;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#26) { // InnerClasses
+ [] { // InnerClasses
+ #5 #17 #25 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$TargetNoHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TargetNotInstanceHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-instance class
+
+class TestNestmateMembership$TargetNotInstanceHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #20; // #1
+ Field #21 #22; // #2
+ String #23; // #3
+ Method #24 #25; // #4
+ class #26; // #5
+ class #29; // #6
+ Utf8 "oa"; // #7
+ Utf8 "[LInvalidNestHost;"; // #8 - modified
+ Utf8 "f"; // #9
+ Utf8 "I"; // #10
+ Utf8 "<init>"; // #11
+ Utf8 "()V"; // #12
+ Utf8 "Code"; // #13
+ Utf8 "LineNumberTable"; // #14
+ Utf8 "m"; // #15
+ Utf8 "SourceFile"; // #16
+ Utf8 "TestNestmateMembership.java"; // #17
+ Utf8 "NestHost"; // #18
+ class #30; // #19
+ NameAndType #11 #12; // #20
+ class #31; // #21
+ NameAndType #32 #33; // #22
+ Utf8 "TargetNotInstanceHost.m() - java version"; // #23
+ class #34; // #24
+ NameAndType #35 #36; // #25
+ Utf8 "TestNestmateMembership$TargetNotInstanceHost"; // #26
+ Utf8 "TargetNotInstanceHost"; // #27
+ Utf8 "InnerClasses"; // #28
+ Utf8 "java/lang/Object"; // #29
+ Utf8 "TestNestmateMembership"; // #30
+ Utf8 "java/lang/System"; // #31
+ Utf8 "out"; // #32
+ Utf8 "Ljava/io/PrintStream;"; // #33
+ Utf8 "java/io/PrintStream"; // #34
+ Utf8 "println"; // #35
+ Utf8 "(Ljava/lang/String;)V"; // #36
+ class #8; // #37 added
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access
+ #11; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 363;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #15; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#13) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#14) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 366;
+ 8 367;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#16) { // SourceFile
+ #17;
+ } // end SourceFile
+ ;
+ Attr(#18) { // NestHost
+ 0x0025; // modified - #37
+ } // end NestHost
+ ;
+ Attr(#28) { // InnerClasses
+ [] { // InnerClasses
+ #5 #19 #27 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$TargetNotInstanceHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TargetNotOurHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with no nest
+
+class TestNestmateMembership$TargetNotOurHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #18; // #1
+ Field #19 #20; // #2
+ String #21; // #3
+ Method #22 #23; // #4
+ class #24; // #5
+ class #27; // #6
+ Utf8 "f"; // #7
+ Utf8 "I"; // #8
+ Utf8 "<init>"; // #9
+ Utf8 "()V"; // #10
+ Utf8 "Code"; // #11
+ Utf8 "LineNumberTable"; // #12
+ Utf8 "m"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestNestmateMembership.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #28; // #17
+ NameAndType #9 #10; // #18
+ class #29; // #19
+ NameAndType #30 #31; // #20
+ Utf8 "TargetNotOurHost.m() - java version"; // #21
+ class #32; // #22
+ NameAndType #33 #34; // #23
+ Utf8 "TestNestmateMembership$TargetNotOurHost"; // #24
+ Utf8 "TargetNotOurHost"; // #25
+ Utf8 "InnerClasses"; // #26
+ Utf8 "java/lang/Object"; // #27
+ Utf8 "TestNestmateMembership"; // #28
+ Utf8 "java/lang/System"; // #29
+ Utf8 "out"; // #30
+ Utf8 "Ljava/io/PrintStream;"; // #31
+ Utf8 "java/io/PrintStream"; // #32
+ Utf8 "println"; // #33
+ Utf8 "(Ljava/lang/String;)V"; // #34
+ // Added
+ Utf8 "InvalidNestHost"; // #35
+ class #35; // #36
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 371;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #13; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 374;
+ 8 375;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#16) { // NestHost
+ 0x0024; // modified - #36
+ } // end NestHost
+ ;
+ Attr(#26) { // InnerClasses
+ [] { // InnerClasses
+ #5 #17 #25 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$TargetNotOurHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TargetSelfHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// NestHost attribute refers to current class
+
+class TestNestmateMembership$TargetSelfHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #18; // #1
+ Field #19 #20; // #2
+ String #21; // #3
+ Method #22 #23; // #4
+ class #24; // #5
+ class #27; // #6
+ Utf8 "f"; // #7
+ Utf8 "I"; // #8
+ Utf8 "<init>"; // #9
+ Utf8 "()V"; // #10
+ Utf8 "Code"; // #11
+ Utf8 "LineNumberTable"; // #12
+ Utf8 "m"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestNestmateMembership.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #28; // #17
+ NameAndType #9 #10; // #18
+ class #29; // #19
+ NameAndType #30 #31; // #20
+ Utf8 "TargetSelfHost.m() - java version"; // #21
+ class #32; // #22
+ NameAndType #33 #34; // #23
+ Utf8 "TestNestmateMembership$TargetSelfHost"; // #24
+ Utf8 "TargetSelfHost"; // #25
+ Utf8 "InnerClasses"; // #26
+ Utf8 "java/lang/Object"; // #27
+ Utf8 "TestNestmateMembership"; // #28
+ Utf8 "java/lang/System"; // #29
+ Utf8 "out"; // #30
+ Utf8 "Ljava/io/PrintStream;"; // #31
+ Utf8 "java/io/PrintStream"; // #32
+ Utf8 "println"; // #33
+ Utf8 "(Ljava/lang/String;)V"; // #34
+ // Added
+ class #24; // #35
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x000A; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 371;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access
+ #13; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 374;
+ 8 375;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#16) { // NestHost
+ 0x0023; // modified - #35
+ } // end NestHost
+ ;
+ Attr(#26) { // InnerClasses
+ [] { // InnerClasses
+ #5 #17 #25 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestNestmateMembership$TargetSelfHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,1776 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @bug 8046171
+ * @summary Test the various rules for nest members and nest-hosts by
+ * triggering nestmate access checks on all possible paths
+ * @compile TestNestmateMembership.java
+ * PackagedNestHost.java
+ * PackagedNestHost2.java
+ * InvalidNestHost.java
+ *
+ * @compile TargetNoHost.jcod
+ * CallerNoHost.jcod
+ * TargetSelfHost.jcod
+ * CallerSelfHost.jcod
+ * TargetMissingHost.jcod
+ * CallerMissingHost.jcod
+ * TargetNotInstanceHost.jcod
+ * CallerNotInstanceHost.jcod
+ * TargetNotOurHost.jcod
+ * CallerNotOurHost.jcod
+ * PackagedNestHost.jcod
+ * PackagedNestHost2Member.jcod
+ * PackagedNestHostMember.jcod
+ *
+ * @run main/othervm TestNestmateMembership method
+ * @run main/othervm TestNestmateMembership constructor
+ * @run main/othervm TestNestmateMembership getField
+ * @run main/othervm TestNestmateMembership putField
+ * @run main/othervm -Xcomp TestNestmateMembership getField
+ */
+
+// We test all the "illegal" relationships between a nest member and its nest-host
+// except for the case where the name of the nest-member matches the name listed
+// in the nest-host, but resolves to a different class. There doesn't seem to
+// be a way to construct that scenario.
+// For each nested class below there is a corresponding .jcod file which breaks one
+// of the rules regarding nest membership. For the package related tests we have
+// additional PackageNestHost*.java sources.[1]
+//
+// Note that all the .java files must be compiled in the same step, while all
+// .jcod files must be compiled in a later step.
+
+// We test all the different nestmate access check paths: method invocation, constructor
+// invocations, field get and field put. The test is invoked four times with each using
+// a different test mode. Plus an extra Xcomp run for field access to hit ciField path.
+//
+// As access checking requires resolution and validation of the nest-host of
+// both the caller class and the target class, we must check that all
+// combinations of good/bad caller/target are checked for each of the
+// possible errors:
+// - no nest-host attribute
+// - nest-host refers to self
+// - nest-host class can not be found
+// - nest-host class is not an instance class (but is in same package)
+// - class is not a member of nest-host's nest (but is in same package)
+// - class and nest-host are in different packages
+//
+// To provide coverage for reflection and MethodHandle paths through
+// JVM_AreNestmates, we add reflection/MH accesses to a subset of the tests.
+// We only need to test one case (for Caller.xxx) as all cases use the same path; further
+// we don't need to test all failure cases, as all exceptions are equivalent in that regard,
+// but for good measure we test the four basic error situations (eliding the different
+// package test for simplicity).
+//
+// [1] In earlier versions the package-test was the final check done in nest membership
+// validation, so we needed actual test classes in different packages that claimed
+// membership. The final spec requires the package test to be done first, so it can
+// be trivially tested by using Object as the nest-host. But we leave the explicit
+// package tests as they are, and adjust the other tests so that a "bad host" is
+// always in the same package.
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestNestmateMembership {
+
+ static final MethodType VOID_T = MethodType.methodType(void.class);
+
+ static class Caller {
+
+ private Caller() {}
+
+ private static void m() {
+ System.out.println("Caller.m()");
+ }
+
+ // direct static method invocations
+
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetNoHost() {
+ TargetNoHost.m();
+ }
+ public static void invokeTargetSelfHost() {
+ TargetSelfHost.m();
+ }
+ public static void invokeTargetMissingHost() {
+ TargetMissingHost.m();
+ }
+ public static void invokeTargetNotInstanceHost() {
+ TargetNotInstanceHost.m();
+ }
+ public static void invokeTargetNotOurHost() {
+ TargetNotOurHost.m();
+ }
+
+ // reflective static method invocations
+
+ public static void invokeTargetNoHostReflectively() throws Throwable {
+ TargetNoHost.class.getDeclaredMethod("m", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ public static void invokeTargetSelfHostReflectively() throws Throwable {
+ TargetSelfHost.class.getDeclaredMethod("m", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ public static void invokeTargetMissingHostReflectively() throws Throwable {
+ TargetMissingHost.class.getDeclaredMethod("m", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ public static void invokeTargetNotInstanceHostReflectively() throws Throwable {
+ TargetNotInstanceHost.class.getDeclaredMethod("m", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ public static void invokeTargetNotOurHostReflectively() throws Throwable {
+ TargetNotOurHost.class.getDeclaredMethod("m", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+
+ // MethodHandle static method lookup (no invoke as the lookup should fail)
+
+ public static void invokeTargetNoHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStatic(TargetNoHost.class, "m", VOID_T);
+ }
+ public static void invokeTargetSelfHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStatic(TargetSelfHost.class, "m", VOID_T);
+ }
+ public static void invokeTargetMissingHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStatic(TargetMissingHost.class, "m", VOID_T);
+ }
+ public static void invokeTargetNotInstanceHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStatic(TargetNotInstanceHost.class, "m", VOID_T);
+ }
+ public static void invokeTargetNotOurHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStatic(TargetNotOurHost.class, "m", VOID_T);
+ }
+
+
+ // direct constructor invocations
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetNoHost() {
+ Object o = new TargetNoHost();
+ }
+ public static void newTargetSelfHost() {
+ Object o = new TargetSelfHost();
+ }
+ public static void newTargetMissingHost() {
+ Object o = new TargetMissingHost();
+ }
+ public static void newTargetNotInstanceHost() {
+ Object o = new TargetNotInstanceHost();
+ }
+ public static void newTargetNotOurHost() {
+ Object o = new TargetNotOurHost();
+ }
+
+ // reflective constructor invocations
+
+ public static void newTargetNoHostReflectively() throws Throwable {
+ Object o = TargetNoHost.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public static void newTargetSelfHostReflectively() throws Throwable {
+ Object o = TargetSelfHost.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public static void newTargetMissingHostReflectively() throws Throwable {
+ Object o = TargetMissingHost.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public static void newTargetNotInstanceHostReflectively() throws Throwable {
+ Object o = TargetNotInstanceHost.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public static void newTargetNotOurHostReflectively() throws Throwable {
+ Object o = TargetNotOurHost.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+
+ // MethodHandle constructor lookup (no invoke as the lookup should fail)
+
+ public static void newTargetNoHostMH() throws Throwable {
+ MethodHandle mh = lookup().findConstructor(TargetNoHost.class, VOID_T);
+ }
+ public static void newTargetSelfHostMH() throws Throwable {
+ MethodHandle mh = lookup().findConstructor(TargetSelfHost.class, VOID_T);
+ }
+ public static void newTargetMissingHostMH() throws Throwable {
+ MethodHandle mh = lookup().findConstructor(TargetMissingHost.class, VOID_T);
+ }
+ public static void newTargetNotInstanceHostMH() throws Throwable {
+ MethodHandle mh = lookup().findConstructor(TargetNotInstanceHost.class, VOID_T);
+ }
+ public static void newTargetNotOurHostMH() throws Throwable {
+ MethodHandle mh = lookup().findConstructor(TargetNotOurHost.class, VOID_T);
+ }
+
+ private static int f;
+
+ // direct field accesses
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetNoHost() {
+ int x = TargetNoHost.f;
+ }
+ public static void getFieldTargetSelfHost() {
+ int x = TargetSelfHost.f;
+ }
+ public static void getFieldTargetMissingHost() {
+ int x = TargetMissingHost.f;
+ }
+ public static void getFieldTargetNotInstanceHost() {
+ int x = TargetNotInstanceHost.f;
+ }
+ public static void getFieldTargetNotOurHost() {
+ int x = TargetNotOurHost.f;
+ }
+
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetNoHost() {
+ TargetNoHost.f = 42;
+ }
+ public static void putFieldTargetSelfHost() {
+ TargetSelfHost.f = 42;
+ }
+ public static void putFieldTargetMissingHost() {
+ TargetMissingHost.f = 42;
+ }
+ public static void putFieldTargetNotInstanceHost() {
+ TargetNotInstanceHost.f = 42;
+ }
+ public static void putFieldTargetNotOurHost() {
+ TargetNotOurHost.f = 42;
+ }
+
+ // reflective field accesses
+
+ public static void getFieldTargetNoHostReflectively() throws Throwable {
+ int x = TargetNoHost.class.getDeclaredField("f").getInt(null);
+ }
+ public static void getFieldTargetSelfHostReflectively() throws Throwable {
+ int x = TargetSelfHost.class.getDeclaredField("f").getInt(null);
+ }
+ public static void getFieldTargetMissingHostReflectively() throws Throwable {
+ int x = TargetMissingHost.class.getDeclaredField("f").getInt(null);
+ }
+ public static void getFieldTargetNotInstanceHostReflectively() throws Throwable {
+ int x = TargetNotInstanceHost.class.getDeclaredField("f").getInt(null);
+ }
+ public static void getFieldTargetNotOurHostReflectively() throws Throwable {
+ int x = TargetNotOurHost.class.getDeclaredField("f").getInt(null);
+ }
+
+ public static void putFieldTargetNoHostReflectively() throws Throwable {
+ TargetNoHost.class.getDeclaredField("f").setInt(null, 42);
+ }
+ public static void putFieldTargetSelfHostReflectively() throws Throwable {
+ TargetSelfHost.class.getDeclaredField("f").setInt(null, 42);
+ }
+ public static void putFieldTargetMissingHostReflectively() throws Throwable {
+ TargetMissingHost.class.getDeclaredField("f").setInt(null, 42);
+ }
+ public static void putFieldTargetNotInstanceHostReflectively() throws Throwable {
+ TargetNotInstanceHost.class.getDeclaredField("f").setInt(null, 42);
+ }
+ public static void putFieldTargetNotOurHostReflectively() throws Throwable {
+ TargetNotOurHost.class.getDeclaredField("f").setInt(null, 42);
+ }
+
+ // MethodHandle field lookup (no access as the lookup will fail)
+
+ public static void getFieldTargetNoHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(TargetNoHost.class, "f", int.class);
+ }
+ public static void getFieldTargetSelfHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(TargetSelfHost.class, "f", int.class);
+ }
+ public static void getFieldTargetMissingHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(TargetMissingHost.class, "f", int.class);
+ }
+ public static void getFieldTargetNotInstanceHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(TargetNotInstanceHost.class, "f", int.class);
+ }
+ public static void getFieldTargetNotOurHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(TargetNotOurHost.class, "f", int.class);
+ }
+
+ public static void putFieldTargetNoHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticSetter(TargetNoHost.class, "f", int.class);
+ }
+ public static void putFieldTargetSelfHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticSetter(TargetSelfHost.class, "f", int.class);
+ }
+ public static void putFieldTargetMissingHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticSetter(TargetMissingHost.class, "f", int.class);
+ }
+ public static void putFieldTargetNotInstanceHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticSetter(TargetNotInstanceHost.class, "f", int.class);
+ }
+ public static void putFieldTargetNotOurHostMH() throws Throwable {
+ MethodHandle mh = lookup().findStaticSetter(TargetNotOurHost.class, "f", int.class);
+ }
+
+ }
+
+ static class CallerNoHost {
+
+ // method invocations
+
+ private static void m() {
+ System.out.println("CallerNoHost.m() - java version");
+ }
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetNoHost() {
+ TargetNoHost.m();
+ }
+
+ // constructor invocations
+
+ private CallerNoHost() {}
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetNoHost() {
+ Object o = new TargetNoHost();
+ }
+
+ // field accesses
+
+ private static int f;
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetNoHost() {
+ int x = TargetNoHost.f;
+ }
+
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetNoHost() {
+ TargetNoHost.f = 42;
+ }
+
+ }
+
+ static class CallerSelfHost {
+
+ // method invocations
+
+ private static void m() {
+ System.out.println("CallerSelfHost.m() - java version");
+ }
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetSelfHost() {
+ TargetSelfHost.m();
+ }
+
+ // constructor invocations
+
+ private CallerSelfHost() {}
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetSelfHost() {
+ Object o = new TargetSelfHost();
+ }
+
+ // field accesses
+
+ private static int f;
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetSelfHost() {
+ int x = TargetSelfHost.f;
+ }
+
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetSelfHost() {
+ TargetSelfHost.f = 42;
+ }
+
+ }
+
+ static class CallerMissingHost {
+ String msg = "NoCallerMissingHost"; // for cp entry
+
+ // method invocations
+
+ private static void m() {
+ System.out.println("CallerMissingHost.m() - java version");
+ }
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetMissingHost() {
+ TargetMissingHost.m();
+ }
+
+ // constructor invocations
+
+ private CallerMissingHost() {}
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetMissingHost() {
+ Object o = new TargetMissingHost();
+ }
+
+ // field accesses
+
+ private static int f;
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetMissingHost() {
+ int x = TargetMissingHost.f;
+ }
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetMissingHost() {
+ TargetMissingHost.f = 42;
+ }
+
+ }
+
+ static class CallerNotInstanceHost {
+ Object[] oa; // create CP entry to use in jcod change
+
+ // method invocations
+
+ private static void m() {
+ System.out.println("CallerNotInstanceHost.m() - java version");
+ }
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetNotInstanceHost() {
+ TargetNotInstanceHost.m();
+ }
+
+ // constructor invocations
+
+ private CallerNotInstanceHost() {}
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetNotInstanceHost() {
+ Object o = new TargetNotInstanceHost();
+ }
+
+ // field accesses
+
+ private static int f;
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetNotInstanceHost() {
+ int x = TargetNotInstanceHost.f;
+ }
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetNotInstanceHost() {
+ TargetNotInstanceHost.f = 42;
+ }
+ }
+
+ static class CallerNotOurHost {
+
+ // method invocations
+
+ private static void m() {
+ System.out.println("CallerNotOurHost.m() - java version");
+ }
+ public static void invokeTarget() {
+ Target.m();
+ }
+ public static void invokeTargetNotOurHost() {
+ TargetNotOurHost.m();
+ }
+
+ // constructor invocations
+
+ private CallerNotOurHost() {}
+
+ public static void newTarget() {
+ Object o = new Target();
+ }
+ public static void newTargetNotOurHost() {
+ Object o = new TargetNotOurHost();
+ }
+
+ // field accesses
+
+ private static int f;
+
+ public static void getFieldTarget() {
+ int x = Target.f;
+ }
+ public static void getFieldTargetNotOurHost() {
+ int x = TargetNotOurHost.f;
+ }
+ public static void putFieldTarget() {
+ Target.f = 42;
+ }
+ public static void putFieldTargetNotOurHost() {
+ TargetNotOurHost.f = 42;
+ }
+
+ }
+
+ static class Target {
+ private Target() {}
+ private static int f;
+ private static void m() {
+ System.out.println("Target.m()");
+ }
+ }
+
+ static class TargetNoHost {
+ private TargetNoHost() {}
+ private static int f;
+ private static void m() {
+ System.out.println("TargetNoHost.m() - java version");
+ }
+ }
+
+ static class TargetSelfHost {
+ private TargetSelfHost() {}
+ private static int f;
+ private static void m() {
+ System.out.println("TargetSelfHost.m() - java version");
+ }
+ }
+
+ static class TargetMissingHost {
+ String msg = "NoTargetMissingHost"; // for cp entry
+ private TargetMissingHost() {}
+ private static int f;
+ private static void m() {
+ System.out.println("TargetMissingHost.m() - java version");
+ }
+ }
+
+ static class TargetNotInstanceHost {
+ Object[] oa; // create CP entry to use in jcod change
+ private TargetNotInstanceHost() {}
+ private static int f;
+ private static void m() {
+ System.out.println("TargetNotInstanceHost.m() - java version");
+ }
+ }
+
+ static class TargetNotOurHost {
+ private TargetNotOurHost() {}
+ private static int f;
+ private static void m() {
+ System.out.println("TargetNotOurHost.m() - java version");
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ if (args.length < 1) {
+ throw new Error("Test mode argument must be one of: method, constructor, getField or putField");
+ }
+ switch(args[0]) {
+ case "method":
+ System.out.println("TESTING METHOD INVOCATIONS:");
+ test_GoodInvoke();
+ test_NoHostInvoke();
+ test_SelfHostInvoke();
+ test_MissingHostInvoke();
+ test_NotInstanceHostInvoke();
+ test_NotOurHostInvoke();
+ test_WrongPackageHostInvoke();
+ break;
+ case "constructor":
+ System.out.println("TESTING CONSTRUCTOR INVOCATIONS:");
+ test_GoodConstruct();
+ test_NoHostConstruct();
+ test_SelfHostConstruct();
+ test_MissingHostConstruct();
+ test_NotInstanceHostConstruct();
+ test_NotOurHostConstruct();
+ test_WrongPackageHostConstruct();
+ break;
+ case "getField":
+ System.out.println("TESTING GETFIELD INVOCATIONS:");
+ test_GoodGetField();
+ test_NoHostGetField();
+ test_SelfHostGetField();
+ test_MissingHostGetField();
+ test_NotInstanceHostGetField();
+ test_NotOurHostGetField();
+ test_WrongPackageHostGetField();
+ break;
+ case "putField":
+ System.out.println("TESTING PUTFIELD INVOCATIONS:");
+ test_GoodPutField();
+ test_NoHostPutField();
+ test_SelfHostPutField();
+ test_MissingHostPutField();
+ test_NotInstanceHostPutField();
+ test_NotOurHostPutField();
+ test_WrongPackageHostPutField();
+ break;
+ default:
+ throw new Error("Uknown mode: " + args[0] +
+ ". Must be one of: method, constructor, getField or putField");
+ }
+ }
+
+ static void test_GoodInvoke(){
+ try {
+ Caller.invokeTarget();
+ }
+ catch (Exception e) {
+ throw new Error("Unexpected exception on good invocation " + e);
+ }
+ }
+
+ static void test_NoHostInvoke() throws Throwable {
+ System.out.println("Testing for missing nest-host attribute");
+ String msg = "tried to access method " +
+ "TestNestmateMembership$TargetNoHost.m()V from class " +
+ "TestNestmateMembership$Caller";
+ try {
+ Caller.invokeTargetNoHost();
+ throw new Error("Missing IllegalAccessError: " + msg);
+ }
+ catch (IllegalAccessError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "TestNestmateMembership$Caller cannot access a member of class " +
+ "TestNestmateMembership$TargetNoHost with modifiers \"private static\"";
+ try {
+ Caller.invokeTargetNoHostReflectively();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetNoHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetNoHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "tried to access method TestNestmateMembership$Target.m()V" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.invokeTarget();
+ throw new Error("Missing IllegalAccessError: " + msg);
+ }
+ catch (IllegalAccessError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "tried to access method TestNestmateMembership$TargetNoHost.m()V" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.invokeTargetNoHost();
+ throw new Error("Missing IllegalAccessError: " + msg);
+ }
+ catch (IllegalAccessError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_SelfHostInvoke() throws Throwable {
+ System.out.println("Testing for class that lists itself as nest-host");
+ String msg = "Type TestNestmateMembership$TargetSelfHost is not a nest member" +
+ " of TestNestmateMembership$TargetSelfHost: current type is not listed as a nest member";
+ try {
+ Caller.invokeTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.invokeTargetSelfHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetSelfHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetSelfHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.invokeTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.invokeTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_MissingHostInvoke() throws Throwable {
+ System.out.println("Testing for nest-host class that does not exist");
+ String msg = "Unable to load nest-host class (NoTargetMissingHost) of " +
+ "TestNestmateMembership$TargetMissingHost";
+ String cause_msg = "NoTargetMissingHost";
+ try {
+ Caller.invokeTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.invokeTargetMissingHostReflectively();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetMissingHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetMissingHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetMissingHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetMissingHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of " +
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.invokeTarget();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of "+
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.invokeTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ }
+
+ static void test_NotInstanceHostInvoke() throws Throwable {
+ System.out.println("Testing for nest-host class that is not an instance class");
+ String msg = "Type TestNestmateMembership$TargetNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ Caller.invokeTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.invokeTargetNotInstanceHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetNotInstanceHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetNotInstanceHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.invokeTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.invokeTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_NotOurHostInvoke() throws Throwable {
+ System.out.println("Testing for nest-host class that does not list us in its nest");
+ String msg = "Type TestNestmateMembership$TargetNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ Caller.invokeTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.invokeTargetNotOurHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such method: TestNestmateMembership$TargetNotOurHost.m()void/invokeStatic";
+ try {
+ Caller.invokeTargetNotOurHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.invokeTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.invokeTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_WrongPackageHostInvoke() {
+ System.out.println("Testing for nest-host and nest-member in different packages");
+ String msg = "Type P2.PackagedNestHost2$Member is not a nest member of " +
+ "P1.PackagedNestHost: types are in different packages";
+ try {
+ P1.PackagedNestHost.doInvoke();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ P2.PackagedNestHost2.Member.doInvoke();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ // constructor tests
+
+ static void test_GoodConstruct(){
+ try {
+ Caller.newTarget();
+ }
+ catch (Exception e) {
+ throw new Error("Unexpected exception on good construction: " + e);
+ }
+ }
+
+ static void test_NoHostConstruct() throws Throwable {
+ System.out.println("Testing for missing nest-host attribute");
+ String msg = "tried to access method TestNestmateMembership$TargetNoHost.<init>()V" +
+ " from class TestNestmateMembership$Caller";
+ try {
+ Caller.newTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "class TestNestmateMembership$Caller cannot access a member of class " +
+ "TestNestmateMembership$TargetNoHost with modifiers \"private\"";
+ try {
+ Caller.newTargetNoHostReflectively();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such constructor: TestNestmateMembership$TargetNoHost.<init>()void/newInvokeSpecial";
+ try {
+ Caller.newTargetNoHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "tried to access method TestNestmateMembership$Target.<init>()V" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.newTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "tried to access method TestNestmateMembership$TargetNoHost.<init>()V" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.newTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_SelfHostConstruct() throws Throwable {
+ System.out.println("Testing for class that lists itself as nest-host");
+ String msg = "Type TestNestmateMembership$TargetSelfHost is not a nest member" +
+ " of TestNestmateMembership$TargetSelfHost: current type is not listed as a nest member";
+ try {
+ Caller.newTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.newTargetSelfHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such constructor: TestNestmateMembership$TargetSelfHost.<init>()void/newInvokeSpecial";
+ try {
+ Caller.newTargetSelfHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.newTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.newTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_MissingHostConstruct() throws Throwable {
+ System.out.println("Testing for nest-host class that does not exist");
+ String msg = "Unable to load nest-host class (NoTargetMissingHost) of " +
+ "TestNestmateMembership$TargetMissingHost";
+ String cause_msg = "NoTargetMissingHost";
+ try {
+ Caller.newTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.newTargetMissingHostReflectively();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "no such constructor: TestNestmateMembership$TargetMissingHost.<init>()void/newInvokeSpecial";
+ try {
+ Caller.newTargetMissingHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of " +
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.newTarget();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of "+
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.newTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ }
+
+ static void test_NotInstanceHostConstruct() throws Throwable {
+ System.out.println("Testing for nest-host class that is not an instance class");
+ String msg = "Type TestNestmateMembership$TargetNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ Caller.newTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.newTargetNotInstanceHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such constructor: TestNestmateMembership$TargetNotInstanceHost.<init>()void/newInvokeSpecial";
+ try {
+ Caller.newTargetNotInstanceHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.newTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.newTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_NotOurHostConstruct() throws Throwable {
+ System.out.println("Testing for nest-host class that does not list us in its nest");
+ String msg = "Type TestNestmateMembership$TargetNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ Caller.newTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.newTargetNotOurHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "no such constructor: TestNestmateMembership$TargetNotOurHost.<init>()void/newInvokeSpecial";
+ try {
+ Caller.newTargetNotOurHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.newTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.newTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_WrongPackageHostConstruct() {
+ System.out.println("Testing for nest-host and nest-member in different packages");
+ String msg = "Type P2.PackagedNestHost2$Member is not a nest member of " +
+ "P1.PackagedNestHost: types are in different packages";
+ try {
+ P1.PackagedNestHost.doConstruct();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ P2.PackagedNestHost2.Member.doConstruct();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ // field tests
+
+ static void test_GoodGetField(){
+ try {
+ Caller.getFieldTarget();
+ }
+ catch (Exception e) {
+ throw new Error("Unexpected exception on good field access: " + e);
+ }
+ }
+
+ static void test_NoHostGetField() throws Throwable {
+ System.out.println("Testing for missing nest-host attribute");
+ String msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
+ " from class TestNestmateMembership$Caller";
+ try {
+ Caller.getFieldTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "class TestNestmateMembership$Caller cannot access a member of class " +
+ "TestNestmateMembership$TargetNoHost with modifiers \"private static\"";
+ try {
+ Caller.getFieldTargetNoHostReflectively();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+ msg = "member is private: TestNestmateMembership$TargetNoHost.f/int/getStatic";
+ try {
+ Caller.getFieldTargetNoHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "tried to access field TestNestmateMembership$Target.f" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.getFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.getFieldTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_SelfHostGetField() throws Throwable {
+ System.out.println("Testing for class that lists itself as nest-host");
+ String msg = "Type TestNestmateMembership$TargetSelfHost is not a nest member" +
+ " of TestNestmateMembership$TargetSelfHost: current type is not listed as a nest member";
+ try {
+ Caller.getFieldTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetSelfHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetSelfHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.getFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.getFieldTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_MissingHostGetField() throws Throwable {
+ System.out.println("Testing for nest-host class that does not exist");
+ String msg = "Unable to load nest-host class (NoTargetMissingHost) of " +
+ "TestNestmateMembership$TargetMissingHost";
+ String cause_msg = "NoTargetMissingHost";
+ try {
+ Caller.getFieldTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.getFieldTargetMissingHostReflectively();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.getFieldTargetMissingHostMH();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of " +
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.getFieldTarget();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of "+
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.getFieldTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ }
+
+ static void test_NotInstanceHostGetField() throws Throwable {
+ System.out.println("Testing for nest-host class that is not an instance class");
+ String msg = "Type TestNestmateMembership$TargetNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ Caller.getFieldTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetNotInstanceHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetNotInstanceHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.getFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.getFieldTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_NotOurHostGetField() throws Throwable {
+ System.out.println("Testing for nest-host class that does not list us in its nest");
+ String msg = "Type TestNestmateMembership$TargetNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ Caller.getFieldTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetNotOurHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.getFieldTargetNotOurHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.getFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.getFieldTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_WrongPackageHostGetField() {
+ System.out.println("Testing for nest-host and nest-member in different packages");
+ String msg = "Type P2.PackagedNestHost2$Member is not a nest member of " +
+ "P1.PackagedNestHost: types are in different packages";
+ try {
+ P1.PackagedNestHost.doGetField();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ P2.PackagedNestHost2.Member.doGetField();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_GoodPutField(){
+ try {
+ Caller.putFieldTarget();
+ }
+ catch (Exception e) {
+ throw new Error("Unexpected exception on good field access: " + e);
+ }
+ }
+
+ static void test_NoHostPutField() throws Throwable {
+ System.out.println("Testing for missing nest-host attribute");
+ String msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
+ " from class TestNestmateMembership$Caller";
+ try {
+ Caller.putFieldTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "class TestNestmateMembership$Caller cannot access a member of class " +
+ "TestNestmateMembership$TargetNoHost with modifiers \"private static\"";
+ try {
+ Caller.putFieldTargetNoHostReflectively();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+ msg = "member is private: TestNestmateMembership$TargetNoHost.f/int/putStatic";
+ try {
+ Caller.putFieldTargetNoHostMH();
+ throw new Error("Missing IllegalAccessException: " + msg);
+ }
+ catch (IllegalAccessException expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "tried to access field TestNestmateMembership$Target.f" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.putFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "tried to access field TestNestmateMembership$TargetNoHost.f" +
+ " from class TestNestmateMembership$CallerNoHost";
+ try {
+ CallerNoHost.putFieldTargetNoHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_SelfHostPutField() throws Throwable {
+ System.out.println("Testing for class that lists itself as nest-host");
+ String msg = "Type TestNestmateMembership$TargetSelfHost is not a nest member" +
+ " of TestNestmateMembership$TargetSelfHost: current type is not listed as a nest member";
+ try {
+ Caller.putFieldTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetSelfHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetSelfHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.putFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerSelfHost is not a nest member" +
+ " of TestNestmateMembership$CallerSelfHost: current type is not listed as a nest member";
+ try {
+ CallerSelfHost.putFieldTargetSelfHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_MissingHostPutField() throws Throwable {
+ System.out.println("Testing for nest-host class that does not exist");
+ String msg = "Unable to load nest-host class (NoTargetMissingHost) of " +
+ "TestNestmateMembership$TargetMissingHost";
+ String cause_msg = "NoTargetMissingHost";
+ try {
+ Caller.putFieldTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.putFieldTargetMissingHostReflectively();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ try {
+ Caller.putFieldTargetMissingHostMH();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of " +
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.putFieldTarget();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ msg = "Unable to load nest-host class (NoCallerMissingHost) of "+
+ "TestNestmateMembership$CallerMissingHost";
+ cause_msg = "NoCallerMissingHost";
+ try {
+ CallerMissingHost.putFieldTargetMissingHost();
+ throw new Error("Missing NoClassDefFoundError: " + msg);
+ }
+ catch (NoClassDefFoundError expected) {
+ check_expected(expected, msg, cause_msg);
+ }
+ }
+
+ static void test_NotInstanceHostPutField() throws Throwable {
+ System.out.println("Testing for nest-host class that is not an instance class");
+ String msg = "Type TestNestmateMembership$TargetNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ Caller.putFieldTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetNotInstanceHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetNotInstanceHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.putFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotInstanceHost is not a "+
+ "nest member of [LInvalidNestHost;: current type is not listed as a nest member";
+ try {
+ CallerNotInstanceHost.putFieldTargetNotInstanceHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_NotOurHostPutField() throws Throwable {
+ System.out.println("Testing for nest-host class that does not list us in its nest");
+ String msg = "Type TestNestmateMembership$TargetNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ Caller.putFieldTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetNotOurHostReflectively();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ Caller.putFieldTargetNotOurHostMH();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.putFieldTarget();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ msg = "Type TestNestmateMembership$CallerNotOurHost is not a nest member" +
+ " of InvalidNestHost: current type is not listed as a nest member";
+ try {
+ CallerNotOurHost.putFieldTargetNotOurHost();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ static void test_WrongPackageHostPutField() {
+ System.out.println("Testing for nest-host and nest-member in different packages");
+ String msg = "Type P2.PackagedNestHost2$Member is not a nest member of " +
+ "P1.PackagedNestHost: types are in different packages";
+ try {
+ P1.PackagedNestHost.doPutField();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ try {
+ P2.PackagedNestHost2.Member.doPutField();
+ throw new Error("Missing IncompatibleClassChangeError: " + msg);
+ }
+ catch (IncompatibleClassChangeError expected) {
+ check_expected(expected, msg);
+ }
+ }
+
+ // utilities
+
+ static void check_expected(Throwable expected, String msg) {
+ if (!expected.getMessage().contains(msg)) {
+ throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" +
+ expected.getMessage() + "\" does not contain \"" +
+ msg + "\"");
+ }
+ System.out.println("OK - got expected exception: " + expected);
+ }
+
+ static void check_expected(Throwable expected, String msg, String cause_msg) {
+ if (!expected.getMessage().contains(msg)) {
+ throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" +
+ expected.getMessage() + "\" does not contain \"" +
+ msg + "\"");
+ }
+ Throwable cause = expected.getCause();
+ if (cause instanceof NoClassDefFoundError) {
+ if (!cause.getMessage().contains(cause_msg)) {
+ throw new Error(expected.getClass().getSimpleName() +
+ " has wrong cause " + cause.getClass().getSimpleName() +": \"" +
+ cause.getMessage() + "\" does not contain \"" +
+ cause_msg + "\"");
+ }
+ }
+ else throw new Error(expected.getClass().getSimpleName() +
+ " has wrong cause " + cause.getClass().getSimpleName());
+
+ System.out.println("OK - got expected exception: " + expected +
+ " with cause " + cause);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PA_I.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,140 @@
+
+// rename m -> bad_m; real_m -> m
+
+class TestInterfaceMethodSelection$PA_I {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #5 #18; // #1
+ String #19; // #2
+ String #20; // #3
+ class #21; // #4
+ class #24; // #5
+ class #25; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "m"; // #11 MODIFIED
+ Utf8 "()Ljava/lang/String;"; // #12
+ Utf8 "bad_m"; // #13 MODIFIED
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestInterfaceMethodSelection.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #27; // #17
+ NameAndType #7 #8; // #18
+ Utf8 "PA_I::m"; // #19
+ Utf8 "Should not see this"; // #20
+ Utf8 "TestInterfaceMethodSelection$PA_I"; // #21
+ Utf8 "PA_I"; // #22
+ Utf8 "InnerClasses"; // #23
+ Utf8 "java/lang/Object"; // #24
+ Utf8 "TestInterfaceMethodSelection$I"; // #25
+ Utf8 "I"; // #26
+ Utf8 "TestInterfaceMethodSelection"; // #27
+ } // Constant Pool
+
+ 0x0020; // access
+ #4;// this_cpx
+ #5;// super_cpx
+
+ [] { // Interfaces
+ #6;
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 113;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #11; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 114;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0001; // access
+ #13; // name_cpx
+ #12; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1203B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 115;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#16) { // NestHost
+ 0x0011;
+ } // end NestHost
+ ;
+ Attr(#23) { // InnerClasses
+ [] { // InnerClasses
+ #4 #17 #22 8;
+ #6 #17 #26 1544;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInterfaceMethodSelection$PA_I
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PB_A.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// m() is declared private
+
+class TestMethodSelection$PB_A {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #20; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #22; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PB_A::m"; // #16
+ Utf8 "TestMethodSelection$PB_A"; // #17
+ Utf8 "PB_A"; // #18
+ Utf8 "InnerClasses"; // #19
+ Utf8 "TestMethodSelection$A"; // #20
+ Utf8 "A"; // #21
+ Utf8 "TestMethodSelection"; // #22
+ } // Constant Pool
+
+ 0x0021; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 119;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 120;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#19) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #18 9;
+ #4 #14 #21 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestMethodSelection$PB_A
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PB_A_I.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,109 @@
+// m() is declared private
+
+class TestInterfaceMethodSelection$PB_A_I {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #20; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestInterfaceMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #22; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PB_A_I::m"; // #16
+ Utf8 "TestInterfaceMethodSelection$PB_A_I"; // #17
+ Utf8 "PB_A_I"; // #18
+ Utf8 "InnerClasses"; // #19
+ Utf8 "TestInterfaceMethodSelection$A_I"; // #20
+ Utf8 "A_I"; // #21
+ Utf8 "TestInterfaceMethodSelection"; // #22
+ } // Constant Pool
+
+ 0x0020; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 125;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 126;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#19) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #18 8;
+ #4 #14 #21 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInterfaceMethodSelection$PB_A_I
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PB_A_PI.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,108 @@
+// m() is declared private
+
+class TestInterfaceMethodSelection$PB_A_PI {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #19; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestInterfaceMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #21; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PB_A_PI"; // #16
+ Utf8 "TestInterfaceMethodSelection$PB_A_PI"; // #17
+ Utf8 "InnerClasses"; // #18
+ Utf8 "TestInterfaceMethodSelection$A_PI"; // #19
+ Utf8 "A_PI"; // #20
+ Utf8 "TestInterfaceMethodSelection"; // #21
+ } // Constant Pool
+
+ 0x0020; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 140;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 141;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#18) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #16 8;
+ #4 #14 #20 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInterfaceMethodSelection$PB_A_PI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PB_PA_I.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,135 @@
+// rename m -> bad_m; real_m -> m
+
+class TestInterfaceMethodSelection$PB_PA_I {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #5 #17; // #1
+ String #18; // #2
+ String #19; // #3
+ class #20; // #4
+ class #22; // #5
+ Utf8 "<init>"; // #6
+ Utf8 "()V"; // #7
+ Utf8 "Code"; // #8
+ Utf8 "LineNumberTable"; // #9
+ Utf8 "bad_m"; // #10 - modified
+ Utf8 "()Ljava/lang/String;"; // #11
+ Utf8 "m"; // #12 - modified
+ Utf8 "SourceFile"; // #13
+ Utf8 "TestInterfaceMethodSelection.java"; // #14
+ Utf8 "NestHost"; // #15
+ class #24; // #16
+ NameAndType #6 #7; // #17
+ Utf8 "Should not see this"; // #18
+ Utf8 "PB_PA_I"; // #19
+ Utf8 "TestInterfaceMethodSelection$PB_PA_I"; // #20
+ Utf8 "InnerClasses"; // #21
+ Utf8 "TestInterfaceMethodSelection$PA_I"; // #22
+ Utf8 "PA_I"; // #23
+ Utf8 "TestInterfaceMethodSelection"; // #24
+ } // Constant Pool
+
+ 0x0020; // access
+ #4;// this_cpx
+ #5;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #6; // name_cpx
+ #7; // sig_cpx
+ [] { // Attributes
+ Attr(#8) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#9) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 132;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0001; // access
+ #10; // name_cpx
+ #11; // sig_cpx
+ [] { // Attributes
+ Attr(#8) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#9) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 133;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #12; // name_cpx
+ #11; // sig_cpx
+ [] { // Attributes
+ Attr(#8) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1203B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#9) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 134;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#13) { // SourceFile
+ #14;
+ } // end SourceFile
+ ;
+ Attr(#15) { // NestHost
+ 0x0010;
+ } // end NestHost
+ ;
+ Attr(#21) { // InnerClasses
+ [] { // InnerClasses
+ #4 #16 #19 8;
+ #5 #16 #23 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInterfaceMethodSelection$PB_PA_I
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PC_B_A.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// m() is declared private
+
+class TestMethodSelection$PC_B_A {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #20; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #22; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PC_B_A::m"; // #16
+ Utf8 "TestMethodSelection$PC_B_A"; // #17
+ Utf8 "PC_B_A"; // #18
+ Utf8 "InnerClasses"; // #19
+ Utf8 "TestMethodSelection$B_A"; // #20
+ Utf8 "B_A"; // #21
+ Utf8 "TestMethodSelection"; // #22
+ } // Constant Pool
+
+ 0x0021; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 130;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 131;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#19) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #18 9;
+ #4 #14 #21 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestMethodSelection$PC_B_A
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PC_B_PA.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// m() is declared private
+
+class TestMethodSelection$PC_B_PA {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #20; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #22; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PC_B_PA::m"; // #16
+ Utf8 "TestMethodSelection$PC_B_PA"; // #17
+ Utf8 "PC_B_PA"; // #18
+ Utf8 "InnerClasses"; // #19
+ Utf8 "TestMethodSelection$B_PA"; // #20
+ Utf8 "B_PA"; // #21
+ Utf8 "TestMethodSelection"; // #22
+ } // Constant Pool
+
+ 0x0021; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 144;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 145;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#19) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #18 9;
+ #4 #14 #21 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestMethodSelection$PC_B_PA
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/PC_PB_A.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// m() is declared private
+
+class TestMethodSelection$PC_PB_A {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #15; // #1
+ String #16; // #2
+ class #17; // #3
+ class #20; // #4
+ Utf8 "<init>"; // #5
+ Utf8 "()V"; // #6
+ Utf8 "Code"; // #7
+ Utf8 "LineNumberTable"; // #8
+ Utf8 "m"; // #9
+ Utf8 "()Ljava/lang/String;"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "TestMethodSelection.java"; // #12
+ Utf8 "NestHost"; // #13
+ class #22; // #14
+ NameAndType #5 #6; // #15
+ Utf8 "PC_PB_A::m"; // #16
+ Utf8 "TestMethodSelection$PC_PB_A"; // #17
+ Utf8 "PC_PB_A"; // #18
+ Utf8 "InnerClasses"; // #19
+ Utf8 "TestMethodSelection$PB_A"; // #20
+ Utf8 "PB_A"; // #21
+ Utf8 "TestMethodSelection"; // #22
+ } // Constant Pool
+
+ 0x0021; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 137;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - modified
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1202B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#8) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 138;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestHost
+ 0x000E;
+ } // end NestHost
+ ;
+ Attr(#19) { // InnerClasses
+ [] { // InnerClasses
+ #3 #14 #18 9;
+ #4 #14 #21 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestMethodSelection$PC_PB_A
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/TestInterfaceMethodSelection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test interface method selection process for private/public nestmate invocation
+ * @compile TestInterfaceMethodSelection.java
+ * @compile PA_I.jcod \
+ * PB_A_I.jcod \
+ * PB_A_PI.jcod \
+ * PB_PA_I.jcod
+ * @run main TestInterfaceMethodSelection
+ * @run main/othervm -Dsun.reflect.noInflation=true TestInterfaceMethodSelection
+ */
+
+// The first run will use NativeMethodAccessor and due to the limited number
+// of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the GeneratedMethodAccessor
+// instead. In this way both sets of Reflection classes are tested.
+
+/*
+We are setting up a basic test structure as follows:
+
+interface I {
+ ?? String m() [ return "I::m"; // private case]
+}
+class A implements I {
+ ?? String m() { return "A::m"; }
+}
+class B extends A {
+ ?? String m() { return "B::m"; }
+}
+
+where the access modifier of m() is either public or private in all combinations.
+The only cases of interest here are private and non-private, so we use public for
+the non-private case. Obviously for an interface, only the private case defines
+a method body for m() - we're not testing default methods here (but they would be
+invoked in the cases where we get AME).
+
+We then have a test function:
+
+void test(I target, String expected) {
+ check(target.m() == expected);
+}
+
+where the call to target.m() is expressed as an invokeinterface I::m on target. We
+then pass either an A instance or a B instance and check the expected method
+is invoked. In all cases the resolved method is I::m, so we are effectively
+testing the method selection rules. We are not testing resolution here.
+
+The expected behaviour is as follows (where P means m() is private and - means
+m() is public).
+
+Target I.m A.m B.m Result Reason
+------------------------------------------
+ A P P n/a I.m [1]
+ A P - n/a I.m [1]
+ A - P n/a AME [2]
+ A - - n/a A.m [3]
+ B P P P I.m [1]
+ B P P - I.m [1]
+ B P - P I.m [1]
+ B P - - I.m [1]
+ B - P P AME [2]
+ B - P - B.m [3]
+ B - - P A.m [4]
+ B - - - B.m [3]
+
+[1] Resolved method is private => selected method == resolved method
+[2] private A.m/B.m doesn't override abstract public I.m => AbstractMethodError
+[3] Normal overriding: most specific method selected
+[4] private B.m doesn't override public A.m/I.m so is ignored => A.m selected
+
+To allow us to do this in source code we encode the inheritance hierarchy in the
+class name, and we use plain I (for example) when m() is public and PI when m()
+is private. So class B_A_I defines a public m() and inherits public m() from
+both A and I. While PB_PA_PI defines a private m() and also has private m()
+defined in its superclass PA and implemented interface PI.
+
+For cases where the subclass makes a public method private we can't write this
+directly in Java source code so we have to have jcod versions that change
+the access modifier to private, but we also need to switch between having a
+method implementation or not, so add fake_m() and then rename in the jcod file.
+The affected cases are:
+
+- PA_I
+- PB_A_I
+- PB_PA_I
+- PB_A_PI
+
+We test direct invocation from Java source, MethodHandle invocation and core
+reflection invocation. For MH and reflection we look for the method in "I" to
+maintain the same resolution process as in the direct case.
+*/
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestInterfaceMethodSelection {
+
+ static final MethodType M_T = MethodType.methodType(String.class);
+
+ static interface I {
+ public String m();
+ }
+ static interface PI {
+ private String m() { return "PI::m"; }
+ }
+
+ static class A_I implements I {
+ public String m() { return "A_I::m"; }
+ }
+ static class A_PI implements PI {
+ public String m() { return "A_PI::m"; }
+ }
+ // jcod version will edit method names
+ static class PA_I implements I {
+ private String real_m() { return "PA_I::m"; }
+ public String m() { return "Should not see this"; }
+ }
+ static class PA_PI implements PI {
+ private String m() { return "PA_PI::m"; }
+ }
+
+ static class B_A_I extends A_I {
+ public String m() { return "B_A_I::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PB_A_I extends A_I {
+ public String m() { return "PB_A_I::m"; }
+ }
+ static class B_PA_I extends PA_I {
+ public String m() { return "B_PA_I::m"; }
+ }
+ // jcod version will edit method names
+ static class PB_PA_I extends PA_I {
+ public String m() { return "Should not see this"; }
+ private String real_m() { return "PB_PA_I"; }
+ }
+ static class B_A_PI extends A_PI {
+ public String m() { return "B_A_PI::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PB_A_PI extends A_PI {
+ public String m() { return "PB_A_PI"; }
+ }
+ static class B_PA_PI extends PA_PI {
+ public String m() { return "B_PA_PI::m"; }
+ }
+ static class PB_PA_PI extends PA_PI {
+ private String m() { return "PB_PA_PI::m"; }
+ }
+
+ // Need a test function for each of the "I" interfaces
+
+ static void doInvoke(I target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(I.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)I.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+ static void doInvoke(PI target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(PI.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)PI.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+
+ static void badInvoke(I target) {
+ badDirectInvoke(target);
+ badMHInvoke(target);
+ badReflectInvoke(target);
+ }
+
+ static void badDirectInvoke(I target) {
+ try {
+ target.m();
+ throw new Error("Unexpected success directly invoking " +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError");
+ }
+ catch (AbstractMethodError expected) {
+ }
+ catch (Throwable t) {
+ throw new Error("Unexpected exception directly invoking " +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError got: " + t);
+ }
+ }
+
+ static void badMHInvoke(I target) {
+ try {
+ lookup().findVirtual(I.class, "m", M_T).invoke(target);
+ throw new Error("Unexpected success for MH invoke of" +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError");
+ }
+ catch (AbstractMethodError expected) {
+ }
+ catch (Throwable t) {
+ throw new Error("Unexpected exception for MH invoke of " +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError got: " + t);
+ }
+ }
+
+ static void badReflectInvoke(I target) {
+ try {
+ I.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]);
+ throw new Error("Unexpected success for Method invoke of" +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError");
+ }
+ catch (InvocationTargetException expected) {
+ Throwable t = expected.getCause();
+ if (!(t instanceof AbstractMethodError)) {
+ throw new Error("Unexpected exception for Method invoke of " +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError got: " + t);
+
+ }
+ }
+ catch (Throwable t) {
+ throw new Error("Unexpected exception for Method invoke of " +
+ target.getClass().getSimpleName() +
+ ".m() - expected AbstractMethodError got: " + t);
+ }
+ }
+
+ static void check(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Selection error: expected " + expected +
+ " but got " + actual);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // First pass a suitable "A" instance
+ doInvoke(new PA_PI(), "PI::m");
+ doInvoke(new A_PI(), "PI::m");
+ badInvoke(new PA_I());
+ doInvoke(new A_I(), "A_I::m");
+ // Now a "B" instance
+ doInvoke(new PB_PA_PI(), "PI::m");
+ doInvoke(new B_PA_PI(), "PI::m");
+ doInvoke(new PB_A_PI(), "PI::m");
+ doInvoke(new B_A_PI(), "PI::m");
+ badInvoke(new PB_PA_I());
+ doInvoke(new B_PA_I(), "B_PA_I::m");
+ doInvoke(new PB_A_I(), "A_I::m");
+ doInvoke(new B_A_I(), "B_A_I::m");
+ }
+}
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/methodSelection/TestMethodSelection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test method selection process for private/public nestmate invocation
+ * @compile TestMethodSelection.java
+ * @compile PB_A.jcod \
+ * PC_B_A.jcod \
+ * PC_B_PA.jcod \
+ * PC_PB_A.jcod
+ * @run main/othervm TestMethodSelection
+ * @run main/othervm -Dsun.reflect.noInflation=true TestMethodSelection
+ */
+
+// The first run will use NativeMethodAccessor and due to the limited number
+// of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the GeneratedMethodAccessor
+// instead. In this way both sets of Reflection classes are tested.
+
+/*
+We are setting up a basic test structure as follows:
+
+class A {
+ ?? String m() { return "A::m"; }
+}
+class B extends A {
+ ?? String m() { return "B::m"; }
+}
+class C extends B {
+ ?? String m() { return "C::m"; }
+}
+
+where the access modifier of m() is either public or private in all combinations.
+The only cases of interest here are private and non-private, so we use public for
+the non-private case.
+
+We then have a test function:
+
+void test(B target, String expected) {
+ check(target.m() == expected);
+}
+
+where the call to target.m() is expressed as an invokevirtual B::m on target. We
+then pass either a B instance or a C instance and check that the expected method
+is invoked. In all cases the resolved method is B::m, so we are effectively
+testing the method selection rules. We are not testing resolution here.
+
+The expected behaviour is as follows (where P means m() is private and - means
+m() is public).
+
+Target A.m B.m C.m Result Reason
+------------------------------------------
+ B P P n/a B.m [1]
+ B P - n/a B.m [2]
+ B - P n/a B.m [1]
+ B - - n/a B.m [2]
+ C P P P B.m [1]
+ C P P - B.m [1]
+ C P - P B.m [3]
+ C P - - C.m [2]
+ c - P P B.m [1]
+ C - P - B.m [1]
+ C - - P B.m [3]
+ C - - - C.m [2]
+
+[1] Resolved method is private => selected method == resolved method
+[2] target-type.m() can override B.m => selected method == target-type.m()
+[3] private C.m does not override resolved public method B.m, but
+ C has a superclass B, with B.m that (trivially) overrides resolved B.m
+ => selected method = B.m
+
+To allow us to do this in source code we encode the inheritance hierarchy in the
+class name, and we use plain A (for example) when m() is public and PA when m()
+is private. So class C_B_A defines a public m() and inherits public m() from
+both B and A. While PC_PB_PA defines a private m() and also has private m()
+defined in its superclasses PB and PA.
+
+For cases where the subclass makes a public method private we can't write this
+directly in Java source code so we have to have jcod versions that change
+the access modifier to private. This occurs for:
+
+- PC_B_A
+- PB_A
+- PC_B_PA
+- PC_PB_A
+
+We test direct invocation from Java source, MethodHandle invocation and core
+reflection invocation. For MH and reflection we look for the method in "B" to
+maintain the same resolution process as in the direct case.
+*/
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+import java.lang.reflect.InvocationTargetException;
+
+public class TestMethodSelection {
+
+ static final MethodType M_T = MethodType.methodType(String.class);
+
+ static class A {
+ public String m() { return "A::m"; }
+ }
+ static class PA {
+ private String m() { return "PA::m"; }
+ }
+
+ static class B_A extends A {
+ public String m() { return "B_A::m"; }
+ }
+ static class B_PA extends PA {
+ public String m() { return "B_PA::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PB_A extends A {
+ public String m() { return "PB_A::m"; }
+ }
+ static class PB_PA extends PA {
+ private String m() { return "PB_PA::m"; }
+ }
+
+ static class C_B_A extends B_A {
+ public String m() { return "C_B_A::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PC_B_A extends B_A {
+ public String m() { return "PC_B_A"; }
+ }
+ static class C_PB_A extends PB_A {
+ public String m() { return "C_PB_A::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PC_PB_A extends PB_A {
+ public String m() { return "PC_PB_A"; }
+ }
+ static class C_B_PA extends B_PA {
+ public String m() { return "C_B_PA::m"; }
+ }
+ // jcod version will rewrite this to have private m()
+ static class PC_B_PA extends B_PA {
+ public String m() { return "PC_B_PA"; }
+ }
+ static class C_PB_PA extends PB_PA {
+ public String m() { return "C_PB_PA::m"; }
+ }
+ static class PC_PB_PA extends PB_PA {
+ private String m() { return "PC_PB_PA::m"; }
+ }
+
+ // Need a test function for each of the "B" classes
+
+ static void doInvoke(B_A target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(B_A.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)B_A.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+ static void doInvoke(B_PA target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(B_PA.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)B_PA.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+ static void doInvoke(PB_A target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(PB_A.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)PB_A.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+ static void doInvoke(PB_PA target, String expected) throws Throwable {
+ // Direct
+ check(target.m(), expected);
+ // MethodHandle
+ MethodHandle mh = lookup().findVirtual(PB_PA.class, "m", M_T);
+ check((String)mh.invoke(target), expected);
+ // Reflection
+ check((String)PB_PA.class.getDeclaredMethod("m", new Class<?>[0]).
+ invoke(target, new Object[0]), expected);
+ }
+
+ static void check(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Selection error: expected " + expected +
+ " but got " + actual);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // First pass a suitable "B" instance
+ doInvoke(new PB_PA(), "PB_PA::m");
+ doInvoke(new B_PA(), "B_PA::m");
+ doInvoke(new PB_A(), "PB_A::m");
+ doInvoke(new B_A(), "B_A::m");
+ // Now a "C" instance
+ doInvoke(new PC_PB_PA(), "PB_PA::m");
+ doInvoke(new C_PB_PA(), "PB_PA::m");
+ doInvoke(new PC_B_PA(), "B_PA::m");
+ doInvoke(new C_B_PA(), "C_B_PA::m");
+ doInvoke(new PC_PB_A(), "PB_A::m");
+ doInvoke(new C_PB_A(), "PB_A::m");
+ doInvoke(new PC_B_A(), "B_A::m");
+ doInvoke(new C_B_A(), "C_B_A::m");
+ }
+}
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/ExternalSub.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Generated from: ExternalSub.java
+
+ Super constructor call is changed from the public NestedA(int)
+ constructor to the private NestedA() constructor.
+*/
+
+class ExternalSub {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #10; // #1
+ class #11; // #2
+ class #13; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestConstructorHierarchy.java"; // #9
+ NameAndType #4 #5; // #10 - modified #16 to #5
+ Utf8 "ExternalSub"; // #11
+ class #17; // #12
+ Utf8 "TestConstructorHierarchy$NestedA"; // #13
+ Utf8 "NestedA"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "(I)V"; // #16
+ Utf8 "TestConstructorHierarchy"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001 // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack - modified from 2
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 84;
+// 5 85;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #3 #12 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class ExternalSub
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/ExternalSuper.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+/* Generated from: ExternalSuper.java
+
+ Constructor access level is changed to private.
+*/
+
+class ExternalSuper {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #10; // #1
+ class #11; // #2
+ class #12; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestConstructorHierarchy.java"; // #9
+ NameAndType #4 #5; // #10
+ Utf8 "ExternalSuper"; // #11
+ Utf8 "java/lang/Object"; // #12
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0002; // access - modified to private
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 78;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ } // Attributes
+} // end class ExternalSuper
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestConstructorHierarchy.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private constructors in the hierarchy that are
+ * outside the nest
+ * @compile TestConstructorHierarchy.java
+ * @compile ExternalSuper.jcod
+ * ExternalSub.jcod
+ * @run main TestConstructorHierarchy
+ */
+
+public class TestConstructorHierarchy {
+
+ static class NestedA extends ExternalSuper {
+ private NestedA() {}
+ protected NestedA(int i) {} // for compile-time only
+ }
+
+ // Access to private members of classes outside the nest is
+ // not permitted. These tests should throw IllegalAccessError
+ // at runtime. To allow them to compile the classes below are
+ // defined with public members. We then replace those class files
+ // with jcod variants that make the member private again.
+
+ public static void main(String[] args) throws Throwable {
+ try {
+ new ExternalSuper();
+ throw new Error("Unexpected construction of ExternalSuper");
+ }
+ catch (IllegalAccessError iae) {
+ if (iae.getMessage().contains("tried to access method ExternalSuper.<init>()V from class TestConstructorHierarchy")) {
+ System.out.println("Got expected exception constructing ExternalSuper: " + iae);
+ }
+ else throw new Error("Unexpected IllegalAccessError: " + iae);
+ }
+ try {
+ new NestedA();
+ throw new Error("Unexpected construction of NestedA and supers");
+ }
+ catch (IllegalAccessError iae) {
+ if (iae.getMessage().contains("tried to access method ExternalSuper.<init>()V from class TestConstructorHierarchy$NestedA")) {
+ System.out.println("Got expected exception constructing NestedA: " + iae);
+ }
+ else throw new Error("Unexpected IllegalAccessError: " + iae);
+ }
+ try {
+ new ExternalSub();
+ throw new Error("Unexpected construction of ExternalSub");
+ }
+ catch (IllegalAccessError iae) {
+ if (iae.getMessage().contains("tried to access method TestConstructorHierarchy$NestedA.<init>()V from class ExternalSub")) {
+ System.out.println("Got expected exception constructing ExternalSub: " + iae);
+ }
+ else throw new Error("Unexpected IllegalAccessError: " + iae);
+ }
+ }
+}
+
+// Classes that are not part of the nest.
+// Being non-public allows us to declare them in this file.
+// The constructor is public to allow this file to compile, but
+// the jcod files change it back to private.
+
+class ExternalSuper {
+ public ExternalSuper() { }
+}
+
+
+class ExternalSub extends TestConstructorHierarchy.NestedA {
+ public ExternalSub() {
+ super(0); // this is changed to super() in jcod file
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestInvokeSpecial.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private constructors between nestmates and nest-host
+ * using different flavours of named nested types that will
+ * generate invokespecial for the calls. The -Xcomp run is a special
+ * regression test for a compiler assertion that would fire when
+ * "loading" a nest-host class.
+ * @run main TestInvokeSpecial
+ * @run main/othervm -Xcomp TestInvokeSpecial
+ */
+
+public class TestInvokeSpecial {
+
+ // All constructors are private to ensure nestmate access checks apply
+
+ // All doConstruct methods are public so they don't involve invoke_special
+
+ private TestInvokeSpecial() {}
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ default void doConstruct(TestInvokeSpecial o) {
+ Object obj = new TestInvokeSpecial();
+ }
+ default void doConstruct(InnerNested o) {
+ Object obj = new TestInvokeSpecial().new InnerNested();
+ }
+ default void doConstruct(StaticNested o) {
+ Object obj = new StaticNested();
+ }
+ default void doConstruct(StaticIface o) {
+ Object obj = new StaticIface() {};
+ }
+ }
+
+ static class StaticNested {
+
+ private StaticNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestInvokeSpecial o) {
+ Object obj = new TestInvokeSpecial();
+ }
+ public void doConstruct(InnerNested o) {
+ Object obj = new TestInvokeSpecial().new InnerNested();
+ }
+ public void doConstruct(StaticNested o) {
+ Object obj = new StaticNested();
+ }
+ public void doConstruct(StaticIface o) {
+ Object obj = new StaticIface() {};
+ }
+ }
+
+ class InnerNested {
+
+ private InnerNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestInvokeSpecial o) {
+ Object obj = new TestInvokeSpecial();
+ }
+ public void doConstruct(InnerNested o) {
+ Object obj = new TestInvokeSpecial().new InnerNested();
+ }
+ public void doConstruct(StaticNested o) {
+ Object obj = new StaticNested();
+ }
+ public void doConstruct(StaticIface o) {
+ Object obj = new StaticIface() {};
+ }
+ }
+
+ public static void main(String[] args) {
+ // These initial constructions test nest-host access
+ TestInvokeSpecial o = new TestInvokeSpecial();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ s.doConstruct(o);
+ s.doConstruct(i);
+ s.doConstruct(s);
+ s.doConstruct(intf);
+
+ i.doConstruct(o);
+ i.doConstruct(i);
+ i.doConstruct(s);
+ i.doConstruct(intf);
+
+ intf.doConstruct(o);
+ intf.doConstruct(i);
+ intf.doConstruct(s);
+ intf.doConstruct(intf);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test JNI access to private constructors between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNI
+ * @run main/othervm/native -Xcheck:jni TestJNI
+ */
+public class TestJNI {
+
+ // Unlike reflection, the calling context is not relevant to JNI
+ // calls, but we keep the same structure as the reflection tests.
+
+
+ // All constructors are private to ensure nestmate access checks apply
+
+ // All doConstruct methods are public so they don't involve nestmate access
+
+ private TestJNI() {}
+
+ // The various nestmates
+
+ // Note: No constructor on interfaces so no StaticIface variants
+
+ static interface StaticIface {
+
+ // Methods that will access private constructors of nestmates.
+
+ default void doConstruct(TestJNI o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ default void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable {
+ Object obj = newInstance(o.getClass(), outerThis);
+ }
+ default void doConstruct(StaticNested o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ }
+
+ static class StaticNested {
+
+ private StaticNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestJNI o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ public void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable {
+ Object obj = newInstance(o.getClass(), outerThis);
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ }
+
+ class InnerNested {
+
+ private InnerNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestJNI o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ public void doConstruct(TestJNI outerThis, InnerNested o) throws Throwable {
+ Object obj = newInstance(o.getClass(), outerThis);
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ Object obj = newInstance(o.getClass());
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // These initial constructions test nest-host access to members
+
+ TestJNI o = newInstance(TestJNI.class);
+ StaticNested s = (StaticNested) newInstance(StaticNested.class);
+ InnerNested i = (InnerNested) newInstance(InnerNested.class, o);
+
+ // We need a StaticIface instance to call doConstruct on
+ StaticIface intf = new StaticIface() {};
+
+ s.doConstruct(o);
+ s.doConstruct(o, i);
+ s.doConstruct(s);
+
+ i.doConstruct(o);
+ i.doConstruct(o, i);
+ i.doConstruct(s);
+
+ intf.doConstruct(o);
+ intf.doConstruct(o, i);
+ intf.doConstruct(s);
+ }
+
+ static <T> T newInstance(Class<T> klass) {
+ return newInstance(klass, null);
+ }
+
+ static <T> T newInstance(Class<T> klass, Object outerThis) {
+ String sig = (outerThis == null) ?
+ "()V" :
+ "(L" + outerThis.getClass().getName() + ";)V";
+ String definingClass = klass.getName();
+ String desc = " Invocation of constructor " + definingClass + sig;
+ try {
+ T ret = (T) NestmatesJNI.newInstance(definingClass, sig, outerThis);
+ System.out.println(desc + " - passed");
+ return ret;
+ }
+ catch (Throwable t) {
+ throw new Error(desc + ": Unexpected exception: " + t, t);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestMethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private constructors between nestmates and nest-host
+ * using different flavours of named nested types using MethodHandles
+ * @run main TestMethodHandles
+ */
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestMethodHandles {
+
+ static final MethodType NOARG_T = MethodType.methodType(void.class);
+ static final MethodType INNER_T = MethodType.methodType(void.class, TestMethodHandles.class);
+
+ // All constructors are private to ensure nestmate access checks apply
+
+ // All doConstruct methods are public so they don't involve invoke_special
+
+ private TestMethodHandles() {}
+
+ // The various nestmates
+
+ // Note: No constructor on interfaces so no StaticIface variants
+
+ static interface StaticIface {
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ default void doConstruct(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(TestMethodHandles.class, NOARG_T);
+ TestMethodHandles obj = (TestMethodHandles) mh.invoke();
+ obj = (TestMethodHandles) mh.invokeExact();
+ }
+ default void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(InnerNested.class, INNER_T);
+ InnerNested obj = (InnerNested) mh.invoke(outer);
+ obj = (InnerNested) mh.invokeExact(outer);
+ }
+ default void doConstruct(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(StaticNested.class, NOARG_T);
+ StaticNested obj = (StaticNested) mh.invoke();
+ obj = (StaticNested) mh.invokeExact();
+ }
+ }
+
+ static class StaticNested {
+
+ private StaticNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(TestMethodHandles.class, NOARG_T);
+ TestMethodHandles obj = (TestMethodHandles) mh.invoke();
+ obj = (TestMethodHandles) mh.invokeExact();
+ }
+ public void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(InnerNested.class, INNER_T);
+ InnerNested obj = (InnerNested) mh.invoke(outer);
+ obj = (InnerNested) mh.invokeExact(outer);
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(StaticNested.class, NOARG_T);
+ StaticNested obj = (StaticNested) mh.invoke();
+ obj = (StaticNested) mh.invokeExact();
+ }
+ }
+
+ class InnerNested {
+
+ private InnerNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(TestMethodHandles.class, NOARG_T);
+ TestMethodHandles obj = (TestMethodHandles) mh.invoke();
+ obj = (TestMethodHandles) mh.invokeExact();
+ }
+ public void doConstruct(TestMethodHandles outer, InnerNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(InnerNested.class, INNER_T);
+ InnerNested obj = (InnerNested) mh.invoke(outer);
+ obj = (InnerNested) mh.invokeExact(outer);
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findConstructor(StaticNested.class, NOARG_T);
+ StaticNested obj = (StaticNested) mh.invoke();
+ obj = (StaticNested) mh.invokeExact();
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // These initial constructions test nest-host access
+ MethodHandle mh =
+ lookup().findConstructor(TestMethodHandles.class, NOARG_T);
+ TestMethodHandles o = (TestMethodHandles) mh.invoke();
+ o = (TestMethodHandles) mh.invokeExact();
+
+ mh = lookup().findConstructor(StaticNested.class, NOARG_T);
+ StaticNested s = (StaticNested) mh.invoke();
+ s = (StaticNested) mh.invokeExact();
+
+ mh = lookup().findConstructor(InnerNested.class, INNER_T);
+ InnerNested i = (InnerNested) mh.invoke(o);
+ i = (InnerNested) mh.invokeExact(o);
+
+ StaticIface intf = new StaticIface() {};
+
+ s.doConstruct(o);
+ s.doConstruct(o, i);
+ s.doConstruct(s);
+
+ i.doConstruct(o);
+ i.doConstruct(o, i);
+ i.doConstruct(s);
+
+ intf.doConstruct(o);
+ intf.doConstruct(o, i);
+ intf.doConstruct(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateConstructors/TestReflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private constructors between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @run main TestReflection
+ * @run main/othervm -Dsun.reflect.noInflation=true TestReflection
+ */
+
+// The first run will use NativeConstructorAccessor and due to the limited
+// number of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the
+// GeneratedConstructorAccessor instead.
+// In this way both sets of Reflection classes are tested.
+
+public class TestReflection {
+
+ // All constructors are private to ensure nestmate access checks apply
+
+ // All doConstruct methods are public so they don't involve invoke_special
+
+ private TestReflection() {}
+
+ // The various nestmates
+
+ // Note: No constructor on interfaces so no StaticIface variants
+
+ static interface StaticIface {
+
+ // Methods that will access private constructors of nestmates.
+
+ default void doConstruct(TestReflection o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ default void doConstruct(TestReflection tr, InnerNested o) throws Throwable {
+ Object obj = InnerNested.class.getDeclaredConstructor(new Class<?>[] {TestReflection.class}).newInstance(new Object[] { tr });
+ }
+ default void doConstruct(StaticNested o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ }
+
+ static class StaticNested {
+
+ private StaticNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestReflection o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public void doConstruct(TestReflection tr, InnerNested o) throws Throwable {
+ Object obj = InnerNested.class.getDeclaredConstructor(new Class<?>[] {TestReflection.class}).newInstance(new Object[] { tr });
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ }
+
+ class InnerNested {
+
+ private InnerNested() {}
+
+ // Methods that will access private constructors of nestmates.
+ // The arg is a dummy for overloading purposes
+
+ public void doConstruct(TestReflection o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ public void doConstruct(TestReflection tr, InnerNested o) throws Throwable {
+ Object obj = InnerNested.class.getDeclaredConstructor(new Class<?>[] {TestReflection.class}).newInstance(new Object[] { tr });
+ }
+ public void doConstruct(StaticNested o) throws Throwable {
+ Object obj = o.getClass().getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // These initial constructions test nest-host access
+ TestReflection o = TestReflection.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ StaticNested s = StaticNested.class.getDeclaredConstructor(new Class<?>[0]).newInstance(new Object[0]);
+ InnerNested i = InnerNested.class.getDeclaredConstructor(new Class<?>[] {TestReflection.class}).newInstance(new Object[] { o });
+
+ StaticIface intf = new StaticIface() {};
+
+ s.doConstruct(o);
+ s.doConstruct(o, i);
+ s.doConstruct(s);
+
+ i.doConstruct(o);
+ i.doConstruct(o, i);
+ i.doConstruct(s);
+
+ intf.doConstruct(o);
+ intf.doConstruct(o, i);
+ intf.doConstruct(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test JNI access to private fields between nestmates and nest-host
+ * using different flavours of named nested types
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNI
+ * @run main/othervm/native -Xcheck:jni TestJNI
+ */
+public class TestJNI {
+
+ // Private field of nest-host for nestmates to access
+ private int priv_field;
+
+ static final String FIELD = "priv_field";
+
+ // public constructor so we aren't relying on private access
+ public TestJNI() {}
+
+ // Methods that will access private fields of nestmates
+
+ // NOTE: No StaticIface variants as interfaces can't have instance fields
+
+ void access_priv(TestJNI o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private fields of nestmates
+
+ default void access_priv(TestJNI o) {
+ int priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ default void access_priv(InnerNested o) {
+ int priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ default void access_priv(StaticNested o) {
+ int priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ }
+
+ static class StaticNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private fields of nestmates
+
+ void access_priv(TestJNI o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ }
+
+ class InnerNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestJNI o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = getAndInc(o, o.getClass(), FIELD);
+ }
+ }
+
+ public static void main(String[] args) {
+ TestJNI o = new TestJNI();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestJNI());
+ o.access_priv(i);
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ }
+
+ static int getAndInc(Object target, Class<?> klass, String field) {
+ String definingClass = klass.getName();
+ String desc = "Access to field " +
+ definingClass + "." + field + " on instance of class " +
+ target.getClass().getName();
+ int first, second;
+ try {
+ first = NestmatesJNI.getIntField(target, definingClass, field);
+ NestmatesJNI.setIntField(target, definingClass, field, (first + 1));
+ second = NestmatesJNI.getIntField(target, definingClass, field);
+ }
+ catch (Throwable t) {
+ throw new Error(desc + ": Unexpected exception: " + t, t);
+ }
+ if (second != first + 1) {
+ throw new Error(desc + ": wrong field values: first=" + first +
+ ", second=" + second + " (should equal first+1)");
+ }
+ System.out.println(desc + " - passed");
+ return first;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestMethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private fields between nestmates and nest-host
+ * using different flavours of named nested types using MethodHandles
+ * @run main TestMethodHandles
+ */
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+
+public class TestMethodHandles {
+
+ // Private field of nest-host for nestmates to access
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestMethodHandles() {}
+
+ // Methods that will access private fields of nestmates
+
+ // NOTE: No StaticIface variants as interfaces can't have instance fields
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, new StaticNested()); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, new StaticNested()); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private fields of nestmates
+
+ default void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ int priv_field = (int) mh.invoke(o);
+ priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ default void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ int priv_field = (int) mh.invoke(o);
+ priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ int priv_field = (int) mh.invoke(o);
+ priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ }
+
+ static class StaticNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private fields of nestmates
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, new TestMethodHandles()); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, new TestMethodHandles()); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ }
+
+ class InnerNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, new StaticNested()); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, new StaticNested()); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findGetter(o.getClass(), "priv_field", int.class);
+ this.priv_field = (int) mh.invoke(o);
+ this.priv_field = (int) mh.invokeExact(o);
+ checkBadInvokeG(mh, this); // wrong nestmate
+ checkBadInvokeG(mh, mh); // completely wrong type
+
+ mh = lookup().findSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(o, 2);
+ mh.invokeExact(o, 3);
+ checkBadInvokeS(mh, this); // wrong nestmate
+ checkBadInvokeS(mh, mh); // completely wrong type
+ }
+ }
+
+ static void checkBadInvokeG(MethodHandle mh, Object o) throws Throwable {
+ try {
+ int x = (int) mh.invoke(o);
+ throw new Error("Invoke on MethodHandle " + mh + " with receiver "
+ + o + "should have failed with ClassCastException!");
+ }
+ catch (ClassCastException expected) {
+ System.out.println("invoke got expected exception: " + expected);
+ }
+ }
+
+ static void checkBadInvokeS(MethodHandle mh, Object o) throws Throwable {
+ try {
+ mh.invoke(o, 42);
+ throw new Error("Invoke on MethodHandle " + mh + " with receiver "
+ + o + "should have failed with ClassCastException!");
+ }
+ catch (ClassCastException expected) {
+ System.out.println("invoke got expected exception: " + expected);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestMethodHandles o = new TestMethodHandles();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestMethodHandles());
+ o.access_priv(i);
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestPrivateField.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private fields between nestmates and nest-host
+ * using different flavours of named nested types
+ * @run main TestPrivateField
+ */
+
+public class TestPrivateField {
+
+ // Private field of nest-host for nestmates to access
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestPrivateField() {}
+
+ // Methods that will access private fields of nestmates
+
+ // NOTE: No StaticIface variants as interfaces can't have instance fields
+
+ void access_priv(TestPrivateField o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = o.priv_field++;
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private fields of nestmates
+
+ default void access_priv(TestPrivateField o) {
+ int priv_field = o.priv_field++;
+ }
+ default void access_priv(InnerNested o) {
+ int priv_field = o.priv_field++;
+ }
+ default void access_priv(StaticNested o) {
+ int priv_field = o.priv_field++;
+ }
+ }
+
+ static class StaticNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private fields of nestmates
+
+ void access_priv(TestPrivateField o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = o.priv_field++;
+ }
+ }
+
+ class InnerNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestPrivateField o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(InnerNested o) {
+ this.priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ this.priv_field = o.priv_field++;
+ }
+ }
+
+ public static void main(String[] args) {
+ TestPrivateField o = new TestPrivateField();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestPrivateField());
+ o.access_priv(i);
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateFields/TestReflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private fields between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @run main TestReflection
+ */
+
+import java.lang.reflect.Field;
+
+public class TestReflection {
+
+ // Private field of nest-host for nestmates to access
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestReflection() {}
+
+ // Methods that will access private fields of nestmates
+
+ // NOTE: No StaticIface variants as interfaces can't have instance fields
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private fields of nestmates
+
+ default void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ int priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ default void access_priv(InnerNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ int priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ int priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ }
+
+ static class StaticNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private fields of nestmates
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ }
+
+ class InnerNested {
+
+ private int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ this.priv_field = f.getInt(o);
+ f.setInt(o, 2);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestReflection o = new TestReflection();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestReflection());
+ o.access_priv(i);
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/ExternalSub.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Generated from the source in TestInvokeHierarchy.java
+// with priv_invoke access modifier changed to private
+
+class ExternalSub {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #16; // #1
+ class #17; // #2
+ String #18; // #3
+ class #20; // #4
+ Utf8 "ID"; // #5
+ Utf8 "Ljava/lang/String;"; // #6
+ Utf8 "ConstantValue"; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "priv_invoke"; // #12
+ Utf8 "()Ljava/lang/String;"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestInvokeHierarchy.java"; // #15
+ NameAndType #8 #9; // #16
+ Utf8 "ExternalSub"; // #17
+ Utf8 "ExternalSub::priv_invoke"; // #18
+ class #23; // #19
+ Utf8 "TestInvokeHierarchy$NestedC"; // #20
+ Utf8 "NestedC"; // #21
+ Utf8 "InnerClasses"; // #22
+ Utf8 "TestInvokeHierarchy"; // #23
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0018; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // ConstantValue
+ #3;
+ } // end ConstantValue
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 129;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - private
+ #12; // name_cpx
+ #13; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1203B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 132;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#22) { // InnerClasses
+ [] { // InnerClasses
+ #4 #19 #21 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class ExternalSub
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/ExternalSuper.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Generated from the source in TestInvokeHierarchy.java
+// with priv_invoke access modifier changed to private
+
+class ExternalSuper {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #16; // #1
+ class #17; // #2
+ String #18; // #3
+ class #19; // #4
+ Utf8 "ID"; // #5
+ Utf8 "Ljava/lang/String;"; // #6
+ Utf8 "ConstantValue"; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "priv_invoke_s"; // #12
+ Utf8 "()Ljava/lang/String;"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "TestInvokeHierarchy.java"; // #15
+ NameAndType #8 #9; // #16
+ Utf8 "ExternalSuper"; // #17
+ Utf8 "ExternalSuper::priv_invoke_s"; // #18
+ Utf8 "java/lang/Object"; // #19
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0018; // access
+ #5; // name_cpx
+ #6; // sig_cpx
+ [] { // Attributes
+ Attr(#7) { // ConstantValue
+ #3;
+ } // end ConstantValue
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 119;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access - private
+ #12; // name_cpx
+ #13; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x1203B0;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 124;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ } // Attributes
+} // end class ExternalSuper
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/MissingMethod.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Generated from the source in TestInvokeErrors.java
+// with priv_invoke renamed to not_priv_invoke so it isn't found
+
+class TestInvokeErrors$MissingMethod {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #16; // #1
+ Field #17 #18; // #2
+ String #19; // #3
+ Method #20 #21; // #4
+ class #22; // #5
+ class #25; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "not_priv_invoke"; // #11 - renamed
+ Utf8 "SourceFile"; // #12
+ Utf8 "TestInvokeErrors.java"; // #13
+ Utf8 "NestHost"; // #14
+ class #26; // #15
+ NameAndType #7 #8; // #16
+ class #27; // #17
+ NameAndType #28 #29; // #18
+ Utf8 "MissingMethod::priv_invoke"; // #19
+ class #30; // #20
+ NameAndType #31 #32; // #21
+ Utf8 "TestInvokeErrors$MissingMethod"; // #22
+ Utf8 "MissingMethod"; // #23
+ Utf8 "InnerClasses"; // #24
+ Utf8 "java/lang/Object"; // #25
+ Utf8 "TestInvokeErrors"; // #26
+ Utf8 "java/lang/System"; // #27
+ Utf8 "out"; // #28
+ Utf8 "Ljava/io/PrintStream;"; // #29
+ Utf8 "java/io/PrintStream"; // #30
+ Utf8 "println"; // #31
+ Utf8 "(Ljava/lang/String;)V"; // #32
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 35;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #11; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 38;
+ 8 39;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ ;
+ Attr(#14) { // NestHost
+ 0x000F;
+ } // end NestHost
+ ;
+ Attr(#24) { // InnerClasses
+ [] { // InnerClasses
+ #5 #15 #23 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInvokeErrors$MissingMethod
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/MissingMethodWithSuper.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Generated from the source in TestInvokeErrors.java
+// with priv_invoke renamed to not_priv_invoke so it isn't found
+
+class TestInvokeErrors$MissingMethodWithSuper {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #16; // #1
+ Field #17 #18; // #2
+ String #19; // #3
+ Method #20 #21; // #4
+ class #22; // #5
+ class #25; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "not_priv_invoke"; // #11 - rename
+ Utf8 "SourceFile"; // #12
+ Utf8 "TestInvokeErrors.java"; // #13
+ Utf8 "NestHost"; // #14
+ class #27; // #15
+ NameAndType #7 #8; // #16
+ class #28; // #17
+ NameAndType #29 #30; // #18
+ Utf8 "MissingMethodWithSuper::priv_invoke"; // #19
+ class #31; // #20
+ NameAndType #32 #33; // #21
+ Utf8 "TestInvokeErrors$MissingMethodWithSuper"; // #22
+ Utf8 "MissingMethodWithSuper"; // #23
+ Utf8 "InnerClasses"; // #24
+ Utf8 "TestInvokeErrors$Nested"; // #25
+ Utf8 "Nested"; // #26
+ Utf8 "TestInvokeErrors"; // #27
+ Utf8 "java/lang/System"; // #28
+ Utf8 "out"; // #29
+ Utf8 "Ljava/io/PrintStream;"; // #30
+ Utf8 "java/io/PrintStream"; // #31
+ Utf8 "println"; // #32
+ Utf8 "(Ljava/lang/String;)V"; // #33
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 49;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #11; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 52;
+ 8 53;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ ;
+ Attr(#14) { // NestHost
+ 0x000F;
+ } // end NestHost
+ ;
+ Attr(#24) { // InnerClasses
+ [] { // InnerClasses
+ #5 #15 #23 8;
+ #6 #15 #26 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInvokeErrors$MissingMethodWithSuper
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/MissingNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Generated from the source in TestInvokeErrors.java
+// with NestHost referring to non-existent class: NoSuchClass
+
+class TestInvokeErrors$MissingNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #16; // #1
+ Field #17 #18; // #2
+ String #19; // #3
+ Method #20 #21; // #4
+ class #22; // #5
+ class #25; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "priv_invoke"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "TestInvokeErrors.java"; // #13
+ Utf8 "NestHost"; // #14
+ class #26; // #15
+ NameAndType #7 #8; // #16
+ class #27; // #17
+ NameAndType #28 #29; // #18
+ Utf8 "MissingNestHost::priv_invoke"; // #19
+ class #30; // #20
+ NameAndType #31 #32; // #21
+ Utf8 "TestInvokeErrors$MissingNestHost"; // #22
+ Utf8 "MissingNestHost"; // #23
+ Utf8 "InnerClasses"; // #24
+ Utf8 "java/lang/Object"; // #25
+ Utf8 "TestInvokeErrors"; // #26
+ Utf8 "java/lang/System"; // #27
+ Utf8 "out"; // #28
+ Utf8 "Ljava/io/PrintStream;"; // #29
+ Utf8 "java/io/PrintStream"; // #30
+ Utf8 "println"; // #31
+ Utf8 "(Ljava/lang/String;)V"; // #32
+ Utf8 "NoSuchClass"; // #33 - added
+ class #33; // #34 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 57;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0002; // access
+ #11; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 2; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 60;
+ 8 61;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ ;
+ Attr(#14) { // NestHost
+ 0x0022; // Modified: class #34 -> NoSuchClass
+ } // end NestHost
+ ;
+ Attr(#24) { // InnerClasses
+ [] { // InnerClasses
+ #5 #15 #23 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestInvokeErrors$MissingNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvoke.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates and nest-host
+ * using different flavours of named nested types
+ * @run main TestInvoke
+ */
+
+public class TestInvoke {
+
+ // Private method of nest-host for nestmates to access
+ private void priv_invoke() {
+ System.out.println("TestInvoke::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestInvoke() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestInvoke o) {
+ o.priv_invoke();
+ }
+ void access_priv(InnerNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticIface o) {
+ o.priv_invoke();
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private void priv_invoke() {
+ System.out.println("StaticIface::priv_invoke");
+ }
+
+ // Methods that will access private methods of nestmates
+
+ default void access_priv(TestInvoke o) {
+ o.priv_invoke();
+ }
+ default void access_priv(InnerNested o) {
+ o.priv_invoke();
+ }
+ default void access_priv(StaticNested o) {
+ o.priv_invoke();
+ }
+ default void access_priv(StaticIface o) {
+ o.priv_invoke();
+ }
+ }
+
+ static class StaticNested {
+
+ private void priv_invoke() {
+ System.out.println("StaticNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestInvoke o) {
+ o.priv_invoke();
+ }
+ void access_priv(InnerNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticIface o) {
+ o.priv_invoke();
+ }
+ }
+
+ class InnerNested {
+
+ private void priv_invoke() {
+ System.out.println("InnerNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv() {
+ TestInvoke.this.priv_invoke(); // check this$0 access
+ }
+ void access_priv(TestInvoke o) {
+ o.priv_invoke();
+ }
+ void access_priv(InnerNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_invoke();
+ }
+ void access_priv(StaticIface o) {
+ o.priv_invoke();
+ }
+ }
+
+ public static void main(String[] args) {
+ TestInvoke o = new TestInvoke();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestInvoke());
+ o.access_priv(i);
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv();
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeErrors.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Setup nestmate calls to private methods then use
+ * modified jcod classes to introduce errors. Test with
+ * and without verification enabled
+ * @compile TestInvokeErrors.java
+ * @compile MissingMethod.jcod
+ * MissingMethodWithSuper.jcod
+ * MissingNestHost.jcod
+ * @run main TestInvokeErrors true
+ * @run main/othervm -Xverify:none TestInvokeErrors false
+ */
+
+public class TestInvokeErrors {
+
+ static class Nested {
+ private void priv_invoke() {
+ System.out.println("Nested::priv_invoke");
+ }
+ }
+
+ static class MissingMethod {
+ // jcod version will rename this method to not_priv_invoke
+ private void priv_invoke() {
+ System.out.println("MissingMethod::priv_invoke");
+ }
+ }
+
+ static class MissingMethodWithSuper extends Nested {
+ // jcod version will rename this method to not_priv_invoke
+ private void priv_invoke() {
+ System.out.println("MissingMethodWithSuper::priv_invoke");
+ }
+ }
+
+ static class MissingNestHost {
+ // jcod version will change NestHost to a non-existent class
+ private void priv_invoke() {
+ System.out.println("MissingNestHost::priv_invoke");
+ }
+ }
+
+ // Helper class adds a level of indirection to avoid the main class
+ // failing verification if these tests are written directly in main.
+ // That can only happen if using invokespecial for nestmate invocation.
+ static class Helper {
+ static void doTest() {
+ try {
+ MissingNestHost m = new MissingNestHost();
+ m.priv_invoke();
+ throw new Error("Unexpected success invoking MissingNestHost.priv_invoke");
+ }
+ catch (NoClassDefFoundError ncdfe) {
+ System.out.println("Got expected exception:" + ncdfe);
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ // some errors change depending on whether they are caught by the
+ // verifier first
+ boolean verifying = Boolean.parseBoolean(args[0]);
+ System.out.println("Verification is " +
+ (verifying ? "enabled" : "disabled"));
+
+ try {
+ MissingMethod m = new MissingMethod();
+ m.priv_invoke();
+ throw new Error("Unexpected success invoking MissingMethod.priv_invoke");
+ }
+ catch (NoSuchMethodError nsme) {
+ System.out.println("Got expected exception:" + nsme);
+ }
+
+ try {
+ MissingMethodWithSuper m = new MissingMethodWithSuper();
+ m.priv_invoke();
+ throw new Error("Unexpected success invoking MissingMethodWithSuper.priv_invoke");
+ }
+ catch (NoSuchMethodError nsme) {
+ System.out.println("Got expected exception:" + nsme);
+ }
+
+ // Verification of Helper will trigger the nestmate access check failure
+ try {
+ Helper.doTest();
+ }
+ catch (NoClassDefFoundError ncdfe) {
+ if (verifying)
+ System.out.println("Got expected exception:" + ncdfe);
+ else
+ throw new Error("Unexpected error loading Helper class with verification disabled");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestInvokeHierarchy.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates where there
+ * is an inheritance hierarchy and we invoke private methods that
+ * exist in specific classes in the hierarchy.
+ * @compile TestInvokeHierarchy.java
+ * @compile ExternalSuper.jcod ExternalSub.jcod
+ * @run main TestInvokeHierarchy
+ */
+
+public class TestInvokeHierarchy {
+
+ static class NestedA extends ExternalSuper {
+ static final String ID = "NestedA::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals(a.priv_invoke(), NestedA.ID);
+ }
+ }
+
+ static class NestedB extends NestedA {
+ static final String ID = "NestedB::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals(a.priv_invoke(), NestedA.ID);
+ }
+ }
+
+ static class NestedC extends NestedB {
+ static final String ID = "NestedC::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals(a.priv_invoke(), NestedA.ID);
+ }
+ }
+
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals(a.priv_invoke(), NestedA.ID);
+ }
+
+ static void checkB(NestedB b) throws Throwable {
+ verifyEquals(b.priv_invoke(), NestedB.ID);
+ }
+
+ static void checkC(NestedC c) throws Throwable {
+ verifyEquals(c.priv_invoke(), NestedC.ID);
+ }
+
+
+ // Access to private members of classes outside the nest is
+ // not permitted. These tests should throw IllegalAccessError
+ // at runtime. To allow them to compile the classes below are
+ // defined with public members. We then replace those class files
+ // with jcod variants that make the member private again.
+
+ static void checkExternalSuper(ExternalSuper s) throws Throwable {
+ try {
+ String str = s.priv_invoke_s();
+ throw new Error("Unexpected access to ExternalSuper.priv_invoke_s");
+ }
+ catch (IllegalAccessError iae) {
+ System.out.println("Got expected exception accessing ExternalSuper.priv_invoke_s:" + iae);
+ }
+ }
+
+ static void checkExternalSub(ExternalSub s) throws Throwable {
+ try {
+ String str = s.priv_invoke();
+ throw new Error("Unexpected access to ExternalSub.priv_invoke");
+ }
+ catch (IllegalAccessError iae) {
+ System.out.println("Got expected exception accessing ExternalSub.priv_invoke:" + iae);
+ }
+ }
+
+ static void verifyEquals(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Expected " + expected + " but got " + actual);
+ }
+ System.out.println("Check passed for " + expected);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ NestedA a = new NestedA();
+ NestedB b = new NestedB();
+ NestedC c = new NestedC();
+ ExternalSub sub = new ExternalSub();
+ ExternalSuper sup = new ExternalSuper();
+
+ checkExternalSuper(sup);
+ checkExternalSuper(a);
+ checkExternalSuper(b);
+ checkExternalSuper(c);
+ checkExternalSuper(sub);
+
+ checkA(a);
+ checkA(b);
+ checkA(c);
+ checkA(sub);
+
+ NestedA.checkA(a);
+ NestedA.checkA(b);
+ NestedA.checkA(c);
+ NestedA.checkA(sub);
+
+ NestedB.checkA(a);
+ NestedB.checkA(b);
+ NestedB.checkA(c);
+ NestedB.checkA(sub);
+
+ NestedC.checkA(a);
+ NestedC.checkA(b);
+ NestedC.checkA(c);
+ NestedC.checkA(sub);
+
+ checkB(b);
+ checkB(c);
+ checkB(sub);
+
+ checkC(c);
+ checkC(sub);
+
+ checkExternalSub(sub);
+ }
+}
+
+// Classes that are not part of the nest.
+// Being non-public allows us to declare them in this file.
+// The priv_invoke* member is public to allow this file to compile, but
+// the jcod files change it back to private.
+
+class ExternalSuper {
+ static final String ID = "ExternalSuper::priv_invoke_s";
+ // Can't call this priv_invoke as subclasses make it less accessible
+ // which is not allowed.
+ public String priv_invoke_s() {
+ return ID;
+ }
+}
+
+
+class ExternalSub extends TestInvokeHierarchy.NestedC {
+ static final String ID = "ExternalSub::priv_invoke";
+ public String priv_invoke() {
+ return ID;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test JNI access to private methods between nestmates and nest-host
+ * using different flavours of named nested types
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNI
+ * @run main/othervm/native -Xcheck:jni TestJNI
+ */
+public class TestJNI {
+
+ // Unlike reflection, the calling context is not relevant to JNI
+ // calls, but we keep the same structure as the reflection tests.
+
+ static final String METHOD = "priv_invoke";
+
+ // Private method of nest-host for nestmates to access
+ private void priv_invoke() {
+ System.out.println("TestJNI::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestJNI() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestJNI o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(InnerNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(o, StaticIface.class, METHOD, true);
+ doCall(o, StaticIface.class, METHOD, false);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private void priv_invoke() {
+ System.out.println("StaticIface::priv_invoke");
+ }
+
+ // Methods that will access private methods of nestmates
+
+ default void access_priv(TestJNI o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ default void access_priv(InnerNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ default void access_priv(StaticNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ default void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(o, StaticIface.class, METHOD, true);
+ doCall(o, StaticIface.class, METHOD, false);
+ }
+ }
+
+ static class StaticNested {
+
+ private void priv_invoke() {
+ System.out.println("StaticNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestJNI o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(InnerNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(o, StaticIface.class, METHOD, true);
+ doCall(o, StaticIface.class, METHOD, false);
+ }
+ }
+
+ class InnerNested {
+
+ private void priv_invoke() {
+ System.out.println("InnerNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestJNI o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(InnerNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o, o.getClass(), METHOD, true);
+ doCall(o, o.getClass(), METHOD, false);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(o, StaticIface.class, METHOD, true);
+ doCall(o, StaticIface.class, METHOD, false);
+ }
+ }
+
+ public static void main(String[] args) {
+ TestJNI o = new TestJNI();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestJNI());
+ o.access_priv(i);
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+
+
+ static void doCall(Object target, Class<?> klass, String method,
+ boolean virtual) {
+ String definingClass = klass.getName();
+ String desc = (virtual ? "Virtual" : "Nonvirtual") + " Invocation of " +
+ definingClass + "." + method + " on instance of class " +
+ target.getClass().getName();
+ try {
+ NestmatesJNI.callVoidVoid(target, definingClass, method, virtual);
+ System.out.println(desc + " - passed");
+ }
+ catch (Throwable t) {
+ throw new Error(desc + ": Unexpected exception: " + t, t);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestJNIHierarchy.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates where there
+ * is an inheritance hierarchy and we invoke private methods that
+ * exist in specific classes in the hierarchy.
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNIHierarchy
+ * @run main/othervm/native -Xcheck:jni TestJNIHierarchy
+ */
+
+public class TestJNIHierarchy {
+
+ // Unlike reflection, the calling context is not relevant to JNI
+ // calls, but we keep the same structure as the reflection tests.
+
+ static final String METHOD = "priv_invoke";
+
+ static class NestedA extends ExternalSuper {
+ static final String ID = "NestedA::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) {
+ String res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedA.ID);
+ res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, NestedA.ID);
+ }
+ }
+
+ static class NestedB extends NestedA {
+ static final String ID = "NestedB::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) {
+ String res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedA.ID);
+
+ res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, NestedA.ID);
+ }
+ }
+
+ static class NestedC extends NestedB {
+ static final String ID = "NestedC::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) {
+ String res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedA.ID);
+ }
+ }
+
+ static void checkA(NestedA a) {
+ String res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedA.ID);
+
+ res = NestmatesJNI.callStringVoid(a,
+ NestedA.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, NestedA.ID);
+ }
+
+ static void checkB(NestedB b) {
+ String res = NestmatesJNI.callStringVoid(b,
+ NestedB.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedB.ID);
+
+ res = NestmatesJNI.callStringVoid(b,
+ NestedB.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, NestedB.ID);
+
+ }
+
+ static void checkC(NestedC c) {
+ String res = NestmatesJNI.callStringVoid(c,
+ NestedC.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, NestedC.ID);
+
+ res = NestmatesJNI.callStringVoid(c,
+ NestedC.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, NestedC.ID);
+ }
+
+
+ // Access to private members of classes outside the nest is
+ // not permitted in general, but JNI ignores all access checks.
+
+ static void checkExternalSuper(ExternalSuper s) {
+ String res = NestmatesJNI.callStringVoid(s,
+ ExternalSuper.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, ExternalSuper.ID);
+
+ res = NestmatesJNI.callStringVoid(s,
+ ExternalSuper.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, ExternalSuper.ID);
+ }
+
+ static void checkExternalSub(ExternalSub s) {
+ String res = NestmatesJNI.callStringVoid(s,
+ ExternalSub.class.getName(),
+ METHOD,
+ true);
+ verifyEquals(res, ExternalSub.ID);
+
+ res = NestmatesJNI.callStringVoid(s,
+ ExternalSub.class.getName(),
+ METHOD,
+ false);
+ verifyEquals(res, ExternalSub.ID);
+ }
+
+ static void verifyEquals(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Expected " + expected + " but got " + actual);
+ }
+ System.out.println("Check passed for " + expected);
+ }
+
+ public static void main(String[] args) {
+ NestedA a = new NestedA();
+ NestedB b = new NestedB();
+ NestedC c = new NestedC();
+ ExternalSub sub = new ExternalSub();
+ ExternalSuper sup = new ExternalSuper();
+
+ checkExternalSuper(sup);
+ checkExternalSuper(a);
+ checkExternalSuper(b);
+ checkExternalSuper(c);
+ checkExternalSuper(sub);
+
+ checkA(a);
+ checkA(b);
+ checkA(c);
+ checkA(sub);
+
+ NestedA.checkA(a);
+ NestedA.checkA(b);
+ NestedA.checkA(c);
+ NestedA.checkA(sub);
+
+ NestedB.checkA(a);
+ NestedB.checkA(b);
+ NestedB.checkA(c);
+ NestedB.checkA(sub);
+
+ NestedC.checkA(a);
+ NestedC.checkA(b);
+ NestedC.checkA(c);
+ NestedC.checkA(sub);
+
+ checkB(b);
+ checkB(c);
+ checkB(sub);
+
+ checkC(c);
+ checkC(sub);
+
+ checkExternalSub(sub);
+ }
+}
+
+// Classes that are not part of the nest.
+// Being non-public allows us to declare them in this file.
+
+class ExternalSuper {
+ static final String ID = "ExternalSuper::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
+
+
+class ExternalSub extends TestJNIHierarchy.NestedC {
+ static final String ID = "ExternalSub::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestMethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates and nest-host
+ * using different flavours of named nested types using MethodHandles
+ * @run main TestMethodHandles
+ */
+
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestMethodHandles {
+
+ static final MethodType M_T = MethodType.methodType(void.class);
+
+ // Private method of nest-host for nestmates to access
+ private void priv_invoke() {
+ System.out.println("TestMethodHandles::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestMethodHandles() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ // findSpecial also works when this and o are the same class
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(StaticIface.class, "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(StaticIface.class, "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private void priv_invoke() {
+ System.out.println("StaticIface::priv_invoke");
+ }
+
+ // Methods that will access private methods of nestmates
+
+ default void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ default void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ default void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(StaticIface.class, "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ // findSpecial also works when this and o are the same interface
+ mh = lookup().findSpecial(StaticIface.class, "priv_invoke", M_T, StaticIface.class);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ }
+ }
+
+ static class StaticNested {
+
+ private void priv_invoke() {
+ System.out.println("StaticNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new TestMethodHandles()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ // findSpecial also works when this and o are the same class
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new TestMethodHandles()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(StaticIface.class, "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(StaticIface.class, "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ }
+
+ class InnerNested {
+
+ private void priv_invoke() {
+ System.out.println("InnerNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ // findSpecial also works when this and o are the same class
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, new StaticNested()); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(o.getClass(), "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(o.getClass(), "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh = lookup().findVirtual(StaticIface.class, "priv_invoke", M_T);
+ mh.invoke(o);
+ mh.invokeExact(o);
+ checkBadInvoke(mh, this); // wrong nestmate
+ checkBadInvoke(mh, mh); // completely wrong type
+ try {
+ mh = lookup().findSpecial(StaticIface.class, "priv_invoke", M_T, this.getClass());
+ throw new Error("findSpecial() succeeded unexpectedly");
+ }
+ catch (IllegalAccessException expected) {}
+ }
+ }
+
+ static void checkBadInvoke(MethodHandle mh, Object o) throws Throwable {
+ try {
+ mh.invoke(o);
+ throw new Error("Invoke on MethodHandle " + mh + " with receiver "
+ + o + "should have failed with ClassCastException!");
+ }
+ catch (ClassCastException expected) {
+ System.out.println("invoke got expected exception: " + expected);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestMethodHandles o = new TestMethodHandles();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestMethodHandles());
+ o.access_priv(i);
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestMethodHandlesHierarchy.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates where there
+ * is an inheritance hierarchy and we invoke private methods that
+ * exist in specific classes in the hierarchy.
+ * @run main TestMethodHandlesHierarchy
+ */
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestMethodHandlesHierarchy {
+
+ static final MethodType M_T = MethodType.methodType(String.class);
+
+ static class NestedA extends ExternalSuper {
+ static final String ID = "NestedA::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ MethodHandle mh =
+ lookup().findSpecial(NestedA.class, "priv_invoke",
+ M_T, NestedA.class);
+ verifyEquals((String)mh.invoke(a), NestedA.ID);
+ verifyEquals((String)mh.invokeExact(a), NestedA.ID);
+
+ mh = lookup().findVirtual(NestedA.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(a), NestedA.ID);
+ verifyEquals((String)mh.invokeExact(a), NestedA.ID);
+ }
+ }
+
+ static class NestedB extends NestedA {
+ static final String ID = "NestedB::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(NestedA.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(a), NestedA.ID);
+ verifyEquals((String)mh.invokeExact(a), NestedA.ID);
+ }
+ }
+
+ static class NestedC extends NestedB {
+ static final String ID = "NestedC::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(NestedA.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(a), NestedA.ID);
+ verifyEquals((String)mh.invokeExact(a), NestedA.ID);
+ }
+ }
+
+ static void checkA(NestedA a) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(NestedA.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(a), NestedA.ID);
+ verifyEquals((String)mh.invokeExact(a), NestedA.ID);
+ }
+
+ static void checkB(NestedB b) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(NestedB.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(b), NestedB.ID);
+ verifyEquals((String)mh.invokeExact(b), NestedB.ID);
+ }
+
+ static void checkC(NestedC c) throws Throwable {
+ MethodHandle mh =
+ lookup().findVirtual(NestedC.class, "priv_invoke", M_T);
+ verifyEquals((String)mh.invoke(c), NestedC.ID);
+ verifyEquals((String)mh.invokeExact(c), NestedC.ID);
+ }
+
+
+ // Access to private members of classes outside the nest is
+ // not permitted. These tests should throw IllegalAccessException
+ // at runtime.
+
+ static void checkExternalSuper(ExternalSuper s) throws Throwable {
+ try {
+ lookup().findVirtual(ExternalSuper.class, "priv_invoke", M_T);
+ throw new Error("Unexpected access to ExternalSuper.priv_invoke");
+ }
+ catch (IllegalAccessException iae) {
+ System.out.println("Got expected exception accessing ExternalSuper.priv_invoke:" + iae);
+ }
+ }
+
+ static void checkExternalSub(ExternalSub s) throws Throwable {
+ try {
+ lookup().findVirtual(ExternalSub.class, "priv_invoke", M_T);
+ throw new Error("Unexpected access to ExternalSub.priv_invoke");
+ }
+ catch (IllegalAccessException iae) {
+ System.out.println("Got expected exception accessing ExternalSub.priv_invoke:" + iae);
+ }
+ }
+
+ static void verifyEquals(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Expected " + expected + " but got " + actual);
+ }
+ System.out.println("Check passed for " + expected);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ NestedA a = new NestedA();
+ NestedB b = new NestedB();
+ NestedC c = new NestedC();
+ ExternalSub sub = new ExternalSub();
+ ExternalSuper sup = new ExternalSuper();
+
+ checkExternalSuper(sup);
+ checkExternalSuper(a);
+ checkExternalSuper(b);
+ checkExternalSuper(c);
+ checkExternalSuper(sub);
+
+ checkA(a);
+ checkA(b);
+ checkA(c);
+ checkA(sub);
+
+ NestedA.checkA(a);
+ NestedA.checkA(b);
+ NestedA.checkA(c);
+ NestedA.checkA(sub);
+
+ NestedB.checkA(a);
+ NestedB.checkA(b);
+ NestedB.checkA(c);
+ NestedB.checkA(sub);
+
+ NestedC.checkA(a);
+ NestedC.checkA(b);
+ NestedC.checkA(c);
+ NestedC.checkA(sub);
+
+ checkB(b);
+ checkB(c);
+ checkB(sub);
+
+ checkC(c);
+ checkC(sub);
+
+ checkExternalSub(sub);
+ }
+}
+
+// Classes that are not part of the nest.
+// Being non-public allows us to declare them in this file.
+
+class ExternalSuper {
+ static final String ID = "ExternalSuper::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
+
+
+class ExternalSub extends TestMethodHandlesHierarchy.NestedC {
+ static final String ID = "ExternalSub::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestReflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @run main TestReflection
+ * @run main/othervm -Dsun.reflect.noInflation=true TestReflection
+ */
+
+// The first run will use NativeMethodAccessor and due to the limited number
+// of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the GeneratedMethodAccessor
+// instead. In this way both sets of Reflection classes are tested.
+
+public class TestReflection {
+
+ // Private method of nest-host for nestmates to access
+ private void priv_invoke() {
+ System.out.println("TestReflection::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestReflection() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private void priv_invoke() {
+ System.out.println("StaticIface::priv_invoke");
+ }
+
+ // Methods that will access private methods of nestmates
+
+ default void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ default void access_priv(InnerNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ default void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ }
+
+ static class StaticNested {
+
+ private void priv_invoke() {
+ System.out.println("StaticNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private methods of nestmates
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ }
+
+ class InnerNested {
+
+ private void priv_invoke() {
+ System.out.println("InnerNested::priv_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(InnerNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_invoke", new Class<?>[0]).invoke(o, new Object[0]);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestReflection o = new TestReflection();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestReflection());
+ o.access_priv(i);
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(i);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(o.new InnerNested());
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(i);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateMethods/TestReflectionHierarchy.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private methods between nestmates where there
+ * is an inheritance hierarchy and we invoke private methods that
+ * exist in specific classes in the hierarchy.
+ * @run main TestReflectionHierarchy
+ * @run main/othervm -Dsun.reflect.noInflation=true TestReflectionHierarchy
+ */
+
+// The first run will use NativeMethodAccessor and due to the limited number
+// of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the GeneratedMethodAccessor
+// instead. In this way both sets of Reflection classes are tested.
+
+
+public class TestReflectionHierarchy {
+
+ static class NestedA extends ExternalSuper {
+ static final String ID = "NestedA::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals((String)NestedA.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(a, new Object[0]),
+ NestedA.ID);
+ }
+ }
+
+ static class NestedB extends NestedA {
+ static final String ID = "NestedB::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals((String)NestedA.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(a, new Object[0]),
+ NestedA.ID);
+ }
+ }
+
+ static class NestedC extends NestedB {
+ static final String ID = "NestedC::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals((String)NestedA.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(a, new Object[0]),
+ NestedA.ID);
+ }
+ }
+
+ static void checkA(NestedA a) throws Throwable {
+ verifyEquals((String)NestedA.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(a, new Object[0]),
+ NestedA.ID);
+ }
+
+ static void checkB(NestedB b) throws Throwable {
+ verifyEquals((String)NestedB.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(b, new Object[0]),
+ NestedB.ID);
+ }
+
+ static void checkC(NestedC c) throws Throwable {
+ verifyEquals((String)NestedC.class.
+ getDeclaredMethod("priv_invoke",
+ new Class<?>[0]).
+ invoke(c, new Object[0]),
+ NestedC.ID);
+ }
+
+
+ // Access to private members of classes outside the nest is
+ // not permitted. These tests should throw IllegalAccessException
+ // at runtime.
+
+ static void checkExternalSuper(ExternalSuper s) throws Throwable {
+ try {
+ ExternalSuper.class.
+ getDeclaredMethod("priv_invoke", new Class<?>[0]).
+ invoke(s, new Object[0]);
+ throw new Error("Unexpected access to ExternalSuper.priv_invoke");
+ }
+ catch (IllegalAccessException iae) {
+ System.out.println("Got expected exception accessing ExternalSuper.priv_invoke:" + iae);
+ }
+ }
+
+ static void checkExternalSub(ExternalSub s) throws Throwable {
+ try {
+ ExternalSub.class.
+ getDeclaredMethod("priv_invoke", new Class<?>[0]).
+ invoke(s, new Object[0]);
+ throw new Error("Unexpected access to ExternalSub.priv_invoke");
+ }
+ catch (IllegalAccessException iae) {
+ System.out.println("Got expected exception accessing ExternalSub.priv_invoke:" + iae);
+ }
+ }
+
+ static void verifyEquals(String actual, String expected) {
+ if (!actual.equals(expected)) {
+ throw new Error("Expected " + expected + " but got " + actual);
+ }
+ System.out.println("Check passed for " + expected);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ NestedA a = new NestedA();
+ NestedB b = new NestedB();
+ NestedC c = new NestedC();
+ ExternalSub sub = new ExternalSub();
+ ExternalSuper sup = new ExternalSuper();
+
+ checkExternalSuper(sup);
+ checkExternalSuper(a);
+ checkExternalSuper(b);
+ checkExternalSuper(c);
+ checkExternalSuper(sub);
+
+ checkA(a);
+ checkA(b);
+ checkA(c);
+ checkA(sub);
+
+ NestedA.checkA(a);
+ NestedA.checkA(b);
+ NestedA.checkA(c);
+ NestedA.checkA(sub);
+
+ NestedB.checkA(a);
+ NestedB.checkA(b);
+ NestedB.checkA(c);
+ NestedB.checkA(sub);
+
+ NestedC.checkA(a);
+ NestedC.checkA(b);
+ NestedC.checkA(c);
+ NestedC.checkA(sub);
+
+ checkB(b);
+ checkB(c);
+ checkB(sub);
+
+ checkC(c);
+ checkC(sub);
+
+ checkExternalSub(sub);
+ }
+}
+
+// Classes that are not part of the nest.
+// Being non-public allows us to declare them in this file.
+
+class ExternalSuper {
+ static final String ID = "ExternalSuper::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
+
+
+class ExternalSub extends TestReflectionHierarchy.NestedC {
+ static final String ID = "ExternalSub::priv_invoke";
+ private String priv_invoke() {
+ return ID;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test JNI access to private static fields between nestmates and nest-host
+ * using different flavours of named nested types
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNI
+ * @run main/othervm/native -Xcheck:jni TestJNI
+ */
+public class TestJNI {
+
+ // Private field of nest-host for nestmates to access
+ private static int priv_field;
+
+ static final String FIELD = "priv_field";
+
+ // public constructor so we aren't relying on private access
+ public TestJNI() {}
+
+ // Methods that will access private static fields of nestmates
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static fields. Also no StaticIface calls as static interface
+ // fields must be public (and final)
+
+ void access_priv(TestJNI o) {
+ priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ priv_field = getAndInc(o.getClass(), FIELD);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private static fields of nestmates
+
+ default void access_priv(TestJNI o) {
+ int priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ default void access_priv(StaticNested o) {
+ int priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ }
+
+ static class StaticNested {
+
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static fields of nestmates
+
+ void access_priv(TestJNI o) {
+ priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestJNI o) {
+ int priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ void access_priv(StaticNested o) {
+ int priv_field = getAndInc(o.getClass(), FIELD);
+ }
+ }
+
+ public static void main(String[] args) {
+ TestJNI o = new TestJNI();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestJNI());
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ }
+
+ static int getAndInc(Class<?> klass, String field) {
+ String definingClass = klass.getName();
+ String desc = "Access to static field " + definingClass + "." + field;
+ int first, second;
+ try {
+ first = NestmatesJNI.getStaticIntField(definingClass, field);
+ NestmatesJNI.setStaticIntField(definingClass, field, (first + 1));
+ second = NestmatesJNI.getStaticIntField(definingClass, field);
+ }
+ catch (Throwable t) {
+ throw new Error(desc + ": Unexpected exception: " + t, t);
+ }
+ if (second != first + 1) {
+ throw new Error(desc + ": wrong field values: first=" + first +
+ ", second=" + second + " (should equal first+1)");
+ }
+ System.out.println(desc + " - passed");
+ return first;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestMethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static fields between nestmates and nest-host
+ * using different flavours of named nested types using MethodHandles
+ * @run main TestMethodHandles
+ */
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+
+import java.lang.reflect.Field;
+
+public class TestMethodHandles {
+
+ // private static field of nest-host for nestmates to access
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestMethodHandles() {}
+
+ // Methods that will access private static fields of nestmates
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static fields. Also no StaticIface calls as static interface
+ // fields must be public (and final)
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private static fields of nestmates
+
+ default void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ int priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ int priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ }
+
+ static class StaticNested {
+
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static fields of nestmates
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh = lookup().findStaticGetter(o.getClass(), "priv_field", int.class);
+ priv_field = (int) mh.invoke();
+ priv_field = (int) mh.invokeExact();
+ mh = lookup().findStaticSetter(o.getClass(), "priv_field", int.class);
+ mh.invoke(2);
+ mh.invokeExact(3);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestMethodHandles o = new TestMethodHandles();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestMethodHandles());
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestPrivateStaticField.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static fields between nestmates and nest-host
+ * using different flavours of named nested types
+ * @run main TestPrivateStaticField
+ */
+
+public class TestPrivateStaticField {
+
+ // Private static field of nest-host for nestmates to access
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestPrivateStaticField() {}
+
+ // Methods that will access private static fields of nestmates
+ // We use the arguments for overloading purposes and use the fact
+ // you can access a static field through an object reference for
+ // convenience.
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static fields. Also no StaticIface calls as static interface
+ // fields must be public (and final)
+
+ void access_priv(TestPrivateStaticField o) {
+ priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ priv_field = o.priv_field++;
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private static fields of nestmates
+
+ default void access_priv(TestPrivateStaticField o) {
+ int priv_field = o.priv_field++;
+ }
+ default void access_priv(StaticNested o) {
+ int priv_field = o.priv_field++;
+ }
+ }
+
+ static class StaticNested {
+
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static fields of nestmates
+
+ void access_priv(TestPrivateStaticField o) {
+ priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ priv_field = o.priv_field++;
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestPrivateStaticField o) {
+ int priv_field = o.priv_field++;
+ }
+ void access_priv(StaticNested o) {
+ int priv_field = o.priv_field++;
+ }
+ }
+
+ public static void main(String[] args) {
+ TestPrivateStaticField o = new TestPrivateStaticField();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestPrivateStaticField());
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticFields/TestReflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static fields between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @run main TestReflection
+ */
+
+import java.lang.reflect.Field;
+
+public class TestReflection {
+
+ // private static field of nest-host for nestmates to access
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public TestReflection() {}
+
+ // Methods that will access private static fields of nestmates
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static fields. Also no StaticIface calls as static interface
+ // fields must be public (and final)
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ // Methods that will access private static fields of nestmates
+
+ default void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ int priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ int priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ }
+
+ static class StaticNested {
+
+ private static int priv_field;
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static fields of nestmates
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestReflection o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ Field f = o.getClass().getDeclaredField("priv_field");
+ priv_field = f.getInt(null);
+ f.setInt(null, 2);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestReflection o = new TestReflection();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestReflection());
+ o.access_priv(s);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+
+ i.access_priv(o);
+ i.access_priv(s);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestInvokeStatic.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static methods between nestmates and nest-host
+ * using different flavours of named nested types
+ * @run main TestInvokeStatic
+ */
+
+public class TestInvokeStatic {
+
+ // Private static method of nest-host for nestmates to access
+ private static void priv_static_invoke() {
+ System.out.println("TestInvokeStatic::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestInvokeStatic() {}
+
+ // Methods that will access private static methods of nestmates
+ // We use the arguments for overloading purposes and use the fact
+ // you can invoke a static method through an object reference for
+ // convenience. Except for static interface methods of course.
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static method
+
+ void access_priv(TestInvokeStatic o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticIface o) {
+ StaticIface.priv_static_invoke();
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticIface::priv_static_invoke");
+ }
+
+ // Methods that will access private static methods of nestmates
+
+ default void access_priv(TestInvokeStatic o) {
+ o.priv_static_invoke();
+ }
+ default void access_priv(StaticNested o) {
+ o.priv_static_invoke();
+ }
+ default void access_priv(StaticIface o) {
+ StaticIface.priv_static_invoke();
+ }
+ }
+
+ static class StaticNested {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticNested::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static methods of nestmates
+
+ void access_priv(TestInvokeStatic o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticIface o) {
+ StaticIface.priv_static_invoke();
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestInvokeStatic o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticNested o) {
+ o.priv_static_invoke();
+ }
+ void access_priv(StaticIface o) {
+ StaticIface.priv_static_invoke();
+ }
+ }
+
+ public static void main(String[] args) {
+ TestInvokeStatic o = new TestInvokeStatic();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestInvokeStatic());
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestJNI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test JNI access to private methods between nestmates and nest-host
+ * using different flavours of named nested types
+ * @compile ../NestmatesJNI.java
+ * @run main/othervm/native TestJNI
+ * @run main/othervm/native -Xcheck:jni TestJNI
+ */
+public class TestJNI {
+
+ // Unlike reflection, the calling context is not relevant to JNI
+ // calls, but we keep the same structure as the reflection tests.
+
+ // Private static method of nest-host for nestmates to access
+ private static void priv_static_invoke() {
+ System.out.println("TestJNI::priv_static_invoke");
+ }
+
+ static final String METHOD = "priv_static_invoke";
+
+ // public constructor so we aren't relying on private access
+ public TestJNI() {}
+
+ // Methods that will access private static methods of nestmates
+ // We use the arguments for overloading purposes and use the fact
+ // you can invoke a static method through an object reference for
+ // convenience. Except for static interface methods of course.
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static method
+
+ void access_priv(TestJNI o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(StaticIface.class, METHOD);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticIface::priv_static_invoke");
+ }
+
+ // Methods that will access private static methods of nestmates
+
+ default void access_priv(TestJNI o) {
+ doCall(o.getClass(), METHOD);
+ }
+ default void access_priv(StaticNested o) {
+ doCall(o.getClass(), METHOD);
+ }
+ default void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(StaticIface.class, METHOD);
+ }
+ }
+
+ static class StaticNested {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticNested::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static methods of nestmates
+
+ void access_priv(TestJNI o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(StaticIface.class, METHOD);
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestJNI o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticNested o) {
+ doCall(o.getClass(), METHOD);
+ }
+ void access_priv(StaticIface o) {
+ // Can't use o.getClass() as the method is not in that class
+ doCall(StaticIface.class, METHOD);
+ }
+ }
+
+ public static void main(String[] args) {
+ TestJNI o = new TestJNI();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestJNI());
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+
+ static void doCall(Class<?> klass, String method) {
+ String definingClass = klass.getName();
+ String desc = "Static invocation of " + definingClass + "." + method;
+ try {
+ NestmatesJNI.callStaticVoidVoid(definingClass, method);
+ System.out.println(desc + " - passed");
+ }
+ catch (Throwable t) {
+ throw new Error(desc + ": Unexpected exception: " + t, t);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestMethodHandles.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static methods between nestmates and nest-host
+ * using different flavours of named nested types using MethodHandles
+ * @run main TestMethodHandles
+ */
+
+
+import java.lang.invoke.*;
+import static java.lang.invoke.MethodHandles.*;
+import static java.lang.invoke.MethodType.*;
+
+public class TestMethodHandles {
+
+ static final MethodType INVOKE_T = MethodType.methodType(void.class);
+
+ // Private static method of nest-host for nestmates to access
+ private static void priv_static_invoke() {
+ System.out.println("TestMethodHandles::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestMethodHandles() {}
+
+ // Methods that will access private static methods of nestmates
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static methods
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(StaticIface.class, "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticIface::priv_static_invoke");
+ }
+
+ // Methods that will access private static methods of nestmates
+
+ default void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ default void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(StaticIface.class, "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ }
+
+ static class StaticNested {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticNested::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static methods of nestmates
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(StaticIface.class, "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestMethodHandles o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(o.getClass(), "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ MethodHandle mh =
+ lookup().findStatic(StaticIface.class, "priv_static_invoke", INVOKE_T);
+ mh.invoke();
+ mh.invokeExact();
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestMethodHandles o = new TestMethodHandles();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestMethodHandles());
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/Nestmates/privateStaticMethods/TestReflection.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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
+ * @bug 8046171
+ * @summary Test access to private static methods between nestmates and nest-host
+ * using different flavours of named nested types using core reflection
+ * @run main TestReflection
+ * @run main/othervm -Dsun.reflect.noInflation=true TestReflection
+ */
+
+// The first run will use NativeMethodAccessor and due to the limited number
+// of calls we will not reach the inflation threshold.
+// The second run disables inflation so we will use the GeneratedMethodAccessor
+// instead. In this way both sets of Reflection classes are tested.
+
+
+public class TestReflection {
+
+ // Private method of nest-host for nestmates to access
+ private static void priv_static_invoke() {
+ System.out.println("TestReflection::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public TestReflection() {}
+
+ // Methods that will access private static methods of nestmates
+
+ // NOTE: No InnerNested calls in this test because non-static nested types
+ // can't have static methods
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+
+ // The various nestmates
+
+ static interface StaticIface {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticIface::priv_static_invoke");
+ }
+
+ // Methods that will access private static methods of nestmates
+
+ default void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ default void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ default void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ }
+
+ static class StaticNested {
+
+ private static void priv_static_invoke() {
+ System.out.println("StaticNested::priv_static_invoke");
+ }
+
+ // public constructor so we aren't relying on private access
+ public StaticNested() {}
+
+ // Methods that will access private static methods of nestmates
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ }
+
+ class InnerNested {
+
+ // public constructor so we aren't relying on private access
+ public InnerNested() {}
+
+ void access_priv(TestReflection o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticNested o) throws Throwable {
+ o.getClass().getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ void access_priv(StaticIface o) throws Throwable {
+ // Can't use o.getClass() as the method is not in that class
+ StaticIface.class.getDeclaredMethod("priv_static_invoke", new Class<?>[0]).invoke(null, new Object[0]);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ TestReflection o = new TestReflection();
+ StaticNested s = new StaticNested();
+ InnerNested i = o.new InnerNested();
+ StaticIface intf = new StaticIface() {};
+
+ o.access_priv(new TestReflection());
+ o.access_priv(s);
+ o.access_priv(intf);
+
+ s.access_priv(o);
+ s.access_priv(new StaticNested());
+ s.access_priv(intf);
+
+ i.access_priv(o);
+ i.access_priv(s);
+ i.access_priv(intf);
+
+ intf.access_priv(o);
+ intf.access_priv(s);
+ intf.access_priv(new StaticIface(){});
+ }
+}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8178870
+ * @bug 8178870 8010319
* @summary Redefine class with CFLH twice to test deleting the cached_class_file
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -34,27 +34,30 @@
* @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
*/
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
+class RedefineDoubleDelete_B {
+ int faa() { System.out.println("foo"); return 1; }
+}
+
public class RedefineDoubleDelete {
// Class gets a redefinition error because it adds a data member
public static String newB =
- "class RedefineDoubleDelete$B {" +
+ "class RedefineDoubleDelete_B {" +
" int count1 = 0;" +
"}";
public static String newerB =
- "class RedefineDoubleDelete$B { " +
+ "class RedefineDoubleDelete_B { " +
" int faa() { System.out.println(\"baa\"); return 2; }" +
"}";
- // The ClassFileLoadHook for this class turns foo into faa and prints out faa.
- static class B {
- int faa() { System.out.println("foo"); return 1; }
- }
-
public static void main(String args[]) throws Exception {
- B b = new B();
+ RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
int val = b.faa();
if (val != 1) {
throw new RuntimeException("return value wrong " + val);
@@ -62,12 +65,12 @@
// Redefine B twice to get cached_class_file in both B scratch classes
try {
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
} catch (java.lang.UnsupportedOperationException e) {
// this is expected
}
try {
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
} catch (java.lang.UnsupportedOperationException e) {
// this is expected
}
@@ -76,7 +79,7 @@
System.gc();
// Redefine with a compatible class
- RedefineClassHelper.redefineClass(B.class, newerB);
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
val = b.faa();
if (val != 2) {
throw new RuntimeException("return value wrong " + val);
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6904403
+ * @bug 6904403 8010319
* @summary Don't assert if we redefine finalize method
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -41,27 +41,31 @@
*
* when redefining finalizer method
*/
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineFinalizer_B {
+ protected void finalize() {
+ // should be empty
+ }
+}
+
public class RedefineFinalizer {
public static String newB =
- "class RedefineFinalizer$B {" +
+ "class RedefineFinalizer_B {" +
" protected void finalize() { " +
" System.out.println(\"Finalizer called\");" +
" }" +
"}";
public static void main(String[] args) throws Exception {
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
A a = new A();
}
- static class A extends B {
- }
-
- static class B {
- protected void finalize() {
- // should be empty
- }
+ static class A extends RedefineFinalizer_B {
}
}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8174962
+ * @bug 8174962 8010319
* @summary Redefine class with interface method call
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -39,19 +39,21 @@
interface I1 { default int m() { return 0; } }
interface I2 extends I1 {}
-public class RedefineInterfaceCall {
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineInterfaceCall_C implements I2 {
+ public int test(I2 i) {
+ return i.m(); // invokeinterface cpCacheEntry
+ }
+}
- public static class C implements I2 {
- public int test(I2 i) {
- return i.m(); // invokeinterface cpCacheEntry
- }
- }
+public class RedefineInterfaceCall {
static String newI1 =
"interface I1 { default int m() { return 1; } }";
static String newC =
- "public class RedefineInterfaceCall$C implements I2 { " +
+ "class RedefineInterfaceCall_C implements I2 { " +
" public int test(I2 i) { " +
" return i.m(); " +
" } " +
@@ -62,12 +64,12 @@
}
public static void main(String[] args) throws Exception {
- C c = new C();
+ RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
assertEquals(test(c), 0);
assertEquals(c.test(c), 0);
- RedefineClassHelper.redefineClass(C.class, newC);
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
assertEquals(c.test(c), 0);
@@ -76,7 +78,7 @@
assertEquals(test(c), 1);
assertEquals(c.test(c), 1);
- RedefineClassHelper.redefineClass(C.class, newC);
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
assertEquals(c.test(c), 1);
}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8081800
+ * @bug 8081800 8010319
* @summary Redefine private and default interface methods
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -33,23 +33,27 @@
* @run main RedefineClassHelper
* @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
*/
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+interface RedefineInterfaceMethods_B {
+ int ORIGINAL_RETURN = 1;
+ int NEW_RETURN = 2;
+ private int privateMethod() {
+ return ORIGINAL_RETURN;
+ }
+ public default int defaultMethod() {
+ return privateMethod();
+ }
+}
+
public class RedefineInterfaceMethods {
static final int RET = -2;
- static interface B {
- int ORIGINAL_RETURN = 1;
- int NEW_RETURN = 2;
- private int privateMethod() {
- return ORIGINAL_RETURN;
- }
- public default int defaultMethod() {
- return privateMethod();
- }
- }
-
public static String redefinedPrivateMethod =
- "interface RedefineInterfaceMethods$B {" +
+ "interface RedefineInterfaceMethods_B {" +
" int ORIGINAL_RETURN = 1;" +
" int NEW_RETURN = 2;" +
" private int privateMethod() {" +
@@ -61,7 +65,7 @@
"}";
public static String redefinedDefaultMethod =
- "interface RedefineInterfaceMethods$B {" +
+ "interface RedefineInterfaceMethods_B {" +
" int ORIGINAL_RETURN = 1;" +
" int NEW_RETURN = 2;" +
" private int privateMethod() {" +
@@ -72,7 +76,7 @@
" }" +
"}";
- static class Impl implements B {
+ static class Impl implements RedefineInterfaceMethods_B {
}
@@ -81,20 +85,20 @@
Impl impl = new Impl();
int res = impl.defaultMethod();
- if (res != B.ORIGINAL_RETURN)
+ if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
throw new Error("defaultMethod returned " + res +
- " expected " + B.ORIGINAL_RETURN);
+ " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
- RedefineClassHelper.redefineClass(B.class, redefinedPrivateMethod);
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
res = impl.defaultMethod();
- if (res != B.NEW_RETURN)
+ if (res != RedefineInterfaceMethods_B.NEW_RETURN)
throw new Error("defaultMethod returned " + res +
- " expected " + B.NEW_RETURN);
+ " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
System.gc();
- RedefineClassHelper.redefineClass(B.class, redefinedDefaultMethod);
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
res = impl.defaultMethod();
if (res != RET)
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java Mon Jun 25 09:48:06 2018 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8165246
+ * @bug 8165246 8010319
* @summary Test has_previous_versions flag and processing during class unloading.
* @requires vm.opt.final.ClassUnloading
* @library /test/lib
@@ -38,38 +38,43 @@
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.process.OutputAnalyzer;
+// package access top-level classes to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefinePreviousVersions_B { }
+
+class RedefinePreviousVersions_Running {
+ public static volatile boolean stop = false;
+ public static volatile boolean running = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10); // sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ running = true;
+ while (!stop) { localSleep(); }
+ }
+}
+
+
+
public class RedefinePreviousVersions {
public static String newB =
- "class RedefinePreviousVersions$B {" +
+ "class RedefinePreviousVersions_B {" +
"}";
- static class B { }
-
public static String newRunning =
- "class RedefinePreviousVersions$Running {" +
+ "class RedefinePreviousVersions_Running {" +
" public static volatile boolean stop = true;" +
" public static volatile boolean running = true;" +
" static void localSleep() { }" +
" public static void infinite() { }" +
"}";
- static class Running {
- public static volatile boolean stop = false;
- public static volatile boolean running = false;
- static void localSleep() {
- try{
- Thread.sleep(10); // sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- running = true;
- while (!stop) { localSleep(); }
- }
- }
-
public static void main(String[] args) throws Exception {
if (args.length > 0) {
@@ -88,7 +93,7 @@
// Redefine a class and create some garbage
// Since there are no methods running, the previous version is never added to the
// previous_version_list and the flag _has_previous_versions should stay false
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
@@ -98,17 +103,17 @@
// Start a class that has a method running
new Thread() {
public void run() {
- Running.infinite();
+ RedefinePreviousVersions_Running.infinite();
}
}.start();
- while (!Running.running) {
+ while (!RedefinePreviousVersions_Running.running) {
Thread.sleep(10); // sleep for 10 ms
}
// Since a method of newRunning is running, this class should be added to the previous_version_list
// of Running, and _has_previous_versions should return true at class unloading.
- RedefineClassHelper.redefineClass(Running.class, newRunning);
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
@@ -116,7 +121,7 @@
}
// purge should clean everything up, except Xcomp it might not.
- Running.stop = true;
+ RedefinePreviousVersions_Running.stop = true;
for (int i = 0; i < 10 ; i++) {
String s = new String("some garbage");
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java Mon Jun 25 09:48:06 2018 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8055008 8197901
+ * @bug 8055008 8197901 8010319
* @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -34,10 +34,33 @@
* @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,all=trace:file=all.log RedefineRunningMethods
*/
// Test is executed with full trace logging redirected to a file to ensure there is no crash during logging anonymous classes - see JDK-8197901
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineRunningMethods_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try{
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void infinite_emcp() {
+ while (!stop) { count2++; localSleep(); }
+ }
+}
+
public class RedefineRunningMethods {
public static String newB =
- "class RedefineRunningMethods$B {" +
+ "class RedefineRunningMethods_B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
@@ -56,7 +79,7 @@
"}";
public static String evenNewerB =
- "class RedefineRunningMethods$B {" +
+ "class RedefineRunningMethods_B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
@@ -72,50 +95,31 @@
" }" +
"}";
- static class B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try{
- Thread.currentThread().sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void infinite_emcp() {
- while (!stop) { count2++; localSleep(); }
- }
- }
-
public static void main(String[] args) throws Exception {
new Thread() {
public void run() {
- B.infinite();
+ RedefineRunningMethods_B.infinite();
}
}.start();
new Thread() {
public void run() {
- B.infinite_emcp();
+ RedefineRunningMethods_B.infinite_emcp();
}
}.start();
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
System.gc();
- B.infinite();
+ RedefineRunningMethods_B.infinite();
// Start a thread with the second version of infinite_emcp running
new Thread() {
public void run() {
- B.infinite_emcp();
+ RedefineRunningMethods_B.infinite_emcp();
}
}.start();
@@ -124,22 +128,22 @@
System.gc();
}
- RedefineClassHelper.redefineClass(B.class, evenNewerB);
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
System.gc();
for (int i = 0; i < 20 ; i++) {
- B.infinite();
+ RedefineRunningMethods_B.infinite();
String s = new String("some garbage");
System.gc();
}
- B.infinite_emcp();
+ RedefineRunningMethods_B.infinite_emcp();
// purge should clean everything up.
- B.stop = true;
+ RedefineRunningMethods_B.stop = true;
for (int i = 0; i < 20 ; i++) {
- B.infinite();
+ RedefineRunningMethods_B.infinite();
String s = new String("some garbage");
System.gc();
}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8087315
+ * @bug 8087315 8010319
* @summary Get old method's stack trace elements after GC
* @library /test/lib
* @modules java.base/jdk.internal.misc
@@ -36,16 +36,58 @@
import static jdk.test.lib.Asserts.*;
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefineRunningMethodsWithBacktrace_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void throwable() {
+ // add some stuff to the original constant pool
+ String s1 = new String ("string1");
+ String s2 = new String ("string2");
+ String s3 = new String ("string3");
+ String s4 = new String ("string4");
+ String s5 = new String ("string5");
+ String s6 = new String ("string6");
+ String s7 = new String ("string7");
+ String s8 = new String ("string8");
+ String s9 = new String ("string9");
+ String s10 = new String ("string10");
+ String s11 = new String ("string11");
+ String s12 = new String ("string12");
+ String s13 = new String ("string13");
+ String s14 = new String ("string14");
+ String s15 = new String ("string15");
+ String s16 = new String ("string16");
+ String s17 = new String ("string17");
+ String s18 = new String ("string18");
+ String s19 = new String ("string19");
+ throw new RuntimeException("throwable called");
+ }
+}
+
public class RedefineRunningMethodsWithBacktrace {
public static String newB =
- "class RedefineRunningMethodsWithBacktrace$B {" +
+ "class RedefineRunningMethodsWithBacktrace_B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
" static void localSleep() { " +
" try{ " +
- " Thread.currentThread().sleep(10);" +
+ " Thread.sleep(10);" +
" } catch(InterruptedException ie) { " +
" } " +
" } " +
@@ -58,13 +100,13 @@
"}";
public static String evenNewerB =
- "class RedefineRunningMethodsWithBacktrace$B {" +
+ "class RedefineRunningMethodsWithBacktrace_B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
" static void localSleep() { " +
" try{ " +
- " Thread.currentThread().sleep(1);" +
+ " Thread.sleep(1);" +
" } catch(InterruptedException ie) { " +
" } " +
" } " +
@@ -74,45 +116,6 @@
" }" +
"}";
- static class B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try {
- Thread.currentThread().sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void throwable() {
- // add some stuff to the original constant pool
- String s1 = new String ("string1");
- String s2 = new String ("string2");
- String s3 = new String ("string3");
- String s4 = new String ("string4");
- String s5 = new String ("string5");
- String s6 = new String ("string6");
- String s7 = new String ("string7");
- String s8 = new String ("string8");
- String s9 = new String ("string9");
- String s10 = new String ("string10");
- String s11 = new String ("string11");
- String s12 = new String ("string12");
- String s13 = new String ("string13");
- String s14 = new String ("string14");
- String s15 = new String ("string15");
- String s16 = new String ("string16");
- String s17 = new String ("string17");
- String s18 = new String ("string18");
- String s19 = new String ("string19");
- throw new RuntimeException("throwable called");
- }
- }
-
private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
System.out.println("touchRedefinedMethodInBacktrace: ");
throwable.printStackTrace(); // this actually crashes with the bug in
@@ -133,7 +136,7 @@
private static Throwable getThrowableInB() {
Throwable t = null;
try {
- B.throwable();
+ RedefineRunningMethodsWithBacktrace_B.throwable();
} catch (Exception e) {
t = e;
// Don't print here because Throwable will cache the constructed stacktrace
@@ -147,32 +150,32 @@
new Thread() {
public void run() {
- B.infinite();
+ RedefineRunningMethodsWithBacktrace_B.infinite();
}
}.start();
Throwable t1 = getThrowableInB();
- RedefineClassHelper.redefineClass(B.class, newB);
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
System.gc();
Throwable t2 = getThrowableInB();
- B.infinite();
+ RedefineRunningMethodsWithBacktrace_B.infinite();
for (int i = 0; i < 20 ; i++) {
String s = new String("some garbage");
System.gc();
}
- RedefineClassHelper.redefineClass(B.class, evenNewerB);
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
System.gc();
Throwable t3 = getThrowableInB();
for (int i = 0; i < 20 ; i++) {
- B.infinite();
+ RedefineRunningMethodsWithBacktrace_B.infinite();
String s = new String("some garbage");
System.gc();
}
@@ -182,10 +185,10 @@
touchRedefinedMethodInBacktrace(t3);
// purge should clean everything up.
- B.stop = true;
+ RedefineRunningMethodsWithBacktrace_B.stop = true;
for (int i = 0; i < 20 ; i++) {
- B.infinite();
+ RedefineRunningMethodsWithBacktrace_B.infinite();
String s = new String("some garbage");
System.gc();
}
--- a/test/hotspot/jtreg/runtime/SelectionResolution/InvokeInterfaceICCE.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SelectionResolution/InvokeInterfaceICCE.java Mon Jun 25 09:48:06 2018 -0700
@@ -154,20 +154,7 @@
Template.IfaceMethodrefNotEqualsExpected,
Template.IgnoredAbstract,
Template.AllCallsiteCases,
- Template.IfaceMethodrefAmbiguousResolvedIsIface),
-
- /* Group 175: private method in interface */
- new TestGroup.Simple(initBuilder,
- Template.SetInvoke(SelectionResolutionTestCase.InvokeInstruction.INVOKEINTERFACE),
- Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
- EnumSet.of(MethodData.Access.PRIVATE),
- EnumSet.of(MethodData.Context.INSTANCE),
- EnumSet.of(ClassData.Package.SAME)),
- Template.OverrideAbstractExpectedIface,
- Template.MethodrefEqualsExpected,
- Template.IgnoredAbstract,
- Template.CallsiteEqualsMethodref,
- Template.IfaceMethodrefSelection)
+ Template.IfaceMethodrefAmbiguousResolvedIsIface)
);
private InvokeInterfaceICCE() {
--- a/test/hotspot/jtreg/runtime/SelectionResolution/InvokeInterfaceSuccessTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SelectionResolution/InvokeInterfaceSuccessTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -136,6 +136,20 @@
Template.CallsiteUnrelatedToMethodref,
Template.IfaceMethodrefSelection,
Template.SelectionOverrideAbstract)
+ /* ,
+ // Group 175: private method in interface [was ICCE case up to JDK 11]
+ // Can't get this to work for some reason.
+ new TestGroup.Simple(initBuilder,
+ Template.ResultCombo(EnumSet.of(Template.Kind.INTERFACE),
+ EnumSet.of(MethodData.Access.PRIVATE),
+ EnumSet.of(MethodData.Context.INSTANCE),
+ EnumSet.of(ClassData.Package.SAME)),
+ Template.OverrideAbstractExpectedIface,
+ Template.MethodrefEqualsExpected,
+ Template.IgnoredAbstract,
+ Template.CallsiteEqualsMethodref,
+ Template.IfaceMethodrefSelection)
+ */
);
private InvokeInterfaceSuccessTest() {
--- a/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Template.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/SelectionResolution/classes/selectionresolution/Template.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -4394,6 +4394,15 @@
builder.objectref = C1;
});
+ // NOTE: The selection changes in JVMS 11 mean that private class methods
+ // are never selected to satisfy an interface method invocation, and so no
+ // IllegalAccessError is subsequently thrown. Because of this all the
+ // "private" cases below are commented out. At some point in the future
+ // these should be factored out and moved to a test that expects success
+ // but it is not that simple as the commented out cases result in 2600
+ // testcases being excluded, but only ~150 failing cases were seen. Though
+ // it is not clear from the test if a single failure can result in further
+ // testcases being skipped.
public static final Template IfaceMethodrefSelectionOverrideNonPublic =
new Template("IfaceMethodrefSelection",
/* Case 1: Objectref overrides.
@@ -4401,22 +4410,22 @@
* I[](*) = mref
* C[I](priv) = oref = expected
*/
- (final SelectionResolutionTestCase.Builder builder) -> {
- final ClassData.Package pck =
- builder.classdata.get(builder.methodref).packageId;
- final ClassData oldexpected =
- builder.classdata.get(builder.expected);
- final MethodData meth =
- new MethodData(MethodData.Access.PRIVATE,
- MethodData.Context.INSTANCE);
- final ClassData withDef =
- new ClassData(pck, meth);
- final int I = builder.methodref;
- final int C = builder.addClass(withDef);
- builder.hier.addInherit(C, I);
- builder.objectref = C;
- builder.expected = C;
- },
+ // (final SelectionResolutionTestCase.Builder builder) -> {
+ // final ClassData.Package pck =
+ // builder.classdata.get(builder.methodref).packageId;
+ // final ClassData oldexpected =
+ // builder.classdata.get(builder.expected);
+ // final MethodData meth =
+ // new MethodData(MethodData.Access.PRIVATE,
+ // MethodData.Context.INSTANCE);
+ // final ClassData withDef =
+ // new ClassData(pck, meth);
+ // final int I = builder.methodref;
+ // final int C = builder.addClass(withDef);
+ // builder.hier.addInherit(C, I);
+ // builder.objectref = C;
+ // builder.expected = C;
+ // },
/* Case 2: Objectref overrides.
*
* I[](*) = mref
@@ -4466,27 +4475,27 @@
* C2[I2](priv) = expected, I1[I2]()
* C1[I1,C2]() = oref
*/
- (final SelectionResolutionTestCase.Builder builder) -> {
- final ClassData.Package pck =
- builder.classdata.get(builder.expected).packageId;
- final ClassData oldexpected =
- builder.classdata.get(builder.expected);
- final MethodData meth =
- new MethodData(MethodData.Access.PRIVATE,
- MethodData.Context.INSTANCE);
- final ClassData withDef =
- new ClassData(pck, meth);
- final int I2 = builder.methodref;
- final int I1 = builder.addInterface(emptyClass(pck));
- final int C2 = builder.addClass(withDef);
- final int C1 = builder.addClass(emptyClass(pck));
- builder.hier.addInherit(C1, I1);
- builder.hier.addInherit(C1, C2);
- builder.hier.addInherit(I1, I2);
- builder.hier.addInherit(C2, I2);
- builder.objectref = C1;
- builder.expected = C2;
- },
+ // (final SelectionResolutionTestCase.Builder builder) -> {
+ // final ClassData.Package pck =
+ // builder.classdata.get(builder.expected).packageId;
+ // final ClassData oldexpected =
+ // builder.classdata.get(builder.expected);
+ // final MethodData meth =
+ // new MethodData(MethodData.Access.PRIVATE,
+ // MethodData.Context.INSTANCE);
+ // final ClassData withDef =
+ // new ClassData(pck, meth);
+ // final int I2 = builder.methodref;
+ // final int I1 = builder.addInterface(emptyClass(pck));
+ // final int C2 = builder.addClass(withDef);
+ // final int C1 = builder.addClass(emptyClass(pck));
+ // builder.hier.addInherit(C1, I1);
+ // builder.hier.addInherit(C1, C2);
+ // builder.hier.addInherit(I1, I2);
+ // builder.hier.addInherit(C2, I2);
+ // builder.objectref = C1;
+ // builder.expected = C2;
+ // },
/* Case 5: Diamond, with superclass, expected at top,
* class overriding with package private.
*
@@ -4549,24 +4558,24 @@
* C2[](priv) = expected, I1[](*) = mref
* C1[I1,C2]() = oref
*/
- (final SelectionResolutionTestCase.Builder builder) -> {
- final ClassData.Package pck =
- builder.classdata.get(builder.expected).packageId;
- final ClassData oldexpected =
- builder.classdata.get(builder.expected);
- final MethodData meth =
- new MethodData(MethodData.Access.PRIVATE,
- MethodData.Context.INSTANCE);
- final ClassData withDef =
- new ClassData(pck, meth);
- final int I1 = builder.methodref;
- final int C2 = builder.addClass(withDef);
- final int C1 = builder.addClass(emptyClass(pck));
- builder.hier.addInherit(C1, I1);
- builder.hier.addInherit(C1, C2);
- builder.objectref = C1;
- builder.expected = C2;
- },
+ // (final SelectionResolutionTestCase.Builder builder) -> {
+ // final ClassData.Package pck =
+ // builder.classdata.get(builder.expected).packageId;
+ // final ClassData oldexpected =
+ // builder.classdata.get(builder.expected);
+ // final MethodData meth =
+ // new MethodData(MethodData.Access.PRIVATE,
+ // MethodData.Context.INSTANCE);
+ // final ClassData withDef =
+ // new ClassData(pck, meth);
+ // final int I1 = builder.methodref;
+ // final int C2 = builder.addClass(withDef);
+ // final int C1 = builder.addClass(emptyClass(pck));
+ // builder.hier.addInherit(C1, I1);
+ // builder.hier.addInherit(C1, C2);
+ // builder.objectref = C1;
+ // builder.expected = C2;
+ // },
/* Case 8: Y, with superclass, overlaping, expected
* at top, class overrides
*
@@ -4622,26 +4631,26 @@
* C2[I2](priv) = expected, I1[](*) = mref
* C1[I1,C2]() = oref
*/
- (final SelectionResolutionTestCase.Builder builder) -> {
- final ClassData.Package pck =
- builder.classdata.get(builder.expected).packageId;
- final ClassData oldexpected =
- builder.classdata.get(builder.expected);
- final MethodData meth =
- new MethodData(MethodData.Access.PRIVATE,
- MethodData.Context.INSTANCE);
- final ClassData withDef =
- new ClassData(pck, meth);
- final int I2 = builder.expected;
- final int I1 = builder.methodref;
- final int C2 = builder.addClass(withDef);
- final int C1 = builder.addClass(emptyClass(pck));
- builder.hier.addInherit(C1, I1);
- builder.hier.addInherit(C1, C2);
- builder.hier.addInherit(C2, I2);
- builder.objectref = C1;
- builder.expected = C2;
- },
+ // (final SelectionResolutionTestCase.Builder builder) -> {
+ // final ClassData.Package pck =
+ // builder.classdata.get(builder.expected).packageId;
+ // final ClassData oldexpected =
+ // builder.classdata.get(builder.expected);
+ // final MethodData meth =
+ // new MethodData(MethodData.Access.PRIVATE,
+ // MethodData.Context.INSTANCE);
+ // final ClassData withDef =
+ // new ClassData(pck, meth);
+ // final int I2 = builder.expected;
+ // final int I1 = builder.methodref;
+ // final int C2 = builder.addClass(withDef);
+ // final int C1 = builder.addClass(emptyClass(pck));
+ // builder.hier.addInherit(C1, I1);
+ // builder.hier.addInherit(C1, C2);
+ // builder.hier.addInherit(C2, I2);
+ // builder.objectref = C1;
+ // builder.expected = C2;
+ // },
/* Case 11: Diamond, with superclass, overlaping, expected
* at top, class overrides
*
@@ -4702,25 +4711,25 @@
* C2[I](priv) = expected
* C1[C2]() = oref
*/
- (final SelectionResolutionTestCase.Builder builder) -> {
- final ClassData.Package pck =
- builder.classdata.get(builder.expected).packageId;
- final ClassData oldexpected =
- builder.classdata.get(builder.expected);
- final MethodData meth =
- new MethodData(MethodData.Access.PRIVATE,
- MethodData.Context.INSTANCE);
- final ClassData withDef =
- new ClassData(pck, meth);
- final int I = builder.methodref;
- final int C2 = builder.addClass(withDef);
- final int C1 = builder.addClass(emptyClass(pck));
- builder.hier.addInherit(C1, I);
- builder.hier.addInherit(C1, C2);
- builder.hier.addInherit(C2, I);
- builder.expected = C2;
- builder.objectref = C1;
- },
+ // (final SelectionResolutionTestCase.Builder builder) -> {
+ // final ClassData.Package pck =
+ // builder.classdata.get(builder.expected).packageId;
+ // final ClassData oldexpected =
+ // builder.classdata.get(builder.expected);
+ // final MethodData meth =
+ // new MethodData(MethodData.Access.PRIVATE,
+ // MethodData.Context.INSTANCE);
+ // final ClassData withDef =
+ // new ClassData(pck, meth);
+ // final int I = builder.methodref;
+ // final int C2 = builder.addClass(withDef);
+ // final int C1 = builder.addClass(emptyClass(pck));
+ // builder.hier.addInherit(C1, I);
+ // builder.hier.addInherit(C1, C2);
+ // builder.hier.addInherit(C2, I);
+ // builder.expected = C2;
+ // builder.objectref = C1;
+ // },
/* Case 14: Superclass overrides.
*
* I[](*) = mref
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasic.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasic.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -24,10 +24,21 @@
import sun.hotspot.WhiteBox;
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineBasic_B {
+ public static void okToCallBeforeRedefine() {
+ System.out.println("okToCallBeforeRedefine");
+ }
+ public static void okToCallAfterRedefine() {
+ throw new RuntimeException("okToCallAfterRedefine is called before redefinition, test failed");
+ }
+}
+
public class RedefineBasic {
public static String newB =
- " class RedefineBasic$B { " +
+ " class RedefineBasic_B { " +
" public static void okToCallBeforeRedefine() { " +
" throw new RuntimeException(\"newB: okToCallBeforeRedefine is " +
" called after redefinition, test failed\"); }" +
@@ -36,23 +47,14 @@
" } ";
- static class B {
- public static void okToCallBeforeRedefine() {
- System.out.println("okToCallBeforeRedefine");
- }
- public static void okToCallAfterRedefine() {
- throw new RuntimeException(
- "okToCallAfterRedefine is called before redefinition, test failed");
+
+ static class SubclassOfB extends RedefineBasic_B {
+ public static void testAfterRedefine() {
+ RedefineBasic_B.okToCallAfterRedefine();
}
}
- static class SubclassOfB extends B {
- public static void testAfterRedefine() {
- B.okToCallAfterRedefine();
- }
- }
-
- class Subclass2OfB extends B {
+ class Subclass2OfB extends RedefineBasic_B {
public void testAfterRedefine() {
super.okToCallAfterRedefine();
}
@@ -74,17 +76,17 @@
WhiteBox wb = WhiteBox.getWhiteBox();
verifyClassIsShared(wb, RedefineBasic.class);
- verifyClassIsShared(wb, B.class);
+ verifyClassIsShared(wb, RedefineBasic_B.class);
verifyClassIsShared(wb, SubclassOfB.class);
verifyClassIsShared(wb, Subclass2OfB.class);
// (1) Test case: verify that original B works as expected
// and that redefined B is shared and works as expected,
// with new behavior
- B.okToCallBeforeRedefine();
- RedefineClassHelper.redefineClass(B.class, newB);
- verifyClassIsShared(wb, B.class);
- B.okToCallAfterRedefine();
+ RedefineBasic_B.okToCallBeforeRedefine();
+ RedefineClassHelper.redefineClass(RedefineBasic_B.class, newB);
+ verifyClassIsShared(wb, RedefineBasic_B.class);
+ RedefineBasic_B.okToCallAfterRedefine();
// Static subclass of the super:
// 1. Make sure it is still shared
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -43,7 +43,7 @@
public class RedefineBasicTest {
public static String sharedClasses[] = {
"RedefineBasic",
- "RedefineBasic$B",
+ "RedefineBasic_B",
"RedefineBasic$SubclassOfB",
"RedefineBasic$Subclass2OfB",
"RedefineClassHelper",
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -47,7 +47,7 @@
"RedefineRunningMethods$1",
"RedefineRunningMethods$2",
"RedefineRunningMethods$3",
- "RedefineRunningMethods$B",
+ "RedefineRunningMethods_B",
"RedefineClassHelper",
"jdk/test/lib/compiler/InMemoryJavaCompiler",
"jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper",
--- a/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/exceptionMsgs/IncompatibleClassChangeError/IncompatibleClassChangeErrorTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -212,7 +212,7 @@
}
private static String expectedErrorMessage3 =
- "Class test.ICC3_B can not implement test.ICC3_A, because it is not an interface";
+ "class test.ICC3_B can not implement test.ICC3_A, because it is not an interface (test.ICC3_A is in unnamed module of loader 'app')";
public static void test3_implementsClass() throws Exception {
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/ExpQualToM1PrivateMethodIAE.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @summary Test that if module m1x can read module m2x, AND package p2 in m2x is
+ * exported qualifiedly to m1x, then class p1.c1 in m1x can read p2.c2 in m2x.
+ * However, p1.c1 tries to access a private method within p2.c2, verify
+ * that the IAE message contains the correct loader and module names.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @compile p1/c1.jasm
+ * @compile p2/c2.jasm
+ * @compile myloaders/MySameClassLoader.java
+ * @run main/othervm -Xbootclasspath/a:. ExpQualToM1PrivateMethodIAE
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import myloaders.MySameClassLoader;
+
+public class ExpQualToM1PrivateMethodIAE {
+
+ // Create a layer over the boot layer.
+ // Define modules within this layer to test access between
+ // publically defined classes within packages of those modules.
+ public void createLayerOnBoot() throws Throwable {
+
+ // Define module: m1x
+ // Can read: java.base, m2x
+ // Packages: p1
+ // Packages exported: p1 is exported unqualifiedly
+ ModuleDescriptor descriptor_m1x =
+ ModuleDescriptor.newModule("m1x")
+ .requires("java.base")
+ .requires("m2x")
+ .exports("p1")
+ .build();
+
+ // Define module: m2x
+ // Can read: java.base
+ // Packages: p2
+ // Packages exported: p2 is exported qualifiedly to m1x
+ ModuleDescriptor descriptor_m2x =
+ ModuleDescriptor.newModule("m2x")
+ .requires("java.base")
+ .exports("p2", Set.of("m1x"))
+ .build();
+
+ // Set up a ModuleFinder containing all modules for this layer.
+ ModuleFinder finder = ModuleLibrary.of(descriptor_m1x, descriptor_m2x);
+
+ // Resolves "m1x"
+ Configuration cf = ModuleLayer.boot()
+ .configuration()
+ .resolve(finder, ModuleFinder.of(), Set.of("m1x"));
+
+ // map each module to the same class loader for this test
+ Map<String, ClassLoader> map = new HashMap<>();
+ map.put("m1x", MySameClassLoader.loader1);
+ map.put("m2x", MySameClassLoader.loader1);
+
+ // Create layer that contains m1x & m2x
+ ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get);
+
+ assertTrue(layer.findLoader("m1x") == MySameClassLoader.loader1);
+ assertTrue(layer.findLoader("m2x") == MySameClassLoader.loader1);
+
+ // now use the same loader to load class p1.c1
+ Class p1_c1_class = MySameClassLoader.loader1.loadClass("p1.c1");
+ try {
+ p1_c1_class.newInstance();
+ throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
+ } catch (IllegalAccessError e) {
+ String message = e.getMessage();
+ System.out.println(e.toString());
+ // java.lang.IllegalAccessError:
+ // tried to access method p2.c2.method2()V from class p1.c1 (p2.c2 is in module m2x of loader
+ // myloaders.MySameClassLoader @<id>; p1.c1 is in module m1x of loader myloaders.MySameClassLoader @<id>)
+ if (!message.contains("class p1.c1 tried to access method p2.c2.method2()V (p1.c1 is in module m1x of loader myloaders.MySameClassLoader @") ||
+ !message.contains("; p2.c2 is in module m2x of loader myloaders.MySameClassLoader @")) {
+ throw new RuntimeException("Test Failed, an IAE was thrown with the wrong message: " + e.toString());
+ }
+ } catch (Throwable e) {
+ throw new RuntimeException("Test Failed, an IAE should be thrown since p2/c2's method2 is private");
+ }
+ }
+
+ public static void main(String args[]) throws Throwable {
+ ExpQualToM1PrivateMethodIAE test = new ExpQualToM1PrivateMethodIAE();
+ test.createLayerOnBoot();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p1/c1.jasm Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, 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 p1;
+
+super public class c1 version 55:0 {
+
+ public Method "<init>":"()V"
+ stack 2 locals 2
+ {
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ new class p2/c2;
+ dup;
+ invokespecial Method p2/c2."<init>":"()V";
+ astore_1;
+ aload_1;
+ invokevirtual Method p2/c2.method2:"()V";
+ return;
+ }
+} // end Class c1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/modules/AccessCheck/p2/c2.jasm Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, 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 p2;
+
+super public class c2 version 55:0 {
+ public Method "<init>":"()V"
+ stack 1 locals 1
+ {
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+ }
+
+ private Method method2:"()V"
+ stack 0 locals 1
+ {
+ return;
+ }
+} // end Class c2
--- a/test/hotspot/jtreg/runtime/modules/CCE_module_msg.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/runtime/modules/CCE_module_msg.java Mon Jun 25 09:48:06 2018 -0700
@@ -48,6 +48,7 @@
public static void main(String[] args) throws Throwable {
// Should not display version
invalidObjectToDerived();
+ invalidOriginalInnerToDerived();
invalidTimeToDerived();
invalidHeadersToDerived();
// Should display version
@@ -66,8 +67,25 @@
}
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
- System.out.println(cce.getMessage());
- if (!cce.getMessage().contains("java.base/java.lang.Object cannot be cast to Derived")) {
+ System.out.println(cce.toString());
+ if (!cce.getMessage().contains("class java.lang.Object cannot be cast to class Derived (java.lang.Object is in module java.base of loader 'bootstrap'; Derived is in unnamed module of loader 'app')")) {
+ throw new RuntimeException("Wrong message: " + cce.getMessage());
+ }
+ }
+ }
+
+ public static void invalidOriginalInnerToDerived() {
+ OriginalInner instance = new OriginalInner();
+ int left = 23;
+ int right = 42;
+ try {
+ for (int i = 0; i < 1; i += 1) {
+ left = ((Derived) (java.lang.Object)instance).method(left, right);
+ }
+ throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
+ } catch (ClassCastException cce) {
+ System.out.println(cce.toString());
+ if (!cce.getMessage().contains("class OriginalInner cannot be cast to class Derived (OriginalInner and Derived are in unnamed module of loader 'app')")) {
throw new RuntimeException("Wrong message: " + cce.getMessage());
}
}
@@ -84,8 +102,8 @@
}
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
- System.out.println(cce.getMessage());
- if (!cce.getMessage().contains("java.sql/java.sql.Time cannot be cast to Derived")) {
+ System.out.println(cce.toString());
+ if (!cce.getMessage().contains("class java.sql.Time cannot be cast to class Derived (java.sql.Time is in module java.sql of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
throw new RuntimeException("Wrong message: " + cce.getMessage());
}
}
@@ -102,8 +120,8 @@
}
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
- System.out.println(cce.getMessage());
- if (!cce.getMessage().contains("jdk.httpserver/com.sun.net.httpserver.Headers cannot be cast to Derived")) {
+ System.out.println(cce.toString());
+ if (!cce.getMessage().contains("class com.sun.net.httpserver.Headers cannot be cast to class Derived (com.sun.net.httpserver.Headers is in module jdk.httpserver of loader 'platform'; Derived is in unnamed module of loader 'app')")) {
throw new RuntimeException("Wrong message: " + cce.getMessage());
}
}
@@ -132,10 +150,9 @@
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
String exception = cce.getMessage();
- System.out.println(exception);
- if (exception.contains("module_two/p2.c2") ||
- !(exception.contains("module_two@") &&
- exception.contains("/p2.c2 cannot be cast to java.base/java.lang.String"))) {
+ System.out.println(cce.toString());
+ if (!exception.contains("class p2.c2 cannot be cast to class java.lang.String (p2.c2 is in module module_two@") ||
+ !exception.contains(" of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')")) {
throw new RuntimeException("Wrong message: " + exception);
}
}
@@ -160,14 +177,21 @@
throw new RuntimeException("ClassCastException wasn't thrown, test failed.");
} catch (ClassCastException cce) {
String exception = cce.getMessage();
- System.out.println(exception);
- if (!exception.contains("MyClassLoader//p4.c4 cannot be cast to java.base/java.lang.String")) {
+ System.out.println(cce.toString());
+ if (!exception.contains("class p4.c4 cannot be cast to class java.lang.String (p4.c4 is in unnamed module of loader 'MyClassLoader' @") ||
+ !exception.contains("; java.lang.String is in module java.base of loader 'bootstrap')")) {
throw new RuntimeException("Wrong message: " + exception);
}
}
}
}
+class OriginalInner extends java.lang.Object {
+ public int method(int left, int right) {
+ return right;
+ }
+}
+
class Derived extends java.lang.Object {
public int method(int left, int right) {
return right;
--- a/test/hotspot/jtreg/testlibrary_tests/RedefineClassTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/testlibrary_tests/RedefineClassTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -38,19 +38,22 @@
/*
* Proof of concept test for the test utility class RedefineClassHelper
*/
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineClassTest_A {
+ public int Method() {
+ return 1;
+ }
+}
+
public class RedefineClassTest {
- public static String newClass = "class RedefineClassTest$A { public int Method() { return 2; } }";
+ public static String newClass = "class RedefineClassTest_A { public int Method() { return 2; } }";
public static void main(String[] args) throws Exception {
- A a = new A();
+ RedefineClassTest_A a = new RedefineClassTest_A();
assertTrue(a.Method() == 1);
- RedefineClassHelper.redefineClass(A.class, newClass);
+ RedefineClassHelper.redefineClass(RedefineClassTest_A.class, newClass);
assertTrue(a.Method() == 2);
}
-
- static class A {
- public int Method() {
- return 1;
- }
- }
}
--- a/test/hotspot/jtreg/vmTestbase/jit/t/t113/t113.gold Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/jit/t/t113/t113.gold Mon Jun 25 09:48:06 2018 -0700
@@ -1,2 +1,2 @@
-java.lang.ClassCastException: jit.t.t113.kid1 cannot be cast to jit.t.t113.kid2
+java.lang.ClassCastException: class jit.t.t113.kid1 cannot be cast to class jit.t.t113.kid2 (jit.t.t113.kid1 and jit.t.t113.kid2 are in unnamed module of loader 'app')
at jit.t.t113.t113.main(t113.java:59)
--- a/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java Mon Jun 25 09:48:06 2018 -0700
@@ -211,15 +211,15 @@
Object integerValue = new Integer(0);
Object doubleValue = new Double(0);
Object trash = null;
- Field abraPrivateField;
Field abraIntegerField;
Field abraBooleanField;
+ Field extPrivateField;
try {
- abraPrivateField = Abra.class.getDeclaredField("DONT_TOUCH_ME");
abraIntegerField = Abra.class.getDeclaredField("MAIN_CYR_NUMBER");
abraBooleanField = Abra.class.getDeclaredField("NOT_AN_INTEGER");
+ extPrivateField = Ext.class.getDeclaredField("DONT_TOUCH_ME");
} catch (NoSuchFieldException nsfe) {
- out.println("Test initialisation failed: field not found in class Abra");
+ out.println("Test initialisation failed: field not found: " + nsfe.getMessage());
return 2;
}
@@ -369,7 +369,6 @@
// Check IllegalAccessException (positive):
try {
int junkIt = abraIntegerField.getInt(null); // legal - should pass
-// int junkIt = abraPrivateField.getInt(null); // illegal - should fail
if (TRACE_ON)
log[messages++] = "Success: IllegalAccessException (positive)";
} catch (IllegalAccessException iae) {
@@ -383,8 +382,7 @@
// Check IllegalAccessException (negative):
try {
-// int junkIt = abraIntegerField.getInt(null); // legal - should pass
- int junkIt = abraPrivateField.getInt(null); // illegal - should fail
+ int junkIt = extPrivateField.getInt(null); // illegal - should fail
log[messages++] = "Failure: IllegalAccessException (negative)";
exitCode = 2; // FAILED
} catch (IllegalAccessException iae) {
@@ -512,7 +510,7 @@
/**
* This class should be used to check <code>CloneNotSupportedException</code>,
- * <code>IllegalAccessException</code>, and <code>IllegalArgumentException</code>.
+ * and <code>IllegalArgumentException</code>.
* The class extends <code>except004</code> in order that its (protected)
* method <code>clone()</code> be available from <code>except004</code>.
*/
@@ -527,10 +525,6 @@
/**
* Will try to incorrectly access to this field from outside this class.
*/
- private static final int DONT_TOUCH_ME = 666;
- /**
- * Will try to incorrectly access to this field from outside this class.
- */
public static final int MAIN_CYR_NUMBER = 47;
/**
* Will try to get this field like <code>int<code> zero.
@@ -551,3 +545,11 @@
}
}
}
+
+/* Package accessible class that has non-accessible private member */
+class Ext {
+ /**
+ * Will try to incorrectly access to this field from outside this class.
+ */
+ private static final int DONT_TOUCH_ME = 666;
+}
--- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/BasicTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/BasicTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -81,7 +81,7 @@
expectedClass = IllegalArgumentException.class;
} else if (factory.getExecutionMode().equals("INVOKE_WITH_ARGS")) {
// Notes from JDK-8029926 which details reasons behind CCE.
- // The code below demonstrates the use of a MethodHandle
+ // The code below demonstrates the use of a MethodHandle
// of kind REF_invokeInterface pointing to method I.m.
// Because 'invoke' is called, this MethodHandle is effectively
// wrapped in the type adaptations necessary to accept a C
@@ -157,38 +157,38 @@
}
/*
- * Default method override w/ non-public concrete method
+ * Default method override attempt w/ non-public concrete method.
+ * Private methods never override any other method.
*
- * interface I { void m() default {} }
- * class C implements I {
- * [private/package-private/protected]
- * void m() {}
+ * interface I { int m() default { returns 1; } }
+ * class C/D/E implements I {
+ * [private/protected/package-private]
+ * int m() { returns 2;}
* }
*
*/
- @KnownFailure(modes = {INVOKE_EXACT, INVOKE_GENERIC, INVOKE_WITH_ARGS, INDY}) // NPE, instead of IAE
public void testNonPublicOverride() {
TestBuilder b = factory.getBuilder();
Interface I = b.intf("I")
- .defaultMethod("m","()V").emptyBody().build()
+ .defaultMethod("m", "()I").returns(1).build()
.build();
ConcreteClass C = b.clazz("C").implement(I)
- .concreteMethod("m", "()V").private_().emptyBody().build()
+ .concreteMethod("m", "()I").private_().returns(2).build()
.build();
ConcreteClass D = b.clazz("D").implement(I)
- .concreteMethod("m", "()V").protected_().emptyBody().build()
+ .concreteMethod("m", "()I").protected_().returns(2).build()
.build();
ConcreteClass E = b.clazz("E").implement(I)
- .concreteMethod("m", "()V").package_private().emptyBody().build()
+ .concreteMethod("m", "()I").package_private().returns(2).build()
.build();
- b.test().callSite(I, C, "m", "()V").throws_(IllegalAccessError.class).done()
- .test().callSite(I, D, "m", "()V").throws_(IllegalAccessError.class).done()
- .test().callSite(I, E, "m", "()V").throws_(IllegalAccessError.class).done()
+ b.test().callSite(I, C, "m", "()I").returns(1).done()
+ .test().callSite(I, D, "m", "()I").throws_(IllegalAccessError.class).done()
+ .test().callSite(I, E, "m", "()I").throws_(IllegalAccessError.class).done()
.run();
}
--- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/PrivateMethodsTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -48,11 +48,28 @@
// to even see an interface private method
// Throw ICCE if method resolution returns interface private method
+ // Spec change JDK 11 - invokeinterface can be used for private interface
+ // methods and is now the preferred invocation bytecode - so no ICCE.
+ // Private methods are skipped during selection unless the resolved method
+ // is private.
+ // This change is not dependent on the classfile version.
+
+ // Note on reflection testing:
+ // Reflection is only used for the initial callsite, which is not always
+ // the method of interest. For example where a default method m() calls
+ // the private interface method privateM(). It is the latter call we are
+ // really testing, but it is the call of the default method that occurs
+ // via reflection.
+ // In private cases reflection triggers a NoSuchMethodException instead of the
+ // expected IllegalAccessError. This indicates it is getDeclaredMethod() that is
+ // failing rather than the actual invoke(). Which in turn suggests the wrong class
+ // is being used, or that getMethod() is being used instead of getDeclaredMethod().
+
/*
* testPrivateInvokeVirtual
*
* interface I {
- * default private int privateM() { return 1; }
+ * private int privateM() { return 1; }
* default public int m() { return (I)this.privateM(); } // invokevirtual
* }
* class C implements I {}
@@ -85,13 +102,13 @@
* testPrivateInvokeIntf
*
* interface I {
- * default private int privateM() { return 1; }
+ * private int privateM() { return 1; }
* default public int m() { return (I)this.privateM(); } // invokeinterface
* }
* class C implements I {}
*
- * TEST: I o = new C(); o.m()I throws IncompatibleClassChangeError
- * TEST: C o = new C(); o.m()I throws IncompatibleClassChangeError
+ * TEST: I o = new C(); o.m()I returns 1
+ * TEST: C o = new C(); o.m()I returns 1
*/
public void testPrivateInvokeIntf() {
TestBuilder b = factory.getBuilder();
@@ -105,8 +122,8 @@
ConcreteClass C = b.clazz("C").implement(I).build();
- b.test().callSite(I, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done()
- .test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done()
+ b.test().callSite(I, C, "m", "()I").returns(1).done()
+ .test().callSite(C, C, "m", "()I").returns(1).done()
.run();
}
@@ -115,13 +132,13 @@
* testPrivateInvokeStatic
*
* interface I {
- * default private int privateM() { return 1; }
+ * private int privateM() { return 1; }
* default public int m() { return I.privateM(); } // invokestatic
* }
* class C implements I {}
*
- * TEST: I o = new C(); o.m()I throws LinkageError
- * TEST: C o = new C(); o.m()I throws LinkageError
+ * TEST: I o = new C(); o.m()I throws IncompatibleClassChangeError
+ * TEST: C o = new C(); o.m()I throws IncompatibleClassChangeError
*/
public void testPrivateInvokeStatic() {
TestBuilder b = factory.getBuilder();
@@ -135,8 +152,8 @@
ConcreteClass C = b.clazz("C").implement(I).build();
- b.test().callSite(I, C, "m", "()I").throws_(LinkageError.class).done()
- .test().callSite(C, C, "m", "()I").throws_(LinkageError.class).done()
+ b.test().callSite(I, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done()
+ .test().callSite(C, C, "m", "()I").throws_(IncompatibleClassChangeError.class).done()
.run();
}
@@ -146,8 +163,8 @@
* testPrivateCallSameClass
*
* interface I {
- * default private privateM()I { return 1; }
- * default public int m() { return I.super.privateM(); }
+ * private privateM()I { return 1; }
+ * default public int m() { return I.super.privateM(); } // invokespecial
* }
* class C implements I {}
*
@@ -178,7 +195,7 @@
* Attempt to call from subinterface fails
* interface I {
- * default private privateM()I { return 1; }
+ * private privateM()I { return 1; }
* }
* J, K, L use invokespecial
* interface J extends I {
@@ -248,7 +265,7 @@
* Attempt to call from subclass fails
*
* interface I {
- * default private privateM()I { return 1; }
+ * private privateM()I { return 1; }
* }
* class C implements I {
* public int m() { return I.super.privateM(); }
@@ -260,9 +277,9 @@
* public int m() { return C.super.privateM(); }
* }
*
- * TEST: { C o = new C(); o.m()I throws LinkageError }
- * TEST: { D o = new D(); o.m()I throws LinkageError }
- * TEST: { E o = new E(); o.m()I throws NoSuchMethodError; }
+ * TEST: { C o = new C(); o.m()I throws IllegalAccessError (or VerifyError) }
+ * TEST: { D o = new D(); o.m()I throws VerifyError }
+ * TEST: { E o = new E(); o.m()I throws NoSuchMethodError (or VerifyError); }
*/
@NotApplicableFor(modes = { REDEFINITION }) // Can't redefine a class that gets error during loading
public void testPrivateCallImplClass() {
@@ -289,16 +306,19 @@
.build();
Class eeExpectedClass;
+ Class ccExpectedClass;
if (factory.getVer() >= 52) {
eeExpectedClass = NoSuchMethodError.class;
+ ccExpectedClass = IllegalAccessError.class;
} else {
// The test gets a VerifyError in this case due to an
// invokespecial IMR bytecode. This was not allowed
// until class file version 52. (See 8030249.)
eeExpectedClass = VerifyError.class;
+ ccExpectedClass = VerifyError.class;
}
- b.test().callSite(C, C, "m", "()I").throws_(LinkageError.class).done()
- .test().callSite(D, D, "m", "()I").throws_(LinkageError.class).done()
+ b.test().callSite(C, C, "m", "()I").throws_(ccExpectedClass).done()
+ .test().callSite(D, D, "m", "()I").throws_(VerifyError.class).done()
.test().callSite(E, E, "m", "()I").throws_(eeExpectedClass).done()
.run();
@@ -308,18 +328,18 @@
// method overriding
/*
- * testPrivateDefault
+ * testPrivate
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* class C implements I {}
*
* TEST: { I o = new C(); o.m()I throws IllegalAccessError; }
* -mode reflect throws NoSuchMethodException
- * TEST: { C o = new C(); o.m()I throws java/lang/NoSuchMethodError; }
+ * TEST: { C o = new C(); o.m()I throws NoSuchMethodError; }
*/
- public void testPrivateDefault() {
+ public void testPrivate() {
TestBuilder b = factory.getBuilder();
Interface I = b.intf("I")
@@ -343,10 +363,10 @@
}
/*
- * testPrivateDefaultVsConcrete
+ * testPrivateVsConcrete
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* class C implements I {
* public int m() { return 2; }
@@ -356,7 +376,7 @@
* -mode reflect throws NoSuchMethodException
* TEST: { C o = new C(); o.m()I == 2; }
*/
- public void testPrivateDefaultVsConcrete() {
+ public void testPrivateVsConcrete() {
TestBuilder b = factory.getBuilder();
Interface I = b.intf("I")
@@ -385,7 +405,7 @@
* testPublicOverridePrivate
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* interface J extends I {
* default public int m() { return 2; }
@@ -433,7 +453,7 @@
* default public int m() { return 1; }
* }
* interface J extends I {
- * default private int m() { return 2; }
+ * private int m() { return 2; }
* }
* class C implements J {}
*
@@ -441,14 +461,6 @@
* TEST: { J o = new C(); o.m()I == IllegalAccessError; } II J.m priv
* TEST: { C o = new C(); o.m()I == 1; }
*/
- /*
-
- REFLECTION:
- Test2_J_C_m : FAILED
- nsk.share.TestFailure: Caught exception as expected, but its type is wrong:
- expected: java.lang.IllegalAccessError;
- actual: java.lang.NoSuchMethodException.
- */
public void testPrivateOverrideDefault() {
TestBuilder b = factory.getBuilder();
@@ -475,7 +487,7 @@
* testPrivateReabstract
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* interface J extends I {
* abstract public int m();
@@ -522,23 +534,14 @@
* abstract public int m();
* }
* interface J extends I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* class C implements J {}
*
* TEST: { I o = new C(); o.m()I throws AbstractMethodError }
- * TEST: { J o = new C(); o.m()I throws IncompatibleClassChangeError }
+ * TEST: { J o = new C(); o.m()I throws IllegalAccessError }
* TEST: { C o = new C(); o.m()I throws AbstractMethodError }
*/
- /*
- REFLECTION:
- Test1_I_C_m : FAILED
- nsk.share.TestFailure: No exception was thrown: java.lang.AbstractMethodError
- Test2_J_C_m : FAILED
- nsk.share.TestFailure: No exception was thrown: java.lang.AbstractMethodError
- Test3_C_C_m : FAILED
- nsk.share.TestFailure: No exception was thrown: java.lang.AbstractMethodError
- */
public void testPrivateOverrideAbstract() {
TestBuilder b = factory.getBuilder();
@@ -553,24 +556,17 @@
ConcreteClass C = b.clazz("C").implement(J).build();
- Class expectedClass;
- if (factory.getExecutionMode().equals("REFLECTION")) {
- expectedClass = IllegalAccessException.class;
- } else {
- expectedClass = IncompatibleClassChangeError.class;
- }
-
b.test().callSite(I, C, "m", "()I").throws_(AbstractMethodError.class).done()
- .test().privateCallSite(J, C, "m", "()I").throws_(expectedClass).done()
+ .test().privateCallSite(J, C, "m", "()I").throws_(IllegalAccessError.class).done()
.test().callSite(C, C, "m", "()I").throws_(AbstractMethodError.class).done()
.run();
}
/*
- * testPrivateInheritedDefault
+ * testPrivateInherited
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* class B implements I {}
* class C extends B {}
@@ -580,7 +576,7 @@
* TEST: { B o = new C(); o.m()I throws NoSuchMethodError }
* TEST: { C o = new C(); o.m()I throws NoSuchMethodError }
*/
- public void testPrivateInheritedDefault() {
+ public void testPrivateInherited() {
TestBuilder b = factory.getBuilder();
Interface I = b.intf("I")
@@ -607,10 +603,10 @@
}
/*
- * testPrivateDefaultVsConcreteInherited
+ * testPrivateVsConcreteInherited
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* class B {
* public int m() { return 2; }
@@ -622,7 +618,7 @@
* TEST: { B o = new C(); o.m()I == 2; }
* TEST: { C o = new C(); o.m()I == 2; }
*/
- public void testPrivateDefaultVsConcreteInherited() {
+ public void testPrivateVsConcreteInherited() {
TestBuilder b = factory.getBuilder();
Interface I = b.intf("I")
@@ -653,10 +649,10 @@
/*
* testPrivateConflict
*
- * Conflicting default methods
+ * Conflicting methods
*
* interface I {
- * default private int m() { return 1; }
+ * private int m() { return 1; }
* }
* interface J {
* default public int m() { return 2; }
--- a/test/jdk/ProblemList-graal.txt Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/ProblemList-graal.txt Mon Jun 25 09:48:06 2018 -0700
@@ -69,6 +69,8 @@
java/lang/Runtime/exec/LotsOfOutput.java 8196611 generic-all
java/util/concurrent/ScheduledThreadPoolExecutor/BasicCancelTest.java 8196611 generic-all
+java/lang/invoke/PrivateInterfaceCall.java 8202698 generic-all
+
# Next JFR tests fail with Graal. Assuming 8193210.
jdk/jfr/event/compiler/TestCodeSweeper.java 8193210 generic-all
jdk/jfr/event/compiler/TestCompilerInlining.java 8193210 generic-all
--- a/test/jdk/ProblemList.txt Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/ProblemList.txt Mon Jun 25 09:48:06 2018 -0700
@@ -535,10 +535,6 @@
java/io/pathNames/GeneralWin32.java 8180264 windows-all
-java/io/FileInputStream/UnreferencedFISClosesFd.java 8202292 linux-all
-java/io/FileOutputStream/UnreferencedFOSClosesFd.java 8202292 linux-all
-java/io/RandomAccessFile/UnreferencedRAFClosesFd.java 8202292 linux-all
-
############################################################################
# jdk_management
@@ -636,60 +632,60 @@
sun/security/pkcs11/Cipher/ReinitCipher.java 8204203 windows-all
sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java 8204203 windows-all
sun/security/pkcs11/Cipher/TestRSACipher.java 8204203 windows-all
-sun/security/pkcs11/Cipher/TestRSACipherWrap.java 8204203 windows-all
-sun/security/pkcs11/Cipher/TestRawRSACipher.java 8204203 windows-all
-sun/security/pkcs11/Cipher/TestSymmCiphers.java 8204203 windows-all
-sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestDH.java 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestInterop.java 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/TestShort.java 8204203 windows-all
-sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java 8204203 windows-all
-sun/security/pkcs11/KeyGenerator/DESParity.java 8204203 windows-all
-sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java 8204203 windows-all
-sun/security/pkcs11/KeyPairGenerator/TestDH2048.java 8204203 windows-all
-sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8204203 windows-all
-sun/security/pkcs11/Mac/MacKAT.java 8204203 windows-all
-sun/security/pkcs11/Mac/MacSameTest.java 8204203 windows-all
-sun/security/pkcs11/Mac/ReinitMac.java 8204203 windows-all
-sun/security/pkcs11/MessageDigest/ByteBuffers.java 8204203 windows-all
-sun/security/pkcs11/MessageDigest/DigestKAT.java 8204203 windows-all
-sun/security/pkcs11/MessageDigest/ReinitDigest.java 8204203 windows-all
-sun/security/pkcs11/MessageDigest/TestCloning.java 8204203 windows-all
-sun/security/pkcs11/Provider/ConfigQuotedString.sh 8204203 windows-all
-sun/security/pkcs11/Provider/Login.sh 8204203 windows-all
-sun/security/pkcs11/SampleTest.java 8204203 windows-all
-sun/security/pkcs11/Secmod/AddPrivateKey.java 8204203 windows-all
-sun/security/pkcs11/Secmod/Crypto.java 8204203 windows-all
-sun/security/pkcs11/Secmod/GetPrivateKey.java 8204203 windows-all
-sun/security/pkcs11/Secmod/JksSetPrivateKey.java 8204203 windows-all
-sun/security/pkcs11/Secmod/LoadKeystore.java 8204203 windows-all
-sun/security/pkcs11/Secmod/TestNssDbSqlite.java 8204203 windows-all
-sun/security/pkcs11/SecureRandom/Basic.java 8204203 windows-all
-sun/security/pkcs11/SecureRandom/TestDeserialization.java 8204203 windows-all
-sun/security/pkcs11/Serialize/SerializeProvider.java 8204203 windows-all
-sun/security/pkcs11/Signature/ByteBuffers.java 8204203 windows-all
-sun/security/pkcs11/Signature/ReinitSignature.java 8204203 windows-all
-sun/security/pkcs11/Signature/TestDSA.java 8204203 windows-all
-sun/security/pkcs11/Signature/TestDSAKeyLength.java 8204203 windows-all
-sun/security/pkcs11/Signature/TestRSAKeyLength.java 8204203 windows-all
-sun/security/pkcs11/ec/ReadCertificates.java 8204203 windows-all
-sun/security/pkcs11/ec/ReadPKCS12.java 8204203 windows-all
-sun/security/pkcs11/ec/TestCurves.java 8204203 windows-all
-sun/security/pkcs11/ec/TestECDH.java 8204203 windows-all
-sun/security/pkcs11/ec/TestECDH2.java 8204203 windows-all
-sun/security/pkcs11/ec/TestECDSA.java 8204203 windows-all
-sun/security/pkcs11/ec/TestECDSA2.java 8204203 windows-all
-sun/security/pkcs11/ec/TestECGenSpec.java 8204203 windows-all
-sun/security/pkcs11/rsa/KeyWrap.java 8204203 windows-all
-sun/security/pkcs11/rsa/TestCACerts.java 8204203 windows-all
-sun/security/pkcs11/rsa/TestKeyFactory.java 8204203 windows-all
-sun/security/pkcs11/rsa/TestKeyPairGenerator.java 8204203 windows-all
-sun/security/pkcs11/rsa/TestSignatures.java 8204203 windows-all
-sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8204203 windows-all
-sun/security/pkcs11/tls/TestLeadingZeroesP11.java 8204203 windows-all
-sun/security/pkcs11/tls/TestMasterSecret.java 8204203 windows-all
-sun/security/pkcs11/tls/TestPRF.java 8204203 windows-all
+sun/security/pkcs11/Cipher/TestRSACipherWrap.java 8204203 windows-all
+sun/security/pkcs11/Cipher/TestRawRSACipher.java 8204203 windows-all
+sun/security/pkcs11/Cipher/TestSymmCiphers.java 8204203 windows-all
+sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java 8204203 windows-all
+sun/security/pkcs11/KeyAgreement/SupportedDHKeys.java 8204203 windows-all
+sun/security/pkcs11/KeyAgreement/TestDH.java 8204203 windows-all
+sun/security/pkcs11/KeyAgreement/TestInterop.java 8204203 windows-all
+sun/security/pkcs11/KeyAgreement/TestShort.java 8204203 windows-all
+sun/security/pkcs11/KeyAgreement/UnsupportedDHKeys.java 8204203 windows-all
+sun/security/pkcs11/KeyGenerator/DESParity.java 8204203 windows-all
+sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java 8204203 windows-all
+sun/security/pkcs11/KeyPairGenerator/TestDH2048.java 8204203 windows-all
+sun/security/pkcs11/KeyStore/SecretKeysBasic.sh 8204203 windows-all
+sun/security/pkcs11/Mac/MacKAT.java 8204203 windows-all
+sun/security/pkcs11/Mac/MacSameTest.java 8204203 windows-all
+sun/security/pkcs11/Mac/ReinitMac.java 8204203 windows-all
+sun/security/pkcs11/MessageDigest/ByteBuffers.java 8204203 windows-all
+sun/security/pkcs11/MessageDigest/DigestKAT.java 8204203 windows-all
+sun/security/pkcs11/MessageDigest/ReinitDigest.java 8204203 windows-all
+sun/security/pkcs11/MessageDigest/TestCloning.java 8204203 windows-all
+sun/security/pkcs11/Provider/ConfigQuotedString.sh 8204203 windows-all
+sun/security/pkcs11/Provider/Login.sh 8204203 windows-all
+sun/security/pkcs11/SampleTest.java 8204203 windows-all
+sun/security/pkcs11/Secmod/AddPrivateKey.java 8204203 windows-all
+sun/security/pkcs11/Secmod/Crypto.java 8204203 windows-all
+sun/security/pkcs11/Secmod/GetPrivateKey.java 8204203 windows-all
+sun/security/pkcs11/Secmod/JksSetPrivateKey.java 8204203 windows-all
+sun/security/pkcs11/Secmod/LoadKeystore.java 8204203 windows-all
+sun/security/pkcs11/Secmod/TestNssDbSqlite.java 8204203 windows-all
+sun/security/pkcs11/SecureRandom/Basic.java 8204203 windows-all
+sun/security/pkcs11/SecureRandom/TestDeserialization.java 8204203 windows-all
+sun/security/pkcs11/Serialize/SerializeProvider.java 8204203 windows-all
+sun/security/pkcs11/Signature/ByteBuffers.java 8204203 windows-all
+sun/security/pkcs11/Signature/ReinitSignature.java 8204203 windows-all
+sun/security/pkcs11/Signature/TestDSA.java 8204203 windows-all
+sun/security/pkcs11/Signature/TestDSAKeyLength.java 8204203 windows-all
+sun/security/pkcs11/Signature/TestRSAKeyLength.java 8204203 windows-all
+sun/security/pkcs11/ec/ReadCertificates.java 8204203 windows-all
+sun/security/pkcs11/ec/ReadPKCS12.java 8204203 windows-all
+sun/security/pkcs11/ec/TestCurves.java 8204203 windows-all
+sun/security/pkcs11/ec/TestECDH.java 8204203 windows-all
+sun/security/pkcs11/ec/TestECDH2.java 8204203 windows-all
+sun/security/pkcs11/ec/TestECDSA.java 8204203 windows-all
+sun/security/pkcs11/ec/TestECDSA2.java 8204203 windows-all
+sun/security/pkcs11/ec/TestECGenSpec.java 8204203 windows-all
+sun/security/pkcs11/rsa/KeyWrap.java 8204203 windows-all
+sun/security/pkcs11/rsa/TestCACerts.java 8204203 windows-all
+sun/security/pkcs11/rsa/TestKeyFactory.java 8204203 windows-all
+sun/security/pkcs11/rsa/TestKeyPairGenerator.java 8204203 windows-all
+sun/security/pkcs11/rsa/TestSignatures.java 8204203 windows-all
+sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8204203 windows-all
+sun/security/pkcs11/tls/TestLeadingZeroesP11.java 8204203 windows-all
+sun/security/pkcs11/tls/TestMasterSecret.java 8204203 windows-all
+sun/security/pkcs11/tls/TestPRF.java 8204203 windows-all
sun/security/pkcs11/tls/TestPremaster.java 8204203 windows-all
############################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/Host/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "Host/Host.java";}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/Host/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "Host/redef/Host.java";}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostA/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostA/Host.java";}
+ public static class A {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostA/redef/Host.java"; }
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAB/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAB/Host.java";}
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAB/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABC/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABC/Host.java";}
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABC/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABCD/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABCD/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public static class D {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostABD/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABD/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class D {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostAC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAC/redef/Host.java"; }
+ public static class A {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostACB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostACB/redef/Host.java"; }
+ public static class A {}
+ public static class C {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostB/redef/Host.java"; }
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBA/redef/Host.java"; }
+ public static class B {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBAC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBAC/redef/Host.java"; }
+ public static class B {}
+ public static class A {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostBCA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBCA/redef/Host.java"; }
+ public static class B {}
+ public static class C {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostCAB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostCAB/redef/Host.java"; }
+ public static class C {}
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/HostCBA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostCBA/redef/Host.java"; }
+ public static class C {}
+ public static class B {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/NamedBuffer.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003, 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.io.*;
+
+/*
+ * Copyright 2003 Wily Technology, Inc.
+ */
+
+public class NamedBuffer
+{
+ private final String fName;
+ private final byte[] fBuffer;
+
+ public
+ NamedBuffer( String name,
+ byte[] buffer)
+ {
+ fName = name;
+ fBuffer = buffer;
+ }
+
+ public
+ NamedBuffer( String name,
+ InputStream stream)
+ throws IOException
+ {
+ this( name,
+ loadBufferFromStream(stream));
+ }
+
+ public String
+ getName()
+ {
+ return fName;
+ }
+
+ public byte[]
+ getBuffer()
+ {
+ return fBuffer;
+ }
+
+ public static byte[]
+ loadBufferFromStream(InputStream stream)
+ throws IOException
+ {
+ // hack for now, just assume the stream will fit in our reasonable size buffer.
+ // if not, panic
+ int bufferLimit = 200 * 1024;
+ byte[] readBuffer = new byte[bufferLimit];
+ int actualSize = stream.read(readBuffer);
+ if ( actualSize >= bufferLimit )
+ {
+ // if there might be more bytes, just surrender
+ throw new IOException("too big for buffer");
+ }
+
+ byte[] resultBuffer = new byte[actualSize];
+ System.arraycopy( readBuffer,
+ 0,
+ resultBuffer,
+ 0,
+ actualSize);
+ return resultBuffer;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jdi/RedefineNestmateAttr/TestNestmateAttr.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Class redefinition must preclude changes to nest attributes
+ * @comment This is a copy of test/jdk/java/lang/instrument/RedefineNestmateAttr/
+ * @comment modified for JDI
+ * @library /test/lib ..
+ * @modules java.compiler
+ * @run build TestScaffold VMConnection TargetListener TargetAdapter
+ * @compile NamedBuffer.java
+ * @compile Host/Host.java
+ * @run main/othervm TestNestmateAttr Host
+ * @compile HostA/Host.java
+ * @run main/othervm TestNestmateAttr HostA
+ * @compile HostAB/Host.java
+ * @run main/othervm TestNestmateAttr HostAB
+ * @compile HostABC/Host.java
+ * @run main/othervm TestNestmateAttr HostABC
+ */
+
+/* Test Description
+
+The basic test class is called Host and we have variants that have zero or more
+nested classes named A, B, C etc. Each variant of Host is defined in source
+code in its own directory i.e.
+
+Host/Host.java defines zero nested classes
+HostA/Host.java defines one nested class A
+HostAB/Host.java defines two nested classes A and B (in that order)
+etc.
+
+Each Host class has the form:
+
+ public class Host {
+ public static String getID() { return "<directory name>/Host.java"; }
+
+ < zero or more empty nested classes>
+
+ public int m() {
+ return 1; // original class
+ }
+ }
+
+Under each directory is a directory "redef" with a modified version of the Host
+class that changes the ID to e.g. Host/redef/Host.java, and the method m()
+returns 2. This allows us to check we have the redefined class loaded.
+
+Using Host' to represent the redefined version we test redefinition
+combinations as follows:
+
+Host:
+ Host -> Host' - succeeds m() returns 2
+ Host -> HostA' - fails - added a nest member
+
+HostA:
+ HostA -> HostA' - succeeds m() returns 2
+ HostA -> Host' - fails - removed a nest member
+ HostA -> HostAB' - fails - added a nest member
+ HostA -> HostB' - fails - replaced a nest member
+
+HostAB:
+ HostAB -> HostAB' - succeeds m() returns 2
+ HostAB -> HostBA' - succeeds m() returns 2
+ HostAB -> HostA' - fails - removed a nest member
+ HostAB -> HostABC' - fails - added a nest member
+ HostAB -> HostAC' - fails - replaced a nest member
+
+HostABC:
+ HostABC -> HostABC' - succeeds m() returns 2
+ HostABC -> HostACB' - succeeds m() returns 2
+ HostABC -> HostBAC' - succeeds m() returns 2
+ HostABC -> HostBCA' - succeeds m() returns 2
+ HostABC -> HostCAB' - succeeds m() returns 2
+ HostABC -> HostCBA' - succeeds m() returns 2
+ HostABC -> HostAB' - fails - removed a nest member
+ HostABC -> HostABCD' - fails - added a nest member
+ HostABC -> HostABD' - fails - replaced a nest member
+
+More than three nested classes doesn't add to the code coverage so
+we stop here.
+
+Note that we always try to load the redefined version even when we expect it
+to fail.
+
+We can only directly load one class Host per classloader, so to run all the
+groups we either need to use new classloaders, or we reinvoke the test
+requesting a different primary directory. We chose the latter using
+multiple @run tags. So we proceed as follows:
+
+ @compile Host/Host.java
+ @run TestNestmateAttr Host
+ @compile HostA/Host.java - replaces previous Host.class
+ @run TestNestmateAttr HostA
+ @compile HostAB/Host.java - replaces previous Host.class
+ @run TestNestmateAttr HostAB
+etc.
+
+Within the test we directly compile redefined versions of the classes,
+using CompilerUtil, and then read the .class file directly as a byte[].
+
+Finally we test redefinition of the NestHost attribute - which is
+conceptually simple, but in fact very tricky to do. We do that
+when testing HostA so we can reuse the Host$A class.
+
+*/
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jdk.test.lib.ByteCodeLoader;
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+import static jdk.test.lib.Asserts.assertTrue;
+
+/* For JDI the test is split across two VMs and so split into
+ two main classes. This is the class we will run under the debugger.
+ Package access so we can define in the same source file for ease of
+ reference.
+*/
+class Target {
+ // We have to load all of the variants of the classes that we will
+ // attempt to redefine. This requires some in-memory compilation
+ // and use of additional classloaders.
+ public static void main(String[] args) throws Throwable {
+ String origin = args[0];
+ System.out.println("Target: Testing original Host class from " + origin);
+
+ // Make sure the Host class loaded directly is an original version
+ // and from the expected location
+ Host h = new Host();
+ assertTrue(h.m() == 1);
+ assertTrue(Host.getID().startsWith(origin + "/"));
+
+ // The rest of this setup is only needed for the case
+ // when we perform the checkNestHostChanges() test.
+ if (origin.equals("HostA")) {
+ String name = "Host$A";
+
+ // Have to do this reflectively as there is no Host$A
+ // when compiling the "Host/" case.
+ Class<?> nestedA = Class.forName(name); // triggers initialization
+
+ // This is compiled as a top-level class: the $ in the name is not
+ // significant to the compiler.
+ String hostA = "public class " + name + " {}";
+ byte[] bytes = InMemoryJavaCompiler.compile(name, hostA);
+ // And we have to load this into a new classloader
+ Class<?> topLevelHostA = ByteCodeLoader.load(name, bytes);
+ // The loaded class has not been linked (as per ClassLoader.resolveClass)
+ // and so will be filtered out by VirtualMachine.allClasses(). There are
+ // a number of ways to force linking - this is the simplest.
+ Object o = topLevelHostA.newInstance();
+
+ // sanity check
+ assertTrue(nestedA.getClassLoader() != topLevelHostA.getClassLoader());
+
+ }
+
+ allowRedefine(); // debugger stops us here to attempt redefinitions
+
+ System.out.println("Target executed okay");
+ }
+
+ public static void allowRedefine() { }
+}
+
+public class TestNestmateAttr extends TestScaffold {
+
+ static final String SRC = System.getProperty("test.src");
+ static final String DEST = System.getProperty("test.classes");
+ static final boolean VERBOSE = Boolean.getBoolean("verbose");
+
+ static String origin;
+
+ // override this to correct a bug so arguments can be passed to
+ // the Target class
+ protected void startUp(String targetName) {
+ List<String> argList = new ArrayList<>(Arrays.asList(args));
+ argList.add(0, targetName); // pre-pend so it becomes the first "app" arg
+ println("run args: " + argList);
+ connect((String[]) argList.toArray(args));
+ waitForVMStart();
+ }
+
+ TestNestmateAttr (String[] args) {
+ super(args);
+ }
+
+ public static void main(String[] args) throws Throwable {
+ origin = args[0];
+ new TestNestmateAttr(args).startTests();
+ }
+
+ public void runTests() throws Exception {
+ // Get Target into debuggable state
+ BreakpointEvent bpe = startToMain("Target");
+ EventRequestManager erm = vm().eventRequestManager();
+ MethodEntryRequest mee = erm.createMethodEntryRequest();
+ mee.addClassFilter("Target");
+ mee.enable();
+
+ // Allow application to complete and shut down
+ listenUntilVMDisconnect();
+
+ if (getExceptionCaught()) {
+ throw new Exception("TestNestmateAttr: failed due to unexpected exception - check logs for details");
+ }
+ else if (!testFailed) {
+ println("TestNestmateAttr: passed");
+ } else {
+ throw new Exception("TestNestmateAttr: failure reported - check log for details");
+ }
+ }
+
+ // All the actual work is done from here once we see we've entered Target.allowRedefine()
+ public void methodEntered(MethodEntryEvent event) {
+ Method meth = event.location().method();
+
+ if (!meth.name().equals("allowRedefine")) {
+ return;
+ }
+
+ System.out.println("TestNestmateAttr: Testing original Host class from " + origin);
+
+ String[] badTransforms; // directories of bad classes
+ String[] goodTransforms; // directories of good classes
+
+ boolean testNestHostChanges = false;
+
+ switch (origin) {
+ case "Host":
+ badTransforms = new String[] {
+ "HostA" // add member
+ };
+ goodTransforms = new String[] {
+ origin
+ };
+ break;
+
+ case "HostA":
+ badTransforms = new String[] {
+ "Host", // remove member
+ "HostAB", // add member
+ "HostB" // change member
+ };
+ goodTransforms = new String[] {
+ origin
+ };
+ testNestHostChanges = true;
+ break;
+
+ case "HostAB":
+ badTransforms = new String[] {
+ "HostA", // remove member
+ "HostABC", // add member
+ "HostAC" // change member
+ };
+ goodTransforms = new String[] {
+ origin,
+ "HostBA" // reorder members
+ };
+ break;
+
+ case "HostABC":
+ badTransforms = new String[] {
+ "HostAB", // remove member
+ "HostABCD", // add member
+ "HostABD" // change member
+ };
+ goodTransforms = new String[] {
+ origin,
+ "HostACB", // reorder members
+ "HostBAC", // reorder members
+ "HostBCA", // reorder members
+ "HostCAB", // reorder members
+ "HostCBA" // reorder members
+ };
+ break;
+
+ default: throw new Error("Unknown test directory: " + origin);
+ }
+
+ // Need to locate the type we will be trying to redefine in Target
+ findReferenceTypes();
+
+ try {
+ // Compile and check bad transformations
+ checkBadTransforms(_Host, badTransforms);
+
+ // Compile and check good transformations
+ checkGoodTransforms(_Host, goodTransforms);
+
+ if (testNestHostChanges)
+ checkNestHostChanges();
+ }
+ catch (Throwable t) {
+ failure(t);
+ }
+ }
+
+ // override to give exception details
+ protected void failure(Throwable t) {
+ super.failure(t.getMessage());
+ t.printStackTrace(System.out);
+ }
+
+ // These are references to the types in Target
+ // that we will be trying to redefine.
+ ReferenceType _Host;
+ ReferenceType _Host_A_nested;
+ ReferenceType _Host_A_topLevel;
+
+ void findReferenceTypes() {
+ List<ReferenceType> classes = vm().allClasses();
+ ClassLoaderReference cl = null; // track the main loader
+ ReferenceType a1 = null;
+ ReferenceType a2 = null;
+ for (ReferenceType c : classes) {
+ String name = c.name();
+ if (name.equals("Host")) {
+ _Host = c;
+ cl = c.classLoader();
+ }
+ else if (name.equals("Host$A")) {
+ if (a1 == null) {
+ a1 = c;
+ } else if (a2 == null) {
+ a2 = c;
+ }
+ else {
+ assertTrue(false); // Too many Host$A classes found!
+ }
+ }
+ }
+ assertTrue(_Host != null);
+
+ // The rest of this setup is only needed for the case
+ // when we perform the checkNestHostChanges() test.
+ if (origin.equals("HostA")) {
+ assertTrue(a1 != null);
+ assertTrue(a2 != null);
+
+ if (a1.classLoader() == cl) {
+ _Host_A_nested = a1;
+ assertTrue(a2.classLoader() != cl);
+ _Host_A_topLevel = a2;
+ }
+ else if (a2.classLoader() == cl) {
+ _Host_A_nested = a2;
+ assertTrue(a1.classLoader() != cl);
+ _Host_A_topLevel = a1;
+ }
+ else {
+ assertTrue(false); // Wrong classLoaders found
+ }
+ }
+ }
+
+ void checkNestHostChanges() throws Throwable {
+ Map<ReferenceType, byte[]> map = new HashMap<>();
+
+ // case 1: remove NestHost attribute
+ // - try to redefine nested Host$A with a top-level
+ // class called Host$A
+ System.out.println("Trying bad retransform that removes the NestHost attribute");
+
+ String name = "Host$A";
+
+ // This is compiled as a top-level class: the $ in the name is not
+ // significant to the compiler.
+ String hostA = "public class " + name + " {}";
+ byte[] bytes = InMemoryJavaCompiler.compile(name, hostA);
+
+ map.put(_Host_A_nested, bytes);
+
+ try {
+ vm().redefineClasses(map);
+ throw new Error("Retransformation to top-level class " + name +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("changes to class attribute not implemented")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ map.clear();
+
+ // case 2: add NestHost attribute
+ // - This is tricky because the class with no NestHost attribute
+ // has to have the name of a nested class! But we know how to
+ // do that as we already created a top-level Host$A. So now
+ // we try to replace with a really nested Host$A.
+
+ System.out.println("Trying bad retransform that adds the NestHost attribute");
+
+ byte[] nestedBytes;
+ File clsfile = new File(DEST + "/" + name + ".class");
+ if (VERBOSE) System.out.println("Reading bytes from " + clsfile);
+ try (FileInputStream str = new FileInputStream(clsfile)) {
+ nestedBytes = NamedBuffer.loadBufferFromStream(str);
+ }
+
+ map.put(_Host_A_topLevel, nestedBytes);
+
+ try {
+ vm().redefineClasses(map);
+ throw new Error("Retransformation to nested class " + name +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("changes to class attribute not implemented")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ map.clear();
+
+ // case 3: replace the NestHost attribute
+ // - the easiest way (perhaps only reasonable way) to do this
+ // is to search for the Utf8 entry used by the Constant_ClassRef,
+ // set in the NestHost attribute, and edit it to refer to a different
+ // name. We reuse nestedBytes from above.
+
+ System.out.println("Trying bad retransform that changes the NestHost attribute");
+
+ int utf8Entry_length = 7;
+ boolean found = false;
+ for (int i = 0; i < nestedBytes.length - utf8Entry_length; i++) {
+ if (nestedBytes[i] == 1 && // utf8 tag
+ nestedBytes[i+1] == 0 && // msb of length
+ nestedBytes[i+2] == 4 && // lsb of length
+ nestedBytes[i+3] == (byte) 'H' &&
+ nestedBytes[i+4] == (byte) 'o' &&
+ nestedBytes[i+5] == (byte) 's' &&
+ nestedBytes[i+6] == (byte) 't') {
+
+ if (VERBOSE) System.out.println("Appear to have found Host utf8 entry starting at " + i);
+
+ nestedBytes[i+3] = (byte) 'G';
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ throw new Error("Could not locate 'Host' name in byte array");
+
+ map.put(_Host_A_nested, nestedBytes);
+
+ try {
+ vm().redefineClasses(map);
+ throw new Error("Retransformation to modified nested class" +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("changes to class attribute not implemented")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ }
+
+ void checkGoodTransforms(ReferenceType c, String[] dirs) throws Throwable {
+ // To verify the redefinition actually took place we will invoke the
+ // Host.getID method and check the result. To do that we need to find the
+ // main thread in the target VM. We don't check that "(new Host()).m()"
+ // returns 2 due to the complexity of setting that up via JDI.
+
+ ThreadReference main = null;
+ List<ThreadReference> threads = vm().allThreads();
+ for (ThreadReference t : threads) {
+ if (t.name().equals("main")) {
+ main = t;
+ break;
+ }
+ }
+
+ assertTrue(main != null);
+
+ // Now find the method
+ Method getID = null;
+ List<Method> methods = _Host.methodsByName("getID");
+ assertTrue(methods.size() == 1);
+ getID = methods.get(0);
+
+ Map<ReferenceType, byte[]> map = new HashMap<>();
+ for (String dir : dirs) {
+ dir += "/redef";
+ System.out.println("Trying good retransform from " + dir);
+ byte[] buf = bytesForHostClass(dir);
+ map.put(c, buf);
+ vm().redefineClasses(map);
+ map.clear();
+ // Test redefinition worked
+ Value v = ((ClassType)_Host).invokeMethod(main, getID, Collections.emptyList(), 0);
+ assertTrue(v instanceof StringReference);
+ String id = ((StringReference)v).value();
+ if (VERBOSE) System.out.println("Redefined ID: " + id);
+ assertTrue(id.startsWith(dir));
+ assertTrue(id.contains("/redef/"));
+ }
+ }
+
+ void checkBadTransforms(ReferenceType c, String[] dirs) throws Throwable {
+ Map<ReferenceType, byte[]> map = new HashMap<>();
+ for (String dir : dirs) {
+ dir += "/redef";
+ System.out.println("Trying bad retransform from " + dir);
+ byte[] buf = bytesForHostClass(dir);
+ map.put(c, buf);
+ try {
+ vm().redefineClasses(map);
+ throw new Error("Retransformation from directory " + dir +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("changes to class attribute not implemented")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+ }
+ }
+
+ static byte[] bytesForHostClass(String dir) throws Throwable {
+ compile("/" + dir);
+ File clsfile = new File(DEST + "/" + dir + "/Host.class");
+ if (VERBOSE) System.out.println("Reading bytes from " + clsfile);
+ byte[] buf = null;
+ try (FileInputStream str = new FileInputStream(clsfile)) {
+ return buf = NamedBuffer.loadBufferFromStream(str);
+ }
+ }
+
+ static void compile(String dir) throws Throwable {
+ File src = new File(SRC + dir);
+ File dst = new File(DEST + dir);
+ if (VERBOSE) System.out.println("Compiling from: " + src + "\n" +
+ " to: " + dst);
+ CompilerUtils.compile(src.toPath(),
+ dst.toPath(),
+ false /* don't recurse */,
+ new String[0]);
+ }
+}
--- a/test/jdk/java/io/FileInputStream/UnreferencedFISClosesFd.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/java/io/FileInputStream/UnreferencedFISClosesFd.java Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,8 @@
*
* @test
* @modules java.base/java.io:open
+ * @library /test/lib
+ * @build jdk.test.lib.util.FileUtils UnreferencedFISClosesFd
* @bug 6524062
* @summary Test to ensure that FIS.finalize() invokes the close() method as per
* the specification.
@@ -41,18 +43,15 @@
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.ArrayDeque;
import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import com.sun.management.UnixOperatingSystemMXBean;
+import jdk.test.lib.util.FileUtils;
+
/**
* Tests for FIS unreferenced.
* - Not subclassed - cleaner cleanup
@@ -146,8 +145,8 @@
String name = inFile.getPath();
+ FileUtils.listFileDescriptors(System.out);
long fdCount0 = getFdCount();
- System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
int failCount = 0;
failCount += test(new FileInputStream(name), CleanupType.CLEANER);
@@ -166,11 +165,10 @@
// Check the final count of open file descriptors
long fdCount = getFdCount();
- System.out.printf("final count of open file descriptors: %d%n", fdCount);
if (fdCount != fdCount0) {
- listProcFD();
- throw new AssertionError("raw fd count wrong: expected: " + fdCount0
- + ", actual: " + fdCount);
+ System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
+ System.out.printf("final count of open file descriptors: %d%n", fdCount);
+ FileUtils.listFileDescriptors(System.out);
}
}
@@ -274,27 +272,4 @@
}
return 0;
}
-
- /**
- * Method to list the open file descriptors (if supported by the 'lsof' command).
- */
- static void listProcFD() {
- List<String> lsofDirs = List.of("/usr/bin", "/usr/sbin");
- Optional<Path> lsof = lsofDirs.stream()
- .map(s -> Paths.get(s, "lsof"))
- .filter(f -> Files.isExecutable(f))
- .findFirst();
- lsof.ifPresent(exe -> {
- try {
- System.out.printf("Open File Descriptors:%n");
- long pid = ProcessHandle.current().pid();
- ProcessBuilder pb = new ProcessBuilder(exe.toString(), "-p", Integer.toString((int) pid));
- pb.inheritIO();
- Process p = pb.start();
- p.waitFor(10, TimeUnit.SECONDS);
- } catch (IOException | InterruptedException ie) {
- ie.printStackTrace();
- }
- });
- }
}
--- a/test/jdk/java/io/FileOutputStream/UnreferencedFOSClosesFd.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/java/io/FileOutputStream/UnreferencedFOSClosesFd.java Mon Jun 25 09:48:06 2018 -0700
@@ -25,6 +25,8 @@
*
* @test
* @modules java.base/java.io:open
+ * @library /test/lib
+ * @build jdk.test.lib.util.FileUtils UnreferencedFOSClosesFd
* @bug 6524062
* @summary Test to ensure that FOS.finalize() invokes the close() method as per
* the specification.
@@ -41,11 +43,15 @@
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
import com.sun.management.UnixOperatingSystemMXBean;
+import jdk.test.lib.util.FileUtils;
+
public class UnreferencedFOSClosesFd {
enum CleanupType {
@@ -133,8 +139,8 @@
String name = inFile.getPath();
+ FileUtils.listFileDescriptors(System.out);
long fdCount0 = getFdCount();
- System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
int failCount = 0;
failCount += test(new FileOutputStream(name), CleanupType.CLEANER);
@@ -153,10 +159,10 @@
// Check the final count of open file descriptors
long fdCount = getFdCount();
- System.out.printf("final count of open file descriptors: %d%n", fdCount);
if (fdCount != fdCount0) {
- throw new AssertionError("raw fd count wrong: expected: " + fdCount0
- + ", actual: " + fdCount);
+ System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
+ System.out.printf("final count of open file descriptors: %d%n", fdCount);
+ FileUtils.listFileDescriptors(System.out);
}
}
--- a/test/jdk/java/io/RandomAccessFile/UnreferencedRAFClosesFd.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/java/io/RandomAccessFile/UnreferencedRAFClosesFd.java Mon Jun 25 09:48:06 2018 -0700
@@ -24,6 +24,7 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
@@ -32,13 +33,19 @@
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
+import java.nio.file.Path;
+import java.util.ArrayDeque;
import java.util.HashSet;
import com.sun.management.UnixOperatingSystemMXBean;
+import jdk.test.lib.util.FileUtils;
+
/**
* @test
* @bug 8080225
+ * @library /test/lib
+ * @build jdk.test.lib.util.FileUtils UnreferencedRAFClosesFd
* @modules java.base/java.io:open
* @summary Test to ensure that an unclosed and unreferenced RandomAccessFile closes the fd
* @run main/othervm UnreferencedRAFClosesFd
@@ -54,8 +61,8 @@
inFile.createNewFile();
inFile.deleteOnExit();
+ FileUtils.listFileDescriptors(System.out);
long fdCount0 = getFdCount();
- System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
String name = inFile.getPath();
RandomAccessFile raf;
@@ -101,10 +108,10 @@
// Check the final count of open file descriptors
long fdCount = getFdCount();
- System.out.printf("final count of open file descriptors: %d%n", fdCount);
if (fdCount != fdCount0) {
- throw new AssertionError("raw fd count wrong: expected: " + fdCount0
- + ", actual: " + fdCount);
+ System.out.printf("initial count of open file descriptors: %d%n", fdCount0);
+ System.out.printf("final count of open file descriptors: %d%n", fdCount);
+ FileUtils.listFileDescriptors(System.out);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Class/GetPackageBootLoaderChildLayer.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, 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
+ * @modules jdk.attach
+ * @run main/othervm --limit-modules jdk.attach -Djdk.attach.allowAttachSelf
+ * GetPackageBootLoaderChildLayer
+ * @summary Exercise Class.getPackage on a class defined to the boot loader
+ * but in a module that is in a child layer rather than the boot layer
+ */
+
+import com.sun.tools.attach.VirtualMachine;
+
+public class GetPackageBootLoaderChildLayer {
+ public static void main(String[] args) throws Exception {
+ // ensure that the java.management module is not in the boot layer
+ ModuleLayer.boot().findModule("java.management").ifPresent(m -> {
+ throw new RuntimeException("java.management loaded!!!");
+ });
+
+ // start local JMX agent via the attach mechanism
+ String vmid = "" + ProcessHandle.current().pid();
+ VirtualMachine vm = VirtualMachine.attach(vmid);
+ vm.startLocalManagementAgent();
+
+ // check layer, class loader, and Package object
+ Class<?> clazz = Class.forName("javax.management.MXBean");
+ if (clazz.getModule().getLayer() == ModuleLayer.boot())
+ throw new RuntimeException("Module is in boot layer!!!");
+ ClassLoader loader = clazz.getClassLoader();
+ if (loader != null)
+ throw new RuntimeException("Unexpected class loader: " + loader);
+ Package p = clazz.getPackage();
+ if (!p.getName().equals("javax.management"))
+ throw new RuntimeException("Unexpected package " + p);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/Host/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "Host/Host.java";}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/Host/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "Host/redef/Host.java";}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostA/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostA/Host.java";}
+ public static class A {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostA/redef/Host.java"; }
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAB/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAB/Host.java";}
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAB/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABC/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABC/Host.java";}
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public int m() {
+ return 1; // original class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABC/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABCD/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABCD/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class C {}
+ public static class D {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostABD/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostABD/redef/Host.java"; }
+ public static class A {}
+ public static class B {}
+ public static class D {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostAC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostAC/redef/Host.java"; }
+ public static class A {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostACB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostACB/redef/Host.java"; }
+ public static class A {}
+ public static class C {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostB/redef/Host.java"; }
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBA/redef/Host.java"; }
+ public static class B {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBAC/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBAC/redef/Host.java"; }
+ public static class B {}
+ public static class A {}
+ public static class C {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostBCA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostBCA/redef/Host.java"; }
+ public static class B {}
+ public static class C {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostCAB/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostCAB/redef/Host.java"; }
+ public static class C {}
+ public static class A {}
+ public static class B {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/HostCBA/redef/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+public class Host {
+ public static String getID() { return "HostCBA/redef/Host.java"; }
+ public static class C {}
+ public static class B {}
+ public static class A {}
+ public int m() {
+ return 2; // redefined class
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/instrument/RedefineNestmateAttr/TestNestmateAttr.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Class redefinition must preclude changes to nest attributes
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @compile ../NamedBuffer.java
+ * @run main RedefineClassHelper
+ * @compile Host/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr Host
+ * @compile HostA/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostA
+ * @compile HostAB/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostAB
+ * @compile HostABC/Host.java
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+nestmates=trace TestNestmateAttr HostABC
+ */
+
+/* Test Description
+
+The basic test class is call Host and we have variants that have zero or more
+nested classes named A, B, C etc. Each variant of Host is defined in source
+code in its own directory i.e.
+
+Host/Host.java defines zero nested classes
+HostA/Host.java defines one nested class A
+HostAB/Host.java defines two nested classes A and B (in that order)
+etc.
+
+Each Host class has the form:
+
+ public class Host {
+ public static String getID() { return "<directory name>/Host.java"; }
+
+ < zero or more empty nested classes>
+
+ public int m() {
+ return 1; // original class
+ }
+ }
+
+Under each directory is a directory "redef" with a modified version of the Host
+class that changes the ID to e.g. Host/redef/Host.java, and the method m()
+returns 2. This allows us to check we have the redefined class loaded.
+
+Using Host' to represent the redefined version we test redefinition
+combinations as follows:
+
+Host:
+ Host -> Host' - succeeds m() returns 2
+ Host -> HostA' - fails - added a nest member
+
+HostA:
+ HostA -> HostA' - succeeds m() returns 2
+ HostA -> Host' - fails - removed a nest member
+ HostA -> HostAB' - fails - added a nest member
+ HostA -> HostB' - fails - replaced a nest member
+
+HostAB:
+ HostAB -> HostAB' - succeeds m() returns 2
+ HostAB -> HostBA' - succeeds m() returns 2
+ HostAB -> HostA' - fails - removed a nest member
+ HostAB -> HostABC' - fails - added a nest member
+ HostAB -> HostAC' - fails - replaced a nest member
+
+HostABC:
+ HostABC -> HostABC' - succeeds m() returns 2
+ HostABC -> HostACB' - succeeds m() returns 2
+ HostABC -> HostBAC' - succeeds m() returns 2
+ HostABC -> HostBCA' - succeeds m() returns 2
+ HostABC -> HostCAB' - succeeds m() returns 2
+ HostABC -> HostCBA' - succeeds m() returns 2
+ HostABC -> HostAB' - fails - removed a nest member
+ HostABC -> HostABCD' - fails - added a nest member
+ HostABC -> HostABD' - fails - replaced a nest member
+
+More than three nested classes doesn't add to the code coverage so
+we stop here.
+
+Note that we always try to load the redefined version even when we expect it
+to fail.
+
+We can only directly load one class Host per classloader, so to run all the
+groups we either need to use new classloaders, or we reinvoke the test
+requesting a different primary directory. We chose the latter using
+multiple @run tags. So we preceed as follows:
+
+ @compile Host/Host.java
+ @run TestNestmateAttr Host
+ @compile HostA/Host.java - replaces previous Host.class
+ @run TestNestmateAttr HostA
+ @compile HostAB/Host.java - replaces previous Host.class
+ @run TestNestmateAttr HostAB
+etc.
+
+Within the test we directly compile redefined versions of the classes,
+using CompilerUtil, and then read the .class file directly as a byte[]
+to use with the RedefineClassHelper.
+
+Finally we test redefinition of the NestHost attribute - which is
+conceptually simple, but in fact very tricky to do. We do that
+when testing HostA so we can reuse the Host$A class.
+
+*/
+
+import java.io.File;
+import java.io.FileInputStream;
+import jdk.test.lib.ByteCodeLoader;
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+import static jdk.test.lib.Asserts.assertTrue;
+
+public class TestNestmateAttr {
+
+ static final String SRC = System.getProperty("test.src");
+ static final String DEST = System.getProperty("test.classes");
+ static final boolean VERBOSE = Boolean.getBoolean("verbose");
+
+ public static void main(String[] args) throws Throwable {
+ String origin = args[0];
+ System.out.println("Testing original Host class from " + origin);
+
+ // Make sure the Host class loaded directly is an original version
+ // and from the expected location
+ Host h = new Host();
+ assertTrue(h.m() == 1);
+ assertTrue(Host.getID().startsWith(origin + "/"));
+
+ String[] badTransforms; // directories of bad classes
+ String[] goodTransforms; // directories of good classes
+
+ boolean testNestHostChanges = false;
+
+ switch (origin) {
+ case "Host":
+ badTransforms = new String[] {
+ "HostA" // add member
+ };
+ goodTransforms = new String[] {
+ origin
+ };
+ break;
+
+ case "HostA":
+ badTransforms = new String[] {
+ "Host", // remove member
+ "HostAB", // add member
+ "HostB" // change member
+ };
+ goodTransforms = new String[] {
+ origin
+ };
+ testNestHostChanges = true;
+ break;
+
+ case "HostAB":
+ badTransforms = new String[] {
+ "HostA", // remove member
+ "HostABC", // add member
+ "HostAC" // change member
+ };
+ goodTransforms = new String[] {
+ origin,
+ "HostBA" // reorder members
+ };
+ break;
+
+ case "HostABC":
+ badTransforms = new String[] {
+ "HostAB", // remove member
+ "HostABCD", // add member
+ "HostABD" // change member
+ };
+ goodTransforms = new String[] {
+ origin,
+ "HostACB", // reorder members
+ "HostBAC", // reorder members
+ "HostBCA", // reorder members
+ "HostCAB", // reorder members
+ "HostCBA" // reorder members
+ };
+ break;
+
+ default: throw new Error("Unknown test directory: " + origin);
+ }
+
+ // Compile and check bad transformations
+ checkBadTransforms(Host.class, badTransforms);
+
+ // Compile and check good transformations
+ checkGoodTransforms(Host.class, goodTransforms);
+
+ if (testNestHostChanges)
+ checkNestHostChanges();
+ }
+
+ static void checkNestHostChanges() throws Throwable {
+ // case 1: remove NestHost attribute
+ // - try to redefine Host$A with a top-level
+ // class called Host$A
+ System.out.println("Trying bad retransform that removes the NestHost attribute");
+
+ String name = "Host$A";
+ // This is compiled as a top-level class: the $ in the name is not
+ // significant to the compiler.
+ String hostA = "public class " + name + " {}";
+
+ // Have to do this reflectively as there is no Host$A
+ // when compiling the "Host/" case.
+ Class<?> nestedA = Class.forName(name);
+
+ try {
+ RedefineClassHelper.redefineClass(nestedA, hostA);
+ throw new Error("Retransformation to top-level class " + name +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("attempted to change the class Nest")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ // case 2: add NestHost attribute
+ // - This is tricky because the class with no NestHost attribute
+ // has to have the name of a nested class! Plus we need the
+ // redefining class in bytecode form.
+ // - Use the InMemoryJavaCompiler plus ByteCodeLoader to load
+ // the top-level Host$A class
+ // - Try to redefine that class with a real nested Host$A
+
+ System.out.println("Trying bad retransform that adds the NestHost attribute");
+ byte[] bytes = InMemoryJavaCompiler.compile(name, hostA);
+ Class<?> topLevelHostA = ByteCodeLoader.load(name, bytes);
+
+ byte[] nestedBytes;
+ File clsfile = new File(DEST + "/" + name + ".class");
+ if (VERBOSE) System.out.println("Reading bytes from " + clsfile);
+ try (FileInputStream str = new FileInputStream(clsfile)) {
+ nestedBytes = NamedBuffer.loadBufferFromStream(str);
+ }
+ try {
+ RedefineClassHelper.redefineClass(topLevelHostA, nestedBytes);
+ throw new Error("Retransformation to nested class " + name +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("attempted to change the class Nest")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ // case 3: replace the NestHost attribute
+ // - the easiest way (perhaps only reasonable way) to do this
+ // is to search for the Utf8 entry used by the Constant_ClassRef,
+ // set in the NestHost attribute, and edit it to refer to a different
+ // name.
+ System.out.println("Trying bad retransform that changes the NestHost attribute");
+ int utf8Entry_length = 7;
+ boolean found = false;
+ for (int i = 0; i < nestedBytes.length - utf8Entry_length; i++) {
+ if (nestedBytes[i] == 1 && // utf8 tag
+ nestedBytes[i+1] == 0 && // msb of length
+ nestedBytes[i+2] == 4 && // lsb of length
+ nestedBytes[i+3] == (byte) 'H' &&
+ nestedBytes[i+4] == (byte) 'o' &&
+ nestedBytes[i+5] == (byte) 's' &&
+ nestedBytes[i+6] == (byte) 't') {
+
+ if (VERBOSE) System.out.println("Appear to have found Host utf8 entry starting at " + i);
+
+ nestedBytes[i+3] = (byte) 'G';
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ throw new Error("Could not locate 'Host' name in byte array");
+
+ try {
+ RedefineClassHelper.redefineClass(nestedA, nestedBytes);
+ throw new Error("Retransformation to modified nested class" +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("attempted to change the class Nest")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+
+ }
+
+ static void checkGoodTransforms(Class<?> c, String[] dirs) throws Throwable {
+ for (String dir : dirs) {
+ dir += "/redef";
+ System.out.println("Trying good retransform from " + dir);
+ byte[] buf = bytesForHostClass(dir);
+ RedefineClassHelper.redefineClass(c, buf);
+
+ // Test redefintion worked
+ Host h = new Host();
+ assertTrue(h.m() == 2);
+ if (VERBOSE) System.out.println("Redefined ID: " + Host.getID());
+ assertTrue(Host.getID().startsWith(dir));
+ }
+ }
+
+ static void checkBadTransforms(Class<?> c, String[] dirs) throws Throwable {
+ for (String dir : dirs) {
+ dir += "/redef";
+ System.out.println("Trying bad retransform from " + dir);
+ byte[] buf = bytesForHostClass(dir);
+ try {
+ RedefineClassHelper.redefineClass(c, buf);
+ throw new Error("Retransformation from directory " + dir +
+ " succeeded unexpectedly");
+ }
+ catch (UnsupportedOperationException uoe) {
+ if (uoe.getMessage().contains("attempted to change the class Nest")) {
+ System.out.println("Got expected exception " + uoe);
+ }
+ else throw new Error("Wrong UnsupportedOperationException", uoe);
+ }
+ }
+ }
+
+ static byte[] bytesForHostClass(String dir) throws Throwable {
+ compile("/" + dir);
+ File clsfile = new File(DEST + "/" + dir + "/Host.class");
+ if (VERBOSE) System.out.println("Reading bytes from " + clsfile);
+ byte[] buf = null;
+ try (FileInputStream str = new FileInputStream(clsfile)) {
+ return buf = NamedBuffer.loadBufferFromStream(str);
+ }
+ }
+
+ static void compile(String dir) throws Throwable {
+ File src = new File(SRC + dir);
+ File dst = new File(DEST + dir);
+ if (VERBOSE) System.out.println("Compiling from: " + src + "\n" +
+ " to: " + dst);
+ CompilerUtils.compile(src.toPath(),
+ dst.toPath(),
+ false /* don't recurse */,
+ new String[0]);
+ }
+}
--- a/test/jdk/java/lang/invoke/AccessControlTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/java/lang/invoke/AccessControlTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -241,8 +241,10 @@
LookupCase lc = this.in(c2);
int m1 = lc.lookupModes();
int m2 = fixMods(m.getModifiers());
- // privacy is strictly enforced on lookups
- if (c1 != c2) m1 &= ~PRIVATE;
+ // allow private lookup on nestmates. Otherwise, privacy is strictly enforced
+ if (c1 != c2 && ((m2 & PRIVATE) == 0 || !c1.isNestmateOf(c2))) {
+ m1 &= ~PRIVATE;
+ }
// protected access is sometimes allowed
if ((m2 & PROTECTED) != 0) {
int prev = m2;
@@ -252,7 +254,7 @@
m2 |= PUBLIC; // from a subclass, it acts like a public method also
}
if (verbosity >= 2)
- System.out.println(this+" willAccess "+lc+" m1="+m1+" m2="+m2+" => "+((m2 & m1) != 0));
+ System.out.format("%s willAccess %s m1=0x%h m2=0x%h => %s%n", this, lc, m1, m2, ((m2 & m1) != 0));
return (m2 & m1) != 0;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/FinalVirtualCallFromInterface.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8200167 8010319
+ * @summary Regression test for a bug introduced in 8200167 and fixed in 8010319
+ * @run main FinalVirtualCallFromInterface
+ */
+
+import java.lang.invoke.*;
+
+/*
+ * Test that a MethodHandle for a final method, called from an interface, works correctly.
+ * With only 8200167 applied this fails with:
+ * Exception in thread "main" java.lang.InternalError: Should only be invoked on a subclass
+ * at
+ * java.base/java.lang.invoke.DirectMethodHandle.checkReceiver(DirectMethodHandle.java:441)
+ *
+ * The nestmate update under 8010319 fixes that bug.
+ */
+public class FinalVirtualCallFromInterface {
+
+ static class Final {
+ public final void fm() {}
+ }
+
+ static interface FinalUser {
+ static void test() throws Throwable {
+ MethodType mt = MethodType.methodType(void.class);
+ MethodHandle mh = MethodHandles.lookup().findVirtual(Final.class, "fm", mt);
+ Final f = new Final();
+ mh.invokeExact(f);
+ mh.invoke(f);
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ FinalUser.test();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/PrivateInterfaceCall.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test direct and MethodHandle access to private interface methods using invokeinterface semantics
+ * to ensure all receiver typechecks occur as required.
+ * @comment This complements SpecialInterfaceCall which tests invokespecial semantics.
+ * @compile PrivateInterfaceCall.java
+ * @compile PrivateInterfaceCallI4.jasm
+ * @run main/othervm -Xint PrivateInterfaceCall
+ * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 PrivateInterfaceCall
+ * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=2 PrivateInterfaceCall
+ * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=3 PrivateInterfaceCall
+ * @run main/othervm -Xbatch -XX:-TieredCompilation PrivateInterfaceCall
+ */
+
+// This is an adaptation of SpecialInterfaceCall to only use private interface methods and with
+// virtual invocation semantics. Because we don't have the same corner cases as for invokespecial
+// there's no practical difference between the I3 and I2 cases here. But we do have to ensure the
+// correct versions of the methods get executed.
+// In addition we add tests that involve calls from nestmates - which also covers the distinction
+// between the caller being a class and being an interface.
+
+import java.lang.invoke.*;
+
+public class PrivateInterfaceCall {
+ interface I1 {
+ private void priv_m() { throw new Error("Should not call this"); };
+ }
+ interface I2 extends I1 {
+ private void priv_m() { };
+
+ static void invokeDirect(I2 i) {
+ i.priv_m(); // generates invokeinterface
+ }
+ static void invokeInterfaceMH(I2 i) throws Throwable {
+ // emulates behaviour of invokeDirect
+ mh_I2_priv_m_from_I2.invokeExact(i);
+ }
+ // special case of invoking an Object method via an interface
+ static void invokeInterfaceObjectMH(I2 i) throws Throwable {
+ // emulates invokeInterface of I2.toString on i, which resolves
+ // to Object.toString
+ String s = (String) mh_I2_toString_from_I2.invokeExact(i);
+ }
+ // special case of invoking a final Object method via an interface
+ static void invokeInterfaceObjectFinalMH(I2 i) throws Throwable {
+ // emulates invokeInterface of I1.getClass on i, which resolves
+ // to Object.getClass
+ Class<?> c = (Class<?>) mh_I2_getClass_from_I2.invokeExact(i);
+ }
+
+ static void init() throws Throwable {
+ MethodType mt = MethodType.methodType(void.class);
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+ mh_I2_priv_m_from_I2 = lookup.findVirtual(I2.class, "priv_m", mt);
+
+ mt = MethodType.methodType(String.class);
+ mh_I2_toString_from_I2 = lookup.findVirtual(I2.class, "toString", mt);
+
+ mt = MethodType.methodType(Class.class);
+ mh_I2_getClass_from_I2 = lookup.findVirtual(I2.class, "getClass", mt);
+ }
+ }
+ interface I3 extends I2 {
+ static void invokeInterfaceMH(I2 i) throws Throwable {
+ // emulates behaviour of I2.invokeDirect
+ mh_I2_priv_m_from_I3.invokeExact(i);
+ }
+ static void init() throws Throwable {
+ MethodType mt = MethodType.methodType(void.class);
+ mh_I2_priv_m_from_I3 = MethodHandles.lookup().findVirtual(I2.class, "priv_m", mt);
+ }
+ }
+
+ // This interface acts like I2 but we define directInvoke* methods
+ // that we will rewrite the bytecode of to use invokeinterface
+ // (see PrivateInterfaceCallI4.jasm).
+ interface I4 extends I1 {
+ static void invokeDirect(I4 i) {
+ // invokeinterface I4.toString()
+ throw new Error("Class file for I4 is not overwritten");
+ }
+ static void invokeDirectFinal(I4 i) {
+ // invokeinterface I4.getClass() - final method
+ throw new Error("Class file for I4 is not overwritten");
+ }
+ }
+
+ // check invocations from nestmates outside the
+ // inheritance hierarchy - and from a class not interface
+ static void invokeDirect(I2 i) {
+ i.priv_m(); // generates invokeinterface
+ }
+ static void invokeInterfaceMH(I2 i) throws Throwable {
+ mh_I2_priv_m_from_PIC.invokeExact(i);
+ }
+
+ // Concrete classes
+ static class C2 implements I2 { }
+ static class C3 implements I3 { }
+ static class C4 implements I4 { }
+
+ // Classes that don't implement I2/I3 but do have a
+ // priv_m method in their hierarchy
+ static class D1 implements I1 { }
+ static class E {
+ private void priv_m() { throw new Error("Should not call this"); }
+ }
+
+ // This MH acts like the invocation in I2.invokeDirect with caller I2
+ static MethodHandle mh_I2_priv_m_from_I2;
+
+ // This MH acts like the invocation in I3.invokeDirect with caller I3
+ static MethodHandle mh_I2_priv_m_from_I3;
+
+ // This MH acts like the invocation in PrivateInterfaceCall.invokeDirect
+ // with caller PrivateInterfaceCall
+ static MethodHandle mh_I2_priv_m_from_PIC;
+
+ // This MH acts likes an invokeinterface of I2.toString from I2
+ static MethodHandle mh_I2_toString_from_I2;
+
+ // This MH acts likes an invokeinterface of I2.getClass from I2
+ static MethodHandle mh_I2_getClass_from_I2;
+
+ static {
+ try {
+ MethodType mt = MethodType.methodType(void.class);
+ mh_I2_priv_m_from_PIC = MethodHandles.lookup().findVirtual(I2.class, "priv_m", mt);
+ I2.init();
+ I3.init();
+ } catch (Throwable e) {
+ throw new Error(e);
+ }
+ }
+
+ static void runPositiveTests() {
+ shouldNotThrow(() -> PrivateInterfaceCall.invokeDirect(new C2()));
+ shouldNotThrow(() -> PrivateInterfaceCall.invokeDirect(new C3()));
+ shouldNotThrow(() -> PrivateInterfaceCall.invokeInterfaceMH(new C2()));
+ shouldNotThrow(() -> PrivateInterfaceCall.invokeInterfaceMH(new C3()));
+
+ shouldNotThrow(() -> I2.invokeDirect(new C2()));
+ shouldNotThrow(() -> I2.invokeDirect(new C3()));
+ shouldNotThrow(() -> I2.invokeInterfaceMH(new C2()));
+ shouldNotThrow(() -> I2.invokeInterfaceMH(new C3()));
+ shouldNotThrow(() -> I2.invokeInterfaceObjectMH(new C2()));
+ shouldNotThrow(() -> I2.invokeInterfaceObjectMH(new C3()));
+ shouldNotThrow(() -> I2.invokeInterfaceObjectFinalMH(new C2()));
+ shouldNotThrow(() -> I2.invokeInterfaceObjectFinalMH(new C3()));
+
+ // This looks odd but at runtime the only constraint is that the
+ // receiver is an I2. In contrast in the invokespecial case the
+ // receiver must be an I3.
+ shouldNotThrow(() -> I3.invokeInterfaceMH(unsafeCastI3(new C2())));
+ shouldNotThrow(() -> I3.invokeInterfaceMH(new C3()));
+
+ shouldNotThrow(() -> I4.invokeDirect(new C4()));
+ shouldNotThrow(() -> I4.invokeDirectFinal(new C4()));
+ }
+
+ static void runNegativeTests() {
+ System.out.println("ICCE PrivateInterfaceCall.invokeDirect D1");
+ shouldThrowICCE(() -> PrivateInterfaceCall.invokeDirect(unsafeCastI2(new D1())));
+ System.out.println("ICCE PrivateInterfaceCall.invokeDirect E");
+ shouldThrowICCE(() -> PrivateInterfaceCall.invokeDirect(unsafeCastI2(new E())));
+ System.out.println("ICCE PrivateInterfaceCall.invokeInterfaceMH D1");
+ shouldThrowICCE(() -> PrivateInterfaceCall.invokeInterfaceMH(unsafeCastI2(new D1())));
+ System.out.println("ICCE PrivateInterfaceCall.invokeInterfaceMH E");
+ shouldThrowICCE(() -> PrivateInterfaceCall.invokeInterfaceMH(unsafeCastI2(new E())));
+
+
+ System.out.println("ICCE I2.invokeInterfaceMH D1");
+ shouldThrowICCE(() -> I2.invokeInterfaceMH(unsafeCastI2(new D1())));
+ System.out.println("ICCE I2.invokeInterfaceMH E");
+ shouldThrowICCE(() -> I2.invokeInterfaceMH(unsafeCastI2(new E())));
+
+ System.out.println("ICCE I2.invokeInterfaceObjectFinalMH D1");
+ shouldThrowICCE(() -> I2.invokeInterfaceObjectFinalMH(unsafeCastI2(new D1())));
+ System.out.println("ICCE I2.invokeInterfaceObjectFinalMH E");
+ shouldThrowICCE(() -> I2.invokeInterfaceObjectFinalMH(unsafeCastI2(new E())));
+
+ System.out.println("ICCE I3.invokeInterfaceMH D1");
+ shouldThrowICCE(() -> I3.invokeInterfaceMH(unsafeCastI3(new D1())));
+ System.out.println("ICCE I3.invokeInterfaceMH E");
+ shouldThrowICCE(() -> I3.invokeInterfaceMH(unsafeCastI3(new E())));
+
+ System.out.println("ICCE I4.invokeDirect D1");
+ shouldThrowICCE(() -> I4.invokeDirect(unsafeCastI4(new D1())));
+ System.out.println("ICCE I4.invokeDirect E");
+ shouldThrowICCE(() -> I4.invokeDirect(unsafeCastI4(new E())));
+ }
+
+ static void warmup() {
+ for (int i = 0; i < 20_000; i++) {
+ runPositiveTests();
+ }
+ }
+
+ public static void main(String[] args) throws Throwable {
+ System.out.println("UNRESOLVED:");
+ runNegativeTests();
+ runPositiveTests();
+
+ System.out.println("RESOLVED:");
+ runNegativeTests();
+
+ System.out.println("WARMUP:");
+ warmup();
+
+ System.out.println("COMPILED:");
+ runNegativeTests();
+ runPositiveTests();
+ }
+
+ static interface Test {
+ void run() throws Throwable;
+ }
+
+ static void shouldThrowICCE(Test t) {
+ shouldThrow(IncompatibleClassChangeError.class,
+ "does not implement the requested interface", t);
+ }
+
+ // Depending on whether the exception originates in the linkResolver, the interpreter
+ // or the compiler, the message can be different - which is unfortunate and could be
+ // fixed. So we allow the listed reason or else a null message.
+ static void shouldThrow(Class<?> expectedError, String reason, Test t) {
+ try {
+ t.run();
+ } catch (Throwable e) {
+ // Don't accept subclasses as they can hide unexpected failure modes
+ if (expectedError == e.getClass()) {
+ String msg = e.getMessage();
+ if ((msg != null && msg.contains(reason)) || msg == null) {
+ // passed
+ System.out.println("Threw expected: " + e);
+ return;
+ }
+ else {
+ throw new AssertionError("Wrong exception reason: expected '" + reason
+ + "', got '" + msg + "'", e);
+ }
+ } else {
+ String msg = String.format("Wrong exception thrown: expected=%s; thrown=%s",
+ expectedError.getName(), e.getClass().getName());
+ throw new AssertionError(msg, e);
+ }
+ }
+ throw new AssertionError("No exception thrown: expected " + expectedError.getName());
+ }
+
+ static void shouldNotThrow(Test t) {
+ try {
+ t.run();
+ // passed
+ } catch (Throwable e) {
+ throw new AssertionError("Exception was thrown: ", e);
+ }
+ }
+
+ // Note: these unsafe casts are only possible for interface types
+
+ static I2 unsafeCastI2(Object obj) {
+ try {
+ MethodHandle mh = MethodHandles.identity(Object.class);
+ mh = MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(I2.class));
+ return (I2)mh.invokeExact((Object) obj);
+ } catch (Throwable e) {
+ throw new Error(e);
+ }
+ }
+
+ static I3 unsafeCastI3(Object obj) {
+ try {
+ MethodHandle mh = MethodHandles.identity(Object.class);
+ mh = MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(I3.class));
+ return (I3)mh.invokeExact((Object) obj);
+ } catch (Throwable e) {
+ throw new Error(e);
+ }
+ }
+
+ static I4 unsafeCastI4(Object obj) {
+ try {
+ MethodHandle mh = MethodHandles.identity(Object.class);
+ mh = MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(I4.class));
+ return (I4)mh.invokeExact((Object) obj);
+ } catch (Throwable e) {
+ throw new Error(e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/PrivateInterfaceCallI4.jasm Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// invokeDirect is modified to use invokeinterface instead of invokevirtual
+
+interface PrivateInterfaceCall$I4 implements PrivateInterfaceCall$I1
+ version 55:0
+{
+ public static Method invokeDirect:"(LPrivateInterfaceCall$I4;)V"
+ stack 1 locals 2
+ {
+ aload_0;
+ invokeinterface InterfaceMethod PrivateInterfaceCall$I4.toString:"()Ljava/lang/String;", 1;
+ astore_1;
+ return;
+ }
+
+ public static Method invokeDirectFinal:"(LPrivateInterfaceCall$I4;)V"
+ stack 1 locals 2
+ {
+ aload_0;
+ invokeinterface InterfaceMethod PrivateInterfaceCall$I4.getClass:"()Ljava/lang/Class;", 1;
+ astore_1;
+ return;
+ }
+ static abstract interface InnerClass I4=class PrivateInterfaceCall$I4 of class PrivateInterfaceCall;
+ static abstract interface InnerClass I1=class PrivateInterfaceCall$I1 of class PrivateInterfaceCall;
+
+} // end Class PrivateInterfaceCall$I4
--- a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java Mon Jun 25 09:48:06 2018 -0700
@@ -23,9 +23,10 @@
/**
* @test
- * @bug 8200167
+ * @bug 8200167 8010319
* @summary Test direct and MethodHandle access to interface methods using invokespecial semantics
- * @compile SpecialInterfaceCall.java
+ * @comment This must be compiled so invokespecial is used
+ * @compile -XDdisableVirtualizedPrivateInvoke SpecialInterfaceCall.java
* @compile SpecialInterfaceCallI4.jasm
* @run main/othervm -Xint SpecialInterfaceCall
* @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 SpecialInterfaceCall
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostOfMemberMalformedHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with invalid class file format
+
+class HostOfMemberMalformedHost$MemberMalformedHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "Hosts.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "HostOfMemberMalformedHost$MemberMalformedHost"; // #13
+ Utf8 "MemberMalformedHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "HostOfMemberMalformedHost"; // #17
+ // added
+ Utf8 "MalformedHost"; // #18
+ class #18; // #19
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 68;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0013; // Modified #19
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostOfMemberMalformedHost$MemberMalformedHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostOfMemberMissingHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-existent class
+
+class HostOfMemberMissingHost$MemberMissingHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "Hosts.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "HostOfMemberMissingHost$MemberMissingHost"; // #13
+ Utf8 "MemberMissingHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "HostOfMemberMissingHost"; // #17
+ class #10; // #18 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 60;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0012; // modified
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostOfMemberMissingHost$MemberMissingHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostOfMemberNoHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute deleted
+
+class HostOfMemberNoHost$MemberNoHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "Hosts.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "HostOfMemberNoHost$MemberNoHost"; // #13
+ Utf8 "MemberNoHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "HostOfMemberNoHost"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 57;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostOfMemberNoHost$MemberNoHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostOfMemberNotInstanceHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-instance class
+
+class HostOfMemberNotInstanceHost$MemberNotInstanceHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #18; // #3
+ Utf8 "oa"; // #4
+ Utf8 "[LInvalidNestHost;"; // #5
+ Utf8 "<init>"; // #6
+ Utf8 "()V"; // #7
+ Utf8 "Code"; // #8
+ Utf8 "LineNumberTable"; // #9
+ Utf8 "SourceFile"; // #10
+ Utf8 "Hosts.java"; // #11
+ Utf8 "NestHost"; // #12
+ class #19; // #13
+ NameAndType #6 #7; // #14
+ Utf8 "HostOfMemberNotInstanceHost$MemberNotInstanceHost"; // #15
+ Utf8 "MemberNotInstanceHost"; // #16
+ Utf8 "InnerClasses"; // #17
+ Utf8 "java/lang/Object"; // #18
+ Utf8 "HostOfMemberNotInstanceHost"; // #19
+ class #5; // #20 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #6; // name_cpx
+ #7; // sig_cpx
+ [] { // Attributes
+ Attr(#8) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#9) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 63;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#10) { // SourceFile
+ #11;
+ } // end SourceFile
+ ;
+ Attr(#12) { // NestHost
+ 0x0014; // Modified #20
+ } // end NestHost
+ ;
+ Attr(#17) { // InnerClasses
+ [] { // InnerClasses
+ #2 #13 #16 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostOfMemberNotInstanceHost$MemberNotInstanceHost
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostOfMemberNotOurHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with no nest
+
+class HostOfMemberNotOurHost$MemberNotOurHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "Hosts.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "HostOfMemberNotOurHost$MemberNotOurHost"; // #13
+ Utf8 "MemberNotOurHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "HostOfMemberNotOurHost"; // #17
+ // Added
+ Utf8 "InvalidNestHost"; // #18
+ class #18; // #19
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 68;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0013; // Modified #19
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostOfMemberNotOurHost$MemberNotOurHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostWithDuplicateMembers.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Modify NestMembers attribute to contain multiple duplicates
+
+class HostWithDuplicateMembers {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #16; // #1
+ class #17; // #2
+ class #18; // #3
+ class #19; // #4
+ Utf8 "Member2"; // #5
+ Utf8 "InnerClasses"; // #6
+ class #20; // #7
+ Utf8 "Member1"; // #8
+ Utf8 "<init>"; // #9
+ Utf8 "()V"; // #10
+ Utf8 "Code"; // #11
+ Utf8 "LineNumberTable"; // #12
+ Utf8 "SourceFile"; // #13
+ Utf8 "Hosts.java"; // #14
+ Utf8 "NestMembers"; // #15
+ NameAndType #9 #10; // #16
+ Utf8 "HostWithDuplicateMembers"; // #17
+ Utf8 "java/lang/Object"; // #18
+ Utf8 "HostWithDuplicateMembers$Member2"; // #19
+ Utf8 "HostWithDuplicateMembers$Member1"; // #20
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #9; // name_cpx
+ #10; // sig_cpx
+ [] { // Attributes
+ Attr(#11) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#12) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 60;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#13) { // SourceFile
+ #14;
+ } // end SourceFile
+ ;
+ Attr(#15) { // NestMembers
+ 0x0006000700040007; // modified
+ 0x000400070004;
+ } // end NestMembers
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 1544;
+ #7 #2 #8 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostWithDuplicateMembers
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/HostWithSelfMember.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+// Modify NestMembers attribute to include reference to the currnet class
+
+class HostWithSelfMember {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #16; // #3
+ class #17; // #4
+ Utf8 "Member"; // #5
+ Utf8 "InnerClasses"; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "SourceFile"; // #11
+ Utf8 "Hosts.java"; // #12
+ Utf8 "NestMembers"; // #13
+ NameAndType #7 #8; // #14
+ Utf8 "HostWithSelfMember"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "HostWithSelfMember$Member"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 55;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#11) { // SourceFile
+ #12;
+ } // end SourceFile
+ ;
+ Attr(#13) { // NestMembers
+ 0x000200040002; // modified - added self
+ } // end NestMembers
+ ;
+ Attr(#6) { // InnerClasses
+ [] { // InnerClasses
+ #4 #2 #5 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class HostWithSelfMember
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/Hosts.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Non-public classes so we can keep them all in this one source file
+
+class HostOfMemberNoHost {
+ // Missing NestHost attribute
+ static class MemberNoHost {}
+}
+
+class HostOfMemberMissingHost {
+ // Missing NestHost class
+ static class MemberMissingHost {}
+}
+
+class HostOfMemberNotInstanceHost {
+ // Invalid NestHost class (not instance class)
+ static class MemberNotInstanceHost {
+ Object[] oa; // create CP entry to use in jcod change
+ }
+}
+
+class HostOfMemberNotOurHost {
+ // Valid but different NestHost class
+ static class MemberNotOurHost {}
+}
+
+class HostOfMemberMalformedHost {
+ // Malformed NestHost class
+ static class MemberMalformedHost {}
+}
+
+// Host lists itself as a member along
+// with real member.
+class HostWithSelfMember {
+ static class Member {}
+}
+
+// Host lists duplicate members.
+class HostWithDuplicateMembers {
+ static class Member1 {}
+ static interface Member2 {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/InvalidNestHost.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/* Empty class to use as an invalid nest-host class, in the same package as
+ * the test classes.
+ */
+public class InvalidNestHost {
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MalformedHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// Invalid class file format
+
+class MalformedHost {
+ 0xDEADBEEF; // bad magic number
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "MemberMalformedHost"; // #14
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "TestReflectionAPI"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 68;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ } // Attributes
+} // end class MalformedHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MemberMalformedHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with invalid class file format
+
+class TestReflectionAPI$MemberMalformedHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestReflectionAPI.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "TestReflectionAPI$MemberMalformedHost"; // #13
+ Utf8 "MemberMalformedHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "TestReflectionAPI"; // #17
+ // added
+ Utf8 "MalformedHost"; // #18
+ class #18; // #19
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 68;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0013; // Modified #19
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestReflectionAPI$MemberMalformedHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MemberMissingHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-existent class
+
+class TestReflectionAPI$MemberMissingHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestReflectionAPI.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "TestReflectionAPI$MemberMissingHost"; // #13
+ Utf8 "MemberMissingHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "TestReflectionAPI"; // #17
+ class #10; // #18 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 60;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0012; // modified
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestReflectionAPI$MemberMissingHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MemberNoHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute deleted
+
+class TestReflectionAPI$MemberNoHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestReflectionAPI.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "TestReflectionAPI$MemberNoHost"; // #13
+ Utf8 "MemberNoHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "TestReflectionAPI"; // #17
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 57;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestReflectionAPI$MemberNoHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MemberNotInstanceHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to non-instance class
+
+class TestReflectionAPI$MemberNotInstanceHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #14; // #1
+ class #15; // #2
+ class #18; // #3
+ Utf8 "oa"; // #4
+ Utf8 "[LInvalidNestHost;"; // #5
+ Utf8 "<init>"; // #6
+ Utf8 "()V"; // #7
+ Utf8 "Code"; // #8
+ Utf8 "LineNumberTable"; // #9
+ Utf8 "SourceFile"; // #10
+ Utf8 "TestReflectionAPI.java"; // #11
+ Utf8 "NestHost"; // #12
+ class #19; // #13
+ NameAndType #6 #7; // #14
+ Utf8 "TestReflectionAPI$MemberNotInstanceHost"; // #15
+ Utf8 "MemberNotInstanceHost"; // #16
+ Utf8 "InnerClasses"; // #17
+ Utf8 "java/lang/Object"; // #18
+ Utf8 "TestReflectionAPI"; // #19
+ class #5; // #20 - added
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ } // Attributes
+ } // Member
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #6; // name_cpx
+ #7; // sig_cpx
+ [] { // Attributes
+ Attr(#8) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#9) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 63;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#10) { // SourceFile
+ #11;
+ } // end SourceFile
+ ;
+ Attr(#12) { // NestHost
+ 0x0014; // Modified #20
+ } // end NestHost
+ ;
+ Attr(#17) { // InnerClasses
+ [] { // InnerClasses
+ #2 #13 #16 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestReflectionAPI$MemberNotInstanceHost
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/MemberNotOurHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute refers to class with no nest
+
+class TestReflectionAPI$MemberNotOurHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #3 #12; // #1
+ class #13; // #2
+ class #16; // #3
+ Utf8 "<init>"; // #4
+ Utf8 "()V"; // #5
+ Utf8 "Code"; // #6
+ Utf8 "LineNumberTable"; // #7
+ Utf8 "SourceFile"; // #8
+ Utf8 "TestReflectionAPI.java"; // #9
+ Utf8 "NestHost"; // #10
+ class #17; // #11
+ NameAndType #4 #5; // #12
+ Utf8 "TestReflectionAPI$MemberNotOurHost"; // #13
+ Utf8 "MemberNotOurHost"; // #14
+ Utf8 "InnerClasses"; // #15
+ Utf8 "java/lang/Object"; // #16
+ Utf8 "TestReflectionAPI"; // #17
+ // Added
+ Utf8 "InvalidNestHost"; // #18
+ class #18; // #19
+ } // Constant Pool
+
+ 0x0020; // access
+ #2;// this_cpx
+ #3;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0000; // access
+ #4; // name_cpx
+ #5; // sig_cpx
+ [] { // Attributes
+ Attr(#6) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#7) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 68;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#8) { // SourceFile
+ #9;
+ } // end SourceFile
+ ;
+ Attr(#10) { // NestHost
+ 0x0013; // Modified #19
+ } // end NestHost
+ ;
+ Attr(#15) { // InnerClasses
+ [] { // InnerClasses
+ #2 #11 #14 8;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class TestReflectionAPI$MemberNotOurHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/PackagedNestHost.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 P1;
+
+/*
+ * This is used to produce a jcod file in which we modify the
+ * NestMembers attribute to claim that P2.PackagedNestHost.Member
+ * is a member of our nest.
+ */
+public class PackagedNestHost {
+ public static class Member { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/PackagedNestHost.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestMembers attribute is modified to contain P2.PackagedNestHost2.Member
+
+class P1/PackagedNestHost {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #4 #16; // #1
+ Method #17 #18; // #2
+ class #19; // #3
+ class #20; // #4
+ class #21; // #5
+ Utf8 "Member"; // #6
+ Utf8 "InnerClasses"; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "doAccess"; // #12
+ Utf8 "SourceFile"; // #13
+ Utf8 "PackagedNestHost.java"; // #14
+ Utf8 "NestMembers"; // #15
+ NameAndType #8 #9; // #16
+ class #23; // #17
+ NameAndType #24 #9; // #18
+ Utf8 "P1/PackagedNestHost"; // #19
+ Utf8 "java/lang/Object"; // #20
+ Utf8 "P1/PackagedNestHost$Member"; // #21
+ class #25; // #22
+ Utf8 "P2/PackagedNestHost2$Member"; // #23
+ Utf8 "m"; // #24
+ Utf8 "P2/PackagedNestHost2"; // #25
+ } // Constant Pool
+
+ 0x0021; // access
+ #3;// this_cpx
+ #4;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 31;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #12; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80002B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 44;
+ 3 45;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#13) { // SourceFile
+ #14;
+ } // end SourceFile
+ ;
+ Attr(#15) { // NestMembers
+ 0x00010011; // modified - #17
+ } // end NestMembers
+ ;
+ Attr(#7) { // InnerClasses
+ [] { // InnerClasses
+ #5 #3 #6 9;
+ #17 #22 #6 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P1/PackagedNestHost
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/PackagedNestHost2.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 P2;
+
+/*
+ * This is used to produce a jcod file in which we modify the
+ * NestHost attribute to claim that P2.PackagedNestHost.Member
+ * is a member of the nest of P1.PackagedNestHost.
+ */
+public class PackagedNestHost2 {
+ public static class Member { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/PackagedNestHost2Member.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// NestHost attribute is modified to contain P1.PackagedNestHost
+// m() is declared private
+
+class P2/PackagedNestHost2$Member {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #7 #18; // #1
+ Field #19 #20; // #2
+ String #21; // #3
+ Method #22 #23; // #4
+ Method #24 #25; // #5
+ class #26; // #6
+ class #29; // #7
+ Utf8 "<init>"; // #8
+ Utf8 "()V"; // #9
+ Utf8 "Code"; // #10
+ Utf8 "LineNumberTable"; // #11
+ Utf8 "m"; // #12
+ Utf8 "doAccess"; // #13
+ Utf8 "SourceFile"; // #14
+ Utf8 "PackagedNestHost2.java"; // #15
+ Utf8 "NestHost"; // #16
+ class #30; // #17
+ NameAndType #8 #9; // #18
+ class #31; // #19
+ NameAndType #32 #33; // #20
+ Utf8 "You should never see this!"; // #21
+ class #34; // #22
+ NameAndType #35 #36; // #23
+ class #38; // #24
+ NameAndType #12 #9; // #25
+ Utf8 "P2/PackagedNestHost2$Member"; // #26
+ Utf8 "Member"; // #27
+ Utf8 "InnerClasses"; // #28
+ Utf8 "java/lang/Object"; // #29
+ Utf8 "P2/PackagedNestHost2"; // #30
+ Utf8 "java/lang/System"; // #31
+ Utf8 "out"; // #32
+ Utf8 "Ljava/io/PrintStream;"; // #33
+ Utf8 "java/io/PrintStream"; // #34
+ Utf8 "println"; // #35
+ Utf8 "(Ljava/lang/String;)V"; // #36
+ class #39; // #37
+ Utf8 "P1/PackagedNestHost$Member"; // #38
+ Utf8 "P1/PackagedNestHost"; // #39
+ } // Constant Pool
+
+ 0x0021; // access
+ #6;// this_cpx
+ #7;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #8; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 32;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access - modified
+ #12; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 35;
+ 8 36;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x0009; // access
+ #13; // name_cpx
+ #9; // sig_cpx
+ [] { // Attributes
+ Attr(#10) { // Code
+ 0; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB80005B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#11) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 42;
+ 3 43;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#14) { // SourceFile
+ #15;
+ } // end SourceFile
+ ;
+ Attr(#16) { // NestHost
+ 0x0025; // modified - #37
+ } // end NestHost
+ ;
+ Attr(#28) { // InnerClasses
+ [] { // InnerClasses
+ #6 #17 #27 9;
+ #24 #37 #27 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P2/PackagedNestHost2$Member
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/PackagedNestHostMember.jcod Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, 2018, 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.
+ */
+
+// m() is declared private
+
+class P1/PackagedNestHost$Member {
+ 0xCAFEBABE;
+ 0; // minor version
+ 55; // version
+ [] { // Constant Pool
+ ; // first element is empty
+ Method #6 #16; // #1
+ Field #17 #18; // #2
+ String #19; // #3
+ Method #20 #21; // #4
+ class #22; // #5
+ class #25; // #6
+ Utf8 "<init>"; // #7
+ Utf8 "()V"; // #8
+ Utf8 "Code"; // #9
+ Utf8 "LineNumberTable"; // #10
+ Utf8 "m"; // #11
+ Utf8 "SourceFile"; // #12
+ Utf8 "PackagedNestHost.java"; // #13
+ Utf8 "NestHost"; // #14
+ class #26; // #15
+ NameAndType #7 #8; // #16
+ class #27; // #17
+ NameAndType #28 #29; // #18
+ Utf8 "You should never see this!"; // #19
+ class #30; // #20
+ NameAndType #31 #32; // #21
+ Utf8 "P1/PackagedNestHost$Member"; // #22
+ Utf8 "Member"; // #23
+ Utf8 "InnerClasses"; // #24
+ Utf8 "java/lang/Object"; // #25
+ Utf8 "P1/PackagedNestHost"; // #26
+ Utf8 "java/lang/System"; // #27
+ Utf8 "out"; // #28
+ Utf8 "Ljava/io/PrintStream;"; // #29
+ Utf8 "java/io/PrintStream"; // #30
+ Utf8 "println"; // #31
+ Utf8 "(Ljava/lang/String;)V"; // #32
+ } // Constant Pool
+
+ 0x0021; // access
+ #5;// this_cpx
+ #6;// super_cpx
+
+ [] { // Interfaces
+ } // Interfaces
+
+ [] { // fields
+ } // fields
+
+ [] { // methods
+ { // Member
+ 0x0001; // access
+ #7; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 1; // max_stack
+ 1; // max_locals
+ Bytes[]{
+ 0x2AB70001B1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 32;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ ;
+ { // Member
+ 0x000A; // access - modified
+ #11; // name_cpx
+ #8; // sig_cpx
+ [] { // Attributes
+ Attr(#9) { // Code
+ 2; // max_stack
+ 0; // max_locals
+ Bytes[]{
+ 0xB200021203B60004;
+ 0xB1;
+ };
+ [] { // Traps
+ } // end Traps
+ [] { // Attributes
+ Attr(#10) { // LineNumberTable
+ [] { // LineNumberTable
+ 0 35;
+ 8 36;
+ }
+ } // end LineNumberTable
+ } // Attributes
+ } // end Code
+ } // Attributes
+ } // Member
+ } // methods
+
+ [] { // Attributes
+ Attr(#12) { // SourceFile
+ #13;
+ } // end SourceFile
+ ;
+ Attr(#14) { // NestHost
+ 0x000F;
+ } // end NestHost
+ ;
+ Attr(#24) { // InnerClasses
+ [] { // InnerClasses
+ #5 #15 #23 9;
+ }
+ } // end InnerClasses
+ } // Attributes
+} // end class P1/PackagedNestHost$Member
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/SampleNest.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, 2018, 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.util.Arrays;
+import java.util.List;
+import java.util.LinkedList;
+
+// A sample nest for use with reflection API tests
+public class SampleNest {
+
+ // recursively gather all the named nested types
+
+ static List<Class<?>> _nestedTypes = new LinkedList<>();
+
+ static void gather(Class<?> c) {
+ _nestedTypes.add(c);
+ for (Class<?> d : c.getDeclaredClasses()) {
+ gather(d);
+ }
+ }
+
+ static {
+ gather(SampleNest.class);
+ SampleNest s = new SampleNest();
+ }
+
+ public static Class<?>[] nestedTypes() {
+ return _nestedTypes.toArray(new Class<?>[0]);
+ }
+
+ // Define a nested type of each possible kind
+
+ static class StaticClass { }
+ static interface StaticIface { }
+ class InnerClass { }
+ interface InnerIface { }
+
+ // check multi-level nesting
+
+ static class DeepNest1 {
+ static class DeepNest2 {
+ static class DeepNest3 {
+ }
+ }
+ }
+
+ // local and anonymous classes aren't declared
+ // so they have to add themselves
+ public SampleNest() {
+ class LocalClass { }
+ _nestedTypes.add(LocalClass.class);
+
+ Runnable r = new Runnable() {
+ public void run() {
+ // anonymous class
+ _nestedTypes.add(getClass());
+ }
+ };
+ r.run();
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/TestReflectionAPI.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2017, 2018, 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
+ * @bug 8046171
+ * @summary Test the new nestmate reflection API
+ * @compile TestReflectionAPI.java
+ * PackagedNestHost.java
+ * PackagedNestHost2.java
+ * SampleNest.java
+ * Hosts.java
+ * InvalidNestHost.java
+ *
+ * @compile MemberNoHost.jcod
+ * MemberMissingHost.jcod
+ * MemberNotInstanceHost.jcod
+ * MemberNotOurHost.jcod
+ * MemberMalformedHost.jcod
+ * MalformedHost.jcod
+ * PackagedNestHost.jcod
+ * PackagedNestHost2Member.jcod
+ * PackagedNestHostMember.jcod
+ * HostOfMemberNoHost.jcod
+ * HostOfMemberMissingHost.jcod
+ * HostOfMemberNotInstanceHost.jcod
+ * HostOfMemberNotOurHost.jcod
+ * HostOfMemberMalformedHost.jcod
+ * HostWithSelfMember.jcod
+ * HostWithDuplicateMembers.jcod
+ *
+ * @run main/othervm TestReflectionAPI
+ * @run main/othervm/java.security.policy=empty.policy TestReflectionAPI
+ */
+
+// We need a nest member class that is invalid for each of the possible reasons,
+// plus we need some external classes to test other failure modes.
+// For each nested class below there is a corresponding .jcod file which breaks one
+// of the rules regarding nest membership. For the package related tests we have
+// additional PackageNestHost*.java sources.
+// For testing getNestMembers we need an external host class that has a nested class
+// which we can form a jcod file from such that we get all the expected failure modes.
+// Note that all the .java files must be compiled in the same step, while all
+// .jcod files must be compiled in a later step.
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+
+public class TestReflectionAPI {
+
+ // Valid nest member
+ static class Member {}
+
+ // Missing NestHost attribute
+ static class MemberNoHost {}
+
+ // Missing NestHost class
+ static class MemberMissingHost {}
+
+ // Invalid NestHost class (not instance class)
+ static class MemberNotInstanceHost {
+ Object[] oa; // create CP entry to use in jcod change
+ }
+
+ // Valid but different NestHost class
+ static class MemberNotOurHost {}
+
+ // Malformed NestHost class
+ static class MemberMalformedHost {}
+
+ public static void main(String[] args) throws Throwable {
+ // run tests twice so that failure reasons are
+ // seen to remain the same
+ for (int i = 0; i < 2; i++) {
+ test_getNestHost();
+ test_isNestmateOf();
+ test_getNestMembers();
+ }
+ }
+
+ static void test_getNestHost() {
+ Class<?> host = TestReflectionAPI.class;
+
+ // sampling of "good" checks
+
+ checkHost(host, host);
+ checkHost(Member.class, host);
+ Runnable r = new Runnable() { public void run() {}};
+ checkHost(r.getClass(), host);
+
+ // all the "bad" classes should report themselves as their
+ // own nest host - no exceptions should be thrown
+ Class<?>[] allClasses = host.getDeclaredClasses();
+ for (Class<?> c : allClasses) {
+ if (c == Member.class)
+ continue;
+ checkHost(c, c);
+ }
+ checkHost(P1.PackagedNestHost.Member.class,
+ P1.PackagedNestHost.Member.class);
+ checkHost(P2.PackagedNestHost2.Member.class,
+ P2.PackagedNestHost2.Member.class);
+
+ // test some 'special' classes
+ checkHost(int.class, int.class); // primitive
+ checkHost(Object[].class, Object[].class); // array
+ checkHost(Thread.State.class, Thread.class); // enum
+ checkHost(java.lang.annotation.Documented.class, // annotation
+ java.lang.annotation.Documented.class);
+ }
+
+ static void test_isNestmateOf() {
+ Class<?> host = TestReflectionAPI.class;
+ checkNestmates(host, host, true);
+ checkNestmates(Member.class, host, true);
+ Runnable r = new Runnable() { public void run() {}};
+ checkNestmates(r.getClass(), host, true);
+
+ // all the "bad" classes should report themselves as their
+ // own nest host - no exceptions should be thrown - so not
+ // nestmates
+ Class<?>[] allClasses = host.getDeclaredClasses();
+ for (Class<?> c : allClasses) {
+ if (c == Member.class)
+ continue;
+ checkNestmates(host, c, false);
+ }
+
+ // 'special' classes
+ checkNestmates(int.class, int.class, true); // primitive
+ checkNestmates(int.class, long.class, false); // primitive
+ checkNestmates(Object[].class, Object[].class, true); // array
+ checkNestmates(Object[].class, int[].class, false); // array
+ checkNestmates(Thread.State.class, Thread.class, true); // enum
+ checkNestmates(java.lang.annotation.Documented.class, // annotation
+ java.lang.annotation.Documented.class, true);
+ }
+
+ static void test_getNestMembers() {
+ // Sampling of "good" checks
+ Class<?>[] good = { Object.class, Object[].class, int.class};
+ checkSingletonNests(good);
+
+ // More thorough correctness check
+ checkNest(SampleNest.class, SampleNest.nestedTypes(), false);
+
+ // Special cases - legal but not produced by javac
+ checkNest(HostWithSelfMember.class,
+ new Class<?>[] { HostWithSelfMember.class,
+ HostWithSelfMember.Member.class },
+ true);
+ checkNest(HostWithDuplicateMembers.class,
+ new Class<?>[] { HostWithDuplicateMembers.class,
+ HostWithDuplicateMembers.Member1.class,
+ HostWithDuplicateMembers.Member2.class },
+ true);
+
+ // Hosts with "bad" members
+ Class<?>[] bad = {
+ HostOfMemberNoHost.class,
+ HostOfMemberMissingHost.class,
+ HostOfMemberNotOurHost.class,
+ HostOfMemberNotInstanceHost.class,
+ HostOfMemberMalformedHost.class,
+ };
+ Class<?>[] exceptions = {
+ IncompatibleClassChangeError.class,
+ NoClassDefFoundError.class,
+ IncompatibleClassChangeError.class,
+ IncompatibleClassChangeError.class,
+ ClassFormatError.class,
+ };
+ String[] messages = {
+ "Nest member HostOfMemberNoHost$MemberNoHost in HostOfMemberNoHost " +
+ "declares a different nest host of HostOfMemberNoHost$MemberNoHost",
+ "Unable to load nest-host class (NestHost) of " +
+ "HostOfMemberMissingHost$MemberMissingHost",
+ "Type HostOfMemberNotOurHost$MemberNotOurHost is not a nest member " +
+ "of InvalidNestHost: current type is not listed as a nest member",
+ "Type HostOfMemberNotInstanceHost$MemberNotInstanceHost is not a nest " +
+ "member of [LInvalidNestHost;: current type is not listed as a nest member",
+ "Incompatible magic value 3735928559 in class file MalformedHost",
+ };
+ for (int i = 0; i < bad.length; i++) {
+ try {
+ bad[i].getNestMembers();
+ throw new Error("getNestMembers() succeeded for class " +
+ bad[i].getName());
+ } catch (LinkageError e) {
+ checkException(e, messages[i], exceptions[i]);
+ }
+ }
+ }
+
+ static void checkException(Throwable actual, String msg, Class<?> expected) {
+ if (!actual.getClass().equals(expected))
+ throw new Error("Unexpected exception: got " + actual.getClass().getName()
+ + " but expected " + expected.getName());
+ if (!actual.getMessage().contains(msg))
+ throw new Error("Wrong " + actual.getClass().getSimpleName() +": \"" +
+ actual.getMessage() + "\" does not contain \"" +
+ msg + "\"");
+ System.out.println("OK - got expected exception: " + actual);
+ }
+
+ static void checkHost(Class<?> target, Class<?> expected) {
+ System.out.println("Checking nest host of " + target.getName());
+ Class<?> host = target.getNestHost();
+ if (host != expected)
+ throw new Error("Class " + target.getName() +
+ " has nest host " + host.getName() +
+ " but expected " + expected.getName());
+ }
+
+ static void checkNestmates(Class<?> a, Class<?> b, boolean mates) {
+ System.out.println("Checking if " + a.getName() +
+ " isNestmateOf " + b.getName());
+
+ if (a.isNestmateOf(b) != mates)
+ throw new Error("Class " + a.getName() + " is " +
+ (mates ? "not " : "") +
+ "a nestmate of " + b.getName() + " but should " +
+ (mates ? "" : "not ") + "be");
+ }
+
+ static Comparator<Class<?>> cmp = Comparator.comparing(Class::getName);
+
+ static void checkNest(Class<?> host, Class<?>[] unsortedTypes, boolean expectDups) {
+ Class<?>[] members = host.getNestMembers();
+ Arrays.sort(members, cmp);
+ Class<?>[] nestedTypes = unsortedTypes.clone();
+ Arrays.sort(nestedTypes, cmp);
+ printMembers(host, members);
+ printDeclared(host, nestedTypes);
+ if (!Arrays.equals(members, nestedTypes)) {
+ if (!expectDups) {
+ throw new Error("Class " + host.getName() + " has different members " +
+ "compared to declared classes");
+ }
+ else {
+ // get rid of duplicates
+ Class<?>[] memberSet =
+ Arrays.stream(members).sorted(cmp).distinct().toArray(Class<?>[]::new);
+ if (!Arrays.equals(memberSet, nestedTypes)) {
+ throw new Error("Class " + host.getName() + " has different members " +
+ "compared to declared classes, even after duplicate removal");
+ }
+ }
+ }
+ // verify all the relationships that must hold for nest members
+ for (Class<?> a : members) {
+ checkHost(a, host);
+ checkNestmates(a, host, true);
+ Class<?>[] aMembers = a.getNestMembers();
+ if (aMembers[0] != host) {
+ throw new Error("Class " + a.getName() + " getNestMembers()[0] = " +
+ aMembers[0].getName() + " not " + host.getName());
+
+ }
+ Arrays.sort(aMembers, cmp);
+ if (!Arrays.equals(members, aMembers)) {
+ throw new Error("Class " + a.getName() + " has different members " +
+ "compared to host " + host.getName());
+ }
+ for (Class<?> b : members) {
+ checkNestmates(a, b, true);
+ }
+ }
+ }
+
+ static void checkSingletonNests(Class<?>[] classes) {
+ for (Class<?> host : classes) {
+ Class<?>[] members = host.getNestMembers();
+ if (members.length != 1) {
+ printMembers(host, members);
+ throw new Error("Class " + host.getName() + " lists " + members.length
+ + " members instead of 1 (itself)");
+ }
+ if (members[0] != host) {
+ printMembers(host, members);
+ throw new Error("Class " + host.getName() + " lists " +
+ members[0].getName() + " as member instead of itself");
+ }
+ }
+ }
+
+ static void printMembers(Class<?> host, Class<?>[] members) {
+ System.out.println("Class " + host.getName() + " has members: ");
+ for (Class<?> c : members) {
+ System.out.println(" - " + c.getName());
+ }
+ }
+
+ static void printDeclared(Class<?> host, Class<?>[] declared) {
+ System.out.println("Class " + host.getName() + " has declared types: ");
+ for (Class<?> c : declared) {
+ System.out.println(" - " + c.getName());
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/TestSecurityManagerChecks.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8046171
+ * @summary Test that security checks occur for getNestHost/getNestMembers
+ *
+ * @library /test/lib
+ * @build TestSecurityManagerChecks testPkg.Host testPkg.Singleton
+ * @run driver ClassFileInstaller testPkg.Host testPkg.Host$Member testPkg.Singleton
+ * @run main/othervm -Xbootclasspath/a:. TestSecurityManagerChecks
+ */
+
+// ClassFileInstaller copies the testPkg files into the "current" directory
+// so we can add it to the bootclasspath. Then when we run the test the
+// loader for the testPkg files is the bootloader but the loader for the
+// test class is the system loader, hence a package access check will fail
+// because the system loader is not the same as, nor a parent of, the bootloader.
+import java.security.Security;
+
+public class TestSecurityManagerChecks {
+
+ public static void main(String[] args) throws Throwable {
+
+ // First get hold of the target classes before we enable security
+ Class<?> host = testPkg.Host.class;
+ Class<?> member = testPkg.Host.Member.class;
+ Class<?> memberArray = testPkg.Host.Member[].class;
+ Class<?> singleton = testPkg.Singleton.class;
+
+ // Next add testPkg to the set of packages for which package-access
+ // permission is required
+ Security.setProperty("package.access",
+ Security.getProperty("package.access") + ",testPkg.");
+
+ // Finally install a default security manager
+ SecurityManager sm = new SecurityManager();
+ System.setSecurityManager(sm);
+
+ // These cases all succeed
+ getNestHost(int.class); // primitive
+ getNestHost(int[].class); // primitive[]
+ getNestHost(host); // host class
+ getNestHost(memberArray); // NestedT[]
+ getNestHost(singleton); // Singleton nest
+
+ getNestMembers(int.class); // primitive
+ getNestMembers(int[].class); // primitive[]
+ getNestMembers(memberArray); // NestedT[]
+ getNestMembers(singleton); // Singleton nest
+
+ // these cases all fail
+ getNestHostThrows(member); // NestedT
+
+ getNestMembersThrows(member); // NestedT
+ getNestMembersThrows(host); // host class
+ }
+
+ static void getNestHost(Class<?> c) {
+ Class<?> host = c.getNestHost();
+ System.out.println("OK - getNestHost succeeded for " + c.getName());
+ }
+
+ static void getNestHostThrows(Class<?> c) throws SecurityException {
+ try {
+ Class<?> host = c.getNestHost();
+ throw new Error("getNestHost succeeded for " + c.getName());
+ } catch (SecurityException e) {
+ System.out.println("OK - getNestHost for " + c.getName() +
+ " got expected exception: " + e);
+ }
+ }
+
+ static void getNestMembers(Class<?> c) {
+ Class<?>[] members = c.getNestMembers();
+ System.out.println("OK - getNestMembers succeeded for " + c.getName());
+ }
+
+ static void getNestMembersThrows(Class<?> c) throws SecurityException {
+ try {
+ Class<?>[] members = c.getNestMembers();
+ throw new Error("getNestMembers succeeded for " + c.getName());
+ } catch (SecurityException e) {
+ System.out.println("OK - getNestMembers for " + c.getName() +
+ " got expected exception: " + e);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/empty.policy Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,5 @@
+// A deliberately empty policy file for use with jtreg.
+// Setting othervm/java.security.policy=empty.policy
+// causes jtreg to run under the default system policy
+// and default security manager, with the addition of
+// the permissions jtreg itself needs to run.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/testPkg/Host.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testPkg;
+
+// Host class with single member
+public class Host {
+ public static class Member {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/reflect/Nestmates/testPkg/Singleton.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package testPkg;
+
+// Self-hosting singleton nest
+public class Singleton {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/ExceptionText.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018, 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
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @bug 8204233
+ * @summary Add configurable option for enhanced socket IOException messages
+ * @run main/othervm ExceptionText
+ * @run main/othervm -Djdk.net.includeInExceptions= ExceptionText
+ * @run main/othervm -Djdk.net.includeInExceptions=hostInfo ExceptionText
+ * @run main/othervm -Djdk.net.includeInExceptions=somethingElse ExceptionText
+ */
+
+import java.net.*;
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.*;
+import java.util.concurrent.ExecutionException;
+import jdk.test.lib.Utils;
+
+public class ExceptionText {
+
+ enum TestTarget {SOCKET, CHANNEL, ASYNC_CHANNEL};
+
+ static boolean propEnabled() {
+ String val = System.getProperty("jdk.net.includeInExceptions");
+ if ("hostinfo".equalsIgnoreCase(val))
+ return true;
+ return false;
+ }
+
+ public static void main(String args[]) throws Exception {
+ boolean prop = propEnabled();
+ test(prop);
+ }
+
+ static final InetSocketAddress dest = Utils.refusingEndpoint();
+ static final String PORT = ":" + Integer.toString(dest.getPort());
+ static final String HOST = dest.getHostString();
+
+ static void test(boolean withProperty) {
+ // Socket
+ IOException e = getException(TestTarget.SOCKET);
+ checkResult(e, withProperty);
+ // SocketChannel
+ e = getException(TestTarget.CHANNEL);
+ checkResult(e, withProperty);
+ // AsyncSocketChannel
+ e = getException(TestTarget.ASYNC_CHANNEL);
+ checkResult(e, withProperty);
+ }
+
+ static void checkResult(IOException e, boolean withProperty) {
+ String msg = e.getMessage();
+ if (!withProperty) {
+ if (msg.contains(HOST) || msg.contains(PORT)) {
+ System.err.println("msg = " + msg);
+ throw new RuntimeException("Test failed: exception contains address info");
+ }
+ } else {
+ if (!msg.contains(HOST) || !msg.contains(PORT)) {
+ if (e instanceof ClosedChannelException)
+ return; // has no detail msg
+ System.err.println("msg = " + msg);
+ throw new RuntimeException("Test failed: exception does not contain address info");
+ }
+ }
+ }
+
+ static IOException getException(TestTarget target) {
+ try {
+ if (target == TestTarget.SOCKET) {
+ Socket s = new Socket();
+ s.connect(dest);
+ } else if (target == TestTarget.CHANNEL) {
+ SocketChannel c = SocketChannel.open(dest);
+ } else if (target == TestTarget.ASYNC_CHANNEL) {
+ AsynchronousSocketChannel c = AsynchronousSocketChannel.open();
+ try {
+ c.connect(dest).get();
+ } catch (InterruptedException | ExecutionException ee) {
+ if (ee.getCause() instanceof IOException)
+ throw (IOException)ee.getCause();
+ throw new RuntimeException(ee.getCause());
+ }
+ }
+ return null;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return e;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/nio/channels/FileChannel/TempDirectBuffersReclamation.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018, 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.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.management.BufferPoolMXBean;
+import java.lang.management.ManagementFactory;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+/*
+ * @test
+ * @bug 8202788
+ * @summary Test reclamation of thread-local temporary direct byte buffers at thread exit
+ * @modules java.management
+ * @run main/othervm TempDirectBuffersReclamation
+ */
+public class TempDirectBuffersReclamation {
+
+ public static void main(String[] args) throws IOException {
+
+ BufferPoolMXBean dbPool = ManagementFactory
+ .getPlatformMXBeans(BufferPoolMXBean.class)
+ .stream()
+ .filter(bp -> bp.getName().equals("direct"))
+ .findFirst()
+ .orElseThrow(() -> new RuntimeException("Can't obtain direct BufferPoolMXBean"));
+
+ long count0 = dbPool.getCount();
+ long memoryUsed0 = dbPool.getMemoryUsed();
+
+ Thread thread = new Thread(TempDirectBuffersReclamation::doFileChannelWrite);
+ thread.start();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ long count1 = dbPool.getCount();
+ long memoryUsed1 = dbPool.getMemoryUsed();
+
+ if (count0 != count1 || memoryUsed0 != memoryUsed1) {
+ throw new AssertionError(
+ "Direct BufferPool not same before thread activity and after thread exit.\n" +
+ "Before: # of buffers: " + count0 + ", memory used: " + memoryUsed0 + "\n" +
+ " After: # of buffers: " + count1 + ", memory used: " + memoryUsed1 + "\n"
+ );
+ }
+ }
+
+ static void doFileChannelWrite() {
+ try {
+ Path file = Files.createTempFile("test", ".tmp");
+ try (FileChannel fc = FileChannel.open(file, CREATE, WRITE, TRUNCATE_EXISTING)) {
+ fc.write(ByteBuffer.wrap("HELLO".getBytes(StandardCharsets.UTF_8)));
+ } finally {
+ Files.delete(file);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+}
--- a/test/jdk/javax/management/security/HashedPasswordFileTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/javax/management/security/HashedPasswordFileTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -22,15 +22,17 @@
*/
/* @test
- * @bug 5016517
+ * @bug 5016517 8204661
* @summary Test Hashed passwords
* @library /test/lib
* @modules java.management
+ * jdk.management.agent/jdk.internal.agent
* @build HashedPasswordFileTest
* @run testng/othervm HashedPasswordFileTest
*
*/
+import jdk.internal.agent.ConnectorAddressLink;
import jdk.test.lib.Utils;
import jdk.test.lib.process.ProcessTools;
import org.testng.Assert;
@@ -405,7 +407,6 @@
@Test
public void testDefaultAgent() throws Exception {
List<String> pbArgs = new ArrayList<>();
- int port = Utils.getFreePort();
generateClearTextPasswordFile();
// This will run only on a POSIX compliant system
@@ -424,10 +425,12 @@
pbArgs.add("-cp");
pbArgs.add(System.getProperty("test.class.path"));
- pbArgs.add("-Dcom.sun.management.jmxremote.port=" + port);
+ pbArgs.add("-Dcom.sun.management.jmxremote.port=0");
pbArgs.add("-Dcom.sun.management.jmxremote.authenticate=true");
pbArgs.add("-Dcom.sun.management.jmxremote.password.file=" + file.getAbsolutePath());
pbArgs.add("-Dcom.sun.management.jmxremote.ssl=false");
+ pbArgs.add("--add-exports");
+ pbArgs.add("jdk.management.agent/jdk.internal.agent=ALL-UNNAMED");
pbArgs.add(TestApp.class.getSimpleName());
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
@@ -445,7 +448,6 @@
@Test
public void testDefaultAgentNoHash() throws Exception {
List<String> pbArgs = new ArrayList<>();
- int port = Utils.getFreePort();
generateClearTextPasswordFile();
// This will run only on a POSIX compliant system
@@ -464,11 +466,13 @@
pbArgs.add("-cp");
pbArgs.add(System.getProperty("test.class.path"));
- pbArgs.add("-Dcom.sun.management.jmxremote.port=" + port);
+ pbArgs.add("-Dcom.sun.management.jmxremote.port=0");
pbArgs.add("-Dcom.sun.management.jmxremote.authenticate=true");
pbArgs.add("-Dcom.sun.management.jmxremote.password.file=" + file.getAbsolutePath());
pbArgs.add("-Dcom.sun.management.jmxremote.password.toHashes=false");
pbArgs.add("-Dcom.sun.management.jmxremote.ssl=false");
+ pbArgs.add("--add-exports");
+ pbArgs.add("jdk.management.agent/jdk.internal.agent=ALL-UNNAMED");
pbArgs.add(TestApp.class.getSimpleName());
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
@@ -496,12 +500,12 @@
public static void main(String[] args) throws IOException {
try {
- JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:"
- + System.getProperty("com.sun.management.jmxremote.port") + "/jmxrmi");
+ Map<String, String> propsMap = ConnectorAddressLink.importRemoteFrom(0);
+ String jmxServiceUrl = propsMap.get("sun.management.JMXConnectorServer.0.remoteAddress");
Map<String, Object> env = new HashMap<>(1);
// any dummy credentials will do. We just have to trigger password hashing
env.put("jmx.remote.credentials", new String[]{"a", "a"});
- try (JMXConnector cc = JMXConnectorFactory.connect(url, env)) {
+ try (JMXConnector cc = JMXConnectorFactory.connect(new JMXServiceURL(jmxServiceUrl), env)) {
cc.getMBeanServerConnection();
}
} catch (SecurityException ex) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018, 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 jdk.internal.misc.TerminatingThreadLocal;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
+
+/*
+ * @test
+ * @bug 8202788
+ * @summary TerminatingThreadLocal unit test
+ * @modules java.base/jdk.internal.misc
+ * @run main TestTerminatingThreadLocal
+ */
+public class TestTerminatingThreadLocal {
+
+ public static void main(String[] args) {
+ ttlTestSet(42, 112);
+ ttlTestSet(null, 112);
+ ttlTestSet(42, null);
+ }
+
+ static <T> void ttlTestSet(T v0, T v1) {
+ ttlTest(v0, ttl -> { } );
+ ttlTest(v0, ttl -> { ttl.get(); }, v0);
+ ttlTest(v0, ttl -> { ttl.get(); ttl.remove(); } );
+ ttlTest(v0, ttl -> { ttl.get(); ttl.set(v1); }, v1);
+ ttlTest(v0, ttl -> { ttl.set(v1); }, v1);
+ ttlTest(v0, ttl -> { ttl.set(v1); ttl.remove(); } );
+ ttlTest(v0, ttl -> { ttl.set(v1); ttl.remove(); ttl.get(); }, v0);
+ ttlTest(v0, ttl -> { ttl.get(); ttl.remove(); ttl.set(v1); }, v1);
+ }
+
+ @SafeVarargs
+ static <T> void ttlTest(T initialValue,
+ Consumer<? super TerminatingThreadLocal<T>> ttlOps,
+ T... expectedTerminatedValues)
+ {
+ List<T> terminatedValues = new CopyOnWriteArrayList<>();
+
+ TerminatingThreadLocal<T> ttl = new TerminatingThreadLocal<>() {
+ @Override
+ protected void threadTerminated(T value) {
+ terminatedValues.add(value);
+ }
+
+ @Override
+ protected T initialValue() {
+ return initialValue;
+ }
+ };
+
+ Thread thread = new Thread(() -> ttlOps.accept(ttl));
+ thread.start();
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ if (!terminatedValues.equals(Arrays.asList(expectedTerminatedValues))) {
+ throw new AssertionError("Expected terminated values: " +
+ Arrays.toString(expectedTerminatedValues) +
+ " but got: " + terminatedValues);
+ }
+ }
+}
--- a/test/jdk/jdk/jfr/jcmd/JcmdAsserts.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/jdk/jfr/jcmd/JcmdAsserts.java Mon Jun 25 09:48:06 2018 -0700
@@ -47,7 +47,7 @@
output.shouldMatch("Flight Recorder has been used");
}
- public static void assertRecordingDumpedToFile(OutputAnalyzer output, String name, File recording) {
+ public static void assertRecordingDumpedToFile(OutputAnalyzer output, File recording) {
output.shouldContain("Dumped recording");
output.shouldContain(recording.getAbsolutePath());
}
--- a/test/jdk/jdk/jfr/jcmd/TestJcmdDump.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/jdk/jfr/jcmd/TestJcmdDump.java Mon Jun 25 09:48:06 2018 -0700
@@ -26,8 +26,16 @@
package jdk.jfr.jcmd;
import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
-import jdk.test.lib.jfr.FileHelper;
+import jdk.jfr.Event;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordingFile;
+import jdk.test.lib.jfr.EventNames;
import jdk.test.lib.process.OutputAnalyzer;
/*
@@ -35,24 +43,129 @@
* @summary The test verifies JFR.dump command
* @key jfr
* @library /test/lib /test/jdk
- * @run main/othervm jdk.jfr.jcmd.TestJcmdDump
+ * @run main/othervm -XX:FlightRecorderOptions:maxchunksize=1M jdk.jfr.jcmd.TestJcmdDump
*/
public class TestJcmdDump {
+ static class StoppedEvent extends Event {
+ }
+ static class RunningEvent extends Event {
+ }
+
+ private static final String[] names = { null, "r1" };
+ private static final boolean booleanValues[] = { true, false };
+
public static void main(String[] args) throws Exception {
- String name = "TestJcmdDump";
- File recording = new File(name + ".jfr");
+
+ // Create a stopped recording in the repository to complicate things
+ Recording r = new Recording();
+ r.start();
+ StoppedEvent de = new StoppedEvent();
+ de.commit();
+ r.stop();
+ // The implementation of JFR.dump touch code that can't be executed using the
+ // Java API. It is therefore important to try all combinations. The
+ // implementation is non-trivial and depends on the combination
+ for (String name : names) {
+ for (boolean disk : booleanValues) {
+ try (Recording r1 = new Recording(); Recording r2 = new Recording()) {
+ System.out.println();
+ System.out.println();
+ System.out.println("Starting recordings with disk=" + disk);
+ r1.setToDisk(disk);
+ // To complicate things, only enable OldObjectSample for one recording
+ r1.enable(EventNames.OldObjectSample).withoutStackTrace();
+ r1.setName("r1");
+ r2.setToDisk(disk);
+ r2.setName("r2");
+ r1.start();
+ r2.start();
+
+ // Expect no path to GC roots
+ jfrDump(Boolean.FALSE, name, disk, rootCount -> rootCount == 0);
+ // Expect path to GC roots
+ jfrDump(null, name, disk, rootCount -> rootCount == 0);
+ // Expect at least one path to a GC root
+ jfrDump(Boolean.TRUE, name, disk, rootCount -> rootCount > 0);
+ }
+ }
+ }
+ r.close(); // release recording data from the stopped recording
+ }
- OutputAnalyzer output = JcmdHelper.jcmd("JFR.start", "name=" + name);
- JcmdAsserts.assertRecordingHasStarted(output);
- JcmdHelper.waitUntilRunning(name);
+ private static void jfrDump(Boolean pathToGCRoots, String name, boolean disk, Predicate<Integer> successPredicate) throws Exception {
+ List<Object> leakList = new ArrayList<>();
+ leakList.add(new Object[1000_0000]);
+ System.gc();
+ while (true) {
+ RunningEvent re = new RunningEvent();
+ re.commit();
+ leakList.add(new Object[1000_0000]);
+ leakList.add(new Object[1000_0000]);
+ leakList.add(new Object[1000_0000]);
+ System.gc(); // This will shorten time for object to be emitted.
+ File recording = new File("TestJCMdDump.jfr");
+ String[] params = buildParameters(pathToGCRoots, name, recording);
+ OutputAnalyzer output = JcmdHelper.jcmd(params);
+ JcmdAsserts.assertRecordingDumpedToFile(output, recording);
+ int rootCount = 0;
+ int oldObjectCount = 0;
+ int stoppedEventCount = 0;
+ int runningEventCount = 0;
+ for (RecordedEvent e : RecordingFile.readAllEvents(recording.toPath())) {
+ if (e.getEventType().getName().equals(EventNames.OldObjectSample)) {
+ if (e.getValue("root") != null) {
+ rootCount++;
+ }
+ oldObjectCount++;
+ }
+ if (e.getEventType().getName().equals(StoppedEvent.class.getName())) {
+ stoppedEventCount++;
+ }
+ if (e.getEventType().getName().equals(RunningEvent.class.getName())) {
+ runningEventCount++;
+ }
+ }
+ System.out.println("Name: " + name);
+ System.out.println("Disk: " + disk);
+ System.out.println("Path to GC roots: " + pathToGCRoots);
+ System.out.println("Old Objects: " + oldObjectCount);
+ System.out.println("Root objects: "+ rootCount);
+ System.out.println("Stopped events: "+ stoppedEventCount);
+ System.out.println("Running events: "+ runningEventCount);
- output = JcmdHelper.jcmd("JFR.dump",
- "name=" + name,
- "filename=" + recording.getAbsolutePath());
- JcmdAsserts.assertRecordingDumpedToFile(output, name, recording);
- JcmdHelper.stopAndCheck(name);
- FileHelper.verifyRecording(recording);
+ System.out.println();
+ if (runningEventCount == 0) {
+ throw new Exception("Missing event from running recording");
+ }
+ if (name == null && stoppedEventCount == 0) {
+ throw new Exception("Missing event from stopped recording");
+ }
+ if (name != null && stoppedEventCount > 0) {
+ throw new Exception("Stopped event should not be part of dump");
+ }
+ if (oldObjectCount != 0 && successPredicate.test(rootCount)) {
+ return;
+ }
+ System.out.println();
+ System.out.println();
+ System.out.println();
+ System.out.println("************* Retrying! **************");
+ Files.delete(recording.toPath());
+ }
+ }
+
+ private static String[] buildParameters(Boolean pathToGCRoots, String name, File recording) {
+ List<String> params = new ArrayList<>();
+ params.add("JFR.dump");
+ params.add("filename=" + recording.getAbsolutePath());
+ if (pathToGCRoots != null) { // if path-to-gc-roots is omitted, default is used (disabled).
+ params.add("path-to-gc-roots=" + pathToGCRoots);
+ }
+ if (name != null) { // if name is omitted, all recordings will be dumped
+ params.add("name=" + name);
+ }
+ return params.toArray(new String[0]);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/jfr/jcmd/TestJcmdDumpGeneratedFilename.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, 2018, 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.jfr.jcmd;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Iterator;
+
+import jdk.jfr.Configuration;
+import jdk.jfr.Recording;
+import jdk.test.lib.jfr.FileHelper;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/*
+ * @test
+ * @summary The test verifies JFR.dump command
+ * @key jfr
+ * @library /test/lib /test/jdk
+ * @run main/othervm jdk.jfr.jcmd.TestJcmdDumpGeneratedFilename
+ */
+public class TestJcmdDumpGeneratedFilename {
+
+ public static void main(String[] args) throws Exception {
+ // Increase the id for a recording
+ for (int i = 0; i < 300; i++) {
+ new Recording();
+ }
+ try (Recording r = new Recording(Configuration.getConfiguration("default"))) {
+ r.start();
+ r.stop();
+ testDumpFilename();
+ testDumpFilename(r);
+ testDumpDiectory();
+ testDumpDiectory(r);
+ }
+ }
+
+ private static void testDumpFilename() throws Exception {
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump");
+ verifyFile(readFilename(output), null);
+ }
+
+ private static void testDumpFilename(Recording r) throws Exception {
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "name=" + r.getId());
+ verifyFile(readFilename(output), r.getId());
+ }
+
+ private static void testDumpDiectory() throws Exception {
+ Path directory = Paths.get(".").toAbsolutePath().normalize();
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + directory);
+ String filename = readFilename(output);
+ verifyFile(filename, null);
+ verifyDirectory(filename, directory);
+ }
+
+ private static void testDumpDiectory(Recording r) throws Exception {
+ Path directory = Paths.get(".").toAbsolutePath().normalize();
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "name=" + r.getId(), "filename=" + directory);
+ String filename = readFilename(output);
+ verifyFile(filename, r.getId());
+ verifyDirectory(filename, directory);
+ }
+
+ private static void verifyDirectory(String filename, Path directory) throws Exception {
+ if (!filename.contains(directory.toAbsolutePath().normalize().toString())) {
+ throw new Exception("Expected dump to be at " + directory);
+ }
+ }
+
+ private static void verifyFile(String filename, Long id) throws Exception {
+ String idText = id == null ? "" : "-id-" + Long.toString(id);
+ String expectedName = "hotspot-pid-" + ProcessHandle.current().pid() + idText;
+ if (!filename.contains(expectedName)) {
+ throw new Exception("Expected filename to contain " + expectedName);
+ }
+ FileHelper.verifyRecording(new File(filename));
+ }
+
+ private static String readFilename(OutputAnalyzer output) throws Exception {
+ Iterator<String> it = output.asLines().iterator();
+ while (it.hasNext()) {
+ String line = it.next();
+ if (line.contains("written to")) {
+ line = it.next(); // blank line
+ return it.next();
+ }
+ }
+ throw new Exception("Could not find filename of dumped recording.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/jfr/jcmd/TestJcmdDumpLimited.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2015, 2018, 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.jfr.jcmd;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import jdk.jfr.Event;
+import jdk.jfr.Recording;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/*
+ * @test
+ * @summary The test verifies JFR.dump command
+ * @key jfr
+ * @library /test/lib /test/jdk
+ * @run main/othervm -XX:FlightRecorderOptions jdk.jfr.jcmd.TestJcmdDumpLimited
+ */
+public class TestJcmdDumpLimited {
+
+ static class TestEvent extends Event {
+ int id;
+ int number;
+ }
+
+ static class TestRecording {
+ Instant time;
+ final Recording r;
+ Path path;
+ int size;
+ int total;
+ int id;
+ Instant now;
+
+ TestRecording(int id, int events) throws IOException, InterruptedException {
+ r = new Recording();
+ r.start();
+ for (int i = 0; i < events; i++) {
+ TestEvent event = new TestEvent();
+ event.id = id;
+ event.number = i;
+ event.commit();
+ if (i == events / 2) {
+ time = Instant.now();
+ }
+ }
+ r.stop();
+ Thread.sleep(1);
+ path = Paths.get("dump-" + id + ".jfr");
+ r.dump(path);
+ size = (int) Files.size(path);
+ this.id = id;
+ this.now = Instant.now();
+ }
+
+ public void close() {
+ r.close();
+ }
+ }
+
+ private static long totalSize;
+ private static long lastFiveSize;
+ private static long firstFiveSize;
+ private static long middleSize;
+ private static long centerSize;
+ private static long lastSize;
+
+ private static Instant middle;
+ private static Instant centerLeft;
+ private static Instant centerRight;
+
+ public static void main(String[] args) throws Exception {
+
+ List<TestRecording> recs = new ArrayList<>();
+
+ for (int i = 0; i < 9; i++) {
+ recs.add(new TestRecording(i, 100));
+ }
+ int last = 0;
+ List<TestRecording> reversed = new ArrayList<>(recs);
+ Collections.reverse(reversed);
+ for (TestRecording r : reversed) {
+ r.total = r.size + last;
+ last += r.size;
+ }
+
+ for (TestRecording r : recs) {
+ System.out.println("Recording " + r.id + ": size=" + r.size + " (total=" + r.total + ", time=" + r.now + ")");
+ }
+
+ centerLeft = recs.get(3).time;
+ middle = recs.get(4).time;
+ centerRight = recs.get(5).time;
+
+ totalSize = size(recs, 0, 9);
+ lastFiveSize = size(recs, 4, 5);
+ firstFiveSize = size(recs, 0, 5);
+ middleSize = size(recs, 4, 1);
+ centerSize = size(recs, 3, 3);
+ lastSize = size(recs, 8, 1);
+
+ testDump();
+ testDumpMaxSize();
+ testDumpMaxSizeSmall();
+ testDumpBegin();
+ testDumpEnd();
+ testDumpBeginEndInstant();
+ testDumpBeginEndLocalDateTime();
+ testDumpBeginEndLocalTime();
+ testDumpBeginEndSame();
+ testDumpMaxAge();
+ testDumpBeginEndRelative();
+ testDumpTooEarly();
+ testDumpTooLate();
+ testDumpBeginMaxAge();
+ TestDumpEndMaxage();
+ testDumpEndBegin();
+ testDumpInvalidTime();
+ }
+
+ private static int size(List<TestRecording> recs, int skip, int limit) {
+ return recs.stream().skip(skip).limit(limit).mapToInt(r -> r.size).sum();
+ }
+
+ private static void testDumpEndBegin() throws Exception {
+ Path testEndBegin = Paths.get("testEndBegin.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testEndBegin.toFile().getAbsolutePath(), "begin=" + Instant.now(), "end=" + Instant.now().minusSeconds(200));
+ output.shouldContain("Dump failed, begin must preceed end.");
+ assertMissingFile(testEndBegin);
+ }
+
+ private static void TestDumpEndMaxage() throws Exception {
+ Path testEndMaxAge = Paths.get("testEndMaxAge.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testEndMaxAge.toFile().getAbsolutePath(), "end=" + Instant.now(), "maxage=2h");
+ output.shouldContain("Dump failed, maxage can't be combined with begin or end.");
+ assertMissingFile(testEndMaxAge);
+ }
+
+ private static Path testDumpBeginMaxAge() throws Exception {
+ Path testBeginMaxAge = Paths.get("testBeginMaxAge.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginMaxAge.toFile().getAbsolutePath(), "begin=" + Instant.now().minusSeconds(100), "maxage=2h");
+ output.shouldContain("Dump failed, maxage can't be combined with begin or end.");
+ assertMissingFile(testBeginMaxAge);
+ return testBeginMaxAge;
+ }
+
+ private static void testDumpTooLate() throws Exception {
+ Path missing = Paths.get("missing2.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + missing.toFile().getAbsolutePath(), "begin=" + Instant.now().plus(Duration.ofHours(1)),
+ "end=" + Instant.now().plus(Duration.ofHours(2)));
+ output.shouldContain("Dump failed. No data found in the specified interval.");
+ assertMissingFile(missing);
+ }
+
+ private static void testDumpTooEarly() throws Exception {
+ Path missing = Paths.get("missing.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + missing.toFile().getAbsolutePath(), "end=" + Instant.now().minus(Duration.ofHours(1)));
+ output.shouldContain("Dump failed. No data found in the specified interval.");
+ assertMissingFile(missing);
+ }
+
+ private static void testDumpBeginEndRelative() throws IOException {
+ Path testBeginEndRelative = Paths.get("testBeginEndRelative.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEndRelative.toFile().getAbsolutePath(), "begin=-3h", "end=-0s");
+ Asserts.assertEquals(totalSize, Files.size(testBeginEndRelative), "Expected dump with begin=-3h end=0s to contain data from all recordings");
+ Files.delete(testBeginEndRelative);
+ }
+
+ private static void testDumpMaxAge() throws IOException {
+ Path testMaxAge = Paths.get("testMaxAge.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxAge.toFile().getAbsolutePath(), "maxage=2h");
+ Asserts.assertEquals(totalSize, Files.size(testMaxAge), "Expected dump with maxage=2h to contain data from all recordings");
+ Files.delete(testMaxAge);
+ }
+
+ private static void testDumpBeginEndSame() throws IOException {
+ Path testBeginEnd = Paths.get("testBeginEndSame.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + middle, "end=" + middle);
+ Asserts.assertEquals(middleSize, Files.size(testBeginEnd), "Expected dump with begin=" + middle + "end=" + middle + " contain data from middle recording");
+ Files.delete(testBeginEnd);
+ }
+
+ private static void testDumpBeginEndInstant() throws IOException {
+ Path testBeginEnd = Paths.get("testBeginEndInstant.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeft, "end=" + centerRight);
+ Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeft + " end=" + centerRight + " contain data from the 'center'-recordings");
+ Files.delete(testBeginEnd);
+ }
+
+ private static void testDumpBeginEndLocalDateTime() throws IOException {
+ LocalDateTime centerLeftLocal = LocalDateTime.ofInstant(centerLeft, ZoneOffset.systemDefault());
+ LocalDateTime centerRightLocal = LocalDateTime.ofInstant(centerRight, ZoneOffset.systemDefault());
+ Path testBeginEnd = Paths.get("testBeginEndLocalDateTime.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeftLocal, "end=" + centerRightLocal);
+ Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeftLocal + " end=" + centerRightLocal + " contain data from the 'center'-recordings");
+ Files.delete(testBeginEnd);
+ }
+
+ private static void testDumpBeginEndLocalTime() throws IOException {
+ LocalTime centerLeftLocal = LocalTime.ofInstant(centerLeft, ZoneOffset.systemDefault());
+ LocalTime centerRightLocal = LocalTime.ofInstant(centerRight, ZoneOffset.systemDefault());
+ Path testBeginEnd = Paths.get("testBeginEndLocalTime.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBeginEnd.toFile().getAbsolutePath(), "begin=" + centerLeftLocal, "end=" + centerRightLocal);
+ Asserts.assertEquals(centerSize, Files.size(testBeginEnd), "Expected dump with begin=" + centerLeftLocal + " end=" + centerRightLocal + " contain data from the 'center'-recordings");
+ Files.delete(testBeginEnd);
+ }
+
+ private static void testDumpEnd() throws IOException {
+ Path testEnd = Paths.get("testEnd.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testEnd.toFile().getAbsolutePath(), "end=" + middle);
+ Asserts.assertEquals(firstFiveSize, Files.size(testEnd), "Expected dump with end=" + middle + " to contain data from the five first recordings");
+ Files.delete(testEnd);
+ }
+
+ private static void testDumpBegin() throws IOException {
+ Path testBegin = Paths.get("testBegin.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testBegin.toFile().getAbsolutePath(), "begin=" + middle);
+ Asserts.assertEquals(lastFiveSize, Files.size(testBegin), "Expected dump with begin=" + middle + " to contain data from the last five recordings");
+ Files.delete(testBegin);
+ }
+
+ private static void testDumpMaxSize() throws IOException {
+ Path testMaxSize = Paths.get("testMaxSize.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxSize.toFile().getAbsolutePath(), "maxsize=" + lastFiveSize);
+ Asserts.assertEquals(lastFiveSize, Files.size(testMaxSize), "Expected dump with maxsize=" + lastFiveSize + " to contain data from the last five recordings");
+ Files.delete(testMaxSize);
+ }
+
+ private static void testDumpMaxSizeSmall() throws IOException {
+ Path testMaxSizeSmall = Paths.get("testMaxSizeSmall.jfr");
+ JcmdHelper.jcmd("JFR.dump", "filename=" + testMaxSizeSmall.toFile().getAbsolutePath(), "maxsize=1k");
+ Asserts.assertEquals(lastSize, Files.size(testMaxSizeSmall), "Expected dump with maxsize=1k to contain data from the last recording");
+ Files.delete(testMaxSizeSmall);
+ }
+
+ private static void testDump() throws IOException {
+ Path all = Paths.get("all.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + all.toFile().getAbsolutePath());
+ JcmdAsserts.assertRecordingDumpedToFile(output, all.toFile());
+ Asserts.assertEquals(totalSize, Files.size(all), "Expected dump to be sum of all recordings");
+ Files.delete(all);
+ }
+
+ private static void testDumpInvalidTime() throws Exception {
+ Path invalidTime = Paths.get("invalidTime.jfr");
+ OutputAnalyzer output = JcmdHelper.jcmd("JFR.dump", "filename=" + invalidTime.toFile().getAbsolutePath(), "begin=4711");
+ output.shouldContain("Dump failed, not a valid begin time.");
+ assertMissingFile(invalidTime);
+ }
+
+ private static void assertMissingFile(Path missing) throws Exception {
+ if (Files.exists(missing)) {
+ throw new Exception("Unexpected dumpfile found");
+ }
+ }
+
+}
--- a/test/jdk/jdk/jfr/jcmd/TestJcmdLegacy.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/jdk/jfr/jcmd/TestJcmdLegacy.java Mon Jun 25 09:48:06 2018 -0700
@@ -28,6 +28,7 @@
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
+import java.nio.file.Paths;
import jdk.jfr.Recording;
import jdk.jfr.consumer.RecordedEvent;
@@ -58,13 +59,13 @@
private static void testJcmd() throws Exception {
String name = "testLegacy";
- File p = new File(name + ".jfr");
+ Path p = Paths.get(name + ".jfr").toAbsolutePath().normalize();
OutputAnalyzer output = JcmdHelper.jcmd("JFR.start", "name=" + name, "settings=" + SETTINGS.getCanonicalPath());
JcmdAsserts.assertRecordingHasStarted(output);
JcmdHelper.waitUntilRunning(name);
- JcmdHelper.stopWriteToFileAndCheck(name, p);
- FileHelper.verifyRecording(p);
- verify(p.toPath());
+ JcmdHelper.stopWriteToFileAndCheck(name, p.toFile());
+ FileHelper.verifyRecording(p.toFile());
+ verify(p);
}
private static void testAPI() throws IOException, Exception {
--- a/test/jdk/jdk/jfr/jcmd/TestJcmdStartStopDefault.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/jdk/jfr/jcmd/TestJcmdStartStopDefault.java Mon Jun 25 09:48:06 2018 -0700
@@ -25,7 +25,8 @@
package jdk.jfr.jcmd;
-import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -43,7 +44,7 @@
public class TestJcmdStartStopDefault {
public static void main(String[] args) throws Exception {
- File recording = new File("TestJcmdStartStopDefault.jfr");
+ Path recording = Paths.get(".","TestJcmdStartStopDefault.jfr").toAbsolutePath().normalize();
OutputAnalyzer output = JcmdHelper.jcmd("JFR.start");
JcmdAsserts.assertRecordingHasStarted(output);
@@ -53,10 +54,10 @@
output = JcmdHelper.jcmd("JFR.dump",
"name=" + name,
- "filename=" + recording.getAbsolutePath());
- JcmdAsserts.assertRecordingDumpedToFile(output, name, recording);
+ "filename=" + recording);
+ JcmdAsserts.assertRecordingDumpedToFile(output, recording.toFile());
JcmdHelper.stopAndCheck(name);
- FileHelper.verifyRecording(recording);
+ FileHelper.verifyRecording(recording.toFile());
}
private static String parseRecordingName(OutputAnalyzer output) {
--- a/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/jdk/lambda/vm/InterfaceAccessFlagsTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -71,7 +71,8 @@
}
}
- @Test(groups = "vm_prototype")
+ /* excluded: 8187655 */
+ @Test(enabled=false, groups = "vm_prototype")
public void testPrivateMethodCall() {
testMethodCallWithFlag(AccessFlag.PRIVATE);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/DefaultModules.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8197532
+ * @modules jdk.compiler
+ * jdk.jlink
+ * jdk.zipfs
+ * @library src /lib/testlibrary
+ * @build java.json/*
+ * @run main DefaultModules
+ * @summary Test that all modules that export an API are in the set of modules
+ * resolved when compiling or running code on the class path
+ */
+
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.spi.ToolProvider;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+/**
+ * This test compiles and runs the following tests on the class path:
+ *
+ * TestRootModules.java.java - tests that every module that exports an API
+ * is resolved. Also tests that java.se is not resolved.
+ *
+ * TestJson.java - exercises APIs exported by the java.json module. The
+ * java.json module is not a Java SE module.
+ */
+
+public class DefaultModules {
+ private static final PrintStream out = System.out;
+
+ public static void main(String[] args) throws Exception {
+ String javaHome = System.getProperty("java.home");
+ String testSrc = System.getProperty("test.src");
+
+ // $JDK_HOME/bin/java TestModules.java
+ String source = Path.of(testSrc, "src", "TestRootModules.java").toString();
+ ProcessTools.executeTestJava(source)
+ .outputTo(System.out)
+ .errorTo(System.err)
+ .shouldHaveExitValue(0);
+
+ /**
+ * Create a run-time image containing java.se, java.json and the javac
+ * compiler. Use the run-time image to compile and run both
+ * TestModules.java and JsonTest.java
+ */
+ if (Files.exists(Path.of(javaHome, "jmods", "java.se.jmod"))) {
+ // jlink --add-modules java.se,java.json,jdk.compiler,jdk.zipfs
+ Path here = Path.of(".");
+ Path image = Files.createTempDirectory(here, "images").resolve("myimage");
+ ToolProvider jlink = ToolProvider.findFirst("jlink")
+ .orElseThrow(() -> new RuntimeException("jlink not found"));
+ int exitCode = jlink.run(System.out, System.err,
+ "--module-path", System.getProperty("test.module.path"),
+ "--add-modules", "java.se,java.json,jdk.compiler,jdk.zipfs",
+ "--output", image.toString());
+ if (exitCode != 0)
+ throw new RuntimeException("jlink failed");
+
+ // path to java launcher in run-time image
+ String javaLauncher = image.resolve("bin").resolve("java").toString();
+ if (System.getProperty("os.name").startsWith("Windows"))
+ javaLauncher += ".exe";
+
+ // $CUSTOM_JDK/bin/java TestRootModules.java
+ source = Path.of(testSrc, "src", "TestRootModules.java").toString();
+ out.format("Command line: [%s %s]%n", javaLauncher, source);
+ ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
+ .outputTo(System.out)
+ .errorTo(System.err)
+ .shouldHaveExitValue(0);
+
+ // $CUSTOM_JDK/bin/java TestJson.java
+ source = Path.of(testSrc, "src", "TestJson.java").toString();
+ out.format("Command line: [%s %s]%n", javaLauncher, source);
+ ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
+ .outputTo(System.out)
+ .errorTo(System.err)
+ .shouldHaveExitValue(0);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/TestJson.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, 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 javax.json.*;
+import java.io.InputStream;
+
+/**
+ * Exercise APIs exported by the java.json module
+ */
+
+public class TestJson {
+ public static void main(String[] args) {
+ JsonParser parser = Json.createParser(InputStream.nullInputStream());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/TestRootModules.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, 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.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+
+/**
+ * Test the set of modules in the boot layer includes all modules that export
+ * an API. Also test that java.se is not resolved.
+ */
+
+public class TestRootModules {
+ public static void main(String[] args) {
+ // all modules that export an API should be resolved
+ // For now, this test ignores the ModuleResolution attribute
+ ModuleLayer bootLayer = ModuleLayer.boot();
+ ModuleFinder.ofSystem().findAll().stream()
+ .map(ModuleReference::descriptor)
+ .filter(descriptor -> descriptor.exports()
+ .stream()
+ .filter(e -> !e.isQualified())
+ .findAny()
+ .isPresent())
+ .map(ModuleDescriptor::name)
+ .forEach(name -> {
+ if (!bootLayer.findModule(name).isPresent())
+ throw new RuntimeException(name + " not in boot layer");
+ });
+
+ // java.se should not be resolved
+ ModuleLayer.boot()
+ .findModule("java.se")
+ .map(m -> { throw new RuntimeException("java.se should not be resolved"); });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/javax/json/Json.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.json;
+
+import java.io.InputStream;
+
+public class Json {
+ private Json() { }
+
+ public static JsonParser createParser(InputStream in) {
+ return new JsonParser() { };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/javax/json/JsonParser.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.json;
+
+public interface JsonParser {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/module-info.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+module java.json {
+ exports javax.json;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/nio/Basic.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2018, 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
+ * @bug 8198372
+ * @modules jdk.net java.base/sun.nio.ch:+open
+ * @run testng Basic
+ * @summary Basic tests for jdk.nio.Channels
+ */
+
+import java.io.Closeable;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import jdk.nio.Channels;
+import jdk.nio.Channels.SelectableChannelCloser;
+
+import sun.nio.ch.IOUtil;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+@Test
+public class Basic {
+
+ /**
+ * A loopback connection
+ */
+ static class Connection implements Closeable {
+ private final SocketChannel sc1;
+ private final SocketChannel sc2;
+
+ private Connection(SocketChannel sc1, SocketChannel sc2) {
+ this.sc1 = sc1;
+ this.sc2 = sc2;
+ }
+
+ static Connection open() throws IOException {
+ try (ServerSocketChannel ssc = ServerSocketChannel.open()) {
+ InetAddress lb = InetAddress.getLoopbackAddress();
+ ssc.bind(new InetSocketAddress(lb, 0));
+ SocketChannel sc1 = SocketChannel.open(ssc.getLocalAddress());
+ SocketChannel sc2 = ssc.accept();
+ return new Connection(sc1, sc2);
+ }
+ }
+
+ SocketChannel channel1() {
+ return sc1;
+ }
+
+ SocketChannel channel2() {
+ return sc2;
+ }
+
+ public void close() throws IOException {
+ try {
+ sc1.close();
+ } finally {
+ sc2.close();
+ }
+ }
+ }
+
+ /**
+ * A SelectableChannelCloser that tracks if the implCloseChannel and
+ * implReleaseChannel methods are invoked
+ */
+ static class Closer implements SelectableChannelCloser {
+ int closeCount;
+ SelectableChannel invokedToClose;
+ int releaseCount;
+ SelectableChannel invokedToRelease;
+
+ @Override
+ public void implCloseChannel(SelectableChannel sc) {
+ closeCount++;
+ invokedToClose = sc;
+ }
+
+ @Override
+ public void implReleaseChannel(SelectableChannel sc) {
+ releaseCount++;
+ invokedToRelease = sc;
+ }
+ }
+
+ /**
+ * Basic test of channel registered with Selector
+ */
+ public void testSelect() throws IOException {
+ Selector sel = Selector.open();
+ try (Connection connection = Connection.open()) {
+
+ // create channel with the file descriptor from one end of the connection
+ FileDescriptor fd = getFD(connection.channel1());
+ SelectableChannel ch = Channels.readWriteSelectableChannel(fd, new Closer());
+
+ // register for read events, channel should not be selected
+ ch.configureBlocking(false);
+ SelectionKey key = ch.register(sel, SelectionKey.OP_READ);
+ int n = sel.selectNow();
+ assertTrue(n == 0);
+
+ // write bytes to other end of connection
+ SocketChannel peer = connection.channel2();
+ ByteBuffer msg = ByteBuffer.wrap("hello".getBytes("UTF-8"));
+ int nwrote = peer.write(msg);
+ assertTrue(nwrote >= 0);
+
+ // channel should be selected
+ n = sel.select();
+ assertTrue(n == 1);
+ assertTrue(sel.selectedKeys().contains(key));
+ assertTrue(key.isReadable());
+ assertFalse(key.isWritable());
+ sel.selectedKeys().clear();
+
+ // change interest set for writing, channel should be selected
+ key.interestOps(SelectionKey.OP_WRITE);
+ n = sel.select();
+ assertTrue(n == 1);
+ assertTrue(sel.selectedKeys().contains(key));
+ assertTrue(key.isWritable());
+ assertFalse(key.isReadable());
+ sel.selectedKeys().clear();
+
+ // change interest set for reading + writing, channel should be selected
+ key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ n = sel.select();
+ assertTrue(n == 1);
+ assertTrue(sel.selectedKeys().contains(key));
+ assertTrue(key.isWritable());
+ assertTrue(key.isReadable());
+ sel.selectedKeys().clear();
+
+ // change interest set to 0 to deregister, channel should not be selected
+ key.interestOps(0);
+ n = sel.selectNow();
+ assertTrue(n == 0);
+
+ } finally {
+ sel.close();
+ }
+ }
+
+ /**
+ * Test that the SelectableChannelCloser implCloseChannel method is invoked.
+ */
+ public void testImplCloseChannel() throws IOException {
+ try (Connection connection = Connection.open()) {
+ FileDescriptor fd = getFD(connection.channel1());
+ Closer closer = new Closer();
+ SelectableChannel ch = Channels.readWriteSelectableChannel(fd, closer);
+
+ // close channel twice, checking that the closer is invoked only once
+ for (int i=0; i<2; i++) {
+ ch.close();
+
+ // implCloseChannel should been invoked once
+ assertTrue(closer.closeCount == 1);
+ assertTrue(closer.invokedToClose == ch);
+
+ // implReleaseChannel should not have been invoked
+ assertTrue(closer.releaseCount == 0);
+ }
+ }
+ }
+
+ /**
+ * Test that the SelectableChannelCloser implReleaseChannel method is invoked.
+ */
+ public void testImplReleaseChannel() throws IOException {
+ Selector sel = Selector.open();
+ try (Connection connection = Connection.open()) {
+ FileDescriptor fd = getFD(connection.channel1());
+ Closer closer = new Closer();
+ SelectableChannel ch = Channels.readWriteSelectableChannel(fd, closer);
+
+ // register with Selector, invoking selectNow to ensure registered
+ ch.configureBlocking(false);
+ ch.register(sel, SelectionKey.OP_WRITE);
+ sel.selectNow();
+
+ // close channel
+ ch.close();
+
+ // implCloseChannel should have been invoked
+ assertTrue(closer.closeCount == 1);
+ assertTrue(closer.invokedToClose == ch);
+
+ // implReleaseChannel should not have been invoked
+ assertTrue(closer.releaseCount == 0);
+
+ // flush the selector
+ sel.selectNow();
+
+ // implReleaseChannel should have been invoked
+ assertTrue(closer.releaseCount == 1);
+ assertTrue(closer.invokedToRelease == ch);
+
+ } finally {
+ sel.close();
+ }
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testInvalidFileDescriptor() throws IOException {
+ FileDescriptor fd = IOUtil.newFD(-1);
+ Channels.readWriteSelectableChannel(fd, new SelectableChannelCloser() {
+ @Override
+ public void implCloseChannel(SelectableChannel sc) { }
+ @Override
+ public void implReleaseChannel(SelectableChannel sc) { }
+ });
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullFileDescriptor() throws IOException {
+ Channels.readWriteSelectableChannel(null, new SelectableChannelCloser() {
+ @Override
+ public void implCloseChannel(SelectableChannel sc) { }
+ @Override
+ public void implReleaseChannel(SelectableChannel sc) { }
+ });
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullCloser() throws IOException {
+ try (Connection connection = Connection.open()) {
+ FileDescriptor fd = getFD(connection.channel1());
+ Channels.readWriteSelectableChannel(fd, null);
+ }
+ }
+
+ private static FileDescriptor getFD(SocketChannel sc) {
+ try {
+ Class<?> clazz = sc.getClass();
+ Field f = clazz.getDeclaredField("fd");
+ f.setAccessible(true);
+ return (FileDescriptor) f.get(sc);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
--- a/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java Mon Jun 25 09:48:06 2018 -0700
@@ -39,6 +39,7 @@
import java.util.List;
import java.util.Random;
+import java.util.concurrent.CountDownLatch;
/*
* @test
@@ -93,6 +94,7 @@
// by setting the jdk.nio.maxCachedBufferSize property.
private static class Worker implements Runnable {
private final int id;
+ private final CountDownLatch finishLatch, exitLatch;
private final Random random = new Random();
private long smallBufferCount = 0;
private long largeBufferCount = 0;
@@ -152,6 +154,13 @@
}
} catch (IOException e) {
throw new Error("I/O error", e);
+ } finally {
+ finishLatch.countDown();
+ try {
+ exitLatch.await();
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
}
@@ -160,8 +169,10 @@
loop();
}
- public Worker(int id) {
+ public Worker(int id, CountDownLatch finishLatch, CountDownLatch exitLatch) {
this.id = id;
+ this.finishLatch = finishLatch;
+ this.exitLatch = exitLatch;
}
}
@@ -171,10 +182,6 @@
System.out.printf("Direct %d / %dK\n",
directCount, directTotalCapacity / 1024);
- // Note that directCount could be < expectedCount. This can
- // happen if a GC occurs after one of the worker threads exits
- // since its thread-local DirectByteBuffer could be cleaned up
- // before we reach here.
if (directCount > expectedCount) {
throw new Error(String.format(
"inconsistent direct buffer total count, expected = %d, found = %d",
@@ -208,46 +215,57 @@
threadNum, iters, maxBufferSize);
System.out.println();
+ final CountDownLatch finishLatch = new CountDownLatch(threadNum);
+ final CountDownLatch exitLatch = new CountDownLatch(1);
final Thread[] threads = new Thread[threadNum];
for (int i = 0; i < threadNum; i += 1) {
- threads[i] = new Thread(new Worker(i));
+ threads[i] = new Thread(new Worker(i, finishLatch, exitLatch));
threads[i].start();
}
try {
- for (int i = 0; i < threadNum; i += 1) {
- threads[i].join();
+ try {
+ finishLatch.await();
+ } catch (InterruptedException e) {
+ throw new Error("finishLatch.await() interrupted!", e);
}
- } catch (InterruptedException e) {
- throw new Error("join() interrupted!", e);
- }
- // There is an assumption here that, at this point, only the
- // cached DirectByteBuffers should be active. Given we
- // haven't used any other DirectByteBuffers in this test, this
- // should hold.
- //
- // Also note that we can only do the sanity checking at the
- // end and not during the run given that, at any time, there
- // could be buffers currently in use by some of the workers
- // that will not be cached.
+ // There is an assumption here that, at this point, only the
+ // cached DirectByteBuffers should be active. Given we
+ // haven't used any other DirectByteBuffers in this test, this
+ // should hold.
+ //
+ // Also note that we can only do the sanity checking at the
+ // end and not during the run given that, at any time, there
+ // could be buffers currently in use by some of the workers
+ // that will not be cached.
- System.out.println();
- if (maxBufferSize < SMALL_BUFFER_MAX_SIZE) {
- // The max buffer size is smaller than all buffers that
- // were allocated. No buffers should have been cached.
- checkDirectBuffers(0, 0);
- } else if (maxBufferSize < LARGE_BUFFER_MIN_SIZE) {
- // The max buffer size is larger than all small buffers
- // but smaller than all large buffers that were
- // allocated. Only small buffers could have been cached.
- checkDirectBuffers(threadNum,
- (long) threadNum * (long) SMALL_BUFFER_MAX_SIZE);
- } else {
- // The max buffer size is larger than all buffers that
- // were allocated. All buffers could have been cached.
- checkDirectBuffers(threadNum,
- (long) threadNum * (long) LARGE_BUFFER_MAX_SIZE);
+ System.out.println();
+ if (maxBufferSize < SMALL_BUFFER_MAX_SIZE) {
+ // The max buffer size is smaller than all buffers that
+ // were allocated. No buffers should have been cached.
+ checkDirectBuffers(0, 0);
+ } else if (maxBufferSize < LARGE_BUFFER_MIN_SIZE) {
+ // The max buffer size is larger than all small buffers
+ // but smaller than all large buffers that were
+ // allocated. Only small buffers could have been cached.
+ checkDirectBuffers(threadNum,
+ (long) threadNum * (long) SMALL_BUFFER_MAX_SIZE);
+ } else {
+ // The max buffer size is larger than all buffers that
+ // were allocated. All buffers could have been cached.
+ checkDirectBuffers(threadNum,
+ (long) threadNum * (long) LARGE_BUFFER_MAX_SIZE);
+ }
+ } finally {
+ exitLatch.countDown();
+ try {
+ for (int i = 0; i < threadNum; i += 1) {
+ threads[i].join();
+ }
+ } catch (InterruptedException e) {
+ // ignore
+ }
}
}
}
--- a/test/jdk/sun/security/ec/InvalidCurve.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/security/ec/InvalidCurve.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -40,7 +40,7 @@
try {
keyGen = KeyPairGenerator.getInstance("EC", "SunEC");
ECGenParameterSpec brainpoolSpec =
- new ECGenParameterSpec("brainpoolP256r1");
+ new ECGenParameterSpec("brainpoolP160r1");
keyGen.initialize(brainpoolSpec);
} catch (InvalidAlgorithmParameterException ex) {
System.out.println(ex.getMessage());
--- a/test/jdk/sun/security/krb5/auto/KDC.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/security/krb5/auto/KDC.java Mon Jun 25 09:48:06 2018 -0700
@@ -713,10 +713,10 @@
/**
* Returns a KerberosTime.
*
- * @param offset offset from NOW in milliseconds
+ * @param offset offset from NOW in seconds
*/
- private static KerberosTime timeFor(long offset) {
- return new KerberosTime(new Date().getTime() + offset);
+ private static KerberosTime timeAfter(int offset) {
+ return new KerberosTime(new Date().getTime() + offset * 1000L);
}
/**
@@ -832,12 +832,12 @@
KerberosTime from = body.from;
KerberosTime till = body.till;
if (from == null || from.isZero()) {
- from = timeFor(0);
+ from = timeAfter(0);
}
if (till == null) {
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
} else if (till.isZero()) {
- till = timeFor(1000 * DEFAULT_LIFETIME);
+ till = timeAfter(DEFAULT_LIFETIME);
}
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
@@ -863,7 +863,7 @@
}
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
- //renew = timeFor(1000 * 3600 * 24 * 7);
+ //renew = timeAfter(3600 * 24 * 7);
}
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
@@ -933,7 +933,7 @@
key,
cname,
new TransitedEncoding(1, new byte[0]), // TODO
- timeFor(0),
+ timeAfter(0),
from,
till, renewTill,
body.addresses != null ? body.addresses
@@ -952,13 +952,13 @@
EncTGSRepPart enc_part = new EncTGSRepPart(
key,
new LastReq(new LastReqEntry[] {
- new LastReqEntry(0, timeFor(-10000))
+ new LastReqEntry(0, timeAfter(-10))
}),
body.getNonce(), // TODO: detect replay
- timeFor(1000 * 3600 * 24),
+ timeAfter(3600 * 24),
// Next 5 and last MUST be same with ticket
tFlags,
- timeFor(0),
+ timeAfter(0),
from,
till, renewTill,
service,
@@ -986,7 +986,7 @@
+ " " +ke.returnCodeMessage());
if (kerr == null) {
kerr = new KRBError(null, null, null,
- timeFor(0),
+ timeAfter(0),
0,
ke.returnCode(),
body.cname,
@@ -1059,20 +1059,21 @@
KerberosTime till = body.till;
KerberosTime rtime = body.rtime;
if (from == null || from.isZero()) {
- from = timeFor(0);
+ from = timeAfter(0);
}
if (till == null) {
throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
} else if (till.isZero()) {
- till = timeFor(1000 * DEFAULT_LIFETIME);
- } else if (till.greaterThan(timeFor(24 * 3600 * 1000))) {
+ till = timeAfter(DEFAULT_LIFETIME);
+ } else if (till.greaterThan(timeAfter(24 * 3600))
+ && System.getProperty("test.kdc.force.till") == null) {
// If till is more than 1 day later, make it renewable
- till = timeFor(1000 * DEFAULT_LIFETIME);
+ till = timeAfter(DEFAULT_LIFETIME);
body.kdcOptions.set(KDCOptions.RENEWABLE, true);
if (rtime == null) rtime = till;
}
if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
- rtime = timeFor(1000 * DEFAULT_RENEWTIME);
+ rtime = timeAfter(DEFAULT_RENEWTIME);
}
//body.from
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
@@ -1088,7 +1089,7 @@
}
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
- //renew = timeFor(1000 * 3600 * 24 * 7);
+ //renew = timeAfter(3600 * 24 * 7);
}
if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
@@ -1234,7 +1235,7 @@
key,
body.cname,
new TransitedEncoding(1, new byte[0]),
- timeFor(0),
+ timeAfter(0),
from,
till, rtime,
body.addresses,
@@ -1246,13 +1247,13 @@
EncASRepPart enc_part = new EncASRepPart(
key,
new LastReq(new LastReqEntry[]{
- new LastReqEntry(0, timeFor(-10000))
+ new LastReqEntry(0, timeAfter(-10))
}),
body.getNonce(), // TODO: detect replay?
- timeFor(1000 * 3600 * 24),
+ timeAfter(3600 * 24),
// Next 5 and last MUST be same with ticket
tFlags,
- timeFor(0),
+ timeAfter(0),
from,
till, rtime,
service,
@@ -1314,7 +1315,7 @@
eData = temp.toByteArray();
}
kerr = new KRBError(null, null, null,
- timeFor(0),
+ timeAfter(0),
0,
ke.returnCode(),
body.cname,
--- a/test/jdk/sun/security/krb5/auto/LongLife.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/security/krb5/auto/LongLife.java Mon Jun 25 09:48:06 2018 -0700
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8131051 8194486
+ * @bug 8131051 8194486 8187218
* @summary KDC might issue a renewable ticket even if not requested
* @library /test/lib
* @compile -XDignore.symbol.file LongLife.java
@@ -31,7 +31,12 @@
* @run main/othervm -Djdk.net.hosts.file=TestHosts LongLife
*/
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSManager;
import sun.security.krb5.Config;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+import java.security.PrivilegedExceptionAction;
public class LongLife {
@@ -39,11 +44,53 @@
OneKDC kdc = new OneKDC(null).writeJAASConf();
- // A lifetime 2d will make it renewable
+ test(kdc, "10h", false, 36000, false);
+ test(kdc, "2d", false, KDC.DEFAULT_LIFETIME, true);
+ test(kdc, "2d", true, 2 * 24 * 3600, false);
+
+ // 8187218: getRemainingLifetime() is negative if lifetime
+ // is longer than 30 days.
+ test(kdc, "30d", true, 30 * 24 * 3600, false);
+ }
+
+ static void test(
+ KDC kdc,
+ String ticketLifetime,
+ boolean forceTill, // if true, KDC will not try RENEWABLE
+ int expectedLifeTime,
+ boolean expectedRenewable) throws Exception {
+
KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
- "ticket_lifetime = 2d");
+ "ticket_lifetime = " + ticketLifetime);
Config.refresh();
- Context.fromJAAS("client");
+ if (forceTill) {
+ System.setProperty("test.kdc.force.till", "");
+ } else {
+ System.clearProperty("test.kdc.force.till");
+ }
+
+ Context c = Context.fromJAAS("client");
+
+ GSSCredential cred = Subject.doAs(c.s(),
+ (PrivilegedExceptionAction<GSSCredential>)
+ ()-> {
+ GSSManager m = GSSManager.getInstance();
+ return m.createCredential(GSSCredential.INITIATE_ONLY);
+ });
+
+ KerberosTicket tgt = c.s().getPrivateCredentials(KerberosTicket.class)
+ .iterator().next();
+ System.out.println(tgt);
+
+ int actualLifeTime = cred.getRemainingLifetime();
+ if (actualLifeTime < expectedLifeTime - 60
+ || actualLifeTime > expectedLifeTime + 60) {
+ throw new Exception("actualLifeTime is " + actualLifeTime);
+ }
+
+ if (tgt.isRenewable() != expectedRenewable) {
+ throw new Exception("TGT's RENEWABLE flag is " + tgt.isRenewable());
+ }
}
}
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java Mon Jun 25 09:48:06 2018 -0700
@@ -47,6 +47,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
@@ -576,21 +577,8 @@
}
curve = kcProp.substring(begin, end);
- ECParameterSpec e = getECParameterSpec(p, curve);
- System.out.print("\t "+ curve + ": ");
- try {
- KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
- kpg.initialize(e);
- kpg.generateKeyPair();
- results.add(e);
- System.out.println("Supported");
- } catch (ProviderException ex) {
- System.out.println("Unsupported: PKCS11: " +
- ex.getCause().getMessage());
- } catch (InvalidAlgorithmParameterException ex) {
- System.out.println("Unsupported: Key Length: " +
- ex.getMessage());
- }
+ getSupportedECParameterSpec(curve, p)
+ .ifPresent(spec -> results.add(spec));
}
if (results.size() == 0) {
@@ -600,6 +588,27 @@
return results;
}
+ static Optional<ECParameterSpec> getSupportedECParameterSpec(String curve,
+ Provider p) throws Exception {
+ ECParameterSpec e = getECParameterSpec(p, curve);
+ System.out.print("\t "+ curve + ": ");
+ try {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p);
+ kpg.initialize(e);
+ kpg.generateKeyPair();
+ System.out.println("Supported");
+ return Optional.of(e);
+ } catch (ProviderException ex) {
+ System.out.println("Unsupported: PKCS11: " +
+ ex.getCause().getMessage());
+ return Optional.empty();
+ } catch (InvalidAlgorithmParameterException ex) {
+ System.out.println("Unsupported: Key Length: " +
+ ex.getMessage());
+ return Optional.empty();
+ }
+ }
+
private static ECParameterSpec getECParameterSpec(Provider p, String name)
throws Exception {
--- a/test/jdk/sun/security/pkcs11/ec/TestECDH.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/sun/security/pkcs11/ec/TestECDH.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -61,8 +61,37 @@
private final static String secret163 = "04:ae:71:c1:c6:4d:f4:34:4d:72:70:a4:64:65:7f:2d:88:2d:3f:50:be";
- @Override
- public void main(Provider p) throws Exception {
+
+ // from https://tools.ietf.org/html/rfc7027#appendix-A.1
+ private final static String pubBrainpoolP256r1a = "305a301406072a8648ce3d020106092b24030302080101070342000444106e913f92bc02a1705d9953a8414db95e1aaa49e81d9e85f929a8e3100be58ab4846f11caccb73ce49cbdd120f5a900a69fd32c272223f789ef10eb089bdc";
+ private final static String privBrainpoolP256r1a = "3042020100301406072a8648ce3d020106092b240303020801010704273025020101042081db1ee100150ff2ea338d708271be38300cb54241d79950f77b063039804f1d";
+ private final static String pubBrainpoolP256r1b = "305a301406072a8648ce3d020106092b2403030208010107034200048d2d688c6cf93e1160ad04cc4429117dc2c41825e1e9fca0addd34e6f1b39f7b990c57520812be512641e47034832106bc7d3e8dd0e4c7f1136d7006547cec6a";
+ private final static String privBrainpoolP256r1b = "3042020100301406072a8648ce3d020106092b240303020801010704273025020101042055e40bc41e37e3e2ad25c3c6654511ffa8474a91a0032087593852d3e7d76bd3";
+ private final static String secretBrainpoolP256r1 = "89afc39d41d3b327814b80940b042590f96556ec91e6ae7939bce31f3a18bf2b";
+
+ // from https://tools.ietf.org/html/draft-merkle-ikev2-ke-brainpool-00#appendix-A.5
+ private final static String pubBrainpoolP320r1a = "306a301406072a8648ce3d020106092b240303020801010903520004bc43666c00e4b943fe1c785dd8aa842a42ab54b0b49819f960f77694193cd3afa71b6b3c826c773469e998892c0764468023c8e3a7b8f219a1446042be175d4476b2fdfd85b22ead2f29101a1242a578";
+ private final static String privBrainpoolP320r1a = "304a020100301406072a8648ce3d020106092b2403030208010109042f302d02010104287cd9c454ba907f7617e262a7fd73764c4a3157c13f82279ef9f062be5d49a8e390b66a4dcedfa867";
+ private final static String pubBrainpoolP320r1b = "306a301406072a8648ce3d020106092b240303020801010903520004b1246229429354d1d687bca48bccd6fc733b146dac03642a0ad4b896f5d8bcbd2f4bca16776e4526a41683898f9a76ef36ea2dc7b74d419e55cf3664721890d6a2b2fb8ceb7c113167ed137a358ee37f";
+ private final static String privBrainpoolP320r1b = "304a020100301406072a8648ce3d020106092b2403030208010109042f302d0201010428b832a73da5f671e80d87f09372544801f6812224b19a4bc1b37aa7db0842e6dd3ca11de0f802bfed";
+ private final static String secretBrainpoolP320r1 = "730314d906b2f21dc11be05031b028d665696beec7139328cdf70c718be5d208659bb96743a88067";
+
+ // from https://tools.ietf.org/html/rfc7027#appendix-A.2
+ private final static String pubBrainpoolP384r1a = "307a301406072a8648ce3d020106092b240303020801010b0362000468b665dd91c195800650cdd363c625f4e742e8134667b767b1b476793588f885ab698c852d4a6e77a252d6380fcaf06855bc91a39c9ec01dee36017b7d673a931236d2f1f5c83942d049e3fa20607493e0d038ff2fd30c2ab67d15c85f7faa59";
+ private final static String privBrainpoolP384r1a = "3052020100301406072a8648ce3d020106092b240303020801010b0437303502010104301e20f5e048a5886f1f157c74e91bde2b98c8b52d58e5003d57053fc4b0bd65d6f15eb5d1ee1610df870795143627d042";
+ private final static String pubBrainpoolP384r1b = "307a301406072a8648ce3d020106092b240303020801010b036200044d44326f269a597a5b58bba565da5556ed7fd9a8a9eb76c25f46db69d19dc8ce6ad18e404b15738b2086df37e71d1eb462d692136de56cbe93bf5fa3188ef58bc8a3a0ec6c1e151a21038a42e9185329b5b275903d192f8d4e1f32fe9cc78c48";
+ private final static String privBrainpoolP384r1b = "3052020100301406072a8648ce3d020106092b240303020801010b043730350201010430032640bc6003c59260f7250c3db58ce647f98e1260acce4acda3dd869f74e01f8ba5e0324309db6a9831497abac96670";
+ private final static String secretBrainpoolP384r1 = "0bd9d3a7ea0b3d519d09d8e48d0785fb744a6b355e6304bc51c229fbbce239bbadf6403715c35d4fb2a5444f575d4f42";
+
+
+ // from https://tools.ietf.org/html/rfc7027#appendix-A.3
+ private final static String pubBrainpoolP512r1a = "30819b301406072a8648ce3d020106092b240303020801010d03818200040a420517e406aac0acdce90fcd71487718d3b953efd7fbec5f7f27e28c6149999397e91e029e06457db2d3e640668b392c2a7e737a7f0bf04436d11640fd09fd72e6882e8db28aad36237cd25d580db23783961c8dc52dfa2ec138ad472a0fcef3887cf62b623b2a87de5c588301ea3e5fc269b373b60724f5e82a6ad147fde7";
+ private final static String privBrainpoolP512r1a = "3062020100301406072a8648ce3d020106092b240303020801010d04473045020101044016302ff0dbbb5a8d733dab7141c1b45acbc8715939677f6a56850a38bd87bd59b09e80279609ff333eb9d4c061231fb26f92eeb04982a5f1d1764cad57665422";
+ private final static String pubBrainpoolP512r1b = "30819b301406072a8648ce3d020106092b240303020801010d03818200049d45f66de5d67e2e6db6e93a59ce0bb48106097ff78a081de781cdb31fce8ccbaaea8dd4320c4119f1e9cd437a2eab3731fa9668ab268d871deda55a5473199f2fdc313095bcdd5fb3a91636f07a959c8e86b5636a1e930e8396049cb481961d365cc11453a06c719835475b12cb52fc3c383bce35e27ef194512b71876285fa";
+ private final static String privBrainpoolP512r1b = "3062020100301406072a8648ce3d020106092b240303020801010d044730450201010440230e18e1bcc88a362fa54e4ea3902009292f7f8033624fd471b5d8ace49d12cfabbc19963dab8e2f1eba00bffb29e4d72d13f2224562f405cb80503666b25429";
+ private final static String secretBrainpoolP512r1 = "a7927098655f1f9976fa50a9d566865dc530331846381c87256baf3226244b76d36403c024d7bbf0aa0803eaff405d3d24f11a9b5c0bef679fe1454b21c4cd1f";
+
+ @Override public void main(Provider p) throws Exception {
if (p.getService("KeyAgreement", "ECDH") == null) {
System.out.println("Provider does not support ECDH, skipping");
return;
@@ -93,6 +122,19 @@
test(p, pub192a, priv192a, pub192b, priv192b, secret192);
test(p, pub163a, priv163a, pub163b, priv163b, secret163);
+ if (getSupportedECParameterSpec("brainpoolP256r1", p).isPresent()) {
+ test(p, pubBrainpoolP256r1a, privBrainpoolP256r1a, pubBrainpoolP256r1b, privBrainpoolP256r1b, secretBrainpoolP256r1);
+ }
+ if (getSupportedECParameterSpec("brainpoolP320r1", p).isPresent()) {
+ test(p, pubBrainpoolP320r1a, privBrainpoolP320r1a, pubBrainpoolP320r1b, privBrainpoolP320r1b, secretBrainpoolP320r1);
+ }
+ if (getSupportedECParameterSpec("brainpoolP384r1", p).isPresent()) {
+ test(p, pubBrainpoolP384r1a, privBrainpoolP384r1a, pubBrainpoolP384r1b, privBrainpoolP384r1b, secretBrainpoolP384r1);
+ }
+ if (getSupportedECParameterSpec("brainpoolP512r1", p).isPresent()) {
+ test(p, pubBrainpoolP512r1a, privBrainpoolP512r1a, pubBrainpoolP512r1b, privBrainpoolP512r1b, secretBrainpoolP512r1);
+ }
+
System.out.println("OK");
}
--- a/test/jdk/tools/pack200/BandIntegrity.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/tools/pack200/BandIntegrity.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -22,7 +22,7 @@
*/
/*
- * @test
+ * @test 8187645
* @summary test ensures the proper sequencing of bands, dump bands as well.
* @compile -XDignore.symbol.file Utils.java BandIntegrity.java
* @run main BandIntegrity
--- a/test/jdk/tools/pack200/pack200-verifier/make/build.xml Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/tools/pack200/pack200-verifier/make/build.xml Mon Jun 25 09:48:06 2018 -0700
@@ -22,18 +22,18 @@
<target name="compile" depends="init">
<!-- Compile the java code from ${src} into ${build} -->
<javac
- source="1.8"
+ source="1.9"
srcdir="${src}"
destdir="${build}/classes"
verbose="no"
debug="on">
- <compilerarg value="--add-exports=jdk.jdeps/com.sun.tools.classfile"/>
+ <compilerarg line="--add-exports jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED"/>
</javac>
</target>
<target name="doc" depends="init, compile">
<javadoc
- source="1.8"
+ source="1.9"
sourcepath="${src}"
destdir="${api}"
/>
--- a/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/jdk/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, 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
@@ -85,6 +85,8 @@
import com.sun.tools.classfile.ModuleResolution_attribute;
import com.sun.tools.classfile.ModuleTarget_attribute;
import com.sun.tools.classfile.ModulePackages_attribute;
+import com.sun.tools.classfile.NestHost_attribute;
+import com.sun.tools.classfile.NestMembers_attribute;
import com.sun.tools.classfile.Opcode;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
@@ -1566,6 +1568,30 @@
p.add(e);
return null;
}
+
+ @Override
+ public Element visitNestHost(NestHost_attribute attr, Element p) {
+ String aname = x.getCpString(attr.attribute_name_index);
+ String hname = x.getCpString(attr.top_index);
+ Element se = new Element(aname);
+ se.add(hname);
+ se.trimToSize();
+ p.add(se);
+ return null;
+ }
+
+ @Override
+ public Element visitNestMembers(NestMembers_attribute attr, Element p) {
+ Element ee = new Element(x.getCpString(attr.attribute_name_index));
+ for (int idx : attr.members_indexes) {
+ Element n = new Element("Item");
+ n.setAttr("class", x.getCpString(idx));
+ ee.add(n);
+ }
+ ee.trimToSize();
+ p.add(ee);
+ return null;
+ }
}
class StackMapVisitor implements StackMapTable_attribute.stack_map_frame.Visitor<Element, Void> {
--- a/test/langtools/jdk/jshell/ClassesTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/jdk/jshell/ClassesTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8145239 8129559 8080354 8189248
+ * @bug 8145239 8129559 8080354 8189248 8010319
* @summary Tests for EvaluationState.classes
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng ClassesTest
@@ -308,7 +308,7 @@
public void testInnerClassesCrash() {
Snippet a = classKey(assertEval("class A { class B extends A {} }"));
Snippet a2 = classKey(assertEval("class A { interface I1 extends I2 {} interface I2 {} }",
- ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
assertEval("class A { A a = new A() {}; }",
ste(MAIN_SNIPPET, VALID, VALID, true, null),
--- a/test/langtools/jdk/jshell/ForwardReferenceTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/jdk/jshell/ForwardReferenceTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -22,7 +22,7 @@
*/
/*
- * @test 8173232
+ * @test 8173232 8010319
* @summary Test of forward referencing of snippets.
* @build KullaTesting TestingInputStream
* @run testng ForwardReferenceTest
@@ -315,7 +315,7 @@
Snippet f = methodKey(assertEval("void f() { class A {} g(); }", added(RECOVERABLE_DEFINED)));
assertEval("void g() {}",
added(VALID),
- ste(f, RECOVERABLE_DEFINED, VALID, false, null));
+ ste(f, RECOVERABLE_DEFINED, VALID, true, null));
assertEval("f();", "");
}
}
--- a/test/langtools/jdk/jshell/GetResourceTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/jdk/jshell/GetResourceTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8179531
+ * @bug 8179531 8010319
* @summary Check that ClassLoader.getResource works as expected in the JShell agent.
* @modules jdk.jshell
* @build KullaTesting TestingInputStream
@@ -80,7 +80,7 @@
null,
DiagCheck.DIAG_OK,
DiagCheck.DIAG_OK,
- ste(MAIN_SNIPPET, VALID, VALID, false, null),
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(testMethod, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
assertEval("test()", "true");
}
--- a/test/langtools/lib/annotations/annotations/classfile/ClassfileInspector.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/lib/annotations/annotations/classfile/ClassfileInspector.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -1253,6 +1253,11 @@
}
@Override
+ public Void visitNestHost(NestHost_attribute attr, T p) {
+ return null;
+ }
+
+ @Override
public Void visitMethodParameters(MethodParameters_attribute attr, T p) {
return null;
}
@@ -1288,6 +1293,11 @@
}
@Override
+ public Void visitNestMembers(NestMembers_attribute attr, T p) {
+ return null;
+ }
+
+ @Override
public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, T p) {
return null;
}
--- a/test/langtools/tools/javac/6917288/GraphicalInstallerTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/6917288/GraphicalInstallerTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, 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
@@ -47,7 +47,6 @@
}
check(classes,
- "GraphicalInstaller$1.class",
"GraphicalInstaller$1X$1.class",
"GraphicalInstaller$1X.class",
"GraphicalInstaller$BackgroundInstaller.class",
--- a/test/langtools/tools/javac/6917288/T6917288.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/6917288/T6917288.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, 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
@@ -69,7 +69,14 @@
return;
}
- check(classesDir, "Test.class", "Test$Inner.class", "Test$1.class");
+ switch (k) {
+ case ALWAYS:
+ case TRUE:
+ check(classesDir, "Test.class", "Test$Inner.class", "Test$1.class");
+ break;
+ default:
+ check(classesDir, "Test.class", "Test$Inner.class");
+ }
}
/**
--- a/test/langtools/tools/javac/7199823/InnerClassCannotBeVerified.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/7199823/InnerClassCannotBeVerified.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -29,6 +29,7 @@
* @run main InnerClassCannotBeVerified
*/
+import java.nio.file.NoSuchFileException;
import java.util.Arrays;
import javax.tools.JavaFileObject;
import java.net.URI;
@@ -43,6 +44,17 @@
public class InnerClassCannotBeVerified {
+ enum CompilationKind {
+ PRE_NESTMATES("-source", "10", "-target", "10"),
+ POST_NESTMATES();
+
+ String[] opts;
+
+ CompilationKind(String... opts) {
+ this.opts = opts;
+ }
+ }
+
private static final String errorMessage =
"Compile error while compiling the following source:\n";
@@ -51,34 +63,49 @@
}
void run() throws Exception {
- JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
- JavaSource source = new JavaSource();
- JavacTask ct = (JavacTask)comp.getTask(null, null, null,
- null, null, Arrays.asList(source));
- try {
- if (!ct.call()) {
+ for (CompilationKind ck : CompilationKind.values()) {
+ File file = new File("Test$1.class");
+ if (file.exists()) {
+ file.delete();
+ }
+ JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
+ JavaSource source = new JavaSource();
+ JavacTask ct = (JavacTask)comp.getTask(null, null, null,
+ Arrays.asList(ck.opts), null, Arrays.asList(source));
+ try {
+ if (!ct.call()) {
+ throw new AssertionError(errorMessage +
+ source.getCharContent(true));
+ }
+ } catch (Throwable ex) {
throw new AssertionError(errorMessage +
source.getCharContent(true));
}
- } catch (Throwable ex) {
- throw new AssertionError(errorMessage +
- source.getCharContent(true));
+ check(ck);
}
- check();
}
- private void check() throws IOException, ConstantPoolException {
- File file = new File("Test$1.class");
- ClassFile classFile = ClassFile.read(file);
- boolean inheritsFromObject =
- classFile.getSuperclassName().equals("java/lang/Object");
- boolean implementsNoInterface = classFile.interfaces.length == 0;
- boolean noMethods = classFile.methods.length == 0;
- if (!(inheritsFromObject &&
- implementsNoInterface &&
- noMethods)) {
- throw new AssertionError("The inner classes reused as " +
- "access constructor tag for this code must be empty");
+ private void check(CompilationKind ck) throws IOException, ConstantPoolException {
+ try {
+ File file = new File("Test$1.class");
+ ClassFile classFile = ClassFile.read(file);
+ if (ck == CompilationKind.POST_NESTMATES) {
+ throw new AssertionError("Unexpected constructor tag class!");
+ }
+ boolean inheritsFromObject =
+ classFile.getSuperclassName().equals("java/lang/Object");
+ boolean implementsNoInterface = classFile.interfaces.length == 0;
+ boolean noMethods = classFile.methods.length == 0;
+ if (!(inheritsFromObject &&
+ implementsNoInterface &&
+ noMethods)) {
+ throw new AssertionError("The inner classes reused as " +
+ "access constructor tag for this code must be empty");
+ }
+ } catch (NoSuchFileException ex) {
+ if (ck == CompilationKind.PRE_NESTMATES) {
+ throw new AssertionError("Constructor tag class missing!");
+ }
}
}
--- a/test/langtools/tools/javac/MethodParameters/AttributeVisitor.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/MethodParameters/AttributeVisitor.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -42,6 +42,7 @@
public R visitLineNumberTable(LineNumberTable_attribute attr, P p) { return null; }
public R visitLocalVariableTable(LocalVariableTable_attribute attr, P p) { return null; }
public R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p) { return null; }
+ public R visitNestHost(NestHost_attribute attr, P p) { return null; }
public R visitMethodParameters(MethodParameters_attribute attr, P p) { return null; }
public R visitModule(Module_attribute attr, P p) { return null; }
public R visitModuleHashes(ModuleHashes_attribute attr, P p) { return null; }
@@ -49,6 +50,7 @@
public R visitModulePackages(ModulePackages_attribute attr, P p) { return null; }
public R visitModuleResolution(ModuleResolution_attribute attr, P p) { return null; }
public R visitModuleTarget(ModuleTarget_attribute attr, P p) { return null; }
+ public R visitNestMembers(NestMembers_attribute attr, P p) { return null; }
public R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p) { return null; }
public R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p) { return null; }
--- a/test/langtools/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/SourceFile/SyntheticClassTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -30,14 +30,30 @@
* jdk.compiler/com.sun.tools.javac.main
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox InMemoryFileManager TestBase SourceFileTestBase
- * @run main SyntheticClassTest
+ * @compile -source 10 -target 10 SyntheticClassTest.java
+ * @run main SyntheticClassTest true
+ * @clean SyntheticClassTest$1
+ * @compile SyntheticClassTest.java
+ * @run main SyntheticClassTest false
*/
+import java.nio.file.NoSuchFileException;
+
public class SyntheticClassTest extends SourceFileTestBase {
public static void main(String[] args) throws Exception {
+ boolean expectSynthetic = Boolean.parseBoolean(args[0]);
new Inner();
- new SyntheticClassTest().test("SyntheticClassTest$1", "SyntheticClassTest.java");
+ try {
+ new SyntheticClassTest().test("SyntheticClassTest$1", "SyntheticClassTest.java");
+ if (!expectSynthetic) {
+ throw new AssertionError("Synthetic class should not have been emitted!");
+ }
+ } catch (NoSuchFileException ex) {
+ if (expectSynthetic) {
+ throw new AssertionError("Synthetic class should have been emitted!");
+ }
+ }
}
static class Inner {
--- a/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassConstructorsTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassConstructorsTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -31,7 +31,7 @@
* @library /tools/lib /tools/javac/lib ../lib
* @build toolbox.ToolBox InMemoryFileManager TestResult
* @build AccessToPrivateInnerClassConstructorsTest SyntheticTestDriver ExpectedClass ExpectedClasses
- * @run main SyntheticTestDriver AccessToPrivateInnerClassConstructorsTest 1
+ * @run main SyntheticTestDriver AccessToPrivateInnerClassConstructorsTest 0
* @run main AccessToPrivateInnerClassConstructorsTest
*/
@@ -45,7 +45,7 @@
"<init>(AccessToPrivateInnerClassConstructorsTest, " +
"AccessToPrivateInnerClassConstructorsTest$1)"},
expectedNumberOfSyntheticFields = 1,
- expectedNumberOfSyntheticMethods = 2)
+ expectedNumberOfSyntheticMethods = 0)
@ExpectedClass(className = "AccessToPrivateInnerClassConstructorsTest$1Local",
expectedMethods = {"<init>(AccessToPrivateInnerClassConstructorsTest)"},
expectedNumberOfSyntheticFields = 1)
--- a/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateInnerClassMembersTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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,7 @@
* @library /tools/lib /tools/javac/lib ../lib
* @build toolbox.ToolBox InMemoryFileManager TestResult
* @build AccessToPrivateInnerClassMembersTest SyntheticTestDriver ExpectedClass ExpectedClasses
- * @run main SyntheticTestDriver AccessToPrivateInnerClassMembersTest 1
+ * @run main SyntheticTestDriver AccessToPrivateInnerClassMembersTest
*/
/**
@@ -51,12 +51,10 @@
@ExpectedClass(className = "AccessToPrivateInnerClassMembersTest$Inner1",
expectedMethods = {"<init>(AccessToPrivateInnerClassMembersTest)", "function()"},
expectedFields = "var",
- expectedNumberOfSyntheticMethods = 4,
expectedNumberOfSyntheticFields = 1)
@ExpectedClass(className = "AccessToPrivateInnerClassMembersTest$Inner2",
expectedMethods = {"function()", "staticFunction()", "<init>()"},
- expectedFields = {"staticVar", "var"},
- expectedNumberOfSyntheticMethods = 7)
+ expectedFields = {"staticVar", "var"})
public class AccessToPrivateInnerClassMembersTest {
private class Inner1 {
--- a/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/Synthetic/AccessToPrivateSiblingsTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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,7 @@
* @library /tools/lib /tools/javac/lib ../lib
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build AccessToPrivateSiblingsTest SyntheticTestDriver ExpectedClass ExpectedClasses
- * @run main SyntheticTestDriver AccessToPrivateSiblingsTest 1
+ * @run main SyntheticTestDriver AccessToPrivateSiblingsTest
*/
/**
@@ -50,19 +50,16 @@
@ExpectedClass(className = "AccessToPrivateSiblingsTest$Inner1",
expectedMethods = {"function()", "<init>(AccessToPrivateSiblingsTest)"},
expectedFields = "var",
- expectedNumberOfSyntheticMethods = 4,
expectedNumberOfSyntheticFields = 1)
@ExpectedClass(className = "AccessToPrivateSiblingsTest$Inner2",
expectedMethods = "<init>(AccessToPrivateSiblingsTest)",
expectedNumberOfSyntheticFields = 1)
@ExpectedClass(className = "AccessToPrivateSiblingsTest$Inner3",
expectedMethods = {"<init>()", "function()", "staticFunction()", "<clinit>()"},
- expectedFields = {"var", "staticVar"},
- expectedNumberOfSyntheticMethods = 4)
+ expectedFields = {"var", "staticVar"})
@ExpectedClass(className = "AccessToPrivateSiblingsTest$Inner4",
expectedMethods = {"<init>()", "function()", "staticFunction()"},
- expectedFields = {"var", "staticVar"},
- expectedNumberOfSyntheticMethods = 4)
+ expectedFields = {"var", "staticVar"})
public class AccessToPrivateSiblingsTest {
private class Inner1 {
--- a/test/langtools/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/Synthetic/BridgeMethodsForLambdaTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -33,7 +33,7 @@
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build SyntheticTestDriver ExpectedClass ExpectedClasses
* @compile -XDdeduplicateLambdas=false BridgeMethodsForLambdaTest.java
- * @run main SyntheticTestDriver BridgeMethodsForLambdaTest 1
+ * @run main SyntheticTestDriver BridgeMethodsForLambdaTest
*/
import java.util.Comparator;
@@ -59,15 +59,14 @@
@ExpectedClass(className = "BridgeMethodsForLambdaTest$Inner1",
expectedMethods = {"<init>(BridgeMethodsForLambdaTest)", "function()", "run()"},
expectedFields = "lambda1",
- expectedNumberOfSyntheticMethods = 4,
+ expectedNumberOfSyntheticMethods = 1,
expectedNumberOfSyntheticFields = 1)
@ExpectedClass(className = "BridgeMethodsForLambdaTest$Inner2",
expectedMethods = {"<init>()", "staticFunction()"},
expectedFields = "lambda1",
- expectedNumberOfSyntheticMethods = 3)
+ expectedNumberOfSyntheticMethods = 1)
@ExpectedClass(className = "BridgeMethodsForLambdaTest$Inner3",
expectedMethods = {"<init>(BridgeMethodsForLambdaTest)", "function()"},
- expectedNumberOfSyntheticMethods = 1,
expectedNumberOfSyntheticFields = 1)
@ExpectedClass(className = "BridgeMethodsForLambdaTest$Inner4",
expectedMethods = {"<init>(BridgeMethodsForLambdaTest)", "function()"},
--- a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerClassTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -31,21 +31,30 @@
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build InnerClassesInInnerClassTestBase InnerClassesTestBase
- * @run main InnerClassesInInnerClassTest
+ * @run main InnerClassesInInnerClassTest true
+ * @run main InnerClassesInInnerClassTest false
*/
+import java.util.Arrays;
import java.util.List;
public class InnerClassesInInnerClassTest extends InnerClassesInInnerClassTestBase {
+ final boolean expectSyntheticClass;
+
+ public InnerClassesInInnerClassTest(boolean expectSyntheticClass) {
+ this.expectSyntheticClass = expectSyntheticClass;
+ }
+
public static void main(String[] args) throws TestFailedException {
- InnerClassesTestBase test = new InnerClassesInInnerClassTest();
+ boolean expectSyntheticClass = Boolean.parseBoolean(args[0]);
+ InnerClassesTestBase test = new InnerClassesInInnerClassTest(expectSyntheticClass);
test.test("InnerClassesSrc$Inner", "Inner", "1");
}
@Override
public void setProperties() {
- setHasSyntheticClass(true);
+ setHasSyntheticClass(expectSyntheticClass);
setOuterClassType(ClassType.CLASS);
setInnerClassType(ClassType.CLASS);
}
@@ -62,4 +71,11 @@
return sources;
}
+
+ @Override
+ protected List<String> getCompileOptions() {
+ return !expectSyntheticClass ?
+ super.getCompileOptions() :
+ Arrays.asList("-source", "10", "-target", "10");
+ }
}
--- a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesInInnerEnumTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -31,13 +31,24 @@
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build InnerClassesInInnerClassTestBase InnerClassesTestBase
- * @run main InnerClassesInInnerEnumTest
+ * @run main InnerClassesInInnerEnumTest true
+ * @run main InnerClassesInInnerEnumTest false
*/
+import java.util.Arrays;
+import java.util.List;
+
public class InnerClassesInInnerEnumTest extends InnerClassesInInnerClassTestBase {
+ final boolean expectSyntheticClass;
+
+ public InnerClassesInInnerEnumTest(boolean expectSyntheticClass) {
+ this.expectSyntheticClass = expectSyntheticClass;
+ }
+
public static void main(String[] args) throws TestFailedException {
- InnerClassesTestBase test = new InnerClassesInInnerEnumTest();
+ boolean expectSyntheticClass = Boolean.parseBoolean(args[0]);
+ InnerClassesTestBase test = new InnerClassesInInnerEnumTest(expectSyntheticClass);
test.test("InnerClassesSrc$Inner", "Inner", "1");
}
@@ -46,8 +57,15 @@
setOuterOtherModifiers(Modifier.EMPTY, Modifier.STATIC);
setOuterClassType(ClassType.ENUM);
setInnerClassType(ClassType.CLASS);
- setHasSyntheticClass(true);
+ setHasSyntheticClass(expectSyntheticClass);
setPrefix("Inner {;");
setSuffix("}");
}
+
+ @Override
+ protected List<String> getCompileOptions() {
+ return !expectSyntheticClass ?
+ super.getCompileOptions() :
+ Arrays.asList("-source", "10", "-target", "10");
+ }
}
--- a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -31,20 +31,29 @@
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @build InnerClassesTestBase
- * @run main InnerClassesTest
+ * @run main InnerClassesTest true
+ * @run main InnerClassesTest false
*/
+import java.util.Arrays;
import java.util.List;
public class InnerClassesTest extends InnerClassesTestBase {
+ final boolean expectSyntheticClass;
+
+ public InnerClassesTest(boolean expectSyntheticClass) {
+ this.expectSyntheticClass = expectSyntheticClass;
+ }
+
public static void main(String[] args) throws TestFailedException {
- new InnerClassesTest().test("InnerClassesSrc");
+ boolean expectSyntheticClass = Boolean.parseBoolean(args[0]);
+ new InnerClassesTest(expectSyntheticClass).test("InnerClassesSrc");
}
private List<TestCase> generateClasses() {
setInnerClassType(ClassType.CLASS);
- setHasSyntheticClass(true);
+ setHasSyntheticClass(expectSyntheticClass);
return super.generateTestCases();
}
@@ -82,4 +91,11 @@
sources.addAll(generateAnnotations());
return sources;
}
+
+ @Override
+ protected List<String> getCompileOptions() {
+ return !expectSyntheticClass ?
+ super.getCompileOptions() :
+ Arrays.asList("-source", "10", "-target", "10");
+ }
}
--- a/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/classfiles/attributes/innerclasses/InnerClassesTestBase.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -199,7 +199,7 @@
printf("Testing :\n%s\n", test.getSource());
try {
Map<String, Set<String>> class2Flags = test.getFlags();
- ClassFile cf = readClassFile(compile(test.getSource())
+ ClassFile cf = readClassFile(compile(getCompileOptions(), test.getSource())
.getClasses().get(classToTest));
InnerClasses_attribute innerClasses = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
@@ -324,6 +324,10 @@
return flags;
}
+ protected List<String> getCompileOptions() {
+ return Collections.emptyList();
+ }
+
private List<List<Modifier>> getAllCombinations(Modifier[] accessModifiers, Modifier[] otherModifiers) {
List<List<Modifier>> list = new ArrayList<>();
for (Modifier access : accessModifiers) {
--- a/test/langtools/tools/javac/nativeHeaders/NativeHeaderTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/nativeHeaders/NativeHeaderTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -122,7 +122,7 @@
// double check the synthetic class was generated
checkEqual("generatedClasses",
- createSet("C.class", "C$1.class", "C$Inner.class"),
+ createSet("C.class", "C$Inner.class"),
createSet(classesDir.list()));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java Mon Jun 25 09:48:06 2018 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018, 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
+ * @summary Smoke test for nestmate classfile support
+ * @run main CheckNestmateAttrs
+ * @modules
+ * jdk.compiler
+ * jdk.jdeps/com.sun.tools.javap
+ */
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Paths;
+
+public class CheckNestmateAttrs {
+
+ private void test() { }
+
+ class Inner {
+ void m() {
+ class LocalInner {
+ void testInner() {
+ test();
+ }
+ }
+ }
+ }
+
+ static class Nested {
+ void s() {
+ class LocalNested { }
+ }
+ }
+
+ public static void main(String[] args) {
+ new CheckNestmateAttrs().run();
+ }
+
+ void run() {
+ String [] params = new String [] { "-v",
+ Paths.get(System.getProperty("test.classes"),
+ "CheckNestmateAttrs.class").toString() };
+ runCheck(params, new String [] {
+ "NestMembers:" +
+ " CheckNestmateAttrs$Nested" +
+ " CheckNestmateAttrs$Nested$1LocalNested" +
+ " CheckNestmateAttrs$Inner" +
+ " CheckNestmateAttrs$Inner$1LocalInner"
+ });
+
+ params = new String [] { "-v",
+ Paths.get(System.getProperty("test.classes"),
+ "CheckNestmateAttrs$Inner.class").toString() };
+
+ runCheck(params, new String [] { "NestHost: class CheckNestmateAttrs" });
+
+ params = new String [] { "-v",
+ Paths.get(System.getProperty("test.classes"),
+ "CheckNestmateAttrs$Nested.class").toString() };
+
+ runCheck(params, new String [] { "NestHost: class CheckNestmateAttrs" });
+
+ params = new String [] { "-v",
+ Paths.get(System.getProperty("test.classes"),
+ "CheckNestmateAttrs$Inner$1LocalInner.class").toString() };
+
+ runCheck(params, new String [] {
+ "NestHost: class CheckNestmateAttrs",
+ "0: aload_0",
+ "1: getfield #1 // Field this$1:LCheckNestmateAttrs$Inner;",
+ "4: getfield #3 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
+ "7: invokevirtual #4 // Method CheckNestmateAttrs.test:()V",
+ "10: return"
+ });
+
+ params = new String [] { "-v",
+ Paths.get(System.getProperty("test.classes"),
+ "CheckNestmateAttrs$Nested$1LocalNested.class").toString() };
+
+ runCheck(params, new String [] { "NestHost: class CheckNestmateAttrs" });
+ }
+
+ void runCheck(String [] params, String [] expectedOut) {
+ StringWriter s;
+ String out;
+
+ try (PrintWriter pw = new PrintWriter(s = new StringWriter())) {
+ com.sun.tools.javap.Main.run(params, pw);
+ out = s.toString();
+ }
+ for (String eo: expectedOut) {
+ if (!out.contains(eo)) {
+ System.out.println("Actual output: " + out);
+ throw new AssertionError("Missing output: " + eo);
+ }
+ }
+ }
+}
--- a/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/processing/model/completionfailure/NoAbortForBadClassFile.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -121,6 +121,7 @@
new toolbox.JavacTask(tb)
.outdir(out)
+ .options("-source", "10", "-target", "10")
.files(tb.findJavaFiles(src))
.run(Expect.SUCCESS)
.writeAll()
--- a/test/langtools/tools/javac/sym/ElementStructureTest.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/langtools/tools/javac/sym/ElementStructureTest.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8072480
+ * @bug 8072480 8203814
* @summary Check the platform classpath contains the correct elements.
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.code
@@ -134,10 +134,10 @@
(byte) 0x0C, (byte) 0x2D, (byte) 0x3A, (byte) 0x7C
};
static final byte[] hash8 = new byte[] {
- (byte) 0x37, (byte) 0x0C, (byte) 0xBA, (byte) 0xCE,
- (byte) 0xCF, (byte) 0x81, (byte) 0xAE, (byte) 0xA8,
- (byte) 0x1E, (byte) 0x10, (byte) 0xAB, (byte) 0x72,
- (byte) 0xF7, (byte) 0xE5, (byte) 0x34, (byte) 0x72
+ (byte) 0x44, (byte) 0x77, (byte) 0x6E, (byte) 0x52,
+ (byte) 0x2B, (byte) 0x16, (byte) 0xD3, (byte) 0x3C,
+ (byte) 0x78, (byte) 0x75, (byte) 0xF5, (byte) 0x0A,
+ (byte) 0x01, (byte) 0x24, (byte) 0xBD, (byte) 0x2A
};
final static Map<String, byte[]> version2Hash = new HashMap<>();
--- a/test/lib/jdk/test/lib/util/FileUtils.java Mon Jun 25 08:14:11 2018 -0700
+++ b/test/lib/jdk/test/lib/util/FileUtils.java Mon Jun 25 09:48:06 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -26,18 +26,26 @@
import jdk.test.lib.Platform;
import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.lang.ProcessBuilder.Redirect;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.time.Instant;
+import java.time.Duration;
import java.util.ArrayList;
+import java.util.ArrayDeque;
+import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.TimeUnit;
-
/**
* Common library for various test file utility functions.
*/
@@ -227,4 +235,42 @@
}
return areFileSystemsAccessible;
}
+
+ /**
+ * List the open file descriptors (if supported by the 'lsof' command).
+ * @param ps a printStream to send the output to
+ * @throws UncheckedIOException if an error occurs
+ */
+ public static void listFileDescriptors(PrintStream ps) {
+ List<String> lsofDirs = List.of("/usr/bin", "/usr/sbin");
+ Optional<Path> lsof = lsofDirs.stream()
+ .map(s -> Paths.get(s, "lsof"))
+ .filter(f -> Files.isExecutable(f))
+ .findFirst();
+ lsof.ifPresent(exe -> {
+ try {
+ ps.printf("Open File Descriptors:%n");
+ long pid = ProcessHandle.current().pid();
+ ProcessBuilder pb = new ProcessBuilder(exe.toString(), "-p", Integer.toString((int) pid));
+ pb.redirectErrorStream(true); // combine stderr and stdout
+ pb.redirectOutput(Redirect.PIPE);
+
+ Process p = pb.start();
+ Instant start = Instant.now();
+ p.getInputStream().transferTo(ps);
+
+ try {
+ int timeout = 10;
+ if (!p.waitFor(timeout, TimeUnit.SECONDS)) {
+ System.out.printf("waitFor timed out: %d%n", timeout);
+ }
+ } catch (InterruptedException ie) {
+ throw new IOException("interrupted", ie);
+ }
+ ps.println();
+ } catch (IOException ioe) {
+ throw new UncheckedIOException("error listing file descriptors", ioe);
+ }
+ });
+ }
}