--- a/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
16ba58282d117247f480aae7a79b88141ade52a3 jdk8-b28
e070119aa56ee4dc5506c19d2c4d2eecab8ad429 jdk8-b29
23da7804aca0c9c4e6e86532a1453125a76d95ee jdk8-b30
+bac81e9f7d57b75fba5ab31b571f3fe0dc08af69 jdk8-b31
+2c5208ccb863db936eab523f49450b3fcd230348 jdk8-b32
--- a/.hgtags-top-repo Thu Mar 29 21:16:58 2012 -0700
+++ b/.hgtags-top-repo Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
6e2541d60f4e342b5b67140271d7611643929dc3 jdk8-b28
41460de042580bc4a4ce3f863779c66f39cb8578 jdk8-b29
6cea54809b51db92979c22fd8aa8fcb1cb13d12e jdk8-b30
+0b66f43b89a6c0ac1c15d7ec51992c541cdc9089 jdk8-b31
+88176171e940f02916a312c265a34c32552a8376 jdk8-b32
--- a/corba/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/corba/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
2082eb35d49a9c2aab90b8d4fd31cefb7a23b82e jdk8-b28
6117395d422682f89d228347e319fcaac7edc729 jdk8-b29
4605f8418bf562e78be79b25b6b8a5110281acae jdk8-b30
+1954151dfae8f73db24e396380f7c02bdd47c486 jdk8-b31
+5d820cb6b1afd75b619e7fd69e4f2b0eb1d5d6a1 jdk8-b32
--- a/hotspot/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -232,3 +232,7 @@
d61761bf305031c94f7f8eca49abd978b7d3c5da jdk8-b30
dfae0140457cfb2c381d7679735fbedbae862c62 hs24-b03
f4767e53d6e0d5da7e3f1775904076cce54247c1 hs24-b04
+0cd147eaa673d1642b2f466f5dc257cf192db524 jdk8-b31
+27863e4586de38be7dd17da4163f542038f4d1d7 hs24-b05
+25410a347ebb0bef166c4338a90d9dea82463a20 jdk8-b32
+cd47da9383cd932cb2b659064057feafa2a91134 hs24-b06
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Mar 29 21:22:07 2012 -0700
@@ -359,6 +359,12 @@
public static final int innerClassNextOffset = 4;
};
+ public static interface EnclosingMethodAttributeOffset {
+ public static final int enclosing_method_class_index_offset = 0;
+ public static final int enclosing_method_method_index_offset = 1;
+ public static final int enclosing_method_attribute_size = 2;
+ };
+
// refer to compute_modifier_flags in VM code.
public long computeModifierFlags() {
long access = getAccessFlags();
@@ -367,9 +373,14 @@
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
if (length > 0) {
if (Assert.ASSERTS_ENABLED) {
- Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
+ Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
+ length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
+ "just checking");
}
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
+ if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
+ break;
+ }
int ioff = innerClassList.getShortAt(i +
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
// 'ioff' can be zero.
@@ -419,9 +430,14 @@
int length = ( innerClassList == null)? 0 : (int) innerClassList.getLength();
if (length > 0) {
if (Assert.ASSERTS_ENABLED) {
- Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0, "just checking");
+ Assert.that(length % InnerClassAttributeOffset.innerClassNextOffset == 0 ||
+ length % InnerClassAttributeOffset.innerClassNextOffset == EnclosingMethodAttributeOffset.enclosing_method_attribute_size,
+ "just checking");
}
for (int i = 0; i < length; i += InnerClassAttributeOffset.innerClassNextOffset) {
+ if (i == length - EnclosingMethodAttributeOffset.enclosing_method_attribute_size) {
+ break;
+ }
int ioff = innerClassList.getShortAt(i +
InnerClassAttributeOffset.innerClassInnerClassInfoOffset);
// 'ioff' can be zero.
--- a/hotspot/make/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -271,23 +271,25 @@
ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR)
SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR)
-# Misc files and generated files need to come from C1 or C2 area
-ifeq ($(ZERO_BUILD), true)
-ifeq ($(SHARK_BUILD), true)
- MISC_DIR=$(SHARK_DIR)
- GEN_DIR=$(SHARK_BASE_DIR)/generated
-else
- MISC_DIR=$(ZERO_DIR)
- GEN_DIR=$(ZERO_BASE_DIR)/generated
+ifeq ($(JVM_VARIANT_SERVER), true)
+ MISC_DIR=$(C2_DIR)
+ GEN_DIR=$(C2_BASE_DIR)/generated
+endif
+ifeq ($(JVM_VARIANT_CLIENT), true)
+ MISC_DIR=$(C1_DIR)
+ GEN_DIR=$(C1_BASE_DIR)/generated
endif
-else
-ifeq ($(ARCH_DATA_MODEL), 32)
- MISC_DIR=$(C1_DIR)
- GEN_DIR=$(C1_BASE_DIR)/generated
-else
- MISC_DIR=$(C2_DIR)
- GEN_DIR=$(C2_BASE_DIR)/generated
+ifeq ($(JVM_VARIANT_KERNEL), true)
+ MISC_DIR=$(C2_DIR)
+ GEN_DIR=$(C2_BASE_DIR)/generated
endif
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ MISC_DIR=$(SHARK_DIR)
+ GEN_DIR=$(SHARK_BASE_DIR)/generated
+endif
+ifeq ($(JVM_VARIANT_ZERO), true)
+ MISC_DIR=$(ZERO_DIR)
+ GEN_DIR=$(ZERO_BASE_DIR)/generated
endif
# Bin files (windows)
@@ -332,46 +334,46 @@
# Shared Library
ifneq ($(OSNAME),windows)
- ifeq ($(ZERO_BUILD), true)
- ifeq ($(SHARK_BUILD), true)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
- else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
+ ifeq ($(JVM_VARIANT_SERVER), true)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo
+ $(install-file)
endif
- else
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX)
- $(install-file)
-
-# Debug info for shared library
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo
- $(install-file)
-$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo
- $(install-file)
-$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo
- $(install-file)
-$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo
- $(install-file)
-$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo
- $(install-file)
-$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo
- $(install-file)
- endif
+ ifeq ($(JVM_VARIANT_CLIENT), true)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo
+ $(install-file)
+ $(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo
+ $(install-file)
+ $(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo
+ $(install-file)
+ endif
+ ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ endif
+ ifeq ($(JVM_VARIANT_ZERO), true)
+ $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+ $(install-file)
+ endif
endif
# Jar file (sa-jdi.jar)
@@ -450,18 +452,19 @@
($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -)
test_jdk:
- ifeq ($(ARCH_DATA_MODEL), 32)
- ifneq ($(ZERO_BUILD), true)
- $(JDK_IMAGE_DIR)/bin/java -d32 -client -Xinternalversion
- $(JDK_IMAGE_DIR)/bin/java -d32 -client -version
- endif
- $(JDK_IMAGE_DIR)/bin/java -d32 -server -Xinternalversion
- $(JDK_IMAGE_DIR)/bin/java -d32 -server -version
- endif
- ifeq ($(ARCH_DATA_MODEL), 64)
- $(JDK_IMAGE_DIR)/bin/java -d64 -server -Xinternalversion
- $(JDK_IMAGE_DIR)/bin/java -d64 -server -version
- endif
+ ifeq ($(JVM_VARIANT_CLIENT), true)
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -client -Xinternalversion
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -client -version
+ endif
+ ifeq ($(findstring true, $(JVM_VARIANT_SERVER)\
+ $(JVM_VARIANT_ZERO)$(JVM_VARIANT_ZEROSHARK)), true)
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version
+ endif
+ ifeq ($(JVM_VARIANT_KERNEL), true)
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion
+ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version
+ endif
copy_product_jdk::
$(RM) -r $(JDK_IMAGE_DIR)
--- a/hotspot/make/bsd/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/bsd/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -188,7 +188,7 @@
# in the build.sh script:
TARGETS = debug jvmg fastdebug optimized profiled product
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs
else
SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs
--- a/hotspot/make/bsd/makefiles/buildtree.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/bsd/makefiles/buildtree.make Thu Mar 29 21:22:07 2012 -0700
@@ -69,7 +69,7 @@
# For now, until the compiler is less wobbly:
TESTFLAGS = -Xbatch -showversion
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
else
ifdef USE_SUNCC
--- a/hotspot/make/bsd/makefiles/defs.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/bsd/makefiles/defs.make Thu Mar 29 21:22:07 2012 -0700
@@ -38,7 +38,7 @@
endif
# zero
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
ifeq ($(ARCH_DATA_MODEL), 64)
MAKE_ARGS += LP64=1
endif
@@ -124,6 +124,18 @@
HS_ARCH = ppc
endif
+# On 32 bit bsd we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+ ifeq ($(ARCH_DATA_MODEL), 32)
+ JVM_VARIANTS:=client,server
+ JVM_VARIANT_CLIENT:=true
+ JVM_VARIANT_SERVER:=true
+ else
+ JVM_VARIANTS:=server
+ JVM_VARIANT_SERVER:=true
+ endif
+endif
+
JDK_INCLUDE_SUBDIR=bsd
# Library suffix
@@ -146,16 +158,14 @@
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
-ifndef BUILD_CLIENT_ONLY
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
endif
-ifneq ($(ZERO_BUILD), true)
- ifeq ($(ARCH_DATA_MODEL), 32)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
- endif
+ifeq ($(JVM_VARIANT_CLIENT),true)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
endif
# Serviceability Binaries
--- a/hotspot/make/bsd/makefiles/gcc.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/bsd/makefiles/gcc.make Thu Mar 29 21:22:07 2012 -0700
@@ -105,11 +105,12 @@
VM_PICFLAG/AOUT =
VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
-ifeq ($(ZERO_BUILD), true)
-CFLAGS += $(LIBFFI_CFLAGS)
+ifeq ($(JVM_VARIANT_ZERO), true)
+ CFLAGS += $(LIBFFI_CFLAGS)
endif
-ifeq ($(SHARK_BUILD), true)
-CFLAGS += $(LLVM_CFLAGS)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ CFLAGS += $(LIBFFI_CFLAGS)
+ CFLAGS += $(LLVM_CFLAGS)
endif
CFLAGS += $(VM_PICFLAG)
CFLAGS += -fno-rtti
--- a/hotspot/make/bsd/makefiles/vm.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/bsd/makefiles/vm.make Thu Mar 29 21:22:07 2012 -0700
@@ -42,7 +42,7 @@
-include $(DEP_DIR)/*.d
# read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
include $(MAKEFILES_DIR)/zeroshark.make
else
include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -271,12 +271,12 @@
LIBS_VM += $(LIBS)
endif
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
LIBS_VM += $(LIBFFI_LIBS)
endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ LIBS_VM += $(LIBFFI_LIBS) $(LLVM_LIBS)
LFLAGS_VM += $(LLVM_LDFLAGS)
- LIBS_VM += $(LLVM_LIBS)
endif
--- a/hotspot/make/defs.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/defs.make Thu Mar 29 21:22:07 2012 -0700
@@ -55,6 +55,27 @@
@$(RM) $@
endef
+# Default values for JVM_VARIANT* variables if configure hasn't set
+# it already.
+ifeq ($(JVM_VARIANTS),)
+ ifeq ($(ZERO_BUILD), true)
+ ifeq ($(SHARK_BUILD), true)
+ JVM_VARIANTS:=zeroshark
+ JVM_VARIANT_ZEROSHARK:=true
+ else
+ JVM_VARIANTS:=zero
+ JVM_VARIANT_ZERO:=true
+ endif
+ else
+ # A default is needed
+ ifeq ($(BUILD_CLIENT_ONLY), true)
+ JVM_VARIANTS:=client
+ JVM_VARIANT_CLIENT:=true
+ endif
+ # Further defaults are platform and arch specific
+ endif
+endif
+
# Directory paths and user name
# Unless GAMMADIR is set on the command line, search upward from
# the current directory for a parent directory containing "src/share/vm".
--- a/hotspot/make/hotspot_version Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/hotspot_version Thu Mar 29 21:22:07 2012 -0700
@@ -35,7 +35,7 @@
HS_MAJOR_VER=24
HS_MINOR_VER=0
-HS_BUILD_NUMBER=04
+HS_BUILD_NUMBER=06
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
--- a/hotspot/make/jprt.properties Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/jprt.properties Thu Mar 29 21:22:07 2012 -0700
@@ -446,6 +446,7 @@
jprt.test.targets.jdk8=${jprt.test.targets.standard}
jprt.test.targets.jdk7=${jprt.test.targets.standard}
+jprt.test.targets.jdk7u4=${jprt.test.targets.jdk7}
jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}}
# The default test/Makefile targets that should be run
@@ -505,5 +506,6 @@
jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard}
jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard}
+jprt.make.rule.test.targets.jdk7u4=${jprt.make.rule.test.targets.jdk7}
jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}}
--- a/hotspot/make/linux/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/linux/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -188,7 +188,7 @@
# in the build.sh script:
TARGETS = debug jvmg fastdebug optimized profiled product
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
SUBDIR_DOCS = $(OSNAME)_$(VARIANTARCH)_docs
else
SUBDIR_DOCS = $(OSNAME)_$(BUILDARCH)_docs
--- a/hotspot/make/linux/makefiles/buildtree.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/linux/makefiles/buildtree.make Thu Mar 29 21:22:07 2012 -0700
@@ -66,7 +66,7 @@
# For now, until the compiler is less wobbly:
TESTFLAGS = -Xbatch -showversion
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
PLATFORM_FILE = $(shell dirname $(shell dirname $(shell pwd)))/platform_zero
else
ifdef USE_SUNCC
--- a/hotspot/make/linux/makefiles/defs.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/linux/makefiles/defs.make Thu Mar 29 21:22:07 2012 -0700
@@ -38,7 +38,7 @@
endif
# zero
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
ifeq ($(ARCH_DATA_MODEL), 64)
MAKE_ARGS += LP64=1
endif
@@ -114,6 +114,18 @@
HS_ARCH = ppc
endif
+# On 32 bit linux we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+ ifeq ($(ARCH_DATA_MODEL), 32)
+ JVM_VARIANTS:=client,server
+ JVM_VARIANT_CLIENT:=true
+ JVM_VARIANT_SERVER:=true
+ else
+ JVM_VARIANTS:=server
+ JVM_VARIANT_SERVER:=true
+ endif
+endif
+
# determine if HotSpot is being built in JDK6 or earlier version
JDK6_OR_EARLIER=0
ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1"
@@ -195,22 +207,20 @@
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
-ifndef BUILD_CLIENT_ONLY
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
endif
endif
-ifneq ($(ZERO_BUILD), true)
- ifeq ($(ARCH_DATA_MODEL), 32)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
- ifneq ($(OBJCOPY),)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
- endif
- endif
+ifeq ($(JVM_VARIANT_CLIENT),true)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ ifneq ($(OBJCOPY),)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
+ endif
endif
# Serviceability Binaries
--- a/hotspot/make/linux/makefiles/gcc.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/linux/makefiles/gcc.make Thu Mar 29 21:22:07 2012 -0700
@@ -72,10 +72,11 @@
VM_PICFLAG/AOUT =
VM_PICFLAG = $(VM_PICFLAG/$(LINK_INTO))
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
CFLAGS += $(LIBFFI_CFLAGS)
endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+CFLAGS += $(LIBFFI_CFLAGS)
CFLAGS += $(LLVM_CFLAGS)
endif
CFLAGS += $(VM_PICFLAG)
--- a/hotspot/make/linux/makefiles/vm.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/linux/makefiles/vm.make Thu Mar 29 21:22:07 2012 -0700
@@ -42,7 +42,7 @@
-include $(DEP_DIR)/*.d
# read machine-specific adjustments (%%% should do this via buildtree.make?)
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(findstring true, $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
include $(MAKEFILES_DIR)/zeroshark.make
else
include $(MAKEFILES_DIR)/$(BUILDARCH).make
@@ -236,7 +236,7 @@
vm.def: $(Res_Files) $(Obj_Files)
sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
STATIC_CXX = false
else
ifeq ($(ZERO_LIBARCH), ppc64)
@@ -268,12 +268,12 @@
LIBS_VM += $(LIBS)
endif
-ifeq ($(ZERO_BUILD), true)
+ifeq ($(JVM_VARIANT_ZERO), true)
LIBS_VM += $(LIBFFI_LIBS)
endif
-ifeq ($(SHARK_BUILD), true)
+ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+ LIBS_VM += $(LIBFFI_LIBS) $(LLVM_LIBS)
LFLAGS_VM += $(LLVM_LDFLAGS)
- LIBS_VM += $(LLVM_LIBS)
endif
LINK_VM = $(LINK_LIB.CC)
--- a/hotspot/make/solaris/makefiles/defs.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/solaris/makefiles/defs.make Thu Mar 29 21:22:07 2012 -0700
@@ -59,6 +59,18 @@
endif
endif
+# On 32 bit solaris we build server and client, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+ ifeq ($(ARCH_DATA_MODEL), 32)
+ JVM_VARIANTS:=client,server
+ JVM_VARIANT_CLIENT:=true
+ JVM_VARIANT_SERVER:=true
+ else
+ JVM_VARIANTS:=server
+ JVM_VARIANT_SERVER:=true
+ endif
+endif
+
# determine if HotSpot is being built in JDK6 or earlier version
JDK6_OR_EARLIER=0
ifeq "$(shell expr \( '$(JDK_MAJOR_VERSION)' != '' \& '$(JDK_MINOR_VERSION)' != '' \& '$(JDK_MICRO_VERSION)' != '' \))" "1"
@@ -153,37 +165,37 @@
EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
-ifneq ($(BUILD_CLIENT_ONLY),true)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ifeq ($(JVM_VARIANT_SERVER),true)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ ifeq ($(ARCH_DATA_MODEL),32)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ endif
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.debuginfo
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_db.debuginfo
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm_dtrace.debuginfo
endif
endif
-ifeq ($(ARCH_DATA_MODEL), 32)
+ifeq ($(JVM_VARIANT_CLIENT),true)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.$(LIBRARY_SUFFIX)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ ifeq ($(ARCH_DATA_MODEL),32)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
+ endif
ifneq ($(OBJCOPY),)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm.debuginfo
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_db.debuginfo
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/libjvm_dtrace.debuginfo
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
- EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
- endif
- ifneq ($(BUILD_CLIENT_ONLY), true)
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.$(LIBRARY_SUFFIX)
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.$(LIBRARY_SUFFIX)
- ifneq ($(OBJCOPY),)
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_db.debuginfo
- EXPORT_LIST += $(EXPORT_SERVER_DIR)/64/libjvm_dtrace.debuginfo
+ ifeq ($(ARCH_DATA_MODEL),32)
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_db.debuginfo
+ EXPORT_LIST += $(EXPORT_CLIENT_DIR)/64/libjvm_dtrace.debuginfo
endif
endif
endif
--- a/hotspot/make/windows/makefiles/defs.make Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/make/windows/makefiles/defs.make Thu Mar 29 21:22:07 2012 -0700
@@ -107,6 +107,19 @@
endif
endif
+# On 32 bit windows we build server, client and kernel, on 64 bit just server.
+ifeq ($(JVM_VARIANTS),)
+ ifeq ($(ARCH_DATA_MODEL), 32)
+ JVM_VARIANTS:=client,server,kernel
+ JVM_VARIANT_CLIENT:=true
+ JVM_VARIANT_SERVER:=true
+ JVM_VARIANT_KERNEL:=true
+ else
+ JVM_VARIANTS:=server
+ JVM_VARIANT_SERVER:=true
+ endif
+endif
+
JDK_INCLUDE_SUBDIR=win32
# Library suffix
@@ -177,17 +190,20 @@
EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client
EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
-EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
-EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
-ifeq ($(ARCH_DATA_MODEL), 32)
+ifeq ($(JVM_VARIANT_SERVER),true)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.$(LIBRARY_SUFFIX)
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.pdb
+ EXPORT_LIST += $(EXPORT_SERVER_DIR)/jvm.map
+ EXPORT_LIST += $(EXPORT_LIB_DIR)/jvm.lib
+endif
+ifeq ($(JVM_VARIANT_CLIENT),true)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/Xusage.txt
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.pdb
EXPORT_LIST += $(EXPORT_CLIENT_DIR)/jvm.map
- # kernel vm
+endif
+ifeq ($(JVM_VARIANT_KERNEL),true)
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX)
EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb
--- a/hotspot/src/os/bsd/vm/attachListener_bsd.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/os/bsd/vm/attachListener_bsd.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -206,10 +206,15 @@
// put in listen mode, set permissions, and rename into place
res = ::listen(listener, 5);
if (res == 0) {
- RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+ RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+ if (res == 0) {
+ // make sure the file is owned by the effective user and effective group
+ // (this is the default on linux, but not on mac os)
+ RESTARTABLE(::chown(initial_path, geteuid(), getegid()), res);
if (res == 0) {
- res = ::rename(initial_path, path);
+ res = ::rename(initial_path, path);
}
+ }
}
if (res == -1) {
RESTARTABLE(::close(listener), res);
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -2315,13 +2315,32 @@
#define RECOGNIZED_INNER_CLASS_MODIFIERS (JVM_RECOGNIZED_CLASS_MODIFIERS | JVM_ACC_PRIVATE | JVM_ACC_PROTECTED | JVM_ACC_STATIC)
// Return number of classes in the inner classes attribute table
-u2 ClassFileParser::parse_classfile_inner_classes_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
+u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
+ bool parsed_enclosingmethod_attribute,
+ u2 enclosing_method_class_index,
+ u2 enclosing_method_method_index,
+ constantPoolHandle cp,
+ instanceKlassHandle k, TRAPS) {
ClassFileStream* cfs = stream();
- cfs->guarantee_more(2, CHECK_0); // length
- u2 length = cfs->get_u2_fast();
-
- // 4-tuples of shorts [inner_class_info_index, outer_class_info_index, inner_name_index, inner_class_access_flags]
- typeArrayOop ic = oopFactory::new_permanent_shortArray(length*4, CHECK_0);
+ u1* current_mark = cfs->current();
+ u2 length = 0;
+ if (inner_classes_attribute_start != NULL) {
+ cfs->set_current(inner_classes_attribute_start);
+ cfs->guarantee_more(2, CHECK_0); // length
+ length = cfs->get_u2_fast();
+ }
+
+ // 4-tuples of shorts of inner classes data and 2 shorts of enclosing
+ // method data:
+ // [inner_class_info_index,
+ // outer_class_info_index,
+ // inner_name_index,
+ // inner_class_access_flags,
+ // ...
+ // enclosing_method_class_index,
+ // enclosing_method_method_index]
+ int size = length * 4 + (parsed_enclosingmethod_attribute ? 2 : 0);
+ typeArrayOop ic = oopFactory::new_permanent_shortArray(size, CHECK_0);
typeArrayHandle inner_classes(THREAD, ic);
int index = 0;
int cp_size = cp->length();
@@ -2372,8 +2391,8 @@
// 4347400: make sure there's no duplicate entry in the classes array
if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
- for(int i = 0; i < inner_classes->length(); i += 4) {
- for(int j = i + 4; j < inner_classes->length(); j += 4) {
+ for(int i = 0; i < length * 4; i += 4) {
+ for(int j = i + 4; j < length * 4; j += 4) {
guarantee_property((inner_classes->ushort_at(i) != inner_classes->ushort_at(j) ||
inner_classes->ushort_at(i+1) != inner_classes->ushort_at(j+1) ||
inner_classes->ushort_at(i+2) != inner_classes->ushort_at(j+2) ||
@@ -2384,8 +2403,19 @@
}
}
+ // Set EnclosingMethod class and method indexes.
+ if (parsed_enclosingmethod_attribute) {
+ inner_classes->short_at_put(index++, enclosing_method_class_index);
+ inner_classes->short_at_put(index++, enclosing_method_method_index);
+ }
+ assert(index == size, "wrong size");
+
// Update instanceKlass with inner class info.
k->set_inner_classes(inner_classes());
+
+ // Restore buffer's current position.
+ cfs->set_current(current_mark);
+
return length;
}
@@ -2490,6 +2520,10 @@
int runtime_visible_annotations_length = 0;
u1* runtime_invisible_annotations = NULL;
int runtime_invisible_annotations_length = 0;
+ u1* inner_classes_attribute_start = NULL;
+ u4 inner_classes_attribute_length = 0;
+ u2 enclosing_method_class_index = 0;
+ u2 enclosing_method_method_index = 0;
// Iterate over attributes
while (attributes_count--) {
cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length
@@ -2522,11 +2556,9 @@
} else {
parsed_innerclasses_attribute = true;
}
- u2 num_of_classes = parse_classfile_inner_classes_attribute(cp, k, CHECK);
- if (_need_verify && _major_version >= JAVA_1_5_VERSION) {
- guarantee_property(attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
- "Wrong InnerClasses attribute length in class file %s", CHECK);
- }
+ inner_classes_attribute_start = cfs->get_u1_buffer();
+ inner_classes_attribute_length = attribute_length;
+ cfs->skip_u1(inner_classes_attribute_length, CHECK);
} else if (tag == vmSymbols::tag_synthetic()) {
// Check for Synthetic tag
// Shouldn't we check that the synthetic flags wasn't already set? - not required in spec
@@ -2568,22 +2600,21 @@
parsed_enclosingmethod_attribute = true;
}
cfs->guarantee_more(4, CHECK); // class_index, method_index
- u2 class_index = cfs->get_u2_fast();
- u2 method_index = cfs->get_u2_fast();
- if (class_index == 0) {
+ enclosing_method_class_index = cfs->get_u2_fast();
+ enclosing_method_method_index = cfs->get_u2_fast();
+ if (enclosing_method_class_index == 0) {
classfile_parse_error("Invalid class index in EnclosingMethod attribute in class file %s", CHECK);
}
// Validate the constant pool indices and types
- if (!cp->is_within_bounds(class_index) ||
- !is_klass_reference(cp, class_index)) {
+ if (!cp->is_within_bounds(enclosing_method_class_index) ||
+ !is_klass_reference(cp, enclosing_method_class_index)) {
classfile_parse_error("Invalid or out-of-bounds class index in EnclosingMethod attribute in class file %s", CHECK);
}
- if (method_index != 0 &&
- (!cp->is_within_bounds(method_index) ||
- !cp->tag_at(method_index).is_name_and_type())) {
+ if (enclosing_method_method_index != 0 &&
+ (!cp->is_within_bounds(enclosing_method_method_index) ||
+ !cp->tag_at(enclosing_method_method_index).is_name_and_type())) {
classfile_parse_error("Invalid or out-of-bounds method index in EnclosingMethod attribute in class file %s", CHECK);
}
- k->set_enclosing_method_indices(class_index, method_index);
} else if (tag == vmSymbols::tag_bootstrap_methods() &&
_major_version >= Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
if (parsed_bootstrap_methods_attribute)
@@ -2606,6 +2637,20 @@
CHECK);
k->set_class_annotations(annotations());
+ if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
+ u2 num_of_classes = parse_classfile_inner_classes_attribute(
+ inner_classes_attribute_start,
+ parsed_innerclasses_attribute,
+ enclosing_method_class_index,
+ enclosing_method_method_index,
+ cp, k, CHECK);
+ 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 (_max_bootstrap_specifier_index >= 0) {
guarantee_property(parsed_bootstrap_methods_attribute,
"Missing BootstrapMethods attribute in class file %s", CHECK);
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -130,7 +130,11 @@
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
instanceKlassHandle k, int length, TRAPS);
- u2 parse_classfile_inner_classes_attribute(constantPoolHandle cp,
+ u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
+ bool parsed_enclosingmethod_attribute,
+ u2 enclosing_method_class_index,
+ u2 enclosing_method_method_index,
+ constantPoolHandle cp,
instanceKlassHandle k, TRAPS);
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
--- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -285,7 +285,7 @@
// that the result is the same during all mixed GCs that follow a cycle.
const size_t region_num = (size_t) _length;
- const size_t gc_num = (size_t) G1MaxMixedGCNum;
+ const size_t gc_num = (size_t) G1MixedGCCountTarget;
size_t result = region_num / gc_num;
// emulate ceiling
if (result * gc_num < region_num) {
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -155,7 +155,7 @@
CMCheckpointRootsFinalClosure final_cl(_cm);
sprintf(verbose_str, "GC remark");
- VM_CGC_Operation op(&final_cl, verbose_str);
+ VM_CGC_Operation op(&final_cl, verbose_str, true /* needs_pll */);
VMThread::execute(&op);
}
if (cm()->restart_for_overflow() &&
@@ -189,7 +189,7 @@
CMCleanUp cl_cl(_cm);
sprintf(verbose_str, "GC cleanup");
- VM_CGC_Operation op(&cl_cl, verbose_str);
+ VM_CGC_Operation op(&cl_cl, verbose_str, false /* needs_pll */);
VMThread::execute(&op);
} else {
// We don't want to update the marking status if a GC pause
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -993,7 +993,7 @@
// iteration (after taking the Heap_lock).
result = _mutator_alloc_region.attempt_allocation(word_size,
false /* bot_updates */);
- if (result != NULL ){
+ if (result != NULL) {
return result;
}
@@ -2437,20 +2437,22 @@
true, /* should_initiate_conc_mark */
g1_policy()->max_pause_time_ms(),
cause);
+
VMThread::execute(&op);
if (!op.pause_succeeded()) {
- // Another GC got scheduled and prevented us from scheduling
- // the initial-mark GC. It's unlikely that the GC that
- // pre-empted us was also an initial-mark GC. So, we'll retry
- // the initial-mark GC.
-
if (full_gc_count_before == total_full_collections()) {
- retry_gc = true;
+ retry_gc = op.should_retry_gc();
} else {
// A Full GC happened while we were trying to schedule the
// initial-mark GC. No point in starting a new cycle given
// that the whole heap was collected anyway.
}
+
+ if (retry_gc) {
+ if (GC_locker::is_active_and_needs_gc()) {
+ GC_locker::stall_until_clear();
+ }
+ }
}
} else {
if (cause == GCCause::_gc_locker
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -2608,7 +2608,7 @@
size_t reclaimable_bytes = cset_chooser->remainingReclaimableBytes();
size_t capacity_bytes = _g1->capacity();
double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
- double threshold = (double) G1OldReclaimableThresholdPercent;
+ double threshold = (double) G1HeapWastePercent;
if (perc < threshold) {
ergo_verbose4(ErgoMixedGCs,
false_action_str,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -940,10 +940,9 @@
return _bytes_copied_during_gc;
}
- // Determine whether the next GC should be mixed. Called to determine
- // whether to start mixed GCs or whether to carry on doing mixed
- // GCs. The two action strings are used in the ergo output when the
- // method returns true or false.
+ // Determine whether there are candidate regions so that the
+ // next GC should be mixed. The two action strings are used
+ // in the ergo output when the method returns true or false.
bool next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -299,17 +299,16 @@
"Percentage (0-100) of the heap size to use as maximum " \
"young gen size.") \
\
- develop(uintx, G1OldCSetRegionLiveThresholdPercent, 95, \
+ develop(uintx, G1OldCSetRegionLiveThresholdPercent, 90, \
"Threshold for regions to be added to the collection set. " \
"Regions with more live bytes that this will not be collected.") \
\
- develop(uintx, G1OldReclaimableThresholdPercent, 1, \
- "Threshold for the remaining old reclaimable bytes, expressed " \
- "as a percentage of the heap size. If the old reclaimable bytes " \
- "are under this we will not collect them with more mixed GCs.") \
+ product(uintx, G1HeapWastePercent, 5, \
+ "Amount of space, expressed as a percentage of the heap size, " \
+ "that G1 is willing not to collect to avoid expensive GCs.") \
\
- develop(uintx, G1MaxMixedGCNum, 4, \
- "The maximum desired number of mixed GCs after a marking cycle.") \
+ product(uintx, G1MixedGCCountTarget, 4, \
+ "The target number of mixed GCs after a marking cycle.") \
\
develop(uintx, G1OldCSetRegionThresholdPercent, 10, \
"An upper bound for the number of old CSet regions expressed " \
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -34,7 +34,8 @@
VM_G1CollectForAllocation::VM_G1CollectForAllocation(
unsigned int gc_count_before,
size_t word_size)
- : VM_G1OperationWithAllocRequest(gc_count_before, word_size) {
+ : VM_G1OperationWithAllocRequest(gc_count_before, word_size,
+ GCCause::_allocation_failure) {
guarantee(word_size > 0, "an allocation should always be requested");
}
@@ -57,9 +58,10 @@
bool should_initiate_conc_mark,
double target_pause_time_ms,
GCCause::Cause gc_cause)
- : VM_G1OperationWithAllocRequest(gc_count_before, word_size),
+ : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause),
_should_initiate_conc_mark(should_initiate_conc_mark),
_target_pause_time_ms(target_pause_time_ms),
+ _should_retry_gc(false),
_full_collections_completed_before(0) {
guarantee(target_pause_time_ms > 0.0,
err_msg("target_pause_time_ms = %1.6lf should be positive",
@@ -70,6 +72,22 @@
_gc_cause = gc_cause;
}
+bool VM_G1IncCollectionPause::doit_prologue() {
+ bool res = VM_GC_Operation::doit_prologue();
+ if (!res) {
+ if (_should_initiate_conc_mark) {
+ // The prologue can fail for a couple of reasons. The first is that another GC
+ // got scheduled and prevented the scheduling of the initial mark GC. The
+ // second is that the GC locker may be active and the heap can't be expanded.
+ // In both cases we want to retry the GC so that the initial mark pause is
+ // actually scheduled. In the second case, however, we should stall until
+ // until the GC locker is no longer active and then retry the initial mark GC.
+ _should_retry_gc = true;
+ }
+ }
+ return res;
+}
+
void VM_G1IncCollectionPause::doit() {
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(!_should_initiate_conc_mark ||
@@ -106,11 +124,25 @@
// next GC pause to be an initial mark; it returns false if a
// marking cycle is already in progress.
//
- // If a marking cycle is already in progress just return and skip
- // the pause - the requesting thread should block in doit_epilogue
- // until the marking cycle is complete.
+ // If a marking cycle is already in progress just return and skip the
+ // pause below - if the reason for requesting this initial mark pause
+ // was due to a System.gc() then the requesting thread should block in
+ // doit_epilogue() until the marking cycle is complete.
+ //
+ // If this initial mark pause was requested as part of a humongous
+ // allocation then we know that the marking cycle must just have
+ // been started by another thread (possibly also allocating a humongous
+ // object) as there was no active marking cycle when the requesting
+ // thread checked before calling collect() in
+ // attempt_allocation_humongous(). Retrying the GC, in this case,
+ // will cause the requesting thread to spin inside collect() until the
+ // just started marking cycle is complete - which may be a while. So
+ // we do NOT retry the GC.
if (!res) {
- assert(_word_size == 0, "ExplicitGCInvokesConcurrent shouldn't be allocating");
+ assert(_word_size == 0, "Concurrent Full GC/Humongous Object IM shouldn't be allocating");
+ if (_gc_cause != GCCause::_g1_humongous_allocation) {
+ _should_retry_gc = true;
+ }
return;
}
}
@@ -123,6 +155,13 @@
true /* expect_null_cur_alloc_region */);
} else {
assert(_result == NULL, "invariant");
+ if (!_pause_succeeded) {
+ // Another possible reason reason for the pause to not be successful
+ // is that, again, the GC locker is active (and has become active
+ // since the prologue was executed). In this case we should retry
+ // the pause after waiting for the GC locker to become inactive.
+ _should_retry_gc = true;
+ }
}
}
@@ -168,6 +207,7 @@
}
void VM_CGC_Operation::acquire_pending_list_lock() {
+ assert(_needs_pll, "don't call this otherwise");
// The caller may block while communicating
// with the SLT thread in order to acquire/release the PLL.
ConcurrentMarkThread::slt()->
@@ -175,6 +215,7 @@
}
void VM_CGC_Operation::release_and_notify_pending_list_lock() {
+ assert(_needs_pll, "don't call this otherwise");
// The caller may block while communicating
// with the SLT thread in order to acquire/release the PLL.
ConcurrentMarkThread::slt()->
@@ -198,7 +239,9 @@
bool VM_CGC_Operation::doit_prologue() {
// Note the relative order of the locks must match that in
// VM_GC_Operation::doit_prologue() or deadlocks can occur
- acquire_pending_list_lock();
+ if (_needs_pll) {
+ acquire_pending_list_lock();
+ }
Heap_lock->lock();
SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true;
@@ -210,5 +253,7 @@
// VM_GC_Operation::doit_epilogue()
SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false;
Heap_lock->unlock();
- release_and_notify_pending_list_lock();
+ if (_needs_pll) {
+ release_and_notify_pending_list_lock();
+ }
}
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,8 +43,9 @@
public:
VM_G1OperationWithAllocRequest(unsigned int gc_count_before,
- size_t word_size)
- : VM_GC_Operation(gc_count_before, GCCause::_allocation_failure),
+ size_t word_size,
+ GCCause::Cause gc_cause)
+ : VM_GC_Operation(gc_count_before, gc_cause),
_word_size(word_size), _result(NULL), _pause_succeeded(false) { }
HeapWord* result() { return _result; }
bool pause_succeeded() { return _pause_succeeded; }
@@ -77,6 +78,7 @@
class VM_G1IncCollectionPause: public VM_G1OperationWithAllocRequest {
private:
bool _should_initiate_conc_mark;
+ bool _should_retry_gc;
double _target_pause_time_ms;
unsigned int _full_collections_completed_before;
public:
@@ -86,11 +88,13 @@
double target_pause_time_ms,
GCCause::Cause gc_cause);
virtual VMOp_Type type() const { return VMOp_G1IncCollectionPause; }
+ virtual bool doit_prologue();
virtual void doit();
virtual void doit_epilogue();
virtual const char* name() const {
return "garbage-first incremental collection pause";
}
+ bool should_retry_gc() const { return _should_retry_gc; }
};
// Concurrent GC stop-the-world operations such as remark and cleanup;
@@ -98,6 +102,7 @@
class VM_CGC_Operation: public VM_Operation {
VoidClosure* _cl;
const char* _printGCMessage;
+ bool _needs_pll;
protected:
// java.lang.ref.Reference support
@@ -105,8 +110,8 @@
void release_and_notify_pending_list_lock();
public:
- VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg)
- : _cl(cl), _printGCMessage(printGCMsg) { }
+ VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg, bool needs_pll)
+ : _cl(cl), _printGCMessage(printGCMsg), _needs_pll(needs_pll) { }
virtual VMOp_Type type() const { return VMOp_CGC_Operation; }
virtual void doit();
virtual bool doit_prologue();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP
#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONMANAGER_INLINE_HPP
+#include "gc_implementation/parallelScavenge/psOldGen.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,29 +91,37 @@
MutableSpace *s = ls->space();
if (s->top() < top()) { // For all spaces preceding the one containing top()
if (s->free_in_words() > 0) {
- size_t area_touched_words = pointer_delta(s->end(), s->top());
- CollectedHeap::fill_with_object(s->top(), area_touched_words);
+ intptr_t cur_top = (intptr_t)s->top();
+ size_t words_left_to_fill = pointer_delta(s->end(), s->top());;
+ while (words_left_to_fill > 0) {
+ size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size());
+ assert(words_to_fill >= CollectedHeap::min_fill_size(),
+ err_msg("Remaining size ("SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")",
+ words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size()));
+ CollectedHeap::fill_with_object((HeapWord*)cur_top, words_to_fill);
+ if (!os::numa_has_static_binding()) {
+ size_t touched_words = words_to_fill;
#ifndef ASSERT
- if (!ZapUnusedHeapArea) {
- area_touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
- area_touched_words);
- }
+ if (!ZapUnusedHeapArea) {
+ touched_words = MIN2((size_t)align_object_size(typeArrayOopDesc::header_size(T_INT)),
+ touched_words);
+ }
#endif
- if (!os::numa_has_static_binding()) {
- MemRegion invalid;
- HeapWord *crossing_start = (HeapWord*)round_to((intptr_t)s->top(), os::vm_page_size());
- HeapWord *crossing_end = (HeapWord*)round_to((intptr_t)(s->top() + area_touched_words),
- os::vm_page_size());
- if (crossing_start != crossing_end) {
- // If object header crossed a small page boundary we mark the area
- // as invalid rounding it to a page_size().
- HeapWord *start = MAX2((HeapWord*)round_down((intptr_t)s->top(), page_size()), s->bottom());
- HeapWord *end = MIN2((HeapWord*)round_to((intptr_t)(s->top() + area_touched_words), page_size()),
- s->end());
- invalid = MemRegion(start, end);
+ MemRegion invalid;
+ HeapWord *crossing_start = (HeapWord*)round_to(cur_top, os::vm_page_size());
+ HeapWord *crossing_end = (HeapWord*)round_to(cur_top + touched_words, os::vm_page_size());
+ if (crossing_start != crossing_end) {
+ // If object header crossed a small page boundary we mark the area
+ // as invalid rounding it to a page_size().
+ HeapWord *start = MAX2((HeapWord*)round_down(cur_top, page_size()), s->bottom());
+ HeapWord *end = MIN2((HeapWord*)round_to(cur_top + touched_words, page_size()), s->end());
+ invalid = MemRegion(start, end);
+ }
+
+ ls->add_invalid_region(invalid);
}
-
- ls->add_invalid_region(invalid);
+ cur_top = cur_top + (words_to_fill * HeapWordSize);
+ words_left_to_fill -= words_to_fill;
}
}
} else {
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -85,7 +85,7 @@
const size_t max_len = size_t(arrayOopDesc::max_array_length(T_INT));
const size_t elements_per_word = HeapWordSize / sizeof(jint);
_filler_array_max_size = align_object_size(filler_array_hdr_size() +
- max_len * elements_per_word);
+ max_len / elements_per_word);
_barrier_set = NULL;
_is_gc_active = false;
@@ -303,10 +303,6 @@
return align_object_size(filler_array_hdr_size()); // align to MinObjAlignment
}
-size_t CollectedHeap::filler_array_max_size() {
- return _filler_array_max_size;
-}
-
#ifdef ASSERT
void CollectedHeap::fill_args_check(HeapWord* start, size_t words)
{
@@ -333,10 +329,11 @@
const size_t payload_size = words - filler_array_hdr_size();
const size_t len = payload_size * HeapWordSize / sizeof(jint);
+ assert((int)len >= 0, err_msg("size too large " SIZE_FORMAT " becomes %d", words, (int)len));
// Set the length first for concurrent GC.
((arrayOop)start)->set_length((int)len);
- post_allocation_setup_common(Universe::intArrayKlassObj(), start, words);
+ post_allocation_setup_common(Universe::intArrayKlassObj(), start);
DEBUG_ONLY(zap_filler_array(start, words, zap);)
}
@@ -349,8 +346,7 @@
fill_with_array(start, words, zap);
} else if (words > 0) {
assert(words == min_fill_size(), "unaligned size");
- post_allocation_setup_common(SystemDictionary::Object_klass(), start,
- words);
+ post_allocation_setup_common(SystemDictionary::Object_klass(), start);
}
}
@@ -480,7 +476,7 @@
assert(ScavengeRootsInCode > 0, "must be");
obj = common_mem_allocate_init(size, CHECK_NULL);
}
- post_allocation_setup_common(klass, obj, size);
+ post_allocation_setup_common(klass, obj);
assert(Universe::is_bootstrapping() ||
!((oop)obj)->blueprint()->oop_is_array(), "must not be an array");
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -128,7 +128,6 @@
// Reinitialize tlabs before resuming mutators.
virtual void resize_all_tlabs();
- protected:
// Allocate from the current thread's TLAB, with broken-out slow path.
inline static HeapWord* allocate_from_tlab(Thread* thread, size_t size);
static HeapWord* allocate_from_tlab_slow(Thread* thread, size_t size);
@@ -150,18 +149,14 @@
inline static HeapWord* common_permanent_mem_allocate_init(size_t size, TRAPS);
// Helper functions for (VM) allocation.
- inline static void post_allocation_setup_common(KlassHandle klass,
- HeapWord* obj, size_t size);
+ inline static void post_allocation_setup_common(KlassHandle klass, HeapWord* obj);
inline static void post_allocation_setup_no_klass_install(KlassHandle klass,
- HeapWord* objPtr,
- size_t size);
+ HeapWord* objPtr);
- inline static void post_allocation_setup_obj(KlassHandle klass,
- HeapWord* obj, size_t size);
+ inline static void post_allocation_setup_obj(KlassHandle klass, HeapWord* obj);
inline static void post_allocation_setup_array(KlassHandle klass,
- HeapWord* obj, size_t size,
- int length);
+ HeapWord* obj, int length);
// Clears an allocated object.
inline static void init_obj(HeapWord* obj, size_t size);
@@ -169,7 +164,6 @@
// Filler object utilities.
static inline size_t filler_array_hdr_size();
static inline size_t filler_array_min_size();
- static inline size_t filler_array_max_size();
DEBUG_ONLY(static void fill_args_check(HeapWord* start, size_t words);)
DEBUG_ONLY(static void zap_filler_array(HeapWord* start, size_t words, bool zap = true);)
@@ -197,6 +191,10 @@
G1CollectedHeap
};
+ static inline size_t filler_array_max_size() {
+ return _filler_array_max_size;
+ }
+
virtual CollectedHeap::Name kind() const { return CollectedHeap::Abstract; }
/**
@@ -366,9 +364,7 @@
inline static oop permanent_obj_allocate_no_klass_install(KlassHandle klass,
int size,
TRAPS);
- inline static void post_allocation_install_obj_klass(KlassHandle klass,
- oop obj,
- int size);
+ inline static void post_allocation_install_obj_klass(KlassHandle klass, oop obj);
inline static oop permanent_array_allocate(KlassHandle klass, int size, int length, TRAPS);
// Raw memory allocation facilities
@@ -662,9 +658,6 @@
}
}
- // Allocate GCHeapLog during VM startup
- static void initialize_heap_log();
-
// Heap verification
virtual void verify(bool allow_dirty, bool silent, VerifyOption option) = 0;
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,15 +50,13 @@
// Inline allocation implementations.
void CollectedHeap::post_allocation_setup_common(KlassHandle klass,
- HeapWord* obj,
- size_t size) {
- post_allocation_setup_no_klass_install(klass, obj, size);
- post_allocation_install_obj_klass(klass, oop(obj), (int) size);
+ HeapWord* obj) {
+ post_allocation_setup_no_klass_install(klass, obj);
+ post_allocation_install_obj_klass(klass, oop(obj));
}
void CollectedHeap::post_allocation_setup_no_klass_install(KlassHandle klass,
- HeapWord* objPtr,
- size_t size) {
+ HeapWord* objPtr) {
oop obj = (oop)objPtr;
assert(obj != NULL, "NULL object pointer");
@@ -71,8 +69,7 @@
}
void CollectedHeap::post_allocation_install_obj_klass(KlassHandle klass,
- oop obj,
- int size) {
+ oop obj) {
// These asserts are kind of complicated because of klassKlass
// and the beginning of the world.
assert(klass() != NULL || !Universe::is_fully_initialized(), "NULL klass");
@@ -101,9 +98,8 @@
}
void CollectedHeap::post_allocation_setup_obj(KlassHandle klass,
- HeapWord* obj,
- size_t size) {
- post_allocation_setup_common(klass, obj, size);
+ HeapWord* obj) {
+ post_allocation_setup_common(klass, obj);
assert(Universe::is_bootstrapping() ||
!((oop)obj)->blueprint()->oop_is_array(), "must not be an array");
// notify jvmti and dtrace
@@ -112,14 +108,13 @@
void CollectedHeap::post_allocation_setup_array(KlassHandle klass,
HeapWord* obj,
- size_t size,
int length) {
// Set array length before setting the _klass field
// in post_allocation_setup_common() because the klass field
// indicates that the object is parsable by concurrent GC.
assert(length >= 0, "length should be non-negative");
((arrayOop)obj)->set_length(length);
- post_allocation_setup_common(klass, obj, size);
+ post_allocation_setup_common(klass, obj);
assert(((oop)obj)->blueprint()->oop_is_array(), "must be an array");
// notify jvmti and dtrace (must be after length is set for dtrace)
post_allocation_notify(klass, (oop)obj);
@@ -256,7 +251,7 @@
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL);
- post_allocation_setup_obj(klass, obj, size);
+ post_allocation_setup_obj(klass, obj);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
@@ -269,7 +264,7 @@
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_init(size, CHECK_NULL);
- post_allocation_setup_array(klass, obj, size, length);
+ post_allocation_setup_array(klass, obj, length);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
@@ -283,7 +278,7 @@
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_mem_allocate_noinit(size, CHECK_NULL);
((oop)obj)->set_klass_gap(0);
- post_allocation_setup_array(klass, obj, size, length);
+ post_allocation_setup_array(klass, obj, length);
#ifndef PRODUCT
const size_t hs = oopDesc::header_size()+1;
Universe::heap()->check_for_non_bad_heap_word_value(obj+hs, size-hs);
@@ -293,7 +288,7 @@
oop CollectedHeap::permanent_obj_allocate(KlassHandle klass, int size, TRAPS) {
oop obj = permanent_obj_allocate_no_klass_install(klass, size, CHECK_NULL);
- post_allocation_install_obj_klass(klass, obj, size);
+ post_allocation_install_obj_klass(klass, obj);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value((HeapWord*) obj,
size));
return obj;
@@ -306,7 +301,7 @@
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL);
- post_allocation_setup_no_klass_install(klass, obj, size);
+ post_allocation_setup_no_klass_install(klass, obj);
#ifndef PRODUCT
const size_t hs = oopDesc::header_size();
Universe::heap()->check_for_bad_heap_word_value(obj+hs, size-hs);
@@ -322,7 +317,7 @@
assert(!Universe::heap()->is_gc_active(), "Allocation during gc not allowed");
assert(size >= 0, "int won't convert to size_t");
HeapWord* obj = common_permanent_mem_allocate_init(size, CHECK_NULL);
- post_allocation_setup_array(klass, obj, size, length);
+ post_allocation_setup_array(klass, obj, length);
NOT_PRODUCT(Universe::heap()->check_for_bad_heap_word_value(obj, size));
return (oop)obj;
}
--- a/hotspot/src/share/vm/memory/dump.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/memory/dump.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -297,16 +297,14 @@
if (obj->blueprint()->oop_is_instanceKlass()) {
instanceKlass* ik = instanceKlass::cast((klassOop)obj);
- typeArrayOop inner_classes = ik->inner_classes();
- if (inner_classes != NULL) {
- constantPoolOop constants = ik->constants();
- int n = inner_classes->length();
- for (int i = 0; i < n; i += instanceKlass::inner_class_next_offset) {
- int ioff = i + instanceKlass::inner_class_inner_name_offset;
- int index = inner_classes->ushort_at(ioff);
- if (index != 0) {
- _closure->do_symbol(constants->symbol_at_addr(index));
- }
+ instanceKlassHandle ik_h((klassOop)obj);
+ InnerClassesIterator iter(ik_h);
+ constantPoolOop constants = ik->constants();
+ for (; !iter.done(); iter.next()) {
+ int index = iter.inner_name_index();
+
+ if (index != 0) {
+ _closure->do_symbol(constants->symbol_at_addr(index));
}
}
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1133,6 +1133,36 @@
return probe;
}
+u2 instanceKlass::enclosing_method_data(int offset) {
+ typeArrayOop inner_class_list = inner_classes();
+ if (inner_class_list == NULL) {
+ return 0;
+ }
+ int length = inner_class_list->length();
+ if (length % inner_class_next_offset == 0) {
+ return 0;
+ } else {
+ int index = length - enclosing_method_attribute_size;
+ typeArrayHandle inner_class_list_h(inner_class_list);
+ assert(offset < enclosing_method_attribute_size, "invalid offset");
+ return inner_class_list_h->ushort_at(index + offset);
+ }
+}
+
+void instanceKlass::set_enclosing_method_indices(u2 class_index,
+ u2 method_index) {
+ typeArrayOop inner_class_list = inner_classes();
+ assert (inner_class_list != NULL, "_inner_classes list is not set up");
+ int length = inner_class_list->length();
+ if (length % inner_class_next_offset == enclosing_method_attribute_size) {
+ int index = length - enclosing_method_attribute_size;
+ typeArrayHandle inner_class_list_h(inner_class_list);
+ inner_class_list_h->ushort_at_put(
+ index + enclosing_method_class_index_offset, class_index);
+ inner_class_list_h->ushort_at_put(
+ index + enclosing_method_method_index_offset, method_index);
+ }
+}
// Lookup or create a jmethodID.
// This code is called by the VMThread and JavaThreads so the
@@ -2107,28 +2137,21 @@
jint access = access_flags().as_int();
// But check if it happens to be member class.
- typeArrayOop inner_class_list = inner_classes();
- int length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
- assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
- if (length > 0) {
- typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
- instanceKlassHandle ik(THREAD, k);
- for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
- int ioff = inner_class_list_h->ushort_at(
- i + instanceKlass::inner_class_inner_class_info_offset);
-
- // Inner class attribute can be zero, skip it.
- // Strange but true: JVM spec. allows null inner class refs.
- if (ioff == 0) continue;
-
- // only look at classes that are already loaded
- // since we are looking for the flags for our self.
- Symbol* inner_name = ik->constants()->klass_name_at(ioff);
- if ((ik->name() == inner_name)) {
- // This is really a member class.
- access = inner_class_list_h->ushort_at(i + instanceKlass::inner_class_access_flags_offset);
- break;
- }
+ instanceKlassHandle ik(THREAD, k);
+ InnerClassesIterator iter(ik);
+ for (; !iter.done(); iter.next()) {
+ int ioff = iter.inner_class_info_index();
+ // Inner class attribute can be zero, skip it.
+ // Strange but true: JVM spec. allows null inner class refs.
+ if (ioff == 0) continue;
+
+ // only look at classes that are already loaded
+ // since we are looking for the flags for our self.
+ Symbol* inner_name = ik->constants()->klass_name_at(ioff);
+ if ((ik->name() == inner_name)) {
+ // This is really a member class.
+ access = iter.inner_access_flags();
+ break;
}
}
// Remember to strip ACC_SUPER bit
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -188,7 +188,17 @@
klassOop _host_klass;
// Class signers.
objArrayOop _signers;
- // inner_classes attribute.
+ // The InnerClasses attribute and EnclosingMethod attribute. The
+ // _inner_classes is an array of shorts. If the class has InnerClasses
+ // attribute, then the _inner_classes array begins with 4-tuples of shorts
+ // [inner_class_info_index, outer_class_info_index,
+ // inner_name_index, inner_class_access_flags] for the InnerClasses
+ // attribute. If the EnclosingMethod attribute exists, it occupies the
+ // last two shorts [class_index, method_index] of the array. If only
+ // the InnerClasses attribute exists, the _inner_classes array length is
+ // number_of_inner_classes * 4. If the class has both InnerClasses
+ // and EnclosingMethod attributes the _inner_classes array length is
+ // number_of_inner_classes * 4 + enclosing_method_attribute_size.
typeArrayOop _inner_classes;
// Implementors of this interface (not valid if it overflows)
klassOop _implementors[implementors_limit];
@@ -251,8 +261,6 @@
// Array of interesting part(s) of the previous version(s) of this
// instanceKlass. See PreviousVersionWalker below.
GrowableArray<PreviousVersionNode *>* _previous_versions;
- u2 _enclosing_method_class_index; // Constant pool index for class of enclosing method, or 0 if none
- u2 _enclosing_method_method_index; // Constant pool index for name and type of enclosing method, or 0 if none
// JVMTI fields can be moved to their own structure - see 6315920
unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH
jint _cached_class_file_len; // JVMTI: length of above
@@ -351,6 +359,12 @@
inner_class_next_offset = 4
};
+ enum EnclosingMethodAttributeOffset {
+ enclosing_method_class_index_offset = 0,
+ enclosing_method_method_index_offset = 1,
+ enclosing_method_attribute_size = 2
+ };
+
// method override check
bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
@@ -533,11 +547,15 @@
Symbol* generic_signature() const { return _generic_signature; }
void set_generic_signature(Symbol* sig) { _generic_signature = sig; }
- u2 enclosing_method_class_index() const { return _enclosing_method_class_index; }
- u2 enclosing_method_method_index() const { return _enclosing_method_method_index; }
+ u2 enclosing_method_data(int offset);
+ u2 enclosing_method_class_index() {
+ return enclosing_method_data(enclosing_method_class_index_offset);
+ }
+ u2 enclosing_method_method_index() {
+ return enclosing_method_data(enclosing_method_method_index_offset);
+ }
void set_enclosing_method_indices(u2 class_index,
- u2 method_index) { _enclosing_method_class_index = class_index;
- _enclosing_method_method_index = method_index; }
+ u2 method_index);
// jmethodID support
static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
@@ -1053,4 +1071,83 @@
nmethod* get_nmethod() { return _nmethod; }
};
+// An iterator that's used to access the inner classes indices in the
+// instanceKlass::_inner_classes array.
+class InnerClassesIterator : public StackObj {
+ private:
+ typeArrayHandle _inner_classes;
+ int _length;
+ int _idx;
+ public:
+
+ InnerClassesIterator(instanceKlassHandle k) {
+ _inner_classes = k->inner_classes();
+ if (k->inner_classes() != NULL) {
+ _length = _inner_classes->length();
+ // The inner class array's length should be the multiple of
+ // inner_class_next_offset if it only contains the InnerClasses
+ // attribute data, or it should be
+ // n*inner_class_next_offset+enclosing_method_attribute_size
+ // if it also contains the EnclosingMethod data.
+ assert((_length % instanceKlass::inner_class_next_offset == 0 ||
+ _length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size),
+ "just checking");
+ // Remove the enclosing_method portion if exists.
+ if (_length % instanceKlass::inner_class_next_offset == instanceKlass::enclosing_method_attribute_size) {
+ _length -= instanceKlass::enclosing_method_attribute_size;
+ }
+ } else {
+ _length = 0;
+ }
+ _idx = 0;
+ }
+
+ int length() const {
+ return _length;
+ }
+
+ void next() {
+ _idx += instanceKlass::inner_class_next_offset;
+ }
+
+ bool done() const {
+ return (_idx >= _length);
+ }
+
+ u2 inner_class_info_index() const {
+ return _inner_classes->ushort_at(
+ _idx + instanceKlass::inner_class_inner_class_info_offset);
+ }
+
+ void set_inner_class_info_index(u2 index) {
+ _inner_classes->ushort_at_put(
+ _idx + instanceKlass::inner_class_inner_class_info_offset, index);
+ }
+
+ u2 outer_class_info_index() const {
+ return _inner_classes->ushort_at(
+ _idx + instanceKlass::inner_class_outer_class_info_offset);
+ }
+
+ void set_outer_class_info_index(u2 index) {
+ _inner_classes->ushort_at_put(
+ _idx + instanceKlass::inner_class_outer_class_info_offset, index);
+ }
+
+ u2 inner_name_index() const {
+ return _inner_classes->ushort_at(
+ _idx + instanceKlass::inner_class_inner_name_offset);
+ }
+
+ void set_inner_name_index(u2 index) {
+ _inner_classes->ushort_at_put(
+ _idx + instanceKlass::inner_class_inner_name_offset, index);
+ }
+
+ u2 inner_access_flags() const {
+ return _inner_classes->ushort_at(
+ _idx + instanceKlass::inner_class_access_flags_offset);
+ }
+};
+
#endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -416,7 +416,6 @@
ik->set_methods_annotations(NULL);
ik->set_methods_parameter_annotations(NULL);
ik->set_methods_default_annotations(NULL);
- ik->set_enclosing_method_indices(0, 0);
ik->set_jvmti_cached_class_field_map(NULL);
ik->set_initial_method_idnum(0);
assert(k()->is_parsable(), "should be parsable here.");
--- a/hotspot/src/share/vm/oops/klass.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -174,10 +174,9 @@
}
void Klass_vtbl::post_new_init_klass(KlassHandle& klass,
- klassOop new_klass,
- int size) const {
+ klassOop new_klass) const {
assert(!new_klass->klass_part()->null_vtbl(), "Not a complete klass");
- CollectedHeap::post_allocation_install_obj_klass(klass, new_klass, size);
+ CollectedHeap::post_allocation_install_obj_klass(klass, new_klass);
}
void* Klass_vtbl::operator new(size_t ignored, KlassHandle& klass,
--- a/hotspot/src/share/vm/oops/klass.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -149,7 +149,7 @@
// by the shared "base_create" subroutines.
//
virtual void* allocate_permanent(KlassHandle& klass, int size, TRAPS) const = 0;
- void post_new_init_klass(KlassHandle& klass, klassOop obj, int size) const;
+ void post_new_init_klass(KlassHandle& klass, klassOop obj) const;
// Every subclass on which vtbl_value is called must include this macro.
// Delay the installation of the klassKlass pointer until after the
@@ -160,7 +160,7 @@
if (HAS_PENDING_EXCEPTION) return NULL; \
klassOop new_klass = ((Klass*) result)->as_klassOop(); \
OrderAccess::storestore(); \
- post_new_init_klass(klass_klass, new_klass, size); \
+ post_new_init_klass(klass_klass, new_klass); \
return result; \
}
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -257,6 +257,18 @@
return "exception method";
}
+ if (callee_method->should_not_inline()) {
+ return "disallowed by CompilerOracle";
+ }
+
+ if (UseStringCache) {
+ // Do not inline StringCache::profile() method used only at the beginning.
+ if (callee_method->name() == ciSymbol::profile_name() &&
+ callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
+ return "profiling method";
+ }
+ }
+
// use frequency-based objections only for non-trivial methods
if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL;
@@ -278,18 +290,6 @@
}
}
- if (callee_method->should_not_inline()) {
- return "disallowed by CompilerOracle";
- }
-
- if (UseStringCache) {
- // Do not inline StringCache::profile() method used only at the beginning.
- if (callee_method->name() == ciSymbol::profile_name() &&
- callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
- return "profiling method";
- }
- }
-
return NULL;
}
--- a/hotspot/src/share/vm/opto/c2_globals.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -465,6 +465,9 @@
notproduct(bool, PrintOptimizePtrCompare, false, \
"Print information about optimized pointers compare") \
\
+ notproduct(bool, VerifyConnectionGraph , true, \
+ "Verify Connection Graph construction in Escape Analysis") \
+ \
product(bool, UseOptoBiasInlining, true, \
"Generate biased locking code in C2 ideal graph") \
\
--- a/hotspot/src/share/vm/opto/callnode.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1538,10 +1538,7 @@
// If we are locking an unescaped object, the lock/unlock is unnecessary
//
ConnectionGraph *cgr = phase->C->congraph();
- PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
- if (cgr != NULL)
- es = cgr->escape_state(obj_node());
- if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
+ if (cgr != NULL && cgr->not_global_escape(obj_node())) {
assert(!is_eliminated() || is_coarsened(), "sanity");
// The lock could be marked eliminated by lock coarsening
// code during first IGVN before EA. Replace coarsened flag
@@ -1680,10 +1677,7 @@
// If we are unlocking an unescaped object, the lock/unlock is unnecessary.
//
ConnectionGraph *cgr = phase->C->congraph();
- PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
- if (cgr != NULL)
- es = cgr->escape_state(obj_node());
- if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
+ if (cgr != NULL && cgr->not_global_escape(obj_node())) {
assert(!is_eliminated() || is_coarsened(), "sanity");
// The lock could be marked eliminated by lock coarsening
// code during first IGVN before EA. Replace coarsened flag
--- a/hotspot/src/share/vm/opto/callnode.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/callnode.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -546,6 +546,12 @@
// or result projection is there are several CheckCastPP
// or returns NULL if there is no one.
Node *result_cast();
+ // Does this node returns pointer?
+ bool returns_pointer() const {
+ const TypeTuple *r = tf()->range();
+ return (r->cnt() > TypeFunc::Parms &&
+ r->field_at(TypeFunc::Parms)->isa_ptr());
+ }
// Collect all the interesting edges from a call for use in
// replacing the call by something else. Used by macro expansion
--- a/hotspot/src/share/vm/opto/compile.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/compile.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1707,7 +1707,6 @@
if (major_progress()) print_method("PhaseIdealLoop before EA", 2);
if (failing()) return;
}
- TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
ConnectionGraph::do_analysis(this, &igvn);
if (failing()) return;
@@ -1719,6 +1718,7 @@
if (failing()) return;
if (congraph() != NULL && macro_count() > 0) {
+ NOT_PRODUCT( TracePhase t2("macroEliminate", &_t_macroEliminate, TimeCompiler); )
PhaseMacroExpand mexp(igvn);
mexp.eliminate_macro_nodes();
igvn.set_delay_transform(false);
@@ -1875,10 +1875,10 @@
cfg.Estimate_Block_Frequency();
cfg.GlobalCodeMotion(m,unique(),proj_list);
+ if (failing()) return;
print_method("Global code motion", 2);
- if (failing()) return;
NOT_PRODUCT( verify_graph_edges(); )
debug_only( cfg.verify(); )
--- a/hotspot/src/share/vm/opto/escape.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "ci/bcEscapeAnalyzer.hpp"
+#include "compiler/compileLog.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.hpp"
#include "opto/c2compiler.hpp"
@@ -34,125 +35,1935 @@
#include "opto/phaseX.hpp"
#include "opto/rootnode.hpp"
-void PointsToNode::add_edge(uint targIdx, PointsToNode::EdgeType et) {
- uint v = (targIdx << EdgeShift) + ((uint) et);
- if (_edges == NULL) {
- Arena *a = Compile::current()->comp_arena();
- _edges = new(a) GrowableArray<uint>(a, INITIAL_EDGE_COUNT, 0, 0);
- }
- _edges->append_if_missing(v);
-}
-
-void PointsToNode::remove_edge(uint targIdx, PointsToNode::EdgeType et) {
- uint v = (targIdx << EdgeShift) + ((uint) et);
-
- _edges->remove(v);
-}
-
-#ifndef PRODUCT
-static const char *node_type_names[] = {
- "UnknownType",
- "JavaObject",
- "LocalVar",
- "Field"
-};
-
-static const char *esc_names[] = {
- "UnknownEscape",
- "NoEscape",
- "ArgEscape",
- "GlobalEscape"
-};
-
-static const char *edge_type_suffix[] = {
- "?", // UnknownEdge
- "P", // PointsToEdge
- "D", // DeferredEdge
- "F" // FieldEdge
-};
-
-void PointsToNode::dump(bool print_state) const {
- NodeType nt = node_type();
- tty->print("%s ", node_type_names[(int) nt]);
- if (print_state) {
- EscapeState es = escape_state();
- tty->print("%s %s ", esc_names[(int) es], _scalar_replaceable ? "":"NSR");
- }
- tty->print("[[");
- for (uint i = 0; i < edge_count(); i++) {
- tty->print(" %d%s", edge_target(i), edge_type_suffix[(int) edge_type(i)]);
- }
- tty->print("]] ");
- if (_node == NULL)
- tty->print_cr("<null>");
- else
- _node->dump();
-}
-#endif
-
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
- _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
- _processed(C->comp_arena()),
- pt_ptset(C->comp_arena()),
- pt_visited(C->comp_arena()),
- pt_worklist(C->comp_arena(), 4, 0, 0),
+ _nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
_collecting(true),
- _progress(false),
+ _verify(false),
_compile(C),
_igvn(igvn),
_node_map(C->comp_arena()) {
-
- _phantom_object = C->top()->_idx,
- add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
-
+ // Add unknown java object.
+ add_java_object(C->top(), PointsToNode::GlobalEscape);
+ phantom_obj = ptnode_adr(C->top()->_idx)->as_JavaObject();
// Add ConP(#NULL) and ConN(#NULL) nodes.
Node* oop_null = igvn->zerocon(T_OBJECT);
- _oop_null = oop_null->_idx;
- assert(_oop_null < nodes_size(), "should be created already");
- add_node(oop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true);
-
+ assert(oop_null->_idx < nodes_size(), "should be created already");
+ add_java_object(oop_null, PointsToNode::NoEscape);
+ null_obj = ptnode_adr(oop_null->_idx)->as_JavaObject();
if (UseCompressedOops) {
Node* noop_null = igvn->zerocon(T_NARROWOOP);
- _noop_null = noop_null->_idx;
- assert(_noop_null < nodes_size(), "should be created already");
- add_node(noop_null, PointsToNode::JavaObject, PointsToNode::NoEscape, true);
- } else {
- _noop_null = _oop_null; // Should be initialized
+ assert(noop_null->_idx < nodes_size(), "should be created already");
+ map_ideal_node(noop_null, null_obj);
}
_pcmp_neq = NULL; // Should be initialized
_pcmp_eq = NULL;
}
-void ConnectionGraph::add_pointsto_edge(uint from_i, uint to_i) {
- PointsToNode *f = ptnode_adr(from_i);
- PointsToNode *t = ptnode_adr(to_i);
+bool ConnectionGraph::has_candidates(Compile *C) {
+ // EA brings benefits only when the code has allocations and/or locks which
+ // are represented by ideal Macro nodes.
+ int cnt = C->macro_count();
+ for( int i=0; i < cnt; i++ ) {
+ Node *n = C->macro_node(i);
+ if ( n->is_Allocate() )
+ return true;
+ if( n->is_Lock() ) {
+ Node* obj = n->as_Lock()->obj_node()->uncast();
+ if( !(obj->is_Parm() || obj->is_Con()) )
+ return true;
+ }
+ }
+ return false;
+}
+
+void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
+ Compile::TracePhase t2("escapeAnalysis", &Phase::_t_escapeAnalysis, true);
+ ResourceMark rm;
+
+ // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
+ // to create space for them in ConnectionGraph::_nodes[].
+ Node* oop_null = igvn->zerocon(T_OBJECT);
+ Node* noop_null = igvn->zerocon(T_NARROWOOP);
+ ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
+ // Perform escape analysis
+ if (congraph->compute_escape()) {
+ // There are non escaping objects.
+ C->set_congraph(congraph);
+ }
+ // Cleanup.
+ if (oop_null->outcnt() == 0)
+ igvn->hash_delete(oop_null);
+ if (noop_null->outcnt() == 0)
+ igvn->hash_delete(noop_null);
+}
+
+bool ConnectionGraph::compute_escape() {
+ Compile* C = _compile;
+ PhaseGVN* igvn = _igvn;
+
+ // Worklists used by EA.
+ Unique_Node_List delayed_worklist;
+ GrowableArray<Node*> alloc_worklist;
+ GrowableArray<Node*> ptr_cmp_worklist;
+ GrowableArray<Node*> storestore_worklist;
+ GrowableArray<PointsToNode*> ptnodes_worklist;
+ GrowableArray<JavaObjectNode*> java_objects_worklist;
+ GrowableArray<JavaObjectNode*> non_escaped_worklist;
+ GrowableArray<FieldNode*> oop_fields_worklist;
+ DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )
+
+ { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true);
+
+ // 1. Populate Connection Graph (CG) with PointsTo nodes.
+ ideal_nodes.map(C->unique(), NULL); // preallocate space
+ // Initialize worklist
+ if (C->root() != NULL) {
+ ideal_nodes.push(C->root());
+ }
+ for( uint next = 0; next < ideal_nodes.size(); ++next ) {
+ Node* n = ideal_nodes.at(next);
+ // Create PointsTo nodes and add them to Connection Graph. Called
+ // only once per ideal node since ideal_nodes is Unique_Node list.
+ add_node_to_connection_graph(n, &delayed_worklist);
+ PointsToNode* ptn = ptnode_adr(n->_idx);
+ if (ptn != NULL) {
+ ptnodes_worklist.append(ptn);
+ if (ptn->is_JavaObject()) {
+ java_objects_worklist.append(ptn->as_JavaObject());
+ if ((n->is_Allocate() || n->is_CallStaticJava()) &&
+ (ptn->escape_state() < PointsToNode::GlobalEscape)) {
+ // Only allocations and java static calls results are interesting.
+ non_escaped_worklist.append(ptn->as_JavaObject());
+ }
+ } else if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
+ oop_fields_worklist.append(ptn->as_Field());
+ }
+ }
+ if (n->is_MergeMem()) {
+ // Collect all MergeMem nodes to add memory slices for
+ // scalar replaceable objects in split_unique_types().
+ _mergemem_worklist.append(n->as_MergeMem());
+ } else if (OptimizePtrCompare && n->is_Cmp() &&
+ (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
+ // Collect compare pointers nodes.
+ ptr_cmp_worklist.append(n);
+ } else if (n->is_MemBarStoreStore()) {
+ // Collect all MemBarStoreStore nodes so that depending on the
+ // escape status of the associated Allocate node some of them
+ // may be eliminated.
+ storestore_worklist.append(n);
+#ifdef ASSERT
+ } else if(n->is_AddP()) {
+ // Collect address nodes for graph verification.
+ addp_worklist.append(n);
+#endif
+ }
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ Node* m = n->fast_out(i); // Get user
+ ideal_nodes.push(m);
+ }
+ }
+ if (non_escaped_worklist.length() == 0) {
+ _collecting = false;
+ return false; // Nothing to do.
+ }
+ // Add final simple edges to graph.
+ while(delayed_worklist.size() > 0) {
+ Node* n = delayed_worklist.pop();
+ add_final_edges(n);
+ }
+ int ptnodes_length = ptnodes_worklist.length();
+
+#ifdef ASSERT
+ if (VerifyConnectionGraph) {
+ // Verify that no new simple edges could be created and all
+ // local vars has edges.
+ _verify = true;
+ for (int next = 0; next < ptnodes_length; ++next) {
+ PointsToNode* ptn = ptnodes_worklist.at(next);
+ add_final_edges(ptn->ideal_node());
+ if (ptn->is_LocalVar() && ptn->edge_count() == 0) {
+ ptn->dump();
+ assert(ptn->as_LocalVar()->edge_count() > 0, "sanity");
+ }
+ }
+ _verify = false;
+ }
+#endif
+
+ // 2. Finish Graph construction by propagating references to all
+ // java objects through graph.
+ if (!complete_connection_graph(ptnodes_worklist, non_escaped_worklist,
+ java_objects_worklist, oop_fields_worklist)) {
+ // All objects escaped or hit time or iterations limits.
+ _collecting = false;
+ return false;
+ }
+
+ // 3. Adjust scalar_replaceable state of nonescaping objects and push
+ // scalar replaceable allocations on alloc_worklist for processing
+ // in split_unique_types().
+ int non_escaped_length = non_escaped_worklist.length();
+ for (int next = 0; next < non_escaped_length; next++) {
+ JavaObjectNode* ptn = non_escaped_worklist.at(next);
+ if (ptn->escape_state() == PointsToNode::NoEscape &&
+ ptn->scalar_replaceable()) {
+ adjust_scalar_replaceable_state(ptn);
+ if (ptn->scalar_replaceable()) {
+ alloc_worklist.append(ptn->ideal_node());
+ }
+ }
+ }
+
+#ifdef ASSERT
+ if (VerifyConnectionGraph) {
+ // Verify that graph is complete - no new edges could be added or needed.
+ verify_connection_graph(ptnodes_worklist, non_escaped_worklist,
+ java_objects_worklist, addp_worklist);
+ }
+ assert(C->unique() == nodes_size(), "no new ideal nodes should be added during ConnectionGraph build");
+ assert(null_obj->escape_state() == PointsToNode::NoEscape &&
+ null_obj->edge_count() == 0 &&
+ !null_obj->arraycopy_src() &&
+ !null_obj->arraycopy_dst(), "sanity");
+#endif
+
+ _collecting = false;
+
+ } // TracePhase t3("connectionGraph")
+
+ // 4. Optimize ideal graph based on EA information.
+ bool has_non_escaping_obj = (non_escaped_worklist.length() > 0);
+ if (has_non_escaping_obj) {
+ optimize_ideal_graph(ptr_cmp_worklist, storestore_worklist);
+ }
+
+#ifndef PRODUCT
+ if (PrintEscapeAnalysis) {
+ dump(ptnodes_worklist); // Dump ConnectionGraph
+ }
+#endif
+
+ bool has_scalar_replaceable_candidates = (alloc_worklist.length() > 0);
+#ifdef ASSERT
+ if (VerifyConnectionGraph) {
+ int alloc_length = alloc_worklist.length();
+ for (int next = 0; next < alloc_length; ++next) {
+ Node* n = alloc_worklist.at(next);
+ PointsToNode* ptn = ptnode_adr(n->_idx);
+ assert(ptn->escape_state() == PointsToNode::NoEscape && ptn->scalar_replaceable(), "sanity");
+ }
+ }
+#endif
+
+ // 5. Separate memory graph for scalar replaceable allcations.
+ if (has_scalar_replaceable_candidates &&
+ C->AliasLevel() >= 3 && EliminateAllocations) {
+ // Now use the escape information to create unique types for
+ // scalar replaceable objects.
+ split_unique_types(alloc_worklist);
+ if (C->failing()) return false;
+ C->print_method("After Escape Analysis", 2);
+
+#ifdef ASSERT
+ } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
+ tty->print("=== No allocations eliminated for ");
+ C->method()->print_short_name();
+ if(!EliminateAllocations) {
+ tty->print(" since EliminateAllocations is off ===");
+ } else if(!has_scalar_replaceable_candidates) {
+ tty->print(" since there are no scalar replaceable candidates ===");
+ } else if(C->AliasLevel() < 3) {
+ tty->print(" since AliasLevel < 3 ===");
+ }
+ tty->cr();
+#endif
+ }
+ return has_non_escaping_obj;
+}
+
+// Populate Connection Graph with PointsTo nodes and create simple
+// connection graph edges.
+void ConnectionGraph::add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
+ assert(!_verify, "this method sould not be called for verification");
+ PhaseGVN* igvn = _igvn;
+ uint n_idx = n->_idx;
+ PointsToNode* n_ptn = ptnode_adr(n_idx);
+ if (n_ptn != NULL)
+ return; // No need to redefine PointsTo node during first iteration.
+
+ if (n->is_Call()) {
+ // Arguments to allocation and locking don't escape.
+ if (n->is_AbstractLock()) {
+ // Put Lock and Unlock nodes on IGVN worklist to process them during
+ // first IGVN optimization when escape information is still available.
+ record_for_optimizer(n);
+ } else if (n->is_Allocate()) {
+ add_call_node(n->as_Call());
+ record_for_optimizer(n);
+ } else {
+ if (n->is_CallStaticJava()) {
+ const char* name = n->as_CallStaticJava()->_name;
+ if (name != NULL && strcmp(name, "uncommon_trap") == 0)
+ return; // Skip uncommon traps
+ }
+ // Don't mark as processed since call's arguments have to be processed.
+ delayed_worklist->push(n);
+ // Check if a call returns an object.
+ if (n->as_Call()->returns_pointer() &&
+ n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
+ add_call_node(n->as_Call());
+ }
+ }
+ return;
+ }
+ // Put this check here to process call arguments since some call nodes
+ // point to phantom_obj.
+ if (n_ptn == phantom_obj || n_ptn == null_obj)
+ return; // Skip predefined nodes.
- assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
- assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge");
- assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge");
- if (to_i == _phantom_object) { // Quick test for most common object
- if (f->has_unknown_ptr()) {
- return;
+ int opcode = n->Opcode();
+ switch (opcode) {
+ case Op_AddP: {
+ Node* base = get_addp_base(n);
+ PointsToNode* ptn_base = ptnode_adr(base->_idx);
+ // Field nodes are created for all field types. They are used in
+ // adjust_scalar_replaceable_state() and split_unique_types().
+ // Note, non-oop fields will have only base edges in Connection
+ // Graph because such fields are not used for oop loads and stores.
+ int offset = address_offset(n, igvn);
+ add_field(n, PointsToNode::NoEscape, offset);
+ if (ptn_base == NULL) {
+ delayed_worklist->push(n); // Process it later.
+ } else {
+ n_ptn = ptnode_adr(n_idx);
+ add_base(n_ptn->as_Field(), ptn_base);
+ }
+ break;
+ }
+ case Op_CastX2P: {
+ map_ideal_node(n, phantom_obj);
+ break;
+ }
+ case Op_CastPP:
+ case Op_CheckCastPP:
+ case Op_EncodeP:
+ case Op_DecodeN: {
+ add_local_var_and_edge(n, PointsToNode::NoEscape,
+ n->in(1), delayed_worklist);
+ break;
+ }
+ case Op_CMoveP: {
+ add_local_var(n, PointsToNode::NoEscape);
+ // Do not add edges during first iteration because some could be
+ // not defined yet.
+ delayed_worklist->push(n);
+ break;
+ }
+ case Op_ConP:
+ case Op_ConN: {
+ // assume all oop constants globally escape except for null
+ PointsToNode::EscapeState es;
+ if (igvn->type(n) == TypePtr::NULL_PTR ||
+ igvn->type(n) == TypeNarrowOop::NULL_PTR) {
+ es = PointsToNode::NoEscape;
+ } else {
+ es = PointsToNode::GlobalEscape;
+ }
+ add_java_object(n, es);
+ break;
+ }
+ case Op_CreateEx: {
+ // assume that all exception objects globally escape
+ add_java_object(n, PointsToNode::GlobalEscape);
+ break;
+ }
+ case Op_LoadKlass:
+ case Op_LoadNKlass: {
+ // Unknown class is loaded
+ map_ideal_node(n, phantom_obj);
+ break;
+ }
+ case Op_LoadP:
+ case Op_LoadN:
+ case Op_LoadPLocked: {
+ // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+ // ThreadLocal has RawPrt type.
+ const Type* t = igvn->type(n);
+ if (t->make_ptr() != NULL) {
+ Node* adr = n->in(MemNode::Address);
+#ifdef ASSERT
+ if (!adr->is_AddP()) {
+ assert(igvn->type(adr)->isa_rawptr(), "sanity");
+ } else {
+ assert((ptnode_adr(adr->_idx) == NULL ||
+ ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
+ }
+#endif
+ add_local_var_and_edge(n, PointsToNode::NoEscape,
+ adr, delayed_worklist);
+ }
+ break;
+ }
+ case Op_Parm: {
+ map_ideal_node(n, phantom_obj);
+ break;
+ }
+ case Op_PartialSubtypeCheck: {
+ // Produces Null or notNull and is used in only in CmpP so
+ // phantom_obj could be used.
+ map_ideal_node(n, phantom_obj); // Result is unknown
+ break;
+ }
+ case Op_Phi: {
+ // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+ // ThreadLocal has RawPrt type.
+ const Type* t = n->as_Phi()->type();
+ if (t->make_ptr() != NULL) {
+ add_local_var(n, PointsToNode::NoEscape);
+ // Do not add edges during first iteration because some could be
+ // not defined yet.
+ delayed_worklist->push(n);
+ }
+ break;
+ }
+ case Op_Proj: {
+ // we are only interested in the oop result projection from a call
+ if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
+ n->in(0)->as_Call()->returns_pointer()) {
+ add_local_var_and_edge(n, PointsToNode::NoEscape,
+ n->in(0), delayed_worklist);
+ }
+ break;
+ }
+ case Op_Rethrow: // Exception object escapes
+ case Op_Return: {
+ if (n->req() > TypeFunc::Parms &&
+ igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
+ // Treat Return value as LocalVar with GlobalEscape escape state.
+ add_local_var_and_edge(n, PointsToNode::GlobalEscape,
+ n->in(TypeFunc::Parms), delayed_worklist);
+ }
+ break;
+ }
+ case Op_StoreP:
+ case Op_StoreN:
+ case Op_StorePConditional:
+ case Op_CompareAndSwapP:
+ case Op_CompareAndSwapN: {
+ Node* adr = n->in(MemNode::Address);
+ const Type *adr_type = igvn->type(adr);
+ adr_type = adr_type->make_ptr();
+ if (adr_type->isa_oopptr() ||
+ (opcode == Op_StoreP || opcode == Op_StoreN) &&
+ (adr_type == TypeRawPtr::NOTNULL &&
+ adr->in(AddPNode::Address)->is_Proj() &&
+ adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
+ delayed_worklist->push(n); // Process it later.
+#ifdef ASSERT
+ assert(adr->is_AddP(), "expecting an AddP");
+ if (adr_type == TypeRawPtr::NOTNULL) {
+ // Verify a raw address for a store captured by Initialize node.
+ int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
+ assert(offs != Type::OffsetBot, "offset must be a constant");
+ }
+#endif
+ } else {
+ // Ignore copy the displaced header to the BoxNode (OSR compilation).
+ if (adr->is_BoxLock())
+ break;
+ // Stored value escapes in unsafe access.
+ if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
+ // Pointer stores in G1 barriers looks like unsafe access.
+ // Ignore such stores to be able scalar replace non-escaping
+ // allocations.
+ if (UseG1GC && adr->is_AddP()) {
+ Node* base = get_addp_base(adr);
+ if (base->Opcode() == Op_LoadP &&
+ base->in(MemNode::Address)->is_AddP()) {
+ adr = base->in(MemNode::Address);
+ Node* tls = get_addp_base(adr);
+ if (tls->Opcode() == Op_ThreadLocal) {
+ int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
+ if (offs == in_bytes(JavaThread::satb_mark_queue_offset() +
+ PtrQueue::byte_offset_of_buf())) {
+ break; // G1 pre barier previous oop value store.
+ }
+ if (offs == in_bytes(JavaThread::dirty_card_queue_offset() +
+ PtrQueue::byte_offset_of_buf())) {
+ break; // G1 post barier card address store.
+ }
+ }
+ }
+ }
+ delayed_worklist->push(n); // Process unsafe access later.
+ break;
+ }
+#ifdef ASSERT
+ n->dump(1);
+ assert(false, "not unsafe or G1 barrier raw StoreP");
+#endif
+ }
+ break;
+ }
+ case Op_AryEq:
+ case Op_StrComp:
+ case Op_StrEquals:
+ case Op_StrIndexOf: {
+ add_local_var(n, PointsToNode::ArgEscape);
+ delayed_worklist->push(n); // Process it later.
+ break;
+ }
+ case Op_ThreadLocal: {
+ add_java_object(n, PointsToNode::ArgEscape);
+ break;
+ }
+ default:
+ ; // Do nothing for nodes not related to EA.
+ }
+ return;
+}
+
+#ifdef ASSERT
+#define ELSE_FAIL(name) \
+ /* Should not be called for not pointer type. */ \
+ n->dump(1); \
+ assert(false, name); \
+ break;
+#else
+#define ELSE_FAIL(name) \
+ break;
+#endif
+
+// Add final simple edges to graph.
+void ConnectionGraph::add_final_edges(Node *n) {
+ PointsToNode* n_ptn = ptnode_adr(n->_idx);
+#ifdef ASSERT
+ if (_verify && n_ptn->is_JavaObject())
+ return; // This method does not change graph for JavaObject.
+#endif
+
+ if (n->is_Call()) {
+ process_call_arguments(n->as_Call());
+ return;
+ }
+ assert(n->is_Store() || n->is_LoadStore() ||
+ (n_ptn != NULL) && (n_ptn->ideal_node() != NULL),
+ "node should be registered already");
+ int opcode = n->Opcode();
+ switch (opcode) {
+ case Op_AddP: {
+ Node* base = get_addp_base(n);
+ PointsToNode* ptn_base = ptnode_adr(base->_idx);
+ assert(ptn_base != NULL, "field's base should be registered");
+ add_base(n_ptn->as_Field(), ptn_base);
+ break;
+ }
+ case Op_CastPP:
+ case Op_CheckCastPP:
+ case Op_EncodeP:
+ case Op_DecodeN: {
+ add_local_var_and_edge(n, PointsToNode::NoEscape,
+ n->in(1), NULL);
+ break;
+ }
+ case Op_CMoveP: {
+ for (uint i = CMoveNode::IfFalse; i < n->req(); i++) {
+ Node* in = n->in(i);
+ if (in == NULL)
+ continue; // ignore NULL
+ Node* uncast_in = in->uncast();
+ if (uncast_in->is_top() || uncast_in == n)
+ continue; // ignore top or inputs which go back this node
+ PointsToNode* ptn = ptnode_adr(in->_idx);
+ assert(ptn != NULL, "node should be registered");
+ add_edge(n_ptn, ptn);
+ }
+ break;
+ }
+ case Op_LoadP:
+ case Op_LoadN:
+ case Op_LoadPLocked: {
+ // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+ // ThreadLocal has RawPrt type.
+ const Type* t = _igvn->type(n);
+ if (t->make_ptr() != NULL) {
+ Node* adr = n->in(MemNode::Address);
+ add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
+ break;
+ }
+ ELSE_FAIL("Op_LoadP");
+ }
+ case Op_Phi: {
+ // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
+ // ThreadLocal has RawPrt type.
+ const Type* t = n->as_Phi()->type();
+ if (t->make_ptr() != NULL) {
+ for (uint i = 1; i < n->req(); i++) {
+ Node* in = n->in(i);
+ if (in == NULL)
+ continue; // ignore NULL
+ Node* uncast_in = in->uncast();
+ if (uncast_in->is_top() || uncast_in == n)
+ continue; // ignore top or inputs which go back this node
+ PointsToNode* ptn = ptnode_adr(in->_idx);
+ assert(ptn != NULL, "node should be registered");
+ add_edge(n_ptn, ptn);
+ }
+ break;
+ }
+ ELSE_FAIL("Op_Phi");
+ }
+ case Op_Proj: {
+ // we are only interested in the oop result projection from a call
+ if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() &&
+ n->in(0)->as_Call()->returns_pointer()) {
+ add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0), NULL);
+ break;
+ }
+ ELSE_FAIL("Op_Proj");
+ }
+ case Op_Rethrow: // Exception object escapes
+ case Op_Return: {
+ if (n->req() > TypeFunc::Parms &&
+ _igvn->type(n->in(TypeFunc::Parms))->isa_oopptr()) {
+ // Treat Return value as LocalVar with GlobalEscape escape state.
+ add_local_var_and_edge(n, PointsToNode::GlobalEscape,
+ n->in(TypeFunc::Parms), NULL);
+ break;
+ }
+ ELSE_FAIL("Op_Return");
+ }
+ case Op_StoreP:
+ case Op_StoreN:
+ case Op_StorePConditional:
+ case Op_CompareAndSwapP:
+ case Op_CompareAndSwapN: {
+ Node* adr = n->in(MemNode::Address);
+ const Type *adr_type = _igvn->type(adr);
+ adr_type = adr_type->make_ptr();
+ if (adr_type->isa_oopptr() ||
+ (opcode == Op_StoreP || opcode == Op_StoreN) &&
+ (adr_type == TypeRawPtr::NOTNULL &&
+ adr->in(AddPNode::Address)->is_Proj() &&
+ adr->in(AddPNode::Address)->in(0)->is_Allocate())) {
+ // Point Address to Value
+ PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
+ assert(adr_ptn != NULL &&
+ adr_ptn->as_Field()->is_oop(), "node should be registered");
+ Node *val = n->in(MemNode::ValueIn);
+ PointsToNode* ptn = ptnode_adr(val->_idx);
+ assert(ptn != NULL, "node should be registered");
+ add_edge(adr_ptn, ptn);
+ break;
+ } else if ((opcode == Op_StoreP) && (adr_type == TypeRawPtr::BOTTOM)) {
+ // Stored value escapes in unsafe access.
+ Node *val = n->in(MemNode::ValueIn);
+ PointsToNode* ptn = ptnode_adr(val->_idx);
+ assert(ptn != NULL, "node should be registered");
+ ptn->set_escape_state(PointsToNode::GlobalEscape);
+ // Add edge to object for unsafe access with offset.
+ PointsToNode* adr_ptn = ptnode_adr(adr->_idx);
+ assert(adr_ptn != NULL, "node should be registered");
+ if (adr_ptn->is_Field()) {
+ assert(adr_ptn->as_Field()->is_oop(), "should be oop field");
+ add_edge(adr_ptn, ptn);
+ }
+ break;
+ }
+ ELSE_FAIL("Op_StoreP");
+ }
+ case Op_AryEq:
+ case Op_StrComp:
+ case Op_StrEquals:
+ case Op_StrIndexOf: {
+ // char[] arrays passed to string intrinsic do not escape but
+ // they are not scalar replaceable. Adjust escape state for them.
+ // Start from in(2) edge since in(1) is memory edge.
+ for (uint i = 2; i < n->req(); i++) {
+ Node* adr = n->in(i);
+ const Type* at = _igvn->type(adr);
+ if (!adr->is_top() && at->isa_ptr()) {
+ assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
+ at->isa_ptr() != NULL, "expecting a pointer");
+ if (adr->is_AddP()) {
+ adr = get_addp_base(adr);
+ }
+ PointsToNode* ptn = ptnode_adr(adr->_idx);
+ assert(ptn != NULL, "node should be registered");
+ add_edge(n_ptn, ptn);
+ }
+ }
+ break;
+ }
+ default: {
+ // This method should be called only for EA specific nodes which may
+ // miss some edges when they were created.
+#ifdef ASSERT
+ n->dump(1);
+#endif
+ guarantee(false, "unknown node");
+ }
+ }
+ return;
+}
+
+void ConnectionGraph::add_call_node(CallNode* call) {
+ assert(call->returns_pointer(), "only for call which returns pointer");
+ uint call_idx = call->_idx;
+ if (call->is_Allocate()) {
+ Node* k = call->in(AllocateNode::KlassNode);
+ const TypeKlassPtr* kt = k->bottom_type()->isa_klassptr();
+ assert(kt != NULL, "TypeKlassPtr required.");
+ ciKlass* cik = kt->klass();
+ PointsToNode::EscapeState es = PointsToNode::NoEscape;
+ bool scalar_replaceable = true;
+ if (call->is_AllocateArray()) {
+ if (!cik->is_array_klass()) { // StressReflectiveCode
+ es = PointsToNode::GlobalEscape;
+ } else {
+ int length = call->in(AllocateNode::ALength)->find_int_con(-1);
+ if (length < 0 || length > EliminateAllocationArraySizeLimit) {
+ // Not scalar replaceable if the length is not constant or too big.
+ scalar_replaceable = false;
+ }
+ }
+ } else { // Allocate instance
+ if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
+ !cik->is_instance_klass() || // StressReflectiveCode
+ cik->as_instance_klass()->has_finalizer()) {
+ es = PointsToNode::GlobalEscape;
+ }
+ }
+ add_java_object(call, es);
+ PointsToNode* ptn = ptnode_adr(call_idx);
+ if (!scalar_replaceable && ptn->scalar_replaceable()) {
+ ptn->set_scalar_replaceable(false);
+ }
+ } else if (call->is_CallStaticJava()) {
+ // Call nodes could be different types:
+ //
+ // 1. CallDynamicJavaNode (what happened during call is unknown):
+ //
+ // - mapped to GlobalEscape JavaObject node if oop is returned;
+ //
+ // - all oop arguments are escaping globally;
+ //
+ // 2. CallStaticJavaNode (execute bytecode analysis if possible):
+ //
+ // - the same as CallDynamicJavaNode if can't do bytecode analysis;
+ //
+ // - mapped to GlobalEscape JavaObject node if unknown oop is returned;
+ // - mapped to NoEscape JavaObject node if non-escaping object allocated
+ // during call is returned;
+ // - mapped to ArgEscape LocalVar node pointed to object arguments
+ // which are returned and does not escape during call;
+ //
+ // - oop arguments escaping status is defined by bytecode analysis;
+ //
+ // For a static call, we know exactly what method is being called.
+ // Use bytecode estimator to record whether the call's return value escapes.
+ ciMethod* meth = call->as_CallJava()->method();
+ if (meth == NULL) {
+ const char* name = call->as_CallStaticJava()->_name;
+ assert(strncmp(name, "_multianewarray", 15) == 0, "TODO: add failed case check");
+ // Returns a newly allocated unescaped object.
+ add_java_object(call, PointsToNode::NoEscape);
+ ptnode_adr(call_idx)->set_scalar_replaceable(false);
} else {
- f->set_has_unknown_ptr();
+ BCEscapeAnalyzer* call_analyzer = meth->get_bcea();
+ call_analyzer->copy_dependencies(_compile->dependencies());
+ if (call_analyzer->is_return_allocated()) {
+ // Returns a newly allocated unescaped object, simply
+ // update dependency information.
+ // Mark it as NoEscape so that objects referenced by
+ // it's fields will be marked as NoEscape at least.
+ add_java_object(call, PointsToNode::NoEscape);
+ ptnode_adr(call_idx)->set_scalar_replaceable(false);
+ } else {
+ // Determine whether any arguments are returned.
+ const TypeTuple* d = call->tf()->domain();
+ bool ret_arg = false;
+ for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+ if (d->field_at(i)->isa_ptr() != NULL &&
+ call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
+ ret_arg = true;
+ break;
+ }
+ }
+ if (ret_arg) {
+ add_local_var(call, PointsToNode::ArgEscape);
+ } else {
+ // Returns unknown object.
+ map_ideal_node(call, phantom_obj);
+ }
+ }
+ }
+ } else {
+ // An other type of call, assume the worst case:
+ // returned value is unknown and globally escapes.
+ assert(call->Opcode() == Op_CallDynamicJava, "add failed case check");
+ map_ideal_node(call, phantom_obj);
+ }
+}
+
+void ConnectionGraph::process_call_arguments(CallNode *call) {
+ bool is_arraycopy = false;
+ switch (call->Opcode()) {
+#ifdef ASSERT
+ case Op_Allocate:
+ case Op_AllocateArray:
+ case Op_Lock:
+ case Op_Unlock:
+ assert(false, "should be done already");
+ break;
+#endif
+ case Op_CallLeafNoFP:
+ is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
+ strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
+ // fall through
+ case Op_CallLeaf: {
+ // Stub calls, objects do not escape but they are not scale replaceable.
+ // Adjust escape state for outgoing arguments.
+ const TypeTuple * d = call->tf()->domain();
+ bool src_has_oops = false;
+ for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+ const Type* at = d->field_at(i);
+ Node *arg = call->in(i);
+ const Type *aat = _igvn->type(arg);
+ if (arg->is_top() || !at->isa_ptr() || !aat->isa_ptr())
+ continue;
+ if (arg->is_AddP()) {
+ //
+ // The inline_native_clone() case when the arraycopy stub is called
+ // after the allocation before Initialize and CheckCastPP nodes.
+ // Or normal arraycopy for object arrays case.
+ //
+ // Set AddP's base (Allocate) as not scalar replaceable since
+ // pointer to the base (with offset) is passed as argument.
+ //
+ arg = get_addp_base(arg);
+ }
+ PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
+ assert(arg_ptn != NULL, "should be registered");
+ PointsToNode::EscapeState arg_esc = arg_ptn->escape_state();
+ if (is_arraycopy || arg_esc < PointsToNode::ArgEscape) {
+ assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
+ aat->isa_ptr() != NULL, "expecting an Ptr");
+ bool arg_has_oops = aat->isa_oopptr() &&
+ (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
+ (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
+ if (i == TypeFunc::Parms) {
+ src_has_oops = arg_has_oops;
+ }
+ //
+ // src or dst could be j.l.Object when other is basic type array:
+ //
+ // arraycopy(char[],0,Object*,0,size);
+ // arraycopy(Object*,0,char[],0,size);
+ //
+ // Don't add edges in such cases.
+ //
+ bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy &&
+ arg_has_oops && (i > TypeFunc::Parms);
+#ifdef ASSERT
+ if (!(is_arraycopy ||
+ call->as_CallLeaf()->_name != NULL &&
+ (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 ||
+ strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
+ ) {
+ call->dump();
+ assert(false, "EA: unexpected CallLeaf");
+ }
+#endif
+ // Always process arraycopy's destination object since
+ // we need to add all possible edges to references in
+ // source object.
+ if (arg_esc >= PointsToNode::ArgEscape &&
+ !arg_is_arraycopy_dest) {
+ continue;
+ }
+ set_escape_state(arg_ptn, PointsToNode::ArgEscape);
+ if (arg_is_arraycopy_dest) {
+ Node* src = call->in(TypeFunc::Parms);
+ if (src->is_AddP()) {
+ src = get_addp_base(src);
+ }
+ PointsToNode* src_ptn = ptnode_adr(src->_idx);
+ assert(src_ptn != NULL, "should be registered");
+ if (arg_ptn != src_ptn) {
+ // Special arraycopy edge:
+ // A destination object's field can't have the source object
+ // as base since objects escape states are not related.
+ // Only escape state of destination object's fields affects
+ // escape state of fields in source object.
+ add_arraycopy(call, PointsToNode::ArgEscape, src_ptn, arg_ptn);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case Op_CallStaticJava: {
+ // For a static call, we know exactly what method is being called.
+ // Use bytecode estimator to record the call's escape affects
+#ifdef ASSERT
+ const char* name = call->as_CallStaticJava()->_name;
+ assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only");
+#endif
+ ciMethod* meth = call->as_CallJava()->method();
+ BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
+ // fall-through if not a Java method or no analyzer information
+ if (call_analyzer != NULL) {
+ PointsToNode* call_ptn = ptnode_adr(call->_idx);
+ const TypeTuple* d = call->tf()->domain();
+ for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+ const Type* at = d->field_at(i);
+ int k = i - TypeFunc::Parms;
+ Node* arg = call->in(i);
+ PointsToNode* arg_ptn = ptnode_adr(arg->_idx);
+ if (at->isa_ptr() != NULL &&
+ call_analyzer->is_arg_returned(k)) {
+ // The call returns arguments.
+ if (call_ptn != NULL) { // Is call's result used?
+ assert(call_ptn->is_LocalVar(), "node should be registered");
+ assert(arg_ptn != NULL, "node should be registered");
+ add_edge(call_ptn, arg_ptn);
+ }
+ }
+ if (at->isa_oopptr() != NULL &&
+ arg_ptn->escape_state() < PointsToNode::GlobalEscape) {
+ if (!call_analyzer->is_arg_stack(k)) {
+ // The argument global escapes
+ set_escape_state(arg_ptn, PointsToNode::GlobalEscape);
+ } else {
+ set_escape_state(arg_ptn, PointsToNode::ArgEscape);
+ if (!call_analyzer->is_arg_local(k)) {
+ // The argument itself doesn't escape, but any fields might
+ set_fields_escape_state(arg_ptn, PointsToNode::GlobalEscape);
+ }
+ }
+ }
+ }
+ if (call_ptn != NULL && call_ptn->is_LocalVar()) {
+ // The call returns arguments.
+ assert(call_ptn->edge_count() > 0, "sanity");
+ if (!call_analyzer->is_return_local()) {
+ // Returns also unknown object.
+ add_edge(call_ptn, phantom_obj);
+ }
+ }
+ break;
+ }
+ }
+ default: {
+ // Fall-through here if not a Java method or no analyzer information
+ // or some other type of call, assume the worst case: all arguments
+ // globally escape.
+ const TypeTuple* d = call->tf()->domain();
+ for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
+ const Type* at = d->field_at(i);
+ if (at->isa_oopptr() != NULL) {
+ Node* arg = call->in(i);
+ if (arg->is_AddP()) {
+ arg = get_addp_base(arg);
+ }
+ assert(ptnode_adr(arg->_idx) != NULL, "should be defined already");
+ set_escape_state(ptnode_adr(arg->_idx), PointsToNode::GlobalEscape);
+ }
+ }
}
}
- add_edge(f, to_i, PointsToNode::PointsToEdge);
+}
+
+
+// Finish Graph construction.
+bool ConnectionGraph::complete_connection_graph(
+ GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+ GrowableArray<JavaObjectNode*>& java_objects_worklist,
+ GrowableArray<FieldNode*>& oop_fields_worklist) {
+ // Normally only 1-3 passes needed to build Connection Graph depending
+ // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler.
+ // Set limit to 20 to catch situation when something did go wrong and
+ // bailout Escape Analysis.
+ // Also limit build time to 30 sec (60 in debug VM).
+#define CG_BUILD_ITER_LIMIT 20
+#ifdef ASSERT
+#define CG_BUILD_TIME_LIMIT 60.0
+#else
+#define CG_BUILD_TIME_LIMIT 30.0
+#endif
+
+ // Propagate GlobalEscape and ArgEscape escape states and check that
+ // we still have non-escaping objects. The method pushs on _worklist
+ // Field nodes which reference phantom_object.
+ if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
+ return false; // Nothing to do.
+ }
+ // Now propagate references to all JavaObject nodes.
+ int java_objects_length = java_objects_worklist.length();
+ elapsedTimer time;
+ int new_edges = 1;
+ int iterations = 0;
+ do {
+ while ((new_edges > 0) &&
+ (iterations++ < CG_BUILD_ITER_LIMIT) &&
+ (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+ time.start();
+ new_edges = 0;
+ // Propagate references to phantom_object for nodes pushed on _worklist
+ // by find_non_escaped_objects() and find_field_value().
+ new_edges += add_java_object_edges(phantom_obj, false);
+ for (int next = 0; next < java_objects_length; ++next) {
+ JavaObjectNode* ptn = java_objects_worklist.at(next);
+ new_edges += add_java_object_edges(ptn, true);
+ }
+ if (new_edges > 0) {
+ // Update escape states on each iteration if graph was updated.
+ if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
+ return false; // Nothing to do.
+ }
+ }
+ time.stop();
+ }
+ if ((iterations < CG_BUILD_ITER_LIMIT) &&
+ (time.seconds() < CG_BUILD_TIME_LIMIT)) {
+ time.start();
+ // Find fields which have unknown value.
+ int fields_length = oop_fields_worklist.length();
+ for (int next = 0; next < fields_length; next++) {
+ FieldNode* field = oop_fields_worklist.at(next);
+ if (field->edge_count() == 0) {
+ new_edges += find_field_value(field);
+ // This code may added new edges to phantom_object.
+ // Need an other cycle to propagate references to phantom_object.
+ }
+ }
+ time.stop();
+ } else {
+ new_edges = 0; // Bailout
+ }
+ } while (new_edges > 0);
+
+ // Bailout if passed limits.
+ if ((iterations >= CG_BUILD_ITER_LIMIT) ||
+ (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
+ Compile* C = _compile;
+ if (C->log() != NULL) {
+ C->log()->begin_elem("connectionGraph_bailout reason='reached ");
+ C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time");
+ C->log()->end_elem(" limit'");
+ }
+ assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
+ time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
+ // Possible infinite build_connection_graph loop,
+ // bailout (no changes to ideal graph were made).
+ return false;
+ }
+#ifdef ASSERT
+ if (Verbose && PrintEscapeAnalysis) {
+ tty->print_cr("EA: %d iterations to build connection graph with %d nodes and worklist size %d",
+ iterations, nodes_size(), ptnodes_worklist.length());
+ }
+#endif
+
+#undef CG_BUILD_ITER_LIMIT
+#undef CG_BUILD_TIME_LIMIT
+
+ // Find fields initialized by NULL for non-escaping Allocations.
+ int non_escaped_length = non_escaped_worklist.length();
+ for (int next = 0; next < non_escaped_length; next++) {
+ JavaObjectNode* ptn = non_escaped_worklist.at(next);
+ PointsToNode::EscapeState es = ptn->escape_state();
+ assert(es <= PointsToNode::ArgEscape, "sanity");
+ if (es == PointsToNode::NoEscape) {
+ if (find_init_values(ptn, null_obj, _igvn) > 0) {
+ // Adding references to NULL object does not change escape states
+ // since it does not escape. Also no fields are added to NULL object.
+ add_java_object_edges(null_obj, false);
+ }
+ }
+ Node* n = ptn->ideal_node();
+ if (n->is_Allocate()) {
+ // The object allocated by this Allocate node will never be
+ // seen by an other thread. Mark it so that when it is
+ // expanded no MemBarStoreStore is added.
+ InitializeNode* ini = n->as_Allocate()->initialization();
+ if (ini != NULL)
+ ini->set_does_not_escape();
+ }
+ }
+ return true; // Finished graph construction.
+}
+
+// Propagate GlobalEscape and ArgEscape escape states to all nodes
+// and check that we still have non-escaping java objects.
+bool ConnectionGraph::find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist) {
+ GrowableArray<PointsToNode*> escape_worklist;
+ // First, put all nodes with GlobalEscape and ArgEscape states on worklist.
+ int ptnodes_length = ptnodes_worklist.length();
+ for (int next = 0; next < ptnodes_length; ++next) {
+ PointsToNode* ptn = ptnodes_worklist.at(next);
+ if (ptn->escape_state() >= PointsToNode::ArgEscape ||
+ ptn->fields_escape_state() >= PointsToNode::ArgEscape) {
+ escape_worklist.push(ptn);
+ }
+ }
+ // Set escape states to referenced nodes (edges list).
+ while (escape_worklist.length() > 0) {
+ PointsToNode* ptn = escape_worklist.pop();
+ PointsToNode::EscapeState es = ptn->escape_state();
+ PointsToNode::EscapeState field_es = ptn->fields_escape_state();
+ if (ptn->is_Field() && ptn->as_Field()->is_oop() &&
+ es >= PointsToNode::ArgEscape) {
+ // GlobalEscape or ArgEscape state of field means it has unknown value.
+ if (add_edge(ptn, phantom_obj)) {
+ // New edge was added
+ add_field_uses_to_worklist(ptn->as_Field());
+ }
+ }
+ for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ if (e->is_Arraycopy()) {
+ assert(ptn->arraycopy_dst(), "sanity");
+ // Propagate only fields escape state through arraycopy edge.
+ if (e->fields_escape_state() < field_es) {
+ set_fields_escape_state(e, field_es);
+ escape_worklist.push(e);
+ }
+ } else if (es >= field_es) {
+ // fields_escape_state is also set to 'es' if it is less than 'es'.
+ if (e->escape_state() < es) {
+ set_escape_state(e, es);
+ escape_worklist.push(e);
+ }
+ } else {
+ // Propagate field escape state.
+ bool es_changed = false;
+ if (e->fields_escape_state() < field_es) {
+ set_fields_escape_state(e, field_es);
+ es_changed = true;
+ }
+ if ((e->escape_state() < field_es) &&
+ e->is_Field() && ptn->is_JavaObject() &&
+ e->as_Field()->is_oop()) {
+ // Change escape state of referenced fileds.
+ set_escape_state(e, field_es);
+ es_changed = true;;
+ } else if (e->escape_state() < es) {
+ set_escape_state(e, es);
+ es_changed = true;;
+ }
+ if (es_changed) {
+ escape_worklist.push(e);
+ }
+ }
+ }
+ }
+ // Remove escaped objects from non_escaped list.
+ for (int next = non_escaped_worklist.length()-1; next >= 0 ; --next) {
+ JavaObjectNode* ptn = non_escaped_worklist.at(next);
+ if (ptn->escape_state() >= PointsToNode::GlobalEscape) {
+ non_escaped_worklist.delete_at(next);
+ }
+ if (ptn->escape_state() == PointsToNode::NoEscape) {
+ // Find fields in non-escaped allocations which have unknown value.
+ find_init_values(ptn, phantom_obj, NULL);
+ }
+ }
+ return (non_escaped_worklist.length() > 0);
+}
+
+// Add all references to JavaObject node by walking over all uses.
+int ConnectionGraph::add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist) {
+ int new_edges = 0;
+ if (populate_worklist) {
+ // Populate _worklist by uses of jobj's uses.
+ for (UseIterator i(jobj); i.has_next(); i.next()) {
+ PointsToNode* use = i.get();
+ if (use->is_Arraycopy())
+ continue;
+ add_uses_to_worklist(use);
+ if (use->is_Field() && use->as_Field()->is_oop()) {
+ // Put on worklist all field's uses (loads) and
+ // related field nodes (same base and offset).
+ add_field_uses_to_worklist(use->as_Field());
+ }
+ }
+ }
+ while(_worklist.length() > 0) {
+ PointsToNode* use = _worklist.pop();
+ if (PointsToNode::is_base_use(use)) {
+ // Add reference from jobj to field and from field to jobj (field's base).
+ use = PointsToNode::get_use_node(use)->as_Field();
+ if (add_base(use->as_Field(), jobj)) {
+ new_edges++;
+ }
+ continue;
+ }
+ assert(!use->is_JavaObject(), "sanity");
+ if (use->is_Arraycopy()) {
+ if (jobj == null_obj) // NULL object does not have field edges
+ continue;
+ // Added edge from Arraycopy node to arraycopy's source java object
+ if (add_edge(use, jobj)) {
+ jobj->set_arraycopy_src();
+ new_edges++;
+ }
+ // and stop here.
+ continue;
+ }
+ if (!add_edge(use, jobj))
+ continue; // No new edge added, there was such edge already.
+ new_edges++;
+ if (use->is_LocalVar()) {
+ add_uses_to_worklist(use);
+ if (use->arraycopy_dst()) {
+ for (EdgeIterator i(use); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ if (e->is_Arraycopy()) {
+ if (jobj == null_obj) // NULL object does not have field edges
+ continue;
+ // Add edge from arraycopy's destination java object to Arraycopy node.
+ if (add_edge(jobj, e)) {
+ new_edges++;
+ jobj->set_arraycopy_dst();
+ }
+ }
+ }
+ }
+ } else {
+ // Added new edge to stored in field values.
+ // Put on worklist all field's uses (loads) and
+ // related field nodes (same base and offset).
+ add_field_uses_to_worklist(use->as_Field());
+ }
+ }
+ return new_edges;
+}
+
+// Put on worklist all related field nodes.
+void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) {
+ assert(field->is_oop(), "sanity");
+ int offset = field->offset();
+ add_uses_to_worklist(field);
+ // Loop over all bases of this field and push on worklist Field nodes
+ // with the same offset and base (since they may reference the same field).
+ for (BaseIterator i(field); i.has_next(); i.next()) {
+ PointsToNode* base = i.get();
+ add_fields_to_worklist(field, base);
+ // Check if the base was source object of arraycopy and go over arraycopy's
+ // destination objects since values stored to a field of source object are
+ // accessable by uses (loads) of fields of destination objects.
+ if (base->arraycopy_src()) {
+ for (UseIterator j(base); j.has_next(); j.next()) {
+ PointsToNode* arycp = j.get();
+ if (arycp->is_Arraycopy()) {
+ for (UseIterator k(arycp); k.has_next(); k.next()) {
+ PointsToNode* abase = k.get();
+ if (abase->arraycopy_dst() && abase != base) {
+ // Look for the same arracopy reference.
+ add_fields_to_worklist(field, abase);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+// Put on worklist all related field nodes.
+void ConnectionGraph::add_fields_to_worklist(FieldNode* field, PointsToNode* base) {
+ int offset = field->offset();
+ if (base->is_LocalVar()) {
+ for (UseIterator j(base); j.has_next(); j.next()) {
+ PointsToNode* f = j.get();
+ if (PointsToNode::is_base_use(f)) { // Field
+ f = PointsToNode::get_use_node(f);
+ if (f == field || !f->as_Field()->is_oop())
+ continue;
+ int offs = f->as_Field()->offset();
+ if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
+ add_to_worklist(f);
+ }
+ }
+ }
+ } else {
+ assert(base->is_JavaObject(), "sanity");
+ if (// Skip phantom_object since it is only used to indicate that
+ // this field's content globally escapes.
+ (base != phantom_obj) &&
+ // NULL object node does not have fields.
+ (base != null_obj)) {
+ for (EdgeIterator i(base); i.has_next(); i.next()) {
+ PointsToNode* f = i.get();
+ // Skip arraycopy edge since store to destination object field
+ // does not update value in source object field.
+ if (f->is_Arraycopy()) {
+ assert(base->arraycopy_dst(), "sanity");
+ continue;
+ }
+ if (f == field || !f->as_Field()->is_oop())
+ continue;
+ int offs = f->as_Field()->offset();
+ if (offs == offset || offset == Type::OffsetBot || offs == Type::OffsetBot) {
+ add_to_worklist(f);
+ }
+ }
+ }
+ }
+}
+
+// Find fields which have unknown value.
+int ConnectionGraph::find_field_value(FieldNode* field) {
+ // Escaped fields should have init value already.
+ assert(field->escape_state() == PointsToNode::NoEscape, "sanity");
+ int new_edges = 0;
+ for (BaseIterator i(field); i.has_next(); i.next()) {
+ PointsToNode* base = i.get();
+ if (base->is_JavaObject()) {
+ // Skip Allocate's fields which will be processed later.
+ if (base->ideal_node()->is_Allocate())
+ return 0;
+ assert(base == null_obj, "only NULL ptr base expected here");
+ }
+ }
+ if (add_edge(field, phantom_obj)) {
+ // New edge was added
+ new_edges++;
+ add_field_uses_to_worklist(field);
+ }
+ return new_edges;
+}
+
+// Find fields initializing values for allocations.
+int ConnectionGraph::find_init_values(JavaObjectNode* pta, PointsToNode* init_val, PhaseTransform* phase) {
+ assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
+ int new_edges = 0;
+ Node* alloc = pta->ideal_node();
+ if (init_val == phantom_obj) {
+ // Do nothing for Allocate nodes since its fields values are "known".
+ if (alloc->is_Allocate())
+ return 0;
+ assert(alloc->as_CallStaticJava(), "sanity");
+#ifdef ASSERT
+ if (alloc->as_CallStaticJava()->method() == NULL) {
+ const char* name = alloc->as_CallStaticJava()->_name;
+ assert(strncmp(name, "_multianewarray", 15) == 0, "sanity");
+ }
+#endif
+ // Non-escaped allocation returned from Java or runtime call have
+ // unknown values in fields.
+ for (EdgeIterator i(pta); i.has_next(); i.next()) {
+ PointsToNode* ptn = i.get();
+ if (ptn->is_Field() && ptn->as_Field()->is_oop()) {
+ if (add_edge(ptn, phantom_obj)) {
+ // New edge was added
+ new_edges++;
+ add_field_uses_to_worklist(ptn->as_Field());
+ }
+ }
+ }
+ return new_edges;
+ }
+ assert(init_val == null_obj, "sanity");
+ // Do nothing for Call nodes since its fields values are unknown.
+ if (!alloc->is_Allocate())
+ return 0;
+
+ InitializeNode* ini = alloc->as_Allocate()->initialization();
+ Compile* C = _compile;
+ bool visited_bottom_offset = false;
+ GrowableArray<int> offsets_worklist;
+
+ // Check if an oop field's initializing value is recorded and add
+ // a corresponding NULL if field's value if it is not recorded.
+ // Connection Graph does not record a default initialization by NULL
+ // captured by Initialize node.
+ //
+ for (EdgeIterator i(pta); i.has_next(); i.next()) {
+ PointsToNode* ptn = i.get(); // Field (AddP)
+ if (!ptn->is_Field() || !ptn->as_Field()->is_oop())
+ continue; // Not oop field
+ int offset = ptn->as_Field()->offset();
+ if (offset == Type::OffsetBot) {
+ if (!visited_bottom_offset) {
+ // OffsetBot is used to reference array's element,
+ // always add reference to NULL to all Field nodes since we don't
+ // known which element is referenced.
+ if (add_edge(ptn, null_obj)) {
+ // New edge was added
+ new_edges++;
+ add_field_uses_to_worklist(ptn->as_Field());
+ visited_bottom_offset = true;
+ }
+ }
+ } else {
+ // Check only oop fields.
+ const Type* adr_type = ptn->ideal_node()->as_AddP()->bottom_type();
+ if (adr_type->isa_rawptr()) {
+#ifdef ASSERT
+ // Raw pointers are used for initializing stores so skip it
+ // since it should be recorded already
+ Node* base = get_addp_base(ptn->ideal_node());
+ assert(adr_type->isa_rawptr() && base->is_Proj() &&
+ (base->in(0) == alloc),"unexpected pointer type");
+#endif
+ continue;
+ }
+ if (!offsets_worklist.contains(offset)) {
+ offsets_worklist.append(offset);
+ Node* value = NULL;
+ if (ini != NULL) {
+ BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
+ Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
+ if (store != NULL && store->is_Store()) {
+ value = store->in(MemNode::ValueIn);
+ } else {
+ // There could be initializing stores which follow allocation.
+ // For example, a volatile field store is not collected
+ // by Initialize node.
+ //
+ // Need to check for dependent loads to separate such stores from
+ // stores which follow loads. For now, add initial value NULL so
+ // that compare pointers optimization works correctly.
+ }
+ }
+ if (value == NULL) {
+ // A field's initializing value was not recorded. Add NULL.
+ if (add_edge(ptn, null_obj)) {
+ // New edge was added
+ new_edges++;
+ add_field_uses_to_worklist(ptn->as_Field());
+ }
+ }
+ }
+ }
+ }
+ return new_edges;
}
-void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) {
- PointsToNode *f = ptnode_adr(from_i);
- PointsToNode *t = ptnode_adr(to_i);
+// Adjust scalar_replaceable state after Connection Graph is built.
+void ConnectionGraph::adjust_scalar_replaceable_state(JavaObjectNode* jobj) {
+ // Search for non-escaping objects which are not scalar replaceable
+ // and mark them to propagate the state to referenced objects.
+
+ // 1. An object is not scalar replaceable if the field into which it is
+ // stored has unknown offset (stored into unknown element of an array).
+ //
+ for (UseIterator i(jobj); i.has_next(); i.next()) {
+ PointsToNode* use = i.get();
+ assert(!use->is_Arraycopy(), "sanity");
+ if (use->is_Field()) {
+ FieldNode* field = use->as_Field();
+ assert(field->is_oop() && field->scalar_replaceable() &&
+ field->fields_escape_state() == PointsToNode::NoEscape, "sanity");
+ if (field->offset() == Type::OffsetBot) {
+ jobj->set_scalar_replaceable(false);
+ return;
+ }
+ }
+ assert(use->is_Field() || use->is_LocalVar(), "sanity");
+ // 2. An object is not scalar replaceable if it is merged with other objects.
+ for (EdgeIterator j(use); j.has_next(); j.next()) {
+ PointsToNode* ptn = j.get();
+ if (ptn->is_JavaObject() && ptn != jobj) {
+ // Mark all objects.
+ jobj->set_scalar_replaceable(false);
+ ptn->set_scalar_replaceable(false);
+ }
+ }
+ if (!jobj->scalar_replaceable()) {
+ return;
+ }
+ }
+
+ for (EdgeIterator j(jobj); j.has_next(); j.next()) {
+ // Non-escaping object node should point only to field nodes.
+ FieldNode* field = j.get()->as_Field();
+ int offset = field->as_Field()->offset();
+
+ // 3. An object is not scalar replaceable if it has a field with unknown
+ // offset (array's element is accessed in loop).
+ if (offset == Type::OffsetBot) {
+ jobj->set_scalar_replaceable(false);
+ return;
+ }
+ // 4. Currently an object is not scalar replaceable if a LoadStore node
+ // access its field since the field value is unknown after it.
+ //
+ Node* n = field->ideal_node();
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ if (n->fast_out(i)->is_LoadStore()) {
+ jobj->set_scalar_replaceable(false);
+ return;
+ }
+ }
+
+ // 5. Or the address may point to more then one object. This may produce
+ // the false positive result (set not scalar replaceable)
+ // since the flow-insensitive escape analysis can't separate
+ // the case when stores overwrite the field's value from the case
+ // when stores happened on different control branches.
+ //
+ // Note: it will disable scalar replacement in some cases:
+ //
+ // Point p[] = new Point[1];
+ // p[0] = new Point(); // Will be not scalar replaced
+ //
+ // but it will save us from incorrect optimizations in next cases:
+ //
+ // Point p[] = new Point[1];
+ // if ( x ) p[0] = new Point(); // Will be not scalar replaced
+ //
+ if (field->base_count() > 1) {
+ for (BaseIterator i(field); i.has_next(); i.next()) {
+ PointsToNode* base = i.get();
+ // Don't take into account LocalVar nodes which
+ // may point to only one object which should be also
+ // this field's base by now.
+ if (base->is_JavaObject() && base != jobj) {
+ // Mark all bases.
+ jobj->set_scalar_replaceable(false);
+ base->set_scalar_replaceable(false);
+ }
+ }
+ }
+ }
+}
+
+#ifdef ASSERT
+void ConnectionGraph::verify_connection_graph(
+ GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+ GrowableArray<JavaObjectNode*>& java_objects_worklist,
+ GrowableArray<Node*>& addp_worklist) {
+ // Verify that graph is complete - no new edges could be added.
+ int java_objects_length = java_objects_worklist.length();
+ int non_escaped_length = non_escaped_worklist.length();
+ int new_edges = 0;
+ for (int next = 0; next < java_objects_length; ++next) {
+ JavaObjectNode* ptn = java_objects_worklist.at(next);
+ new_edges += add_java_object_edges(ptn, true);
+ }
+ assert(new_edges == 0, "graph was not complete");
+ // Verify that escape state is final.
+ int length = non_escaped_worklist.length();
+ find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist);
+ assert((non_escaped_length == non_escaped_worklist.length()) &&
+ (non_escaped_length == length) &&
+ (_worklist.length() == 0), "escape state was not final");
+
+ // Verify fields information.
+ int addp_length = addp_worklist.length();
+ for (int next = 0; next < addp_length; ++next ) {
+ Node* n = addp_worklist.at(next);
+ FieldNode* field = ptnode_adr(n->_idx)->as_Field();
+ if (field->is_oop()) {
+ // Verify that field has all bases
+ Node* base = get_addp_base(n);
+ PointsToNode* ptn = ptnode_adr(base->_idx);
+ if (ptn->is_JavaObject()) {
+ assert(field->has_base(ptn->as_JavaObject()), "sanity");
+ } else {
+ assert(ptn->is_LocalVar(), "sanity");
+ for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ if (e->is_JavaObject()) {
+ assert(field->has_base(e->as_JavaObject()), "sanity");
+ }
+ }
+ }
+ // Verify that all fields have initializing values.
+ if (field->edge_count() == 0) {
+ field->dump();
+ assert(field->edge_count() > 0, "sanity");
+ }
+ }
+ }
+}
+#endif
+
+// Optimize ideal graph.
+void ConnectionGraph::optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
+ GrowableArray<Node*>& storestore_worklist) {
+ Compile* C = _compile;
+ PhaseIterGVN* igvn = _igvn;
+ if (EliminateLocks) {
+ // Mark locks before changing ideal graph.
+ int cnt = C->macro_count();
+ for( int i=0; i < cnt; i++ ) {
+ Node *n = C->macro_node(i);
+ if (n->is_AbstractLock()) { // Lock and Unlock nodes
+ AbstractLockNode* alock = n->as_AbstractLock();
+ if (!alock->is_non_esc_obj()) {
+ if (not_global_escape(alock->obj_node())) {
+ assert(!alock->is_eliminated() || alock->is_coarsened(), "sanity");
+ // The lock could be marked eliminated by lock coarsening
+ // code during first IGVN before EA. Replace coarsened flag
+ // to eliminate all associated locks/unlocks.
+ alock->set_non_esc_obj();
+ }
+ }
+ }
+ }
+ }
+
+ if (OptimizePtrCompare) {
+ // Add ConI(#CC_GT) and ConI(#CC_EQ).
+ _pcmp_neq = igvn->makecon(TypeInt::CC_GT);
+ _pcmp_eq = igvn->makecon(TypeInt::CC_EQ);
+ // Optimize objects compare.
+ while (ptr_cmp_worklist.length() != 0) {
+ Node *n = ptr_cmp_worklist.pop();
+ Node *res = optimize_ptr_compare(n);
+ if (res != NULL) {
+#ifndef PRODUCT
+ if (PrintOptimizePtrCompare) {
+ tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ"));
+ if (Verbose) {
+ n->dump(1);
+ }
+ }
+#endif
+ igvn->replace_node(n, res);
+ }
+ }
+ // cleanup
+ if (_pcmp_neq->outcnt() == 0)
+ igvn->hash_delete(_pcmp_neq);
+ if (_pcmp_eq->outcnt() == 0)
+ igvn->hash_delete(_pcmp_eq);
+ }
+
+ // For MemBarStoreStore nodes added in library_call.cpp, check
+ // escape status of associated AllocateNode and optimize out
+ // MemBarStoreStore node if the allocated object never escapes.
+ while (storestore_worklist.length() != 0) {
+ Node *n = storestore_worklist.pop();
+ MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
+ Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
+ assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
+ if (not_global_escape(alloc)) {
+ MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
+ mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
+ mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
+ igvn->register_new_node_with_optimizer(mb);
+ igvn->replace_node(storestore, mb);
+ }
+ }
+}
+
+// Optimize objects compare.
+Node* ConnectionGraph::optimize_ptr_compare(Node* n) {
+ assert(OptimizePtrCompare, "sanity");
+ PointsToNode* ptn1 = ptnode_adr(n->in(1)->_idx);
+ PointsToNode* ptn2 = ptnode_adr(n->in(2)->_idx);
+ JavaObjectNode* jobj1 = unique_java_object(n->in(1));
+ JavaObjectNode* jobj2 = unique_java_object(n->in(2));
+ assert(ptn1->is_JavaObject() || ptn1->is_LocalVar(), "sanity");
+ assert(ptn2->is_JavaObject() || ptn2->is_LocalVar(), "sanity");
- assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
- assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of Deferred edge");
- assert(t->node_type() == PointsToNode::LocalVar || t->node_type() == PointsToNode::Field, "invalid destination of Deferred edge");
- // don't add a self-referential edge, this can occur during removal of
- // deferred edges
- if (from_i != to_i)
- add_edge(f, to_i, PointsToNode::DeferredEdge);
+ // Check simple cases first.
+ if (jobj1 != NULL) {
+ if (jobj1->escape_state() == PointsToNode::NoEscape) {
+ if (jobj1 == jobj2) {
+ // Comparing the same not escaping object.
+ return _pcmp_eq;
+ }
+ Node* obj = jobj1->ideal_node();
+ // Comparing not escaping allocation.
+ if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
+ !ptn2->points_to(jobj1)) {
+ return _pcmp_neq; // This includes nullness check.
+ }
+ }
+ }
+ if (jobj2 != NULL) {
+ if (jobj2->escape_state() == PointsToNode::NoEscape) {
+ Node* obj = jobj2->ideal_node();
+ // Comparing not escaping allocation.
+ if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
+ !ptn1->points_to(jobj2)) {
+ return _pcmp_neq; // This includes nullness check.
+ }
+ }
+ }
+ if (jobj1 != NULL && jobj1 != phantom_obj &&
+ jobj2 != NULL && jobj2 != phantom_obj &&
+ jobj1->ideal_node()->is_Con() &&
+ jobj2->ideal_node()->is_Con()) {
+ // Klass or String constants compare. Need to be careful with
+ // compressed pointers - compare types of ConN and ConP instead of nodes.
+ const Type* t1 = jobj1->ideal_node()->bottom_type()->make_ptr();
+ const Type* t2 = jobj2->ideal_node()->bottom_type()->make_ptr();
+ assert(t1 != NULL && t2 != NULL, "sanity");
+ if (t1->make_ptr() == t2->make_ptr()) {
+ return _pcmp_eq;
+ } else {
+ return _pcmp_neq;
+ }
+ }
+ if (ptn1->meet(ptn2)) {
+ return NULL; // Sets are not disjoint
+ }
+
+ // Sets are disjoint.
+ bool set1_has_unknown_ptr = ptn1->points_to(phantom_obj);
+ bool set2_has_unknown_ptr = ptn2->points_to(phantom_obj);
+ bool set1_has_null_ptr = ptn1->points_to(null_obj);
+ bool set2_has_null_ptr = ptn2->points_to(null_obj);
+ if (set1_has_unknown_ptr && set2_has_null_ptr ||
+ set2_has_unknown_ptr && set1_has_null_ptr) {
+ // Check nullness of unknown object.
+ return NULL;
+ }
+
+ // Disjointness by itself is not sufficient since
+ // alias analysis is not complete for escaped objects.
+ // Disjoint sets are definitely unrelated only when
+ // at least one set has only not escaping allocations.
+ if (!set1_has_unknown_ptr && !set1_has_null_ptr) {
+ if (ptn1->non_escaping_allocation()) {
+ return _pcmp_neq;
+ }
+ }
+ if (!set2_has_unknown_ptr && !set2_has_null_ptr) {
+ if (ptn2->non_escaping_allocation()) {
+ return _pcmp_neq;
+ }
+ }
+ return NULL;
+}
+
+// Connection Graph constuction functions.
+
+void ConnectionGraph::add_local_var(Node *n, PointsToNode::EscapeState es) {
+ PointsToNode* ptadr = _nodes.at(n->_idx);
+ if (ptadr != NULL) {
+ assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity");
+ return;
+ }
+ Compile* C = _compile;
+ ptadr = new (C->comp_arena()) LocalVarNode(C, n, es);
+ _nodes.at_put(n->_idx, ptadr);
+}
+
+void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) {
+ PointsToNode* ptadr = _nodes.at(n->_idx);
+ if (ptadr != NULL) {
+ assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity");
+ return;
+ }
+ Compile* C = _compile;
+ ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es);
+ _nodes.at_put(n->_idx, ptadr);
+}
+
+void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) {
+ PointsToNode* ptadr = _nodes.at(n->_idx);
+ if (ptadr != NULL) {
+ assert(ptadr->is_Field() && ptadr->ideal_node() == n, "sanity");
+ return;
+ }
+ Compile* C = _compile;
+ bool is_oop = is_oop_field(n, offset);
+ FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop);
+ _nodes.at_put(n->_idx, field);
+}
+
+void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
+ PointsToNode* src, PointsToNode* dst) {
+ assert(!src->is_Field() && !dst->is_Field(), "only for JavaObject and LocalVar");
+ assert((src != null_obj) && (dst != null_obj), "not for ConP NULL");
+ PointsToNode* ptadr = _nodes.at(n->_idx);
+ if (ptadr != NULL) {
+ assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity");
+ return;
+ }
+ Compile* C = _compile;
+ ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es);
+ _nodes.at_put(n->_idx, ptadr);
+ // Add edge from arraycopy node to source object.
+ (void)add_edge(ptadr, src);
+ src->set_arraycopy_src();
+ // Add edge from destination object to arraycopy node.
+ (void)add_edge(dst, ptadr);
+ dst->set_arraycopy_dst();
}
+bool ConnectionGraph::is_oop_field(Node* n, int offset) {
+ const Type* adr_type = n->as_AddP()->bottom_type();
+ BasicType bt = T_INT;
+ if (offset == Type::OffsetBot) {
+ // Check only oop fields.
+ if (!adr_type->isa_aryptr() ||
+ (adr_type->isa_aryptr()->klass() == NULL) ||
+ adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
+ // OffsetBot is used to reference array's element. Ignore first AddP.
+ if (find_second_addp(n, n->in(AddPNode::Base)) == NULL) {
+ bt = T_OBJECT;
+ }
+ }
+ } else if (offset != oopDesc::klass_offset_in_bytes()) {
+ if (adr_type->isa_instptr()) {
+ ciField* field = _compile->alias_type(adr_type->isa_instptr())->field();
+ if (field != NULL) {
+ bt = field->layout_type();
+ } else {
+ // Ignore non field load (for example, klass load)
+ }
+ } else if (adr_type->isa_aryptr()) {
+ if (offset == arrayOopDesc::length_offset_in_bytes()) {
+ // Ignore array length load.
+ } else if (find_second_addp(n, n->in(AddPNode::Base)) != NULL) {
+ // Ignore first AddP.
+ } else {
+ const Type* elemtype = adr_type->isa_aryptr()->elem();
+ bt = elemtype->array_element_basic_type();
+ }
+ } else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
+ // Allocation initialization, ThreadLocal field access, unsafe access
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ int opcode = n->fast_out(i)->Opcode();
+ if (opcode == Op_StoreP || opcode == Op_LoadP ||
+ opcode == Op_StoreN || opcode == Op_LoadN) {
+ bt = T_OBJECT;
+ }
+ }
+ }
+ }
+ return (bt == T_OBJECT || bt == T_NARROWOOP || bt == T_ARRAY);
+}
+
+// Returns unique pointed java object or NULL.
+JavaObjectNode* ConnectionGraph::unique_java_object(Node *n) {
+ assert(!_collecting, "should not call when contructed graph");
+ // If the node was created after the escape computation we can't answer.
+ uint idx = n->_idx;
+ if (idx >= nodes_size()) {
+ return NULL;
+ }
+ PointsToNode* ptn = ptnode_adr(idx);
+ if (ptn->is_JavaObject()) {
+ return ptn->as_JavaObject();
+ }
+ assert(ptn->is_LocalVar(), "sanity");
+ // Check all java objects it points to.
+ JavaObjectNode* jobj = NULL;
+ for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ if (e->is_JavaObject()) {
+ if (jobj == NULL) {
+ jobj = e->as_JavaObject();
+ } else if (jobj != e) {
+ return NULL;
+ }
+ }
+ }
+ return jobj;
+}
+
+// Return true if this node points only to non-escaping allocations.
+bool PointsToNode::non_escaping_allocation() {
+ if (is_JavaObject()) {
+ Node* n = ideal_node();
+ if (n->is_Allocate() || n->is_CallStaticJava()) {
+ return (escape_state() == PointsToNode::NoEscape);
+ } else {
+ return false;
+ }
+ }
+ assert(is_LocalVar(), "sanity");
+ // Check all java objects it points to.
+ for (EdgeIterator i(this); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ if (e->is_JavaObject()) {
+ Node* n = e->ideal_node();
+ if ((e->escape_state() != PointsToNode::NoEscape) ||
+ !(n->is_Allocate() || n->is_CallStaticJava())) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Return true if we know the node does not escape globally.
+bool ConnectionGraph::not_global_escape(Node *n) {
+ assert(!_collecting, "should not call during graph construction");
+ // If the node was created after the escape computation we can't answer.
+ uint idx = n->_idx;
+ if (idx >= nodes_size()) {
+ return false;
+ }
+ PointsToNode* ptn = ptnode_adr(idx);
+ PointsToNode::EscapeState es = ptn->escape_state();
+ // If we have already computed a value, return it.
+ if (es >= PointsToNode::GlobalEscape)
+ return false;
+ if (ptn->is_JavaObject()) {
+ return true; // (es < PointsToNode::GlobalEscape);
+ }
+ assert(ptn->is_LocalVar(), "sanity");
+ // Check all java objects it points to.
+ for (EdgeIterator i(ptn); i.has_next(); i.next()) {
+ if (i.get()->escape_state() >= PointsToNode::GlobalEscape)
+ return false;
+ }
+ return true;
+}
+
+
+// Helper functions
+
+// Return true if this node points to specified node or nodes it points to.
+bool PointsToNode::points_to(JavaObjectNode* ptn) const {
+ if (is_JavaObject()) {
+ return (this == ptn);
+ }
+ assert(is_LocalVar(), "sanity");
+ for (EdgeIterator i(this); i.has_next(); i.next()) {
+ if (i.get() == ptn)
+ return true;
+ }
+ return false;
+}
+
+// Return true if one node points to an other.
+bool PointsToNode::meet(PointsToNode* ptn) {
+ if (this == ptn) {
+ return true;
+ } else if (ptn->is_JavaObject()) {
+ return this->points_to(ptn->as_JavaObject());
+ } else if (this->is_JavaObject()) {
+ return ptn->points_to(this->as_JavaObject());
+ }
+ assert(this->is_LocalVar() && ptn->is_LocalVar(), "sanity");
+ int ptn_count = ptn->edge_count();
+ for (EdgeIterator i(this); i.has_next(); i.next()) {
+ PointsToNode* this_e = i.get();
+ for (int j = 0; j < ptn_count; j++) {
+ if (this_e == ptn->edge(j))
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifdef ASSERT
+// Return true if bases point to this java object.
+bool FieldNode::has_base(JavaObjectNode* jobj) const {
+ for (BaseIterator i(this); i.has_next(); i.next()) {
+ if (i.get() == jobj)
+ return true;
+ }
+ return false;
+}
+#endif
+
int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
const Type *adr_type = phase->type(adr);
if (adr->is_AddP() && adr_type->isa_oopptr() == NULL &&
@@ -171,286 +1982,7 @@
return t_ptr->offset();
}
-void ConnectionGraph::add_field_edge(uint from_i, uint to_i, int offset) {
- // Don't add fields to NULL pointer.
- if (is_null_ptr(from_i))
- return;
- PointsToNode *f = ptnode_adr(from_i);
- PointsToNode *t = ptnode_adr(to_i);
-
- assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
- assert(f->node_type() == PointsToNode::JavaObject, "invalid destination of Field edge");
- assert(t->node_type() == PointsToNode::Field, "invalid destination of Field edge");
- assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets");
- t->set_offset(offset);
-
- add_edge(f, to_i, PointsToNode::FieldEdge);
-}
-
-void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) {
- // Don't change non-escaping state of NULL pointer.
- if (is_null_ptr(ni))
- return;
- PointsToNode *npt = ptnode_adr(ni);
- PointsToNode::EscapeState old_es = npt->escape_state();
- if (es > old_es)
- npt->set_escape_state(es);
-}
-
-void ConnectionGraph::add_node(Node *n, PointsToNode::NodeType nt,
- PointsToNode::EscapeState es, bool done) {
- PointsToNode* ptadr = ptnode_adr(n->_idx);
- ptadr->_node = n;
- ptadr->set_node_type(nt);
-
- // inline set_escape_state(idx, es);
- PointsToNode::EscapeState old_es = ptadr->escape_state();
- if (es > old_es)
- ptadr->set_escape_state(es);
-
- if (done)
- _processed.set(n->_idx);
-}
-
-PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
- uint idx = n->_idx;
- PointsToNode::EscapeState es;
-
- // If we are still collecting or there were no non-escaping allocations
- // we don't know the answer yet
- if (_collecting)
- return PointsToNode::UnknownEscape;
-
- // if the node was created after the escape computation, return
- // UnknownEscape
- if (idx >= nodes_size())
- return PointsToNode::UnknownEscape;
-
- es = ptnode_adr(idx)->escape_state();
-
- // if we have already computed a value, return it
- if (es != PointsToNode::UnknownEscape &&
- ptnode_adr(idx)->node_type() == PointsToNode::JavaObject)
- return es;
-
- // PointsTo() calls n->uncast() which can return a new ideal node.
- if (n->uncast()->_idx >= nodes_size())
- return PointsToNode::UnknownEscape;
-
- PointsToNode::EscapeState orig_es = es;
-
- // compute max escape state of anything this node could point to
- for(VectorSetI i(PointsTo(n)); i.test() && es != PointsToNode::GlobalEscape; ++i) {
- uint pt = i.elem;
- PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
- if (pes > es)
- es = pes;
- }
- if (orig_es != es) {
- // cache the computed escape state
- assert(es > orig_es, "should have computed an escape state");
- set_escape_state(idx, es);
- } // orig_es could be PointsToNode::UnknownEscape
- return es;
-}
-
-VectorSet* ConnectionGraph::PointsTo(Node * n) {
- pt_ptset.Reset();
- pt_visited.Reset();
- pt_worklist.clear();
-
-#ifdef ASSERT
- Node *orig_n = n;
-#endif
-
- n = n->uncast();
- PointsToNode* npt = ptnode_adr(n->_idx);
-
- // If we have a JavaObject, return just that object
- if (npt->node_type() == PointsToNode::JavaObject) {
- pt_ptset.set(n->_idx);
- return &pt_ptset;
- }
-#ifdef ASSERT
- if (npt->_node == NULL) {
- if (orig_n != n)
- orig_n->dump();
- n->dump();
- assert(npt->_node != NULL, "unregistered node");
- }
-#endif
- pt_worklist.push(n->_idx);
- while(pt_worklist.length() > 0) {
- int ni = pt_worklist.pop();
- if (pt_visited.test_set(ni))
- continue;
-
- PointsToNode* pn = ptnode_adr(ni);
- // ensure that all inputs of a Phi have been processed
- assert(!_collecting || !pn->_node->is_Phi() || _processed.test(ni),"");
-
- int edges_processed = 0;
- uint e_cnt = pn->edge_count();
- for (uint e = 0; e < e_cnt; e++) {
- uint etgt = pn->edge_target(e);
- PointsToNode::EdgeType et = pn->edge_type(e);
- if (et == PointsToNode::PointsToEdge) {
- pt_ptset.set(etgt);
- edges_processed++;
- } else if (et == PointsToNode::DeferredEdge) {
- pt_worklist.push(etgt);
- edges_processed++;
- } else {
- assert(false,"neither PointsToEdge or DeferredEdge");
- }
- }
- if (edges_processed == 0) {
- // no deferred or pointsto edges found. Assume the value was set
- // outside this method. Add the phantom object to the pointsto set.
- pt_ptset.set(_phantom_object);
- }
- }
- return &pt_ptset;
-}
-
-void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
- // This method is most expensive during ConnectionGraph construction.
- // Reuse vectorSet and an additional growable array for deferred edges.
- deferred_edges->clear();
- visited->Reset();
-
- visited->set(ni);
- PointsToNode *ptn = ptnode_adr(ni);
- assert(ptn->node_type() == PointsToNode::LocalVar ||
- ptn->node_type() == PointsToNode::Field, "sanity");
- assert(ptn->edge_count() != 0, "should have at least phantom_object");
-
- // Mark current edges as visited and move deferred edges to separate array.
- for (uint i = 0; i < ptn->edge_count(); ) {
- uint t = ptn->edge_target(i);
-#ifdef ASSERT
- assert(!visited->test_set(t), "expecting no duplications");
-#else
- visited->set(t);
-#endif
- if (ptn->edge_type(i) == PointsToNode::DeferredEdge) {
- ptn->remove_edge(t, PointsToNode::DeferredEdge);
- deferred_edges->append(t);
- } else {
- i++;
- }
- }
- for (int next = 0; next < deferred_edges->length(); ++next) {
- uint t = deferred_edges->at(next);
- PointsToNode *ptt = ptnode_adr(t);
- uint e_cnt = ptt->edge_count();
- assert(e_cnt != 0, "should have at least phantom_object");
- for (uint e = 0; e < e_cnt; e++) {
- uint etgt = ptt->edge_target(e);
- if (visited->test_set(etgt))
- continue;
-
- PointsToNode::EdgeType et = ptt->edge_type(e);
- if (et == PointsToNode::PointsToEdge) {
- add_pointsto_edge(ni, etgt);
- } else if (et == PointsToNode::DeferredEdge) {
- deferred_edges->append(etgt);
- } else {
- assert(false,"invalid connection graph");
- }
- }
- }
- if (ptn->edge_count() == 0) {
- // No pointsto edges found after deferred edges are removed.
- // For example, in the next case where call is replaced
- // with uncommon trap and as result array's load references
- // itself through deferred edges:
- //
- // A a = b[i];
- // if (c!=null) a = c.foo();
- // b[i] = a;
- //
- // Assume the value was set outside this method and
- // add edge to phantom object.
- add_pointsto_edge(ni, _phantom_object);
- }
-}
-
-
-// Add an edge to node given by "to_i" from any field of adr_i whose offset
-// matches "offset" A deferred edge is added if to_i is a LocalVar, and
-// a pointsto edge is added if it is a JavaObject
-
-void ConnectionGraph::add_edge_from_fields(uint adr_i, uint to_i, int offs) {
- // No fields for NULL pointer.
- if (is_null_ptr(adr_i)) {
- return;
- }
- PointsToNode* an = ptnode_adr(adr_i);
- PointsToNode* to = ptnode_adr(to_i);
- bool deferred = (to->node_type() == PointsToNode::LocalVar);
- bool escaped = (to_i == _phantom_object) && (offs == Type::OffsetTop);
- if (escaped) {
- // Values in fields escaped during call.
- assert(an->escape_state() >= PointsToNode::ArgEscape, "sanity");
- offs = Type::OffsetBot;
- }
- for (uint fe = 0; fe < an->edge_count(); fe++) {
- assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
- int fi = an->edge_target(fe);
- if (escaped) {
- set_escape_state(fi, PointsToNode::GlobalEscape);
- }
- PointsToNode* pf = ptnode_adr(fi);
- int po = pf->offset();
- if (po == offs || po == Type::OffsetBot || offs == Type::OffsetBot) {
- if (deferred)
- add_deferred_edge(fi, to_i);
- else
- add_pointsto_edge(fi, to_i);
- }
- }
-}
-
-// Add a deferred edge from node given by "from_i" to any field of adr_i
-// whose offset matches "offset".
-void ConnectionGraph::add_deferred_edge_to_fields(uint from_i, uint adr_i, int offs) {
- // No fields for NULL pointer.
- if (is_null_ptr(adr_i)) {
- return;
- }
- if (adr_i == _phantom_object) {
- // Add only one edge for unknown object.
- add_pointsto_edge(from_i, _phantom_object);
- return;
- }
- PointsToNode* an = ptnode_adr(adr_i);
- bool is_alloc = an->_node->is_Allocate();
- for (uint fe = 0; fe < an->edge_count(); fe++) {
- assert(an->edge_type(fe) == PointsToNode::FieldEdge, "expecting a field edge");
- int fi = an->edge_target(fe);
- PointsToNode* pf = ptnode_adr(fi);
- int offset = pf->offset();
- if (!is_alloc) {
- // Assume the field was set outside this method if it is not Allocation
- add_pointsto_edge(fi, _phantom_object);
- }
- if (offset == offs || offset == Type::OffsetBot || offs == Type::OffsetBot) {
- add_deferred_edge(from_i, fi);
- }
- }
- // Some fields references (AddP) may still be missing
- // until Connection Graph construction is complete.
- // For example, loads from RAW pointers with offset 0
- // which don't have AddP.
- // A reference to phantom_object will be added if
- // a field reference is still missing after completing
- // Connection Graph (see remove_deferred()).
-}
-
-// Helper functions
-
-static Node* get_addp_base(Node *addp) {
+Node* ConnectionGraph::get_addp_base(Node *addp) {
assert(addp->is_AddP(), "must be AddP");
//
// AddP cases for Base and Address inputs:
@@ -513,30 +2045,30 @@
// | |
// AddP ( base == address )
//
- Node *base = addp->in(AddPNode::Base)->uncast();
- if (base->is_top()) { // The AddP case #3 and #6.
- base = addp->in(AddPNode::Address)->uncast();
+ Node *base = addp->in(AddPNode::Base);
+ if (base->uncast()->is_top()) { // The AddP case #3 and #6.
+ base = addp->in(AddPNode::Address);
while (base->is_AddP()) {
// Case #6 (unsafe access) may have several chained AddP nodes.
- assert(base->in(AddPNode::Base)->is_top(), "expected unsafe access address only");
- base = base->in(AddPNode::Address)->uncast();
+ assert(base->in(AddPNode::Base)->uncast()->is_top(), "expected unsafe access address only");
+ base = base->in(AddPNode::Address);
}
- assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal ||
- base->Opcode() == Op_CastX2P || base->is_DecodeN() ||
- (base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) ||
- (base->is_Proj() && base->in(0)->is_Allocate()), "sanity");
+ Node* uncast_base = base->uncast();
+ int opcode = uncast_base->Opcode();
+ assert(opcode == Op_ConP || opcode == Op_ThreadLocal ||
+ opcode == Op_CastX2P || uncast_base->is_DecodeN() ||
+ (uncast_base->is_Mem() && uncast_base->bottom_type() == TypeRawPtr::NOTNULL) ||
+ (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity");
}
return base;
}
-static Node* find_second_addp(Node* addp, Node* n) {
+Node* ConnectionGraph::find_second_addp(Node* addp, Node* n) {
assert(addp->is_AddP() && addp->outcnt() > 0, "Don't process dead nodes");
-
Node* addp2 = addp->raw_out(0);
if (addp->outcnt() == 1 && addp2->is_AddP() &&
addp2->in(AddPNode::Base) == n &&
addp2->in(AddPNode::Address) == addp) {
-
assert(addp->in(AddPNode::Base) == n, "expecting the same base");
//
// Find array's offset to push it on worklist first and
@@ -575,7 +2107,8 @@
// Adjust the type and inputs of an AddP which computes the
// address of a field of an instance
//
-bool ConnectionGraph::split_AddP(Node *addp, Node *base, PhaseGVN *igvn) {
+bool ConnectionGraph::split_AddP(Node *addp, Node *base) {
+ PhaseGVN* igvn = _igvn;
const TypeOopPtr *base_t = igvn->type(base)->isa_oopptr();
assert(base_t != NULL && base_t->is_known_instance(), "expecting instance oopptr");
const TypeOopPtr *t = igvn->type(addp)->isa_oopptr();
@@ -612,7 +2145,6 @@
!base_t->klass()->is_subtype_of(t->klass())) {
return false; // bail out
}
-
const TypeOopPtr *tinst = base_t->add_offset(t->offset())->is_oopptr();
// Do NOT remove the next line: ensure a new alias index is allocated
// for the instance type. Note: C++ will not remove it since the call
@@ -620,9 +2152,7 @@
int alias_idx = _compile->get_alias_index(tinst);
igvn->set_type(addp, tinst);
// record the allocation in the node map
- assert(ptnode_adr(addp->_idx)->_node != NULL, "should be registered");
- set_map(addp->_idx, get_map(base->_idx));
-
+ set_map(addp, get_map(base->_idx));
// Set addp's Base and Address to 'base'.
Node *abase = addp->in(AddPNode::Base);
Node *adr = addp->in(AddPNode::Address);
@@ -657,8 +2187,9 @@
// created phi or an existing phi. Sets create_new to indicate whether a new
// phi was created. Cache the last newly created phi in the node map.
//
-PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created) {
+PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, bool &new_created) {
Compile *C = _compile;
+ PhaseGVN* igvn = _igvn;
new_created = false;
int phi_alias_idx = C->get_alias_index(orig_phi->adr_type());
// nothing to do if orig_phi is bottom memory or matches alias_idx
@@ -698,12 +2229,7 @@
C->copy_node_notes_to(result, orig_phi);
igvn->set_type(result, result->bottom_type());
record_for_optimizer(result);
-
- debug_only(Node* pn = ptnode_adr(orig_phi->_idx)->_node;)
- assert(pn == NULL || pn == orig_phi, "wrong node");
- set_map(orig_phi->_idx, result);
- ptnode_adr(orig_phi->_idx)->_node = orig_phi;
-
+ set_map(orig_phi, result);
new_created = true;
return result;
}
@@ -712,27 +2238,25 @@
// Return a new version of Memory Phi "orig_phi" with the inputs having the
// specified alias index.
//
-PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn) {
-
+PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist) {
assert(alias_idx != Compile::AliasIdxBot, "can't split out bottom memory");
Compile *C = _compile;
+ PhaseGVN* igvn = _igvn;
bool new_phi_created;
- PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, igvn, new_phi_created);
+ PhiNode *result = create_split_phi(orig_phi, alias_idx, orig_phi_worklist, new_phi_created);
if (!new_phi_created) {
return result;
}
-
GrowableArray<PhiNode *> phi_list;
GrowableArray<uint> cur_input;
-
PhiNode *phi = orig_phi;
uint idx = 1;
bool finished = false;
while(!finished) {
while (idx < phi->req()) {
- Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist, igvn);
+ Node *mem = find_inst_mem(phi->in(idx), alias_idx, orig_phi_worklist);
if (mem != NULL && mem->is_Phi()) {
- PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, igvn, new_phi_created);
+ PhiNode *newphi = create_split_phi(mem->as_Phi(), alias_idx, orig_phi_worklist, new_phi_created);
if (new_phi_created) {
// found an phi for which we created a new split, push current one on worklist and begin
// processing new one
@@ -775,19 +2299,18 @@
return result;
}
-
//
// The next methods are derived from methods in MemNode.
//
-static Node *step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) {
+Node* ConnectionGraph::step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop) {
Node *mem = mmem;
// TypeOopPtr::NOTNULL+any is an OOP with unknown offset - generally
// means an array I have not precisely typed yet. Do not do any
// alias stuff with it any time soon.
- if( toop->base() != Type::AnyPtr &&
+ if (toop->base() != Type::AnyPtr &&
!(toop->klass() != NULL &&
toop->klass()->is_java_lang_Object() &&
- toop->offset() == Type::OffsetBot) ) {
+ toop->offset() == Type::OffsetBot)) {
mem = mmem->memory_at(alias_idx);
// Update input if it is progress over what we have now
}
@@ -797,9 +2320,9 @@
//
// Move memory users to their memory slices.
//
-void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *igvn) {
+void ConnectionGraph::move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis) {
Compile* C = _compile;
-
+ PhaseGVN* igvn = _igvn;
const TypePtr* tp = igvn->type(n->in(MemNode::Address))->isa_ptr();
assert(tp != NULL, "ptr type");
int alias_idx = C->get_alias_index(tp);
@@ -816,7 +2339,7 @@
}
// Replace previous general reference to mem node.
uint orig_uniq = C->unique();
- Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+ Node* m = find_inst_mem(n, general_idx, orig_phis);
assert(orig_uniq == C->unique(), "no new nodes");
mmem->set_memory_at(general_idx, m);
--imax;
@@ -836,7 +2359,7 @@
}
// Move to general memory slice.
uint orig_uniq = C->unique();
- Node* m = find_inst_mem(n, general_idx, orig_phis, igvn);
+ Node* m = find_inst_mem(n, general_idx, orig_phis);
assert(orig_uniq == C->unique(), "no new nodes");
igvn->hash_delete(use);
imax -= use->replace_edge(n, m);
@@ -873,10 +2396,11 @@
// Search memory chain of "mem" to find a MemNode whose address
// is the specified alias index.
//
-Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *phase) {
+Node* ConnectionGraph::find_inst_mem(Node *orig_mem, int alias_idx, GrowableArray<PhiNode *> &orig_phis) {
if (orig_mem == NULL)
return orig_mem;
- Compile* C = phase->C;
+ Compile* C = _compile;
+ PhaseGVN* igvn = _igvn;
const TypeOopPtr *toop = C->get_adr_type(alias_idx)->isa_oopptr();
bool is_instance = (toop != NULL) && toop->is_known_instance();
Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
@@ -887,7 +2411,7 @@
if (result == start_mem)
break; // hit one of our sentinels
if (result->is_Mem()) {
- const Type *at = phase->type(result->in(MemNode::Address));
+ const Type *at = igvn->type(result->in(MemNode::Address));
if (at == Type::TOP)
break; // Dead
assert (at->isa_ptr() != NULL, "pointer type required.");
@@ -909,7 +2433,7 @@
break; // hit one of our sentinels
} else if (proj_in->is_Call()) {
CallNode *call = proj_in->as_Call();
- if (!call->may_modify(toop, phase)) {
+ if (!call->may_modify(toop, igvn)) {
result = call->in(TypeFunc::Memory);
}
} else if (proj_in->is_Initialize()) {
@@ -928,7 +2452,7 @@
if (result == mmem->base_memory()) {
// Didn't find instance memory, search through general slice recursively.
result = mmem->memory_at(C->get_general_index(alias_idx));
- result = find_inst_mem(result, alias_idx, orig_phis, phase);
+ result = find_inst_mem(result, alias_idx, orig_phis);
if (C->failing()) {
return NULL;
}
@@ -936,7 +2460,7 @@
}
} else if (result->is_Phi() &&
C->get_alias_index(result->as_Phi()->adr_type()) != alias_idx) {
- Node *un = result->as_Phi()->unique_input(phase);
+ Node *un = result->as_Phi()->unique_input(igvn);
if (un != NULL) {
orig_phis.append_if_missing(result->as_Phi());
result = un;
@@ -944,7 +2468,7 @@
break;
}
} else if (result->is_ClearArray()) {
- if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), phase)) {
+ if (!ClearArrayNode::step_through(&result, (uint)toop->instance_id(), igvn)) {
// Can not bypass initialization of the instance
// we are looking for.
break;
@@ -952,7 +2476,7 @@
// Otherwise skip it (the call updated 'result' value).
} else if (result->Opcode() == Op_SCMemProj) {
assert(result->in(0)->is_LoadStore(), "sanity");
- const Type *at = phase->type(result->in(0)->in(MemNode::Address));
+ const Type *at = igvn->type(result->in(0)->in(MemNode::Address));
if (at != Type::TOP) {
assert (at->isa_ptr() != NULL, "pointer type required.");
int idx = C->get_alias_index(at->is_ptr());
@@ -972,7 +2496,7 @@
orig_phis.append_if_missing(mphi);
} else if (C->get_alias_index(t) != alias_idx) {
// Create a new Phi with the specified alias index type.
- result = split_memory_phi(mphi, alias_idx, orig_phis, phase);
+ result = split_memory_phi(mphi, alias_idx, orig_phis);
}
}
// the result is either MemNode, PhiNode, InitializeNode.
@@ -1071,12 +2595,12 @@
void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) {
GrowableArray<Node *> memnode_worklist;
GrowableArray<PhiNode *> orig_phis;
-
PhaseIterGVN *igvn = _igvn;
uint new_index_start = (uint) _compile->num_alias_types();
Arena* arena = Thread::current()->resource_area();
VectorSet visited(arena);
-
+ ideal_nodes.clear(); // Reset for use with set_map/get_map.
+ uint unique_old = _compile->unique();
// Phase 1: Process possible allocations from alloc_worklist.
// Create instance types for the CheckCastPP for allocations where possible.
@@ -1088,17 +2612,15 @@
while (alloc_worklist.length() != 0) {
Node *n = alloc_worklist.pop();
uint ni = n->_idx;
- const TypeOopPtr* tinst = NULL;
if (n->is_Call()) {
CallNode *alloc = n->as_Call();
// copy escape information to call node
PointsToNode* ptn = ptnode_adr(alloc->_idx);
- PointsToNode::EscapeState es = escape_state(alloc);
+ PointsToNode::EscapeState es = ptn->escape_state();
// We have an allocation or call which returns a Java object,
// see if it is unescaped.
if (es != PointsToNode::NoEscape || !ptn->scalar_replaceable())
continue;
-
// Find CheckCastPP for the allocate or for the return value of a call
n = alloc->result_cast();
if (n == NULL) { // No uses except Initialize node
@@ -1145,20 +2667,18 @@
// so it could be eliminated.
alloc->as_Allocate()->_is_scalar_replaceable = true;
}
- set_escape_state(n->_idx, es); // CheckCastPP escape state
+ set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state
// in order for an object to be scalar-replaceable, it must be:
// - a direct allocation (not a call returning an object)
// - non-escaping
// - eligible to be a unique type
// - not determined to be ineligible by escape analysis
- assert(ptnode_adr(alloc->_idx)->_node != NULL &&
- ptnode_adr(n->_idx)->_node != NULL, "should be registered");
- set_map(alloc->_idx, n);
- set_map(n->_idx, alloc);
+ set_map(alloc, n);
+ set_map(n, alloc);
const TypeOopPtr *t = igvn->type(n)->isa_oopptr();
if (t == NULL)
continue; // not a TypeOopPtr
- tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni);
+ const TypeOopPtr* tinst = t->cast_to_exactness(true)->is_oopptr()->cast_to_instance_id(ni);
igvn->hash_delete(n);
igvn->set_type(n, tinst);
n->raise_bottom_type(tinst);
@@ -1168,9 +2688,10 @@
// First, put on the worklist all Field edges from Connection Graph
// which is more accurate then putting immediate users from Ideal Graph.
- for (uint e = 0; e < ptn->edge_count(); e++) {
- Node *use = ptnode_adr(ptn->edge_target(e))->_node;
- assert(ptn->edge_type(e) == PointsToNode::FieldEdge && use->is_AddP(),
+ for (EdgeIterator e(ptn); e.has_next(); e.next()) {
+ PointsToNode* tgt = e.get();
+ Node* use = tgt->ideal_node();
+ assert(tgt->is_Field() && use->is_AddP(),
"only AddP nodes are Field edges in CG");
if (use->outcnt() > 0) { // Don't process dead nodes
Node* addp2 = find_second_addp(use, use->in(AddPNode::Base));
@@ -1202,16 +2723,18 @@
}
}
} else if (n->is_AddP()) {
- VectorSet* ptset = PointsTo(get_addp_base(n));
- assert(ptset->Size() == 1, "AddP address is unique");
- uint elem = ptset->getelem(); // Allocation node's index
- if (elem == _phantom_object) {
- assert(false, "escaped allocation");
- continue; // Assume the value was set outside this method.
+ JavaObjectNode* jobj = unique_java_object(get_addp_base(n));
+ if (jobj == NULL || jobj == phantom_obj) {
+#ifdef ASSERT
+ ptnode_adr(get_addp_base(n)->_idx)->dump();
+ ptnode_adr(n->_idx)->dump();
+ assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
+#endif
+ _compile->record_failure(C2Compiler::retry_no_escape_analysis());
+ return;
}
- Node *base = get_map(elem); // CheckCastPP node
- if (!split_AddP(n, base, igvn)) continue; // wrong type from dead path
- tinst = igvn->type(base)->isa_oopptr();
+ Node *base = get_map(jobj->idx()); // CheckCastPP node
+ if (!split_AddP(n, base)) continue; // wrong type from dead path
} else if (n->is_Phi() ||
n->is_CheckCastPP() ||
n->is_EncodeP() ||
@@ -1221,18 +2744,20 @@
assert(n->is_Phi(), "loops only through Phi's");
continue; // already processed
}
- VectorSet* ptset = PointsTo(n);
- if (ptset->Size() == 1) {
- uint elem = ptset->getelem(); // Allocation node's index
- if (elem == _phantom_object) {
- assert(false, "escaped allocation");
- continue; // Assume the value was set outside this method.
- }
- Node *val = get_map(elem); // CheckCastPP node
+ JavaObjectNode* jobj = unique_java_object(n);
+ if (jobj == NULL || jobj == phantom_obj) {
+#ifdef ASSERT
+ ptnode_adr(n->_idx)->dump();
+ assert(jobj != NULL && jobj != phantom_obj, "escaped allocation");
+#endif
+ _compile->record_failure(C2Compiler::retry_no_escape_analysis());
+ return;
+ } else {
+ Node *val = get_map(jobj->idx()); // CheckCastPP node
TypeNode *tn = n->as_Type();
- tinst = igvn->type(val)->isa_oopptr();
+ const TypeOopPtr* tinst = igvn->type(val)->isa_oopptr();
assert(tinst != NULL && tinst->is_known_instance() &&
- (uint)tinst->instance_id() == elem , "instance type expected.");
+ tinst->instance_id() == jobj->idx() , "instance type expected.");
const Type *tn_type = igvn->type(tn);
const TypeOopPtr *tn_t;
@@ -1241,7 +2766,6 @@
} else {
tn_t = tn_type->isa_oopptr();
}
-
if (tn_t != NULL && tinst->klass()->is_subtype_of(tn_t->klass())) {
if (tn_type->isa_narrowoop()) {
tn_type = tinst->make_narrowoop();
@@ -1314,13 +2838,13 @@
}
// New alias types were created in split_AddP().
uint new_index_end = (uint) _compile->num_alias_types();
+ assert(unique_old == _compile->unique(), "there should be no new ideal nodes after Phase 1");
// Phase 2: Process MemNode's from memnode_worklist. compute new address type and
// compute new values for Memory inputs (the Memory inputs are not
// actually updated until phase 4.)
if (memnode_worklist.length() == 0)
return; // nothing to do
-
while (memnode_worklist.length() != 0) {
Node *n = memnode_worklist.pop();
if (visited.test_set(n->_idx))
@@ -1341,17 +2865,14 @@
assert (addr_t->isa_ptr() != NULL, "pointer type required.");
int alias_idx = _compile->get_alias_index(addr_t->is_ptr());
assert ((uint)alias_idx < new_index_end, "wrong alias index");
- Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis, igvn);
+ Node *mem = find_inst_mem(n->in(MemNode::Memory), alias_idx, orig_phis);
if (_compile->failing()) {
return;
}
if (mem != n->in(MemNode::Memory)) {
// We delay the memory edge update since we need old one in
// MergeMem code below when instances memory slices are separated.
- debug_only(Node* pn = ptnode_adr(n->_idx)->_node;)
- assert(pn == NULL || pn == n, "wrong node");
- set_map(n->_idx, mem);
- ptnode_adr(n->_idx)->_node = n;
+ set_map(n, mem);
}
if (n->is_Load()) {
continue; // don't push users
@@ -1442,7 +2963,7 @@
if((uint)_compile->get_general_index(ni) == i) {
Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
if (nmm->is_empty_memory(m)) {
- Node* result = find_inst_mem(mem, ni, orig_phis, igvn);
+ Node* result = find_inst_mem(mem, ni, orig_phis);
if (_compile->failing()) {
return;
}
@@ -1458,7 +2979,7 @@
if (result == nmm->base_memory()) {
// Didn't find instance memory, search through general slice recursively.
result = nmm->memory_at(_compile->get_general_index(ni));
- result = find_inst_mem(result, ni, orig_phis, igvn);
+ result = find_inst_mem(result, ni, orig_phis);
if (_compile->failing()) {
return;
}
@@ -1482,7 +3003,7 @@
igvn->hash_delete(phi);
for (uint i = 1; i < phi->req(); i++) {
Node *mem = phi->in(i);
- Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis, igvn);
+ Node *new_mem = find_inst_mem(mem, alias_idx, orig_phis);
if (_compile->failing()) {
return;
}
@@ -1496,39 +3017,36 @@
// Update the memory inputs of MemNodes with the value we computed
// in Phase 2 and move stores memory users to corresponding memory slices.
-
// Disable memory split verification code until the fix for 6984348.
// Currently it produces false negative results since it does not cover all cases.
#if 0 // ifdef ASSERT
visited.Reset();
Node_Stack old_mems(arena, _compile->unique() >> 2);
#endif
- for (uint i = 0; i < nodes_size(); i++) {
- Node *nmem = get_map(i);
- if (nmem != NULL) {
- Node *n = ptnode_adr(i)->_node;
- assert(n != NULL, "sanity");
- if (n->is_Mem()) {
+ for (uint i = 0; i < ideal_nodes.size(); i++) {
+ Node* n = ideal_nodes.at(i);
+ Node* nmem = get_map(n->_idx);
+ assert(nmem != NULL, "sanity");
+ if (n->is_Mem()) {
#if 0 // ifdef ASSERT
- Node* old_mem = n->in(MemNode::Memory);
- if (!visited.test_set(old_mem->_idx)) {
- old_mems.push(old_mem, old_mem->outcnt());
- }
+ Node* old_mem = n->in(MemNode::Memory);
+ if (!visited.test_set(old_mem->_idx)) {
+ old_mems.push(old_mem, old_mem->outcnt());
+ }
#endif
- assert(n->in(MemNode::Memory) != nmem, "sanity");
- if (!n->is_Load()) {
- // Move memory users of a store first.
- move_inst_mem(n, orig_phis, igvn);
- }
- // Now update memory input
- igvn->hash_delete(n);
- n->set_req(MemNode::Memory, nmem);
- igvn->hash_insert(n);
- record_for_optimizer(n);
- } else {
- assert(n->is_Allocate() || n->is_CheckCastPP() ||
- n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
+ assert(n->in(MemNode::Memory) != nmem, "sanity");
+ if (!n->is_Load()) {
+ // Move memory users of a store first.
+ move_inst_mem(n, orig_phis);
}
+ // Now update memory input
+ igvn->hash_delete(n);
+ n->set_req(MemNode::Memory, nmem);
+ igvn->hash_insert(n);
+ record_for_optimizer(n);
+ } else {
+ assert(n->is_Allocate() || n->is_CheckCastPP() ||
+ n->is_AddP() || n->is_Phi(), "unknown node used for set_map()");
}
}
#if 0 // ifdef ASSERT
@@ -1542,1571 +3060,72 @@
#endif
}
-bool ConnectionGraph::has_candidates(Compile *C) {
- // EA brings benefits only when the code has allocations and/or locks which
- // are represented by ideal Macro nodes.
- int cnt = C->macro_count();
- for( int i=0; i < cnt; i++ ) {
- Node *n = C->macro_node(i);
- if ( n->is_Allocate() )
- return true;
- if( n->is_Lock() ) {
- Node* obj = n->as_Lock()->obj_node()->uncast();
- if( !(obj->is_Parm() || obj->is_Con()) )
- return true;
- }
- }
- return false;
-}
-
-void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
- // Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
- // to create space for them in ConnectionGraph::_nodes[].
- Node* oop_null = igvn->zerocon(T_OBJECT);
- Node* noop_null = igvn->zerocon(T_NARROWOOP);
-
- ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
- // Perform escape analysis
- if (congraph->compute_escape()) {
- // There are non escaping objects.
- C->set_congraph(congraph);
- }
-
- // Cleanup.
- if (oop_null->outcnt() == 0)
- igvn->hash_delete(oop_null);
- if (noop_null->outcnt() == 0)
- igvn->hash_delete(noop_null);
-}
-
-bool ConnectionGraph::compute_escape() {
- Compile* C = _compile;
-
- // 1. Populate Connection Graph (CG) with Ideal nodes.
-
- Unique_Node_List worklist_init;
- worklist_init.map(C->unique(), NULL); // preallocate space
-
- // Initialize worklist
- if (C->root() != NULL) {
- worklist_init.push(C->root());
- }
-
- GrowableArray<Node*> alloc_worklist;
- GrowableArray<Node*> addp_worklist;
- GrowableArray<Node*> ptr_cmp_worklist;
- GrowableArray<Node*> storestore_worklist;
- PhaseGVN* igvn = _igvn;
-
- // Push all useful nodes onto CG list and set their type.
- for( uint next = 0; next < worklist_init.size(); ++next ) {
- Node* n = worklist_init.at(next);
- record_for_escape_analysis(n, igvn);
- // Only allocations and java static calls results are checked
- // for an escape status. See process_call_result() below.
- if (n->is_Allocate() || n->is_CallStaticJava() &&
- ptnode_adr(n->_idx)->node_type() == PointsToNode::JavaObject) {
- alloc_worklist.append(n);
- } else if(n->is_AddP()) {
- // Collect address nodes. Use them during stage 3 below
- // to build initial connection graph field edges.
- addp_worklist.append(n);
- } else if (n->is_MergeMem()) {
- // Collect all MergeMem nodes to add memory slices for
- // scalar replaceable objects in split_unique_types().
- _mergemem_worklist.append(n->as_MergeMem());
- } else if (OptimizePtrCompare && n->is_Cmp() &&
- (n->Opcode() == Op_CmpP || n->Opcode() == Op_CmpN)) {
- // Compare pointers nodes
- ptr_cmp_worklist.append(n);
- } else if (n->is_MemBarStoreStore()) {
- // Collect all MemBarStoreStore nodes so that depending on the
- // escape status of the associated Allocate node some of them
- // may be eliminated.
- storestore_worklist.append(n);
- }
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node* m = n->fast_out(i); // Get user
- worklist_init.push(m);
- }
- }
-
- if (alloc_worklist.length() == 0) {
- _collecting = false;
- return false; // Nothing to do.
- }
-
- // 2. First pass to create simple CG edges (doesn't require to walk CG).
- uint delayed_size = _delayed_worklist.size();
- for( uint next = 0; next < delayed_size; ++next ) {
- Node* n = _delayed_worklist.at(next);
- build_connection_graph(n, igvn);
- }
-
- // 3. Pass to create initial fields edges (JavaObject -F-> AddP)
- // to reduce number of iterations during stage 4 below.
- uint addp_length = addp_worklist.length();
- for( uint next = 0; next < addp_length; ++next ) {
- Node* n = addp_worklist.at(next);
- Node* base = get_addp_base(n);
- if (base->is_Proj() && base->in(0)->is_Call())
- base = base->in(0);
- PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type();
- if (nt == PointsToNode::JavaObject) {
- build_connection_graph(n, igvn);
- }
- }
-
- GrowableArray<int> cg_worklist;
- cg_worklist.append(_phantom_object);
- GrowableArray<uint> worklist;
-
- // 4. Build Connection Graph which need
- // to walk the connection graph.
- _progress = false;
- for (uint ni = 0; ni < nodes_size(); ni++) {
- PointsToNode* ptn = ptnode_adr(ni);
- Node *n = ptn->_node;
- if (n != NULL) { // Call, AddP, LoadP, StoreP
- build_connection_graph(n, igvn);
- if (ptn->node_type() != PointsToNode::UnknownType)
- cg_worklist.append(n->_idx); // Collect CG nodes
- if (!_processed.test(n->_idx))
- worklist.append(n->_idx); // Collect C/A/L/S nodes
- }
- }
-
- // After IGVN user nodes may have smaller _idx than
- // their inputs so they will be processed first in
- // previous loop. Because of that not all Graph
- // edges will be created. Walk over interesting
- // nodes again until no new edges are created.
- //
- // Normally only 1-3 passes needed to build
- // Connection Graph depending on graph complexity.
- // Observed 8 passes in jvm2008 compiler.compiler.
- // Set limit to 20 to catch situation when something
- // did go wrong and recompile the method without EA.
- // Also limit build time to 30 sec (60 in debug VM).
-
-#define CG_BUILD_ITER_LIMIT 20
-
-#ifdef ASSERT
-#define CG_BUILD_TIME_LIMIT 60.0
-#else
-#define CG_BUILD_TIME_LIMIT 30.0
-#endif
+#ifndef PRODUCT
+static const char *node_type_names[] = {
+ "UnknownType",
+ "JavaObject",
+ "LocalVar",
+ "Field",
+ "Arraycopy"
+};
- uint length = worklist.length();
- int iterations = 0;
- elapsedTimer time;
- while(_progress &&
- (iterations++ < CG_BUILD_ITER_LIMIT) &&
- (time.seconds() < CG_BUILD_TIME_LIMIT)) {
- time.start();
- _progress = false;
- for( uint next = 0; next < length; ++next ) {
- int ni = worklist.at(next);
- PointsToNode* ptn = ptnode_adr(ni);
- Node* n = ptn->_node;
- assert(n != NULL, "should be known node");
- build_connection_graph(n, igvn);
- }
- time.stop();
- }
- if ((iterations >= CG_BUILD_ITER_LIMIT) ||
- (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
- assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
- time.seconds(), iterations, nodes_size(), length));
- // Possible infinite build_connection_graph loop,
- // bailout (no changes to ideal graph were made).
- _collecting = false;
- return false;
- }
-#undef CG_BUILD_ITER_LIMIT
-#undef CG_BUILD_TIME_LIMIT
-
- // 5. Propagate escaped states.
- worklist.clear();
-
- // mark all nodes reachable from GlobalEscape nodes
- (void)propagate_escape_state(&cg_worklist, &worklist, PointsToNode::GlobalEscape);
-
- // mark all nodes reachable from ArgEscape nodes
- bool has_non_escaping_obj = propagate_escape_state(&cg_worklist, &worklist, PointsToNode::ArgEscape);
-
- Arena* arena = Thread::current()->resource_area();
- VectorSet visited(arena);
-
- // 6. Find fields initializing values for not escaped allocations
- uint alloc_length = alloc_worklist.length();
- for (uint next = 0; next < alloc_length; ++next) {
- Node* n = alloc_worklist.at(next);
- PointsToNode::EscapeState es = ptnode_adr(n->_idx)->escape_state();
- if (es == PointsToNode::NoEscape) {
- has_non_escaping_obj = true;
- if (n->is_Allocate()) {
- find_init_values(n, &visited, igvn);
- // The object allocated by this Allocate node will never be
- // seen by an other thread. Mark it so that when it is
- // expanded no MemBarStoreStore is added.
- n->as_Allocate()->initialization()->set_does_not_escape();
- }
- } else if ((es == PointsToNode::ArgEscape) && n->is_Allocate()) {
- // Same as above. Mark this Allocate node so that when it is
- // expanded no MemBarStoreStore is added.
- n->as_Allocate()->initialization()->set_does_not_escape();
- }
- }
-
- uint cg_length = cg_worklist.length();
-
- // Skip the rest of code if all objects escaped.
- if (!has_non_escaping_obj) {
- cg_length = 0;
- addp_length = 0;
- }
-
- for (uint next = 0; next < cg_length; ++next) {
- int ni = cg_worklist.at(next);
- PointsToNode* ptn = ptnode_adr(ni);
- PointsToNode::NodeType nt = ptn->node_type();
- if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
- if (ptn->edge_count() == 0) {
- // No values were found. Assume the value was set
- // outside this method - add edge to phantom object.
- add_pointsto_edge(ni, _phantom_object);
- }
- }
- }
-
- // 7. Remove deferred edges from the graph.
- for (uint next = 0; next < cg_length; ++next) {
- int ni = cg_worklist.at(next);
- PointsToNode* ptn = ptnode_adr(ni);
- PointsToNode::NodeType nt = ptn->node_type();
- if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
- remove_deferred(ni, &worklist, &visited);
- }
- }
-
- // 8. Adjust escape state of nonescaping objects.
- for (uint next = 0; next < addp_length; ++next) {
- Node* n = addp_worklist.at(next);
- adjust_escape_state(n);
- }
+static const char *esc_names[] = {
+ "UnknownEscape",
+ "NoEscape",
+ "ArgEscape",
+ "GlobalEscape"
+};
- // push all NoEscape nodes on the worklist
- worklist.clear();
- for( uint next = 0; next < cg_length; ++next ) {
- int nk = cg_worklist.at(next);
- if (ptnode_adr(nk)->escape_state() == PointsToNode::NoEscape &&
- !is_null_ptr(nk))
- worklist.push(nk);
- }
-
- alloc_worklist.clear();
- // Propagate scalar_replaceable value.
- while(worklist.length() > 0) {
- uint nk = worklist.pop();
- PointsToNode* ptn = ptnode_adr(nk);
- Node* n = ptn->_node;
- bool scalar_replaceable = ptn->scalar_replaceable();
- if (n->is_Allocate() && scalar_replaceable) {
- // Push scalar replaceable allocations on alloc_worklist
- // for processing in split_unique_types(). Note,
- // following code may change scalar_replaceable value.
- alloc_worklist.append(n);
- }
- uint e_cnt = ptn->edge_count();
- for (uint ei = 0; ei < e_cnt; ei++) {
- uint npi = ptn->edge_target(ei);
- if (is_null_ptr(npi))
- continue;
- PointsToNode *np = ptnode_adr(npi);
- if (np->escape_state() < PointsToNode::NoEscape) {
- set_escape_state(npi, PointsToNode::NoEscape);
- if (!scalar_replaceable) {
- np->set_scalar_replaceable(false);
- }
- worklist.push(npi);
- } else if (np->scalar_replaceable() && !scalar_replaceable) {
- np->set_scalar_replaceable(false);
- worklist.push(npi);
- }
- }
- }
-
- _collecting = false;
- assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
-
- assert(ptnode_adr(_oop_null)->escape_state() == PointsToNode::NoEscape &&
- ptnode_adr(_oop_null)->edge_count() == 0, "sanity");
- if (UseCompressedOops) {
- assert(ptnode_adr(_noop_null)->escape_state() == PointsToNode::NoEscape &&
- ptnode_adr(_noop_null)->edge_count() == 0, "sanity");
- }
-
- if (EliminateLocks && has_non_escaping_obj) {
- // Mark locks before changing ideal graph.
- int cnt = C->macro_count();
- for( int i=0; i < cnt; i++ ) {
- Node *n = C->macro_node(i);
- if (n->is_AbstractLock()) { // Lock and Unlock nodes
- AbstractLockNode* alock = n->as_AbstractLock();
- if (!alock->is_non_esc_obj()) {
- PointsToNode::EscapeState es = escape_state(alock->obj_node());
- assert(es != PointsToNode::UnknownEscape, "should know");
- if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
- assert(!alock->is_eliminated() || alock->is_coarsened(), "sanity");
- // The lock could be marked eliminated by lock coarsening
- // code during first IGVN before EA. Replace coarsened flag
- // to eliminate all associated locks/unlocks.
- alock->set_non_esc_obj();
- }
- }
- }
- }
- }
-
- if (OptimizePtrCompare && has_non_escaping_obj) {
- // Add ConI(#CC_GT) and ConI(#CC_EQ).
- _pcmp_neq = igvn->makecon(TypeInt::CC_GT);
- _pcmp_eq = igvn->makecon(TypeInt::CC_EQ);
- // Optimize objects compare.
- while (ptr_cmp_worklist.length() != 0) {
- Node *n = ptr_cmp_worklist.pop();
- Node *res = optimize_ptr_compare(n);
- if (res != NULL) {
-#ifndef PRODUCT
- if (PrintOptimizePtrCompare) {
- tty->print_cr("++++ Replaced: %d %s(%d,%d) --> %s", n->_idx, (n->Opcode() == Op_CmpP ? "CmpP" : "CmpN"), n->in(1)->_idx, n->in(2)->_idx, (res == _pcmp_eq ? "EQ" : "NotEQ"));
- if (Verbose) {
- n->dump(1);
- }
- }
-#endif
- _igvn->replace_node(n, res);
- }
- }
- // cleanup
- if (_pcmp_neq->outcnt() == 0)
- igvn->hash_delete(_pcmp_neq);
- if (_pcmp_eq->outcnt() == 0)
- igvn->hash_delete(_pcmp_eq);
+void PointsToNode::dump(bool print_state) const {
+ NodeType nt = node_type();
+ tty->print("%s ", node_type_names[(int) nt]);
+ if (print_state) {
+ EscapeState es = escape_state();
+ EscapeState fields_es = fields_escape_state();
+ tty->print("%s(%s) ", esc_names[(int)es], esc_names[(int)fields_es]);
+ if (nt == PointsToNode::JavaObject && !this->scalar_replaceable())
+ tty->print("NSR");
}
-
- // For MemBarStoreStore nodes added in library_call.cpp, check
- // escape status of associated AllocateNode and optimize out
- // MemBarStoreStore node if the allocated object never escapes.
- while (storestore_worklist.length() != 0) {
- Node *n = storestore_worklist.pop();
- MemBarStoreStoreNode *storestore = n ->as_MemBarStoreStore();
- Node *alloc = storestore->in(MemBarNode::Precedent)->in(0);
- assert (alloc->is_Allocate(), "storestore should point to AllocateNode");
- PointsToNode::EscapeState es = ptnode_adr(alloc->_idx)->escape_state();
- if (es == PointsToNode::NoEscape || es == PointsToNode::ArgEscape) {
- MemBarNode* mb = MemBarNode::make(C, Op_MemBarCPUOrder, Compile::AliasIdxBot);
- mb->init_req(TypeFunc::Memory, storestore->in(TypeFunc::Memory));
- mb->init_req(TypeFunc::Control, storestore->in(TypeFunc::Control));
-
- _igvn->register_new_node_with_optimizer(mb);
- _igvn->replace_node(storestore, mb);
+ if (is_Field()) {
+ FieldNode* f = (FieldNode*)this;
+ tty->print("(");
+ for (BaseIterator i(f); i.has_next(); i.next()) {
+ PointsToNode* b = i.get();
+ tty->print(" %d%s", b->idx(),(b->is_JavaObject() ? "P" : ""));
}
- }
-
-#ifndef PRODUCT
- if (PrintEscapeAnalysis) {
- dump(); // Dump ConnectionGraph
- }
-#endif
-
- bool has_scalar_replaceable_candidates = false;
- alloc_length = alloc_worklist.length();
- for (uint next = 0; next < alloc_length; ++next) {
- Node* n = alloc_worklist.at(next);
- PointsToNode* ptn = ptnode_adr(n->_idx);
- assert(ptn->escape_state() == PointsToNode::NoEscape, "sanity");
- if (ptn->scalar_replaceable()) {
- has_scalar_replaceable_candidates = true;
- break;
- }
- }
-
- if ( has_scalar_replaceable_candidates &&
- C->AliasLevel() >= 3 && EliminateAllocations ) {
-
- // Now use the escape information to create unique types for
- // scalar replaceable objects.
- split_unique_types(alloc_worklist);
-
- if (C->failing()) return false;
-
- C->print_method("After Escape Analysis", 2);
-
-#ifdef ASSERT
- } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
- tty->print("=== No allocations eliminated for ");
- C->method()->print_short_name();
- if(!EliminateAllocations) {
- tty->print(" since EliminateAllocations is off ===");
- } else if(!has_scalar_replaceable_candidates) {
- tty->print(" since there are no scalar replaceable candidates ===");
- } else if(C->AliasLevel() < 3) {
- tty->print(" since AliasLevel < 3 ===");
- }
- tty->cr();
-#endif
+ tty->print(" )");
}
- return has_non_escaping_obj;
-}
-
-// Find fields initializing values for allocations.
-void ConnectionGraph::find_init_values(Node* alloc, VectorSet* visited, PhaseTransform* phase) {
- assert(alloc->is_Allocate(), "Should be called for Allocate nodes only");
- PointsToNode* pta = ptnode_adr(alloc->_idx);
- assert(pta->escape_state() == PointsToNode::NoEscape, "Not escaped Allocate nodes only");
- InitializeNode* ini = alloc->as_Allocate()->initialization();
-
- Compile* C = _compile;
- visited->Reset();
- // Check if a oop field's initializing value is recorded and add
- // a corresponding NULL field's value if it is not recorded.
- // Connection Graph does not record a default initialization by NULL
- // captured by Initialize node.
- //
- uint null_idx = UseCompressedOops ? _noop_null : _oop_null;
- uint ae_cnt = pta->edge_count();
- bool visited_bottom_offset = false;
- for (uint ei = 0; ei < ae_cnt; ei++) {
- uint nidx = pta->edge_target(ei); // Field (AddP)
- PointsToNode* ptn = ptnode_adr(nidx);
- assert(ptn->_node->is_AddP(), "Should be AddP nodes only");
- int offset = ptn->offset();
- if (offset == Type::OffsetBot) {
- if (!visited_bottom_offset) {
- visited_bottom_offset = true;
- // Check only oop fields.
- const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
- if (!adr_type->isa_aryptr() ||
- (adr_type->isa_aryptr()->klass() == NULL) ||
- adr_type->isa_aryptr()->klass()->is_obj_array_klass()) {
- // OffsetBot is used to reference array's element,
- // always add reference to NULL since we don't
- // known which element is referenced.
- add_edge_from_fields(alloc->_idx, null_idx, offset);
- }
- }
- } else if (offset != oopDesc::klass_offset_in_bytes() &&
- !visited->test_set(offset)) {
-
- // Check only oop fields.
- const Type* adr_type = ptn->_node->as_AddP()->bottom_type();
- BasicType basic_field_type = T_INT;
- if (adr_type->isa_instptr()) {
- ciField* field = C->alias_type(adr_type->isa_instptr())->field();
- if (field != NULL) {
- basic_field_type = field->layout_type();
- } else {
- // Ignore non field load (for example, klass load)
- }
- } else if (adr_type->isa_aryptr()) {
- if (offset != arrayOopDesc::length_offset_in_bytes()) {
- const Type* elemtype = adr_type->isa_aryptr()->elem();
- basic_field_type = elemtype->array_element_basic_type();
- } else {
- // Ignore array length load
- }
-#ifdef ASSERT
- } else {
- // Raw pointers are used for initializing stores so skip it
- // since it should be recorded already
- Node* base = get_addp_base(ptn->_node);
- assert(adr_type->isa_rawptr() && base->is_Proj() &&
- (base->in(0) == alloc),"unexpected pointer type");
-#endif
- }
- if (basic_field_type == T_OBJECT ||
- basic_field_type == T_NARROWOOP ||
- basic_field_type == T_ARRAY) {
- Node* value = NULL;
- if (ini != NULL) {
- BasicType ft = UseCompressedOops ? T_NARROWOOP : T_OBJECT;
- Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
- if (store != NULL && store->is_Store()) {
- value = store->in(MemNode::ValueIn);
- } else {
- // There could be initializing stores which follow allocation.
- // For example, a volatile field store is not collected
- // by Initialize node.
- //
- // Need to check for dependent loads to separate such stores from
- // stores which follow loads. For now, add initial value NULL so
- // that compare pointers optimization works correctly.
- }
- }
- if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
- // A field's initializing value was not recorded. Add NULL.
- add_edge_from_fields(alloc->_idx, null_idx, offset);
- }
- }
- }
+ tty->print("[");
+ for (EdgeIterator i(this); i.has_next(); i.next()) {
+ PointsToNode* e = i.get();
+ tty->print(" %d%s%s", e->idx(),(e->is_JavaObject() ? "P" : (e->is_Field() ? "F" : "")), e->is_Arraycopy() ? "cp" : "");
}
-}
-
-// Adjust escape state after Connection Graph is built.
-void ConnectionGraph::adjust_escape_state(Node* n) {
- PointsToNode* ptn = ptnode_adr(n->_idx);
- assert(n->is_AddP(), "Should be called for AddP nodes only");
- // Search for objects which are not scalar replaceable
- // and mark them to propagate the state to referenced objects.
- //
-
- int offset = ptn->offset();
- Node* base = get_addp_base(n);
- VectorSet* ptset = PointsTo(base);
- int ptset_size = ptset->Size();
-
- // An object is not scalar replaceable if the field which may point
- // to it has unknown offset (unknown element of an array of objects).
- //
-
- if (offset == Type::OffsetBot) {
- uint e_cnt = ptn->edge_count();
- for (uint ei = 0; ei < e_cnt; ei++) {
- uint npi = ptn->edge_target(ei);
- ptnode_adr(npi)->set_scalar_replaceable(false);
- }
- }
-
- // Currently an object is not scalar replaceable if a LoadStore node
- // access its field since the field value is unknown after it.
- //
- bool has_LoadStore = false;
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node *use = n->fast_out(i);
- if (use->is_LoadStore()) {
- has_LoadStore = true;
- break;
- }
- }
- // An object is not scalar replaceable if the address points
- // to unknown field (unknown element for arrays, offset is OffsetBot).
- //
- // Or the address may point to more then one object. This may produce
- // the false positive result (set not scalar replaceable)
- // since the flow-insensitive escape analysis can't separate
- // the case when stores overwrite the field's value from the case
- // when stores happened on different control branches.
- //
- // Note: it will disable scalar replacement in some cases:
- //
- // Point p[] = new Point[1];
- // p[0] = new Point(); // Will be not scalar replaced
- //
- // but it will save us from incorrect optimizations in next cases:
- //
- // Point p[] = new Point[1];
- // if ( x ) p[0] = new Point(); // Will be not scalar replaced
- //
- if (ptset_size > 1 || ptset_size != 0 &&
- (has_LoadStore || offset == Type::OffsetBot)) {
- for( VectorSetI j(ptset); j.test(); ++j ) {
- ptnode_adr(j.elem)->set_scalar_replaceable(false);
- }
- }
-}
-
-// Propagate escape states to referenced nodes.
-bool ConnectionGraph::propagate_escape_state(GrowableArray<int>* cg_worklist,
- GrowableArray<uint>* worklist,
- PointsToNode::EscapeState esc_state) {
- bool has_java_obj = false;
-
- // push all nodes with the same escape state on the worklist
- uint cg_length = cg_worklist->length();
- for (uint next = 0; next < cg_length; ++next) {
- int nk = cg_worklist->at(next);
- if (ptnode_adr(nk)->escape_state() == esc_state)
- worklist->push(nk);
- }
- // mark all reachable nodes
- while (worklist->length() > 0) {
- int pt = worklist->pop();
- PointsToNode* ptn = ptnode_adr(pt);
- if (ptn->node_type() == PointsToNode::JavaObject &&
- !is_null_ptr(pt)) {
- has_java_obj = true;
- if (esc_state > PointsToNode::NoEscape) {
- // fields values are unknown if object escapes
- add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
- }
+ tty->print(" [");
+ for (UseIterator i(this); i.has_next(); i.next()) {
+ PointsToNode* u = i.get();
+ bool is_base = false;
+ if (PointsToNode::is_base_use(u)) {
+ is_base = true;
+ u = PointsToNode::get_use_node(u)->as_Field();
}
- uint e_cnt = ptn->edge_count();
- for (uint ei = 0; ei < e_cnt; ei++) {
- uint npi = ptn->edge_target(ei);
- if (is_null_ptr(npi))
- continue;
- PointsToNode *np = ptnode_adr(npi);
- if (np->escape_state() < esc_state) {
- set_escape_state(npi, esc_state);
- worklist->push(npi);
- }
- }
- }
- // Has not escaping java objects
- return has_java_obj && (esc_state < PointsToNode::GlobalEscape);
-}
-
-// Optimize objects compare.
-Node* ConnectionGraph::optimize_ptr_compare(Node* n) {
- assert(OptimizePtrCompare, "sanity");
- // Clone returned Set since PointsTo() returns pointer
- // to the same structure ConnectionGraph.pt_ptset.
- VectorSet ptset1 = *PointsTo(n->in(1));
- VectorSet ptset2 = *PointsTo(n->in(2));
-
- // Check simple cases first.
- if (ptset1.Size() == 1) {
- uint pt1 = ptset1.getelem();
- PointsToNode* ptn1 = ptnode_adr(pt1);
- if (ptn1->escape_state() == PointsToNode::NoEscape) {
- if (ptset2.Size() == 1 && ptset2.getelem() == pt1) {
- // Comparing the same not escaping object.
- return _pcmp_eq;
- }
- Node* obj = ptn1->_node;
- // Comparing not escaping allocation.
- if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
- !ptset2.test(pt1)) {
- return _pcmp_neq; // This includes nullness check.
- }
- }
- } else if (ptset2.Size() == 1) {
- uint pt2 = ptset2.getelem();
- PointsToNode* ptn2 = ptnode_adr(pt2);
- if (ptn2->escape_state() == PointsToNode::NoEscape) {
- Node* obj = ptn2->_node;
- // Comparing not escaping allocation.
- if ((obj->is_Allocate() || obj->is_CallStaticJava()) &&
- !ptset1.test(pt2)) {
- return _pcmp_neq; // This includes nullness check.
- }
- }
+ tty->print(" %d%s%s", u->idx(), is_base ? "b" : "", u->is_Arraycopy() ? "cp" : "");
}
-
- if (!ptset1.disjoint(ptset2)) {
- return NULL; // Sets are not disjoint
- }
-
- // Sets are disjoint.
- bool set1_has_unknown_ptr = ptset1.test(_phantom_object) != 0;
- bool set2_has_unknown_ptr = ptset2.test(_phantom_object) != 0;
- bool set1_has_null_ptr = (ptset1.test(_oop_null) | ptset1.test(_noop_null)) != 0;
- bool set2_has_null_ptr = (ptset2.test(_oop_null) | ptset2.test(_noop_null)) != 0;
-
- if (set1_has_unknown_ptr && set2_has_null_ptr ||
- set2_has_unknown_ptr && set1_has_null_ptr) {
- // Check nullness of unknown object.
- return NULL;
- }
-
- // Disjointness by itself is not sufficient since
- // alias analysis is not complete for escaped objects.
- // Disjoint sets are definitely unrelated only when
- // at least one set has only not escaping objects.
- if (!set1_has_unknown_ptr && !set1_has_null_ptr) {
- bool has_only_non_escaping_alloc = true;
- for (VectorSetI i(&ptset1); i.test(); ++i) {
- uint pt = i.elem;
- PointsToNode* ptn = ptnode_adr(pt);
- Node* obj = ptn->_node;
- if (ptn->escape_state() != PointsToNode::NoEscape ||
- !(obj->is_Allocate() || obj->is_CallStaticJava())) {
- has_only_non_escaping_alloc = false;
- break;
- }
- }
- if (has_only_non_escaping_alloc) {
- return _pcmp_neq;
- }
- }
- if (!set2_has_unknown_ptr && !set2_has_null_ptr) {
- bool has_only_non_escaping_alloc = true;
- for (VectorSetI i(&ptset2); i.test(); ++i) {
- uint pt = i.elem;
- PointsToNode* ptn = ptnode_adr(pt);
- Node* obj = ptn->_node;
- if (ptn->escape_state() != PointsToNode::NoEscape ||
- !(obj->is_Allocate() || obj->is_CallStaticJava())) {
- has_only_non_escaping_alloc = false;
- break;
- }
- }
- if (has_only_non_escaping_alloc) {
- return _pcmp_neq;
- }
- }
- return NULL;
+ tty->print(" ]] ");
+ if (_node == NULL)
+ tty->print_cr("<null>");
+ else
+ _node->dump();
}
-void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *phase) {
- bool is_arraycopy = false;
- switch (call->Opcode()) {
-#ifdef ASSERT
- case Op_Allocate:
- case Op_AllocateArray:
- case Op_Lock:
- case Op_Unlock:
- assert(false, "should be done already");
- break;
-#endif
- case Op_CallLeafNoFP:
- is_arraycopy = (call->as_CallLeaf()->_name != NULL &&
- strstr(call->as_CallLeaf()->_name, "arraycopy") != 0);
- // fall through
- case Op_CallLeaf:
- {
- // Stub calls, objects do not escape but they are not scale replaceable.
- // Adjust escape state for outgoing arguments.
- const TypeTuple * d = call->tf()->domain();
- bool src_has_oops = false;
- for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
- const Type* at = d->field_at(i);
- Node *arg = call->in(i)->uncast();
- const Type *aat = phase->type(arg);
- PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state();
- if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() &&
- (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) {
-#ifdef ASSERT
- assert(aat == Type::TOP || aat == TypePtr::NULL_PTR ||
- aat->isa_ptr() != NULL, "expecting an Ptr");
- if (!(is_arraycopy ||
- call->as_CallLeaf()->_name != NULL &&
- (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 ||
- strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 ))
- ) {
- call->dump();
- assert(false, "EA: unexpected CallLeaf");
- }
-#endif
- if (arg_esc < PointsToNode::ArgEscape) {
- set_escape_state(arg->_idx, PointsToNode::ArgEscape);
- Node* arg_base = arg;
- if (arg->is_AddP()) {
- //
- // The inline_native_clone() case when the arraycopy stub is called
- // after the allocation before Initialize and CheckCastPP nodes.
- // Or normal arraycopy for object arrays case.
- //
- // Set AddP's base (Allocate) as not scalar replaceable since
- // pointer to the base (with offset) is passed as argument.
- //
- arg_base = get_addp_base(arg);
- set_escape_state(arg_base->_idx, PointsToNode::ArgEscape);
- }
- }
-
- bool arg_has_oops = aat->isa_oopptr() &&
- (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() ||
- (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass()));
- if (i == TypeFunc::Parms) {
- src_has_oops = arg_has_oops;
- }
- //
- // src or dst could be j.l.Object when other is basic type array:
- //
- // arraycopy(char[],0,Object*,0,size);
- // arraycopy(Object*,0,char[],0,size);
- //
- // Do nothing special in such cases.
- //
- if (is_arraycopy && (i > TypeFunc::Parms) &&
- src_has_oops && arg_has_oops) {
- // Destination object's fields reference an unknown object.
- Node* arg_base = arg;
- if (arg->is_AddP()) {
- arg_base = get_addp_base(arg);
- }
- for (VectorSetI s(PointsTo(arg_base)); s.test(); ++s) {
- uint ps = s.elem;
- set_escape_state(ps, PointsToNode::ArgEscape);
- add_edge_from_fields(ps, _phantom_object, Type::OffsetBot);
- }
- // Conservatively all values in source object fields globally escape
- // since we don't know if values in destination object fields
- // escape (it could be traced but it is too expensive).
- Node* src = call->in(TypeFunc::Parms)->uncast();
- Node* src_base = src;
- if (src->is_AddP()) {
- src_base = get_addp_base(src);
- }
- for (VectorSetI s(PointsTo(src_base)); s.test(); ++s) {
- uint ps = s.elem;
- set_escape_state(ps, PointsToNode::ArgEscape);
- // Use OffsetTop to indicate fields global escape.
- add_edge_from_fields(ps, _phantom_object, Type::OffsetTop);
- }
- }
- }
- }
- break;
- }
-
- case Op_CallStaticJava:
- // For a static call, we know exactly what method is being called.
- // Use bytecode estimator to record the call's escape affects
- {
- ciMethod *meth = call->as_CallJava()->method();
- BCEscapeAnalyzer *call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL;
- // fall-through if not a Java method or no analyzer information
- if (call_analyzer != NULL) {
- const TypeTuple * d = call->tf()->domain();
- bool copy_dependencies = false;
- for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
- const Type* at = d->field_at(i);
- int k = i - TypeFunc::Parms;
- Node *arg = call->in(i)->uncast();
-
- if (at->isa_oopptr() != NULL &&
- ptnode_adr(arg->_idx)->escape_state() < PointsToNode::GlobalEscape) {
-
- bool global_escapes = false;
- bool fields_escapes = false;
- if (!call_analyzer->is_arg_stack(k)) {
- // The argument global escapes, mark everything it could point to
- set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
- global_escapes = true;
- } else {
- if (!call_analyzer->is_arg_local(k)) {
- // The argument itself doesn't escape, but any fields might
- fields_escapes = true;
- }
- set_escape_state(arg->_idx, PointsToNode::ArgEscape);
- copy_dependencies = true;
- }
-
- for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
- uint pt = j.elem;
- if (global_escapes) {
- // The argument global escapes, mark everything it could point to
- set_escape_state(pt, PointsToNode::GlobalEscape);
- add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
- } else {
- set_escape_state(pt, PointsToNode::ArgEscape);
- if (fields_escapes) {
- // The argument itself doesn't escape, but any fields might.
- // Use OffsetTop to indicate such case.
- add_edge_from_fields(pt, _phantom_object, Type::OffsetTop);
- }
- }
- }
- }
- }
- if (copy_dependencies)
- call_analyzer->copy_dependencies(_compile->dependencies());
- break;
- }
- }
-
- default:
- // Fall-through here if not a Java method or no analyzer information
- // or some other type of call, assume the worst case: all arguments
- // globally escape.
- {
- // adjust escape state for outgoing arguments
- const TypeTuple * d = call->tf()->domain();
- for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
- const Type* at = d->field_at(i);
- if (at->isa_oopptr() != NULL) {
- Node *arg = call->in(i)->uncast();
- set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
- for( VectorSetI j(PointsTo(arg)); j.test(); ++j ) {
- uint pt = j.elem;
- set_escape_state(pt, PointsToNode::GlobalEscape);
- add_edge_from_fields(pt, _phantom_object, Type::OffsetBot);
- }
- }
- }
- }
- }
-}
-void ConnectionGraph::process_call_result(ProjNode *resproj, PhaseTransform *phase) {
- CallNode *call = resproj->in(0)->as_Call();
- uint call_idx = call->_idx;
- uint resproj_idx = resproj->_idx;
-
- switch (call->Opcode()) {
- case Op_Allocate:
- {
- Node *k = call->in(AllocateNode::KlassNode);
- const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr();
- assert(kt != NULL, "TypeKlassPtr required.");
- ciKlass* cik = kt->klass();
-
- PointsToNode::EscapeState es;
- uint edge_to;
- if (cik->is_subclass_of(_compile->env()->Thread_klass()) ||
- !cik->is_instance_klass() || // StressReflectiveCode
- cik->as_instance_klass()->has_finalizer()) {
- es = PointsToNode::GlobalEscape;
- edge_to = _phantom_object; // Could not be worse
- } else {
- es = PointsToNode::NoEscape;
- edge_to = call_idx;
- assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
- }
- set_escape_state(call_idx, es);
- add_pointsto_edge(resproj_idx, edge_to);
- _processed.set(resproj_idx);
- break;
- }
-
- case Op_AllocateArray:
- {
-
- Node *k = call->in(AllocateNode::KlassNode);
- const TypeKlassPtr *kt = k->bottom_type()->isa_klassptr();
- assert(kt != NULL, "TypeKlassPtr required.");
- ciKlass* cik = kt->klass();
-
- PointsToNode::EscapeState es;
- uint edge_to;
- if (!cik->is_array_klass()) { // StressReflectiveCode
- es = PointsToNode::GlobalEscape;
- edge_to = _phantom_object;
- } else {
- es = PointsToNode::NoEscape;
- edge_to = call_idx;
- assert(ptnode_adr(call_idx)->scalar_replaceable(), "sanity");
- int length = call->in(AllocateNode::ALength)->find_int_con(-1);
- if (length < 0 || length > EliminateAllocationArraySizeLimit) {
- // Not scalar replaceable if the length is not constant or too big.
- ptnode_adr(call_idx)->set_scalar_replaceable(false);
- }
- }
- set_escape_state(call_idx, es);
- add_pointsto_edge(resproj_idx, edge_to);
- _processed.set(resproj_idx);
- break;
- }
-
- case Op_CallStaticJava:
- // For a static call, we know exactly what method is being called.
- // Use bytecode estimator to record whether the call's return value escapes
- {
- bool done = true;
- const TypeTuple *r = call->tf()->range();
- const Type* ret_type = NULL;
-
- if (r->cnt() > TypeFunc::Parms)
- ret_type = r->field_at(TypeFunc::Parms);
-
- // Note: we use isa_ptr() instead of isa_oopptr() here because the
- // _multianewarray functions return a TypeRawPtr.
- if (ret_type == NULL || ret_type->isa_ptr() == NULL) {
- _processed.set(resproj_idx);
- break; // doesn't return a pointer type
- }
- ciMethod *meth = call->as_CallJava()->method();
- const TypeTuple * d = call->tf()->domain();
- if (meth == NULL) {
- // not a Java method, assume global escape
- set_escape_state(call_idx, PointsToNode::GlobalEscape);
- add_pointsto_edge(resproj_idx, _phantom_object);
- } else {
- BCEscapeAnalyzer *call_analyzer = meth->get_bcea();
- bool copy_dependencies = false;
-
- if (call_analyzer->is_return_allocated()) {
- // Returns a newly allocated unescaped object, simply
- // update dependency information.
- // Mark it as NoEscape so that objects referenced by
- // it's fields will be marked as NoEscape at least.
- set_escape_state(call_idx, PointsToNode::NoEscape);
- ptnode_adr(call_idx)->set_scalar_replaceable(false);
- // Fields values are unknown
- add_edge_from_fields(call_idx, _phantom_object, Type::OffsetBot);
- add_pointsto_edge(resproj_idx, call_idx);
- copy_dependencies = true;
- } else {
- // determine whether any arguments are returned
- set_escape_state(call_idx, PointsToNode::ArgEscape);
- bool ret_arg = false;
- for (uint i = TypeFunc::Parms; i < d->cnt(); i++) {
- const Type* at = d->field_at(i);
- if (at->isa_oopptr() != NULL) {
- Node *arg = call->in(i)->uncast();
-
- if (call_analyzer->is_arg_returned(i - TypeFunc::Parms)) {
- ret_arg = true;
- PointsToNode *arg_esp = ptnode_adr(arg->_idx);
- if (arg_esp->node_type() == PointsToNode::UnknownType)
- done = false;
- else if (arg_esp->node_type() == PointsToNode::JavaObject)
- add_pointsto_edge(resproj_idx, arg->_idx);
- else
- add_deferred_edge(resproj_idx, arg->_idx);
- }
- }
- }
- if (done) {
- copy_dependencies = true;
- // is_return_local() is true when only arguments are returned.
- if (!ret_arg || !call_analyzer->is_return_local()) {
- // Returns unknown object.
- add_pointsto_edge(resproj_idx, _phantom_object);
- }
- }
- }
- if (copy_dependencies)
- call_analyzer->copy_dependencies(_compile->dependencies());
- }
- if (done)
- _processed.set(resproj_idx);
- break;
- }
-
- default:
- // Some other type of call, assume the worst case that the
- // returned value, if any, globally escapes.
- {
- const TypeTuple *r = call->tf()->range();
- if (r->cnt() > TypeFunc::Parms) {
- const Type* ret_type = r->field_at(TypeFunc::Parms);
-
- // Note: we use isa_ptr() instead of isa_oopptr() here because the
- // _multianewarray functions return a TypeRawPtr.
- if (ret_type->isa_ptr() != NULL) {
- set_escape_state(call_idx, PointsToNode::GlobalEscape);
- add_pointsto_edge(resproj_idx, _phantom_object);
- }
- }
- _processed.set(resproj_idx);
- }
- }
-}
-
-// Populate Connection Graph with Ideal nodes and create simple
-// connection graph edges (do not need to check the node_type of inputs
-// or to call PointsTo() to walk the connection graph).
-void ConnectionGraph::record_for_escape_analysis(Node *n, PhaseTransform *phase) {
- if (_processed.test(n->_idx))
- return; // No need to redefine node's state.
-
- if (n->is_Call()) {
- // Arguments to allocation and locking don't escape.
- if (n->is_Allocate()) {
- add_node(n, PointsToNode::JavaObject, PointsToNode::UnknownEscape, true);
- record_for_optimizer(n);
- } else if (n->is_Lock() || n->is_Unlock()) {
- // Put Lock and Unlock nodes on IGVN worklist to process them during
- // the first IGVN optimization when escape information is still available.
- record_for_optimizer(n);
- _processed.set(n->_idx);
- } else {
- // Don't mark as processed since call's arguments have to be processed.
- PointsToNode::NodeType nt = PointsToNode::UnknownType;
- PointsToNode::EscapeState es = PointsToNode::UnknownEscape;
-
- // Check if a call returns an object.
- const TypeTuple *r = n->as_Call()->tf()->range();
- if (r->cnt() > TypeFunc::Parms &&
- r->field_at(TypeFunc::Parms)->isa_ptr() &&
- n->as_Call()->proj_out(TypeFunc::Parms) != NULL) {
- nt = PointsToNode::JavaObject;
- if (!n->is_CallStaticJava()) {
- // Since the called mathod is statically unknown assume
- // the worst case that the returned value globally escapes.
- es = PointsToNode::GlobalEscape;
- }
- }
- add_node(n, nt, es, false);
- }
- return;
- }
-
- // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
- // ThreadLocal has RawPrt type.
- switch (n->Opcode()) {
- case Op_AddP:
- {
- add_node(n, PointsToNode::Field, PointsToNode::UnknownEscape, false);
- break;
- }
- case Op_CastX2P:
- { // "Unsafe" memory access.
- add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
- break;
- }
- case Op_CastPP:
- case Op_CheckCastPP:
- case Op_EncodeP:
- case Op_DecodeN:
- {
- add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
- int ti = n->in(1)->_idx;
- PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
- if (nt == PointsToNode::UnknownType) {
- _delayed_worklist.push(n); // Process it later.
- break;
- } else if (nt == PointsToNode::JavaObject) {
- add_pointsto_edge(n->_idx, ti);
- } else {
- add_deferred_edge(n->_idx, ti);
- }
- _processed.set(n->_idx);
- break;
- }
- case Op_ConP:
- {
- // assume all pointer constants globally escape except for null
- PointsToNode::EscapeState es;
- if (phase->type(n) == TypePtr::NULL_PTR)
- es = PointsToNode::NoEscape;
- else
- es = PointsToNode::GlobalEscape;
-
- add_node(n, PointsToNode::JavaObject, es, true);
- break;
- }
- case Op_ConN:
- {
- // assume all narrow oop constants globally escape except for null
- PointsToNode::EscapeState es;
- if (phase->type(n) == TypeNarrowOop::NULL_PTR)
- es = PointsToNode::NoEscape;
- else
- es = PointsToNode::GlobalEscape;
-
- add_node(n, PointsToNode::JavaObject, es, true);
- break;
- }
- case Op_CreateEx:
- {
- // assume that all exception objects globally escape
- add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
- break;
- }
- case Op_LoadKlass:
- case Op_LoadNKlass:
- {
- add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, true);
- break;
- }
- case Op_LoadP:
- case Op_LoadN:
- {
- const Type *t = phase->type(n);
- if (t->make_ptr() == NULL) {
- _processed.set(n->_idx);
- return;
- }
- add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
- break;
- }
- case Op_Parm:
- {
- _processed.set(n->_idx); // No need to redefine it state.
- uint con = n->as_Proj()->_con;
- if (con < TypeFunc::Parms)
- return;
- const Type *t = n->in(0)->as_Start()->_domain->field_at(con);
- if (t->isa_ptr() == NULL)
- return;
- // We have to assume all input parameters globally escape
- // (Note: passing 'false' since _processed is already set).
- add_node(n, PointsToNode::JavaObject, PointsToNode::GlobalEscape, false);
- break;
- }
- case Op_PartialSubtypeCheck:
- { // Produces Null or notNull and is used in CmpP.
- add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true);
- break;
- }
- case Op_Phi:
- {
- const Type *t = n->as_Phi()->type();
- if (t->make_ptr() == NULL) {
- // nothing to do if not an oop or narrow oop
- _processed.set(n->_idx);
- return;
- }
- add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
- uint i;
- for (i = 1; i < n->req() ; i++) {
- Node* in = n->in(i);
- if (in == NULL)
- continue; // ignore NULL
- in = in->uncast();
- if (in->is_top() || in == n)
- continue; // ignore top or inputs which go back this node
- int ti = in->_idx;
- PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
- if (nt == PointsToNode::UnknownType) {
- break;
- } else if (nt == PointsToNode::JavaObject) {
- add_pointsto_edge(n->_idx, ti);
- } else {
- add_deferred_edge(n->_idx, ti);
- }
- }
- if (i >= n->req())
- _processed.set(n->_idx);
- else
- _delayed_worklist.push(n);
- break;
- }
- case Op_Proj:
- {
- // we are only interested in the oop result projection from a call
- if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
- const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
- assert(r->cnt() > TypeFunc::Parms, "sanity");
- if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
- add_node(n, PointsToNode::LocalVar, PointsToNode::UnknownEscape, false);
- int ti = n->in(0)->_idx;
- // The call may not be registered yet (since not all its inputs are registered)
- // if this is the projection from backbranch edge of Phi.
- if (ptnode_adr(ti)->node_type() != PointsToNode::UnknownType) {
- process_call_result(n->as_Proj(), phase);
- }
- if (!_processed.test(n->_idx)) {
- // The call's result may need to be processed later if the call
- // returns it's argument and the argument is not processed yet.
- _delayed_worklist.push(n);
- }
- break;
- }
- }
- _processed.set(n->_idx);
- break;
- }
- case Op_Return:
- {
- if( n->req() > TypeFunc::Parms &&
- phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
- // Treat Return value as LocalVar with GlobalEscape escape state.
- add_node(n, PointsToNode::LocalVar, PointsToNode::GlobalEscape, false);
- int ti = n->in(TypeFunc::Parms)->_idx;
- PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
- if (nt == PointsToNode::UnknownType) {
- _delayed_worklist.push(n); // Process it later.
- break;
- } else if (nt == PointsToNode::JavaObject) {
- add_pointsto_edge(n->_idx, ti);
- } else {
- add_deferred_edge(n->_idx, ti);
- }
- }
- _processed.set(n->_idx);
- break;
- }
- case Op_StoreP:
- case Op_StoreN:
- {
- const Type *adr_type = phase->type(n->in(MemNode::Address));
- adr_type = adr_type->make_ptr();
- if (adr_type->isa_oopptr()) {
- add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
- } else {
- Node* adr = n->in(MemNode::Address);
- if (adr->is_AddP() && phase->type(adr) == TypeRawPtr::NOTNULL &&
- adr->in(AddPNode::Address)->is_Proj() &&
- adr->in(AddPNode::Address)->in(0)->is_Allocate()) {
- add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
- // We are computing a raw address for a store captured
- // by an Initialize compute an appropriate address type.
- int offs = (int)phase->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
- assert(offs != Type::OffsetBot, "offset must be a constant");
- } else {
- _processed.set(n->_idx);
- return;
- }
- }
- break;
- }
- case Op_StorePConditional:
- case Op_CompareAndSwapP:
- case Op_CompareAndSwapN:
- {
- const Type *adr_type = phase->type(n->in(MemNode::Address));
- adr_type = adr_type->make_ptr();
- if (adr_type->isa_oopptr()) {
- add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
- } else {
- _processed.set(n->_idx);
- return;
- }
- break;
- }
- case Op_AryEq:
- case Op_StrComp:
- case Op_StrEquals:
- case Op_StrIndexOf:
- {
- // char[] arrays passed to string intrinsics are not scalar replaceable.
- add_node(n, PointsToNode::UnknownType, PointsToNode::UnknownEscape, false);
- break;
- }
- case Op_ThreadLocal:
- {
- add_node(n, PointsToNode::JavaObject, PointsToNode::ArgEscape, true);
- break;
- }
- default:
- ;
- // nothing to do
- }
- return;
-}
-
-void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
- uint n_idx = n->_idx;
- assert(ptnode_adr(n_idx)->_node != NULL, "node should be registered");
-
- // Don't set processed bit for AddP, LoadP, StoreP since
- // they may need more then one pass to process.
- // Also don't mark as processed Call nodes since their
- // arguments may need more then one pass to process.
- if (_processed.test(n_idx))
- return; // No need to redefine node's state.
-
- if (n->is_Call()) {
- CallNode *call = n->as_Call();
- process_call_arguments(call, phase);
- return;
- }
-
- switch (n->Opcode()) {
- case Op_AddP:
- {
- Node *base = get_addp_base(n);
- int offset = address_offset(n, phase);
- // Create a field edge to this node from everything base could point to.
- for( VectorSetI i(PointsTo(base)); i.test(); ++i ) {
- uint pt = i.elem;
- add_field_edge(pt, n_idx, offset);
- }
- break;
- }
- case Op_CastX2P:
- {
- assert(false, "Op_CastX2P");
- break;
- }
- case Op_CastPP:
- case Op_CheckCastPP:
- case Op_EncodeP:
- case Op_DecodeN:
- {
- int ti = n->in(1)->_idx;
- assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "all nodes should be registered");
- if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
- add_pointsto_edge(n_idx, ti);
- } else {
- add_deferred_edge(n_idx, ti);
- }
- _processed.set(n_idx);
- break;
- }
- case Op_ConP:
- {
- assert(false, "Op_ConP");
- break;
- }
- case Op_ConN:
- {
- assert(false, "Op_ConN");
- break;
- }
- case Op_CreateEx:
- {
- assert(false, "Op_CreateEx");
- break;
- }
- case Op_LoadKlass:
- case Op_LoadNKlass:
- {
- assert(false, "Op_LoadKlass");
- break;
- }
- case Op_LoadP:
- case Op_LoadN:
- {
- const Type *t = phase->type(n);
-#ifdef ASSERT
- if (t->make_ptr() == NULL)
- assert(false, "Op_LoadP");
-#endif
-
- Node* adr = n->in(MemNode::Address)->uncast();
- Node* adr_base;
- if (adr->is_AddP()) {
- adr_base = get_addp_base(adr);
- } else {
- adr_base = adr;
- }
-
- // For everything "adr_base" could point to, create a deferred edge from
- // this node to each field with the same offset.
- int offset = address_offset(adr, phase);
- for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
- uint pt = i.elem;
- if (adr->is_AddP()) {
- // Add field edge if it is missing.
- add_field_edge(pt, adr->_idx, offset);
- }
- add_deferred_edge_to_fields(n_idx, pt, offset);
- }
- break;
- }
- case Op_Parm:
- {
- assert(false, "Op_Parm");
- break;
- }
- case Op_PartialSubtypeCheck:
- {
- assert(false, "Op_PartialSubtypeCheck");
- break;
- }
- case Op_Phi:
- {
-#ifdef ASSERT
- const Type *t = n->as_Phi()->type();
- if (t->make_ptr() == NULL)
- assert(false, "Op_Phi");
-#endif
- for (uint i = 1; i < n->req() ; i++) {
- Node* in = n->in(i);
- if (in == NULL)
- continue; // ignore NULL
- in = in->uncast();
- if (in->is_top() || in == n)
- continue; // ignore top or inputs which go back this node
- int ti = in->_idx;
- PointsToNode::NodeType nt = ptnode_adr(ti)->node_type();
- assert(nt != PointsToNode::UnknownType, "all nodes should be known");
- if (nt == PointsToNode::JavaObject) {
- add_pointsto_edge(n_idx, ti);
- } else {
- add_deferred_edge(n_idx, ti);
- }
- }
- _processed.set(n_idx);
- break;
- }
- case Op_Proj:
- {
- // we are only interested in the oop result projection from a call
- if (n->as_Proj()->_con == TypeFunc::Parms && n->in(0)->is_Call() ) {
- assert(ptnode_adr(n->in(0)->_idx)->node_type() != PointsToNode::UnknownType,
- "all nodes should be registered");
- const TypeTuple *r = n->in(0)->as_Call()->tf()->range();
- assert(r->cnt() > TypeFunc::Parms, "sanity");
- if (r->field_at(TypeFunc::Parms)->isa_ptr() != NULL) {
- process_call_result(n->as_Proj(), phase);
- assert(_processed.test(n_idx), "all call results should be processed");
- break;
- }
- }
- assert(false, "Op_Proj");
- break;
- }
- case Op_Return:
- {
-#ifdef ASSERT
- if( n->req() <= TypeFunc::Parms ||
- !phase->type(n->in(TypeFunc::Parms))->isa_oopptr() ) {
- assert(false, "Op_Return");
- }
-#endif
- int ti = n->in(TypeFunc::Parms)->_idx;
- assert(ptnode_adr(ti)->node_type() != PointsToNode::UnknownType, "node should be registered");
- if (ptnode_adr(ti)->node_type() == PointsToNode::JavaObject) {
- add_pointsto_edge(n_idx, ti);
- } else {
- add_deferred_edge(n_idx, ti);
- }
- _processed.set(n_idx);
- break;
- }
- case Op_StoreP:
- case Op_StoreN:
- case Op_StorePConditional:
- case Op_CompareAndSwapP:
- case Op_CompareAndSwapN:
- {
- Node *adr = n->in(MemNode::Address);
- const Type *adr_type = phase->type(adr)->make_ptr();
-#ifdef ASSERT
- if (!adr_type->isa_oopptr())
- assert(phase->type(adr) == TypeRawPtr::NOTNULL, "Op_StoreP");
-#endif
-
- assert(adr->is_AddP(), "expecting an AddP");
- Node *adr_base = get_addp_base(adr);
- Node *val = n->in(MemNode::ValueIn)->uncast();
- int offset = address_offset(adr, phase);
- // For everything "adr_base" could point to, create a deferred edge
- // to "val" from each field with the same offset.
- for( VectorSetI i(PointsTo(adr_base)); i.test(); ++i ) {
- uint pt = i.elem;
- // Add field edge if it is missing.
- add_field_edge(pt, adr->_idx, offset);
- add_edge_from_fields(pt, val->_idx, offset);
- }
- break;
- }
- case Op_AryEq:
- case Op_StrComp:
- case Op_StrEquals:
- case Op_StrIndexOf:
- {
- // char[] arrays passed to string intrinsic do not escape but
- // they are not scalar replaceable. Adjust escape state for them.
- // Start from in(2) edge since in(1) is memory edge.
- for (uint i = 2; i < n->req(); i++) {
- Node* adr = n->in(i)->uncast();
- const Type *at = phase->type(adr);
- if (!adr->is_top() && at->isa_ptr()) {
- assert(at == Type::TOP || at == TypePtr::NULL_PTR ||
- at->isa_ptr() != NULL, "expecting an Ptr");
- if (adr->is_AddP()) {
- adr = get_addp_base(adr);
- }
- // Mark as ArgEscape everything "adr" could point to.
- set_escape_state(adr->_idx, PointsToNode::ArgEscape);
- }
- }
- _processed.set(n_idx);
- break;
- }
- case Op_ThreadLocal:
- {
- assert(false, "Op_ThreadLocal");
- break;
- }
- default:
- // This method should be called only for EA specific nodes.
- ShouldNotReachHere();
- }
-}
-
-#ifndef PRODUCT
-void ConnectionGraph::dump() {
+void ConnectionGraph::dump(GrowableArray<PointsToNode*>& ptnodes_worklist) {
bool first = true;
-
- uint size = nodes_size();
- for (uint ni = 0; ni < size; ni++) {
- PointsToNode *ptn = ptnode_adr(ni);
- PointsToNode::NodeType ptn_type = ptn->node_type();
-
- if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
+ int ptnodes_length = ptnodes_worklist.length();
+ for (int i = 0; i < ptnodes_length; i++) {
+ PointsToNode *ptn = ptnodes_worklist.at(i);
+ if (ptn == NULL || !ptn->is_JavaObject())
continue;
- PointsToNode::EscapeState es = escape_state(ptn->_node);
- if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
+ PointsToNode::EscapeState es = ptn->escape_state();
+ if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
if (first) {
tty->cr();
tty->print("======== Connection graph for ");
@@ -3114,22 +3133,14 @@
tty->cr();
first = false;
}
- tty->print("%6d ", ni);
ptn->dump();
- // Print all locals which reference this allocation
- for (uint li = ni; li < size; li++) {
- PointsToNode *ptn_loc = ptnode_adr(li);
- PointsToNode::NodeType ptn_loc_type = ptn_loc->node_type();
- if ( ptn_loc_type == PointsToNode::LocalVar && ptn_loc->_node != NULL &&
- ptn_loc->edge_count() == 1 && ptn_loc->edge_target(0) == ni ) {
- ptnode_adr(li)->dump(false);
- }
- }
- if (Verbose) {
- // Print all fields which reference this allocation
- for (uint i = 0; i < ptn->edge_count(); i++) {
- uint ei = ptn->edge_target(i);
- ptnode_adr(ei)->dump(false);
+ // Print all locals and fields which reference this allocation
+ for (UseIterator j(ptn); j.has_next(); j.next()) {
+ PointsToNode* use = j.get();
+ if (use->is_LocalVar()) {
+ use->dump(Verbose);
+ } else if (Verbose) {
+ use->dump();
}
}
tty->cr();
--- a/hotspot/src/share/vm/opto/escape.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/escape.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -115,18 +115,36 @@
class CallNode;
class PhiNode;
class PhaseTransform;
+class PointsToNode;
class Type;
class TypePtr;
class VectorSet;
-class PointsToNode {
-friend class ConnectionGraph;
+class JavaObjectNode;
+class LocalVarNode;
+class FieldNode;
+class ArraycopyNode;
+
+// ConnectionGraph nodes
+class PointsToNode : public ResourceObj {
+ GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
+ GrowableArray<PointsToNode*> _uses; // List of nodes which point to this node
+
+ const u1 _type; // NodeType
+ u1 _flags; // NodeFlags
+ u1 _escape; // EscapeState of object
+ u1 _fields_escape; // EscapeState of object's fields
+
+ Node* const _node; // Ideal node corresponding to this PointsTo node.
+ const int _idx; // Cached ideal node's _idx
+
public:
typedef enum {
UnknownType = 0,
JavaObject = 1,
LocalVar = 2,
- Field = 3
+ Field = 3,
+ Arraycopy = 4
} NodeType;
typedef enum {
@@ -140,178 +158,387 @@
} EscapeState;
typedef enum {
- UnknownEdge = 0,
- PointsToEdge = 1,
- DeferredEdge = 2,
- FieldEdge = 3
- } EdgeType;
-
-private:
- enum {
- EdgeMask = 3,
- EdgeShift = 2,
-
- INITIAL_EDGE_COUNT = 4
- };
-
- NodeType _type;
- EscapeState _escape;
- GrowableArray<uint>* _edges; // outgoing edges
- Node* _node; // Ideal node corresponding to this PointsTo node.
- int _offset; // Object fields offsets.
- bool _scalar_replaceable; // Not escaped object could be replaced with scalar
- bool _has_unknown_ptr; // Has edge to phantom_object
-
-public:
- PointsToNode():
- _type(UnknownType),
- _escape(UnknownEscape),
- _edges(NULL),
- _node(NULL),
- _offset(-1),
- _has_unknown_ptr(false),
- _scalar_replaceable(true) {}
+ ScalarReplaceable = 1, // Not escaped object could be replaced with scalar
+ PointsToUnknown = 2, // Has edge to phantom_object
+ ArraycopySrc = 4, // Has edge from Arraycopy node
+ ArraycopyDst = 8 // Has edge to Arraycopy node
+ } NodeFlags;
- EscapeState escape_state() const { return _escape; }
- NodeType node_type() const { return _type;}
- int offset() { return _offset;}
- bool scalar_replaceable() { return _scalar_replaceable;}
- bool has_unknown_ptr() { return _has_unknown_ptr;}
-
- void set_offset(int offs) { _offset = offs;}
- void set_escape_state(EscapeState state) { _escape = state; }
- void set_node_type(NodeType ntype) {
- assert(_type == UnknownType || _type == ntype, "Can't change node type");
- _type = ntype;
- }
- void set_scalar_replaceable(bool v) { _scalar_replaceable = v; }
- void set_has_unknown_ptr() { _has_unknown_ptr = true; }
-
- // count of outgoing edges
- uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
-
- // node index of target of outgoing edge "e"
- uint edge_target(uint e) const {
- assert(_edges != NULL, "valid edge index");
- return (_edges->at(e) >> EdgeShift);
- }
- // type of outgoing edge "e"
- EdgeType edge_type(uint e) const {
- assert(_edges != NULL, "valid edge index");
- return (EdgeType) (_edges->at(e) & EdgeMask);
+ PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type):
+ _edges(C->comp_arena(), 2, 0, NULL),
+ _uses (C->comp_arena(), 2, 0, NULL),
+ _node(n),
+ _idx(n->_idx),
+ _type((u1)type),
+ _escape((u1)es),
+ _fields_escape((u1)es),
+ _flags(ScalarReplaceable) {
+ assert(n != NULL && es != UnknownEscape, "sanity");
}
- // add a edge of the specified type pointing to the specified target
- void add_edge(uint targIdx, EdgeType et);
+ Node* ideal_node() const { return _node; }
+ int idx() const { return _idx; }
+
+ bool is_JavaObject() const { return _type == (u1)JavaObject; }
+ bool is_LocalVar() const { return _type == (u1)LocalVar; }
+ bool is_Field() const { return _type == (u1)Field; }
+ bool is_Arraycopy() const { return _type == (u1)Arraycopy; }
+
+ JavaObjectNode* as_JavaObject() { assert(is_JavaObject(),""); return (JavaObjectNode*)this; }
+ LocalVarNode* as_LocalVar() { assert(is_LocalVar(),""); return (LocalVarNode*)this; }
+ FieldNode* as_Field() { assert(is_Field(),""); return (FieldNode*)this; }
+ ArraycopyNode* as_Arraycopy() { assert(is_Arraycopy(),""); return (ArraycopyNode*)this; }
+
+ EscapeState escape_state() const { return (EscapeState)_escape; }
+ void set_escape_state(EscapeState state) { _escape = (u1)state; }
+
+ EscapeState fields_escape_state() const { return (EscapeState)_fields_escape; }
+ void set_fields_escape_state(EscapeState state) { _fields_escape = (u1)state; }
+
+ bool has_unknown_ptr() const { return (_flags & PointsToUnknown) != 0; }
+ void set_has_unknown_ptr() { _flags |= PointsToUnknown; }
+
+ bool arraycopy_src() const { return (_flags & ArraycopySrc) != 0; }
+ void set_arraycopy_src() { _flags |= ArraycopySrc; }
+ bool arraycopy_dst() const { return (_flags & ArraycopyDst) != 0; }
+ void set_arraycopy_dst() { _flags |= ArraycopyDst; }
- // remove an edge of the specified type pointing to the specified target
- void remove_edge(uint targIdx, EdgeType et);
+ bool scalar_replaceable() const { return (_flags & ScalarReplaceable) != 0;}
+ void set_scalar_replaceable(bool v) {
+ if (v)
+ _flags |= ScalarReplaceable;
+ else
+ _flags &= ~ScalarReplaceable;
+ }
+
+ int edge_count() const { return _edges.length(); }
+ PointsToNode* edge(int e) const { return _edges.at(e); }
+ bool add_edge(PointsToNode* edge) { return _edges.append_if_missing(edge); }
+
+ int use_count() const { return _uses.length(); }
+ PointsToNode* use(int e) const { return _uses.at(e); }
+ bool add_use(PointsToNode* use) { return _uses.append_if_missing(use); }
+
+ // Mark base edge use to distinguish from stored value edge.
+ bool add_base_use(FieldNode* use) { return _uses.append_if_missing((PointsToNode*)((intptr_t)use + 1)); }
+ static bool is_base_use(PointsToNode* use) { return (((intptr_t)use) & 1); }
+ static PointsToNode* get_use_node(PointsToNode* use) { return (PointsToNode*)(((intptr_t)use) & ~1); }
+
+ // Return true if this node points to specified node or nodes it points to.
+ bool points_to(JavaObjectNode* ptn) const;
+
+ // Return true if this node points only to non-escaping allocations.
+ bool non_escaping_allocation();
+
+ // Return true if one node points to an other.
+ bool meet(PointsToNode* ptn);
#ifndef PRODUCT
+ NodeType node_type() const { return (NodeType)_type;}
void dump(bool print_state=true) const;
#endif
};
+class LocalVarNode: public PointsToNode {
+public:
+ LocalVarNode(Compile *C, Node* n, EscapeState es):
+ PointsToNode(C, n, es, LocalVar) {}
+};
+
+class JavaObjectNode: public PointsToNode {
+public:
+ JavaObjectNode(Compile *C, Node* n, EscapeState es):
+ PointsToNode(C, n, es, JavaObject) {
+ if (es > NoEscape)
+ set_scalar_replaceable(false);
+ }
+};
+
+class FieldNode: public PointsToNode {
+ GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node
+ const int _offset; // Field's offset.
+ const bool _is_oop; // Field points to object
+ bool _has_unknown_base; // Has phantom_object base
+public:
+ FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop):
+ PointsToNode(C, n, es, Field),
+ _offset(offs), _is_oop(is_oop),
+ _has_unknown_base(false) {}
+
+ int offset() const { return _offset;}
+ bool is_oop() const { return _is_oop;}
+ bool has_unknown_base() const { return _has_unknown_base; }
+ void set_has_unknown_base() { _has_unknown_base = true; }
+
+ int base_count() const { return _bases.length(); }
+ PointsToNode* base(int e) const { return _bases.at(e); }
+ bool add_base(PointsToNode* base) { return _bases.append_if_missing(base); }
+#ifdef ASSERT
+ // Return true if bases points to this java object.
+ bool has_base(JavaObjectNode* ptn) const;
+#endif
+
+};
+
+class ArraycopyNode: public PointsToNode {
+public:
+ ArraycopyNode(Compile *C, Node* n, EscapeState es):
+ PointsToNode(C, n, es, Arraycopy) {}
+};
+
+// Iterators for PointsTo node's edges:
+// for (EdgeIterator i(n); i.has_next(); i.next()) {
+// PointsToNode* u = i.get();
+class PointsToIterator: public StackObj {
+protected:
+ const PointsToNode* node;
+ const int cnt;
+ int i;
+public:
+ inline PointsToIterator(const PointsToNode* n, int cnt) : node(n), cnt(cnt), i(0) { }
+ inline bool has_next() const { return i < cnt; }
+ inline void next() { i++; }
+ PointsToNode* get() const { ShouldNotCallThis(); return NULL; }
+};
+
+class EdgeIterator: public PointsToIterator {
+public:
+ inline EdgeIterator(const PointsToNode* n) : PointsToIterator(n, n->edge_count()) { }
+ inline PointsToNode* get() const { return node->edge(i); }
+};
+
+class UseIterator: public PointsToIterator {
+public:
+ inline UseIterator(const PointsToNode* n) : PointsToIterator(n, n->use_count()) { }
+ inline PointsToNode* get() const { return node->use(i); }
+};
+
+class BaseIterator: public PointsToIterator {
+public:
+ inline BaseIterator(const FieldNode* n) : PointsToIterator(n, n->base_count()) { }
+ inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); }
+};
+
+
class ConnectionGraph: public ResourceObj {
private:
- GrowableArray<PointsToNode> _nodes; // Connection graph nodes indexed
- // by ideal node index.
-
- Unique_Node_List _delayed_worklist; // Nodes to be processed before
- // the call build_connection_graph().
+ GrowableArray<PointsToNode*> _nodes; // Map from ideal nodes to
+ // ConnectionGraph nodes.
- GrowableArray<MergeMemNode *> _mergemem_worklist; // List of all MergeMem nodes
+ GrowableArray<PointsToNode*> _worklist; // Nodes to be processed
- VectorSet _processed; // Records which nodes have been
- // processed.
-
- bool _collecting; // Indicates whether escape information
- // is still being collected. If false,
- // no new nodes will be processed.
+ bool _collecting; // Indicates whether escape information
+ // is still being collected. If false,
+ // no new nodes will be processed.
- bool _progress; // Indicates whether new Graph's edges
- // were created.
+ bool _verify; // verify graph
- uint _phantom_object; // Index of globally escaping object
- // that pointer values loaded from
- // a field which has not been set
- // are assumed to point to.
- uint _oop_null; // ConP(#NULL)->_idx
- uint _noop_null; // ConN(#NULL)->_idx
- Node* _pcmp_neq; // ConI(#CC_GT)
- Node* _pcmp_eq; // ConI(#CC_EQ)
+ JavaObjectNode* phantom_obj; // Unknown object
+ JavaObjectNode* null_obj;
+ Node* _pcmp_neq; // ConI(#CC_GT)
+ Node* _pcmp_eq; // ConI(#CC_EQ)
- Compile * _compile; // Compile object for current compilation
- PhaseIterGVN * _igvn; // Value numbering
+ Compile* _compile; // Compile object for current compilation
+ PhaseIterGVN* _igvn; // Value numbering
+
+ Unique_Node_List ideal_nodes; // Used by CG construction and types splitting.
// Address of an element in _nodes. Used when the element is to be modified
- PointsToNode *ptnode_adr(uint idx) const {
+ PointsToNode* ptnode_adr(int idx) const {
// There should be no new ideal nodes during ConnectionGraph build,
- // growableArray::adr_at() will throw assert otherwise.
- return _nodes.adr_at(idx);
+ // growableArray::at() will throw assert otherwise.
+ return _nodes.at(idx);
}
uint nodes_size() const { return _nodes.length(); }
- bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); }
+ // Add nodes to ConnectionGraph.
+ void add_local_var(Node* n, PointsToNode::EscapeState es);
+ void add_java_object(Node* n, PointsToNode::EscapeState es);
+ void add_field(Node* n, PointsToNode::EscapeState es, int offset);
+ void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst);
+
+ // Compute the escape state for arguments to a call.
+ void process_call_arguments(CallNode *call);
+
+ // Add PointsToNode node corresponding to a call
+ void add_call_node(CallNode* call);
+
+ // Map ideal node to existing PointsTo node (usually phantom_object).
+ void map_ideal_node(Node *n, PointsToNode* ptn) {
+ assert(ptn != NULL, "only existing PointsTo node");
+ _nodes.at_put(n->_idx, ptn);
+ }
+
+ // Create PointsToNode node and add it to Connection Graph.
+ void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
+
+ // Add final simple edges to graph.
+ void add_final_edges(Node *n);
+
+ // Finish Graph construction.
+ bool complete_connection_graph(GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+ GrowableArray<JavaObjectNode*>& java_objects_worklist,
+ GrowableArray<FieldNode*>& oop_fields_worklist);
+
+#ifdef ASSERT
+ void verify_connection_graph(GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist,
+ GrowableArray<JavaObjectNode*>& java_objects_worklist,
+ GrowableArray<Node*>& addp_worklist);
+#endif
+
+ // Add all references to this JavaObject node.
+ int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
+
+ // Put node on worklist if it is (or was) not there.
+ void add_to_worklist(PointsToNode* pt) {
+ _worklist.push(pt);
+ return;
+ }
+
+ // Put on worklist all uses of this node.
+ void add_uses_to_worklist(PointsToNode* pt) {
+ for (UseIterator i(pt); i.has_next(); i.next())
+ _worklist.push(i.get());
+ }
+
+ // Put on worklist all field's uses and related field nodes.
+ void add_field_uses_to_worklist(FieldNode* field);
+
+ // Put on worklist all related field nodes.
+ void add_fields_to_worklist(FieldNode* field, PointsToNode* base);
+
+ // Find fields which have unknown value.
+ int find_field_value(FieldNode* field);
+
+ // Find fields initializing values for allocations.
+ int find_init_values(JavaObjectNode* ptn, PointsToNode* init_val, PhaseTransform* phase);
+
+ // Set the escape state of an object and its fields.
+ void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
+ // Don't change non-escaping state of NULL pointer.
+ if (ptn != null_obj) {
+ if (ptn->escape_state() < esc)
+ ptn->set_escape_state(esc);
+ if (ptn->fields_escape_state() < esc)
+ ptn->set_fields_escape_state(esc);
+ }
+ }
+ void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
+ // Don't change non-escaping state of NULL pointer.
+ if (ptn != null_obj) {
+ if (ptn->fields_escape_state() < esc)
+ ptn->set_fields_escape_state(esc);
+ }
+ }
- // Add node to ConnectionGraph.
- void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
+ // Propagate GlobalEscape and ArgEscape escape states to all nodes
+ // and check that we still have non-escaping java objects.
+ bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
+ GrowableArray<JavaObjectNode*>& non_escaped_worklist);
+
+ // Adjust scalar_replaceable state after Connection Graph is built.
+ void adjust_scalar_replaceable_state(JavaObjectNode* jobj);
+
+ // Optimize ideal graph.
+ void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
+ GrowableArray<Node*>& storestore_worklist);
+ // Optimize objects compare.
+ Node* optimize_ptr_compare(Node* n);
+
+ // Returns unique corresponding java object or NULL.
+ JavaObjectNode* unique_java_object(Node *n);
+
+ // Add an edge of the specified type pointing to the specified target.
+ bool add_edge(PointsToNode* from, PointsToNode* to) {
+ assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity");
+
+ if (to == phantom_obj) {
+ if (from->has_unknown_ptr()) {
+ return false; // already points to phantom_obj
+ }
+ from->set_has_unknown_ptr();
+ }
+
+ bool is_new = from->add_edge(to);
+ assert(to != phantom_obj || is_new, "sanity");
+ if (is_new) { // New edge?
+ assert(!_verify, "graph is incomplete");
+ is_new = to->add_use(from);
+ assert(is_new, "use should be also new");
+ }
+ return is_new;
+ }
+
+ // Add an edge from Field node to its base and back.
+ bool add_base(FieldNode* from, PointsToNode* to) {
+ assert(!to->is_Arraycopy(), "sanity");
+ if (to == phantom_obj) {
+ if (from->has_unknown_base()) {
+ return false; // already has phantom_obj base
+ }
+ from->set_has_unknown_base();
+ }
+ bool is_new = from->add_base(to);
+ assert(to != phantom_obj || is_new, "sanity");
+ if (is_new) { // New edge?
+ assert(!_verify, "graph is incomplete");
+ if (to == null_obj)
+ return is_new; // Don't add fields to NULL pointer.
+ if (to->is_JavaObject()) {
+ is_new = to->add_edge(from);
+ } else {
+ is_new = to->add_base_use(from);
+ }
+ assert(is_new, "use should be also new");
+ }
+ return is_new;
+ }
+
+ // Add LocalVar node and edge if possible
+ void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to,
+ Unique_Node_List *delayed_worklist) {
+ PointsToNode* ptn = ptnode_adr(to->_idx);
+ if (delayed_worklist != NULL) { // First iteration of CG construction
+ add_local_var(n, es);
+ if (ptn == NULL) {
+ delayed_worklist->push(n);
+ return; // Process it later.
+ }
+ } else {
+ assert(ptn != NULL, "node should be registered");
+ }
+ add_edge(ptnode_adr(n->_idx), ptn);
+ }
+
+ // Helper functions
+ bool is_oop_field(Node* n, int offset);
+ static Node* get_addp_base(Node *addp);
+ static Node* find_second_addp(Node* addp, Node* n);
// offset of a field reference
int address_offset(Node* adr, PhaseTransform *phase);
- // compute the escape state for arguments to a call
- void process_call_arguments(CallNode *call, PhaseTransform *phase);
- // compute the escape state for the return value of a call
- void process_call_result(ProjNode *resproj, PhaseTransform *phase);
-
- // Populate Connection Graph with Ideal nodes.
- void record_for_escape_analysis(Node *n, PhaseTransform *phase);
-
- // Build Connection Graph and set nodes escape state.
- void build_connection_graph(Node *n, PhaseTransform *phase);
-
- // walk the connection graph starting at the node corresponding to "n" and
- // add the index of everything it could point to, to "ptset". This may cause
- // Phi's encountered to get (re)processed (which requires "phase".)
- VectorSet* PointsTo(Node * n);
-
- // Reused structures for PointsTo().
- VectorSet pt_ptset;
- VectorSet pt_visited;
- GrowableArray<uint> pt_worklist;
+ // Propagate unique types created for unescaped allocated objects
+ // through the graph
+ void split_unique_types(GrowableArray<Node *> &alloc_worklist);
- // Edge manipulation. The "from_i" and "to_i" arguments are the
- // node indices of the source and destination of the edge
- void add_pointsto_edge(uint from_i, uint to_i);
- void add_deferred_edge(uint from_i, uint to_i);
- void add_field_edge(uint from_i, uint to_i, int offs);
+ // Helper methods for unique types split.
+ bool split_AddP(Node *addp, Node *base);
- // Add an edge of the specified type pointing to the specified target.
- // Set _progress if new edge is added.
- void add_edge(PointsToNode *f, uint to_i, PointsToNode::EdgeType et) {
- uint e_cnt = f->edge_count();
- f->add_edge(to_i, et);
- _progress |= (f->edge_count() != e_cnt);
- }
+ PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, bool &new_created);
+ PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist);
- // Add an edge to node given by "to_i" from any field of adr_i whose offset
- // matches "offset" A deferred edge is added if to_i is a LocalVar, and
- // a pointsto edge is added if it is a JavaObject
- void add_edge_from_fields(uint adr, uint to_i, int offs);
-
- // Add a deferred edge from node given by "from_i" to any field
- // of adr_i whose offset matches "offset"
- void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
+ void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis);
+ Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist);
+ Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
- // Remove outgoing deferred edges from the node referenced by "ni".
- // Any outgoing edges from the target of the deferred edge are copied
- // to "ni".
- void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited);
+ GrowableArray<MergeMemNode*> _mergemem_worklist; // List of all MergeMem nodes
Node_Array _node_map; // used for bookeeping during type splitting
// Used for the following purposes:
@@ -320,21 +547,18 @@
// MemNode - new memory input for this node
// ChecCastPP - allocation that this is a cast of
// allocation - CheckCastPP of the allocation
- bool split_AddP(Node *addp, Node *base, PhaseGVN *igvn);
- PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn, bool &new_created);
- PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
- void move_inst_mem(Node* n, GrowableArray<PhiNode *> &orig_phis, PhaseGVN *igvn);
- Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *> &orig_phi_worklist, PhaseGVN *igvn);
-
- // Propagate unique types created for unescaped allocated objects
- // through the graph
- void split_unique_types(GrowableArray<Node *> &alloc_worklist);
// manage entries in _node_map
- void set_map(int idx, Node *n) { _node_map.map(idx, n); }
- Node *get_map(int idx) { return _node_map[idx]; }
- PhiNode *get_map_phi(int idx) {
- Node *phi = _node_map[idx];
+
+ void set_map(Node* from, Node* to) {
+ ideal_nodes.push(from);
+ _node_map.map(from->_idx, to);
+ }
+
+ Node* get_map(int idx) { return _node_map[idx]; }
+
+ PhiNode* get_map_phi(int idx) {
+ Node* phi = _node_map[idx];
return (phi == NULL) ? NULL : phi->as_Phi();
}
@@ -344,23 +568,6 @@
_igvn->add_users_to_worklist(n);
}
- // Set the escape state of a node
- void set_escape_state(uint ni, PointsToNode::EscapeState es);
-
- // Find fields initializing values for allocations.
- void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase);
-
- // Adjust escape state after Connection Graph is built.
- void adjust_escape_state(Node* n);
-
- // Propagate escape states to referenced nodes.
- bool propagate_escape_state(GrowableArray<int>* cg_worklist,
- GrowableArray<uint>* worklist,
- PointsToNode::EscapeState esc_state);
-
- // Optimize objects compare.
- Node* optimize_ptr_compare(Node* n);
-
// Compute the escape information
bool compute_escape();
@@ -373,11 +580,10 @@
// Perform escape analysis
static void do_analysis(Compile *C, PhaseIterGVN *igvn);
- // escape state of a node
- PointsToNode::EscapeState escape_state(Node *n);
+ bool not_global_escape(Node *n);
#ifndef PRODUCT
- void dump();
+ void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
#endif
};
--- a/hotspot/src/share/vm/opto/phase.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/phase.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,9 @@
// The next timers used for LogCompilation
elapsedTimer Phase::_t_parser;
-elapsedTimer Phase::_t_escapeAnalysis;
elapsedTimer Phase::_t_optimizer;
+elapsedTimer Phase::_t_escapeAnalysis;
+elapsedTimer Phase::_t_connectionGraph;
elapsedTimer Phase::_t_idealLoop;
elapsedTimer Phase::_t_ccp;
elapsedTimer Phase::_t_matcher;
@@ -51,6 +52,7 @@
elapsedTimer Phase::_t_graphReshaping;
elapsedTimer Phase::_t_scheduler;
elapsedTimer Phase::_t_blockOrdering;
+elapsedTimer Phase::_t_macroEliminate;
elapsedTimer Phase::_t_macroExpand;
elapsedTimer Phase::_t_peephole;
elapsedTimer Phase::_t_codeGeneration;
@@ -104,6 +106,8 @@
if (DoEscapeAnalysis) {
// EA is part of Optimizer.
tty->print_cr (" escape analysis: %3.3f sec", Phase::_t_escapeAnalysis.seconds());
+ tty->print_cr (" connection graph: %3.3f sec", Phase::_t_connectionGraph.seconds());
+ tty->print_cr (" macroEliminate : %3.3f sec", Phase::_t_macroEliminate.seconds());
}
tty->print_cr (" iterGVN : %3.3f sec", Phase::_t_iterGVN.seconds());
tty->print_cr (" idealLoop : %3.3f sec", Phase::_t_idealLoop.seconds());
@@ -112,9 +116,10 @@
tty->print_cr (" iterGVN2 : %3.3f sec", Phase::_t_iterGVN2.seconds());
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" graphReshape : %3.3f sec", Phase::_t_graphReshaping.seconds());
- double optimizer_subtotal = Phase::_t_iterGVN.seconds() +
+ double optimizer_subtotal = Phase::_t_iterGVN.seconds() + Phase::_t_iterGVN2.seconds() +
+ Phase::_t_escapeAnalysis.seconds() + Phase::_t_macroEliminate.seconds() +
Phase::_t_idealLoop.seconds() + Phase::_t_ccp.seconds() +
- Phase::_t_graphReshaping.seconds();
+ Phase::_t_macroExpand.seconds() + Phase::_t_graphReshaping.seconds();
double percent_of_optimizer = ((optimizer_subtotal == 0.0) ? 0.0 : (optimizer_subtotal / Phase::_t_optimizer.seconds() * 100.0));
tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", optimizer_subtotal, percent_of_optimizer);
}
--- a/hotspot/src/share/vm/opto/phase.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/opto/phase.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,8 +72,12 @@
// The next timers used for LogCompilation
static elapsedTimer _t_parser;
- static elapsedTimer _t_escapeAnalysis;
static elapsedTimer _t_optimizer;
+public:
+ // ConnectionGraph can't be Phase since it is used after EA done.
+ static elapsedTimer _t_escapeAnalysis;
+ static elapsedTimer _t_connectionGraph;
+protected:
static elapsedTimer _t_idealLoop;
static elapsedTimer _t_ccp;
static elapsedTimer _t_matcher;
@@ -84,6 +88,7 @@
static elapsedTimer _t_graphReshaping;
static elapsedTimer _t_scheduler;
static elapsedTimer _t_blockOrdering;
+ static elapsedTimer _t_macroEliminate;
static elapsedTimer _t_macroExpand;
static elapsedTimer _t_peephole;
static elapsedTimer _t_codeGeneration;
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1301,9 +1301,6 @@
// Inner class reflection ///////////////////////////////////////////////////////////////////////////////
JVM_ENTRY(jobjectArray, JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass))
- const int inner_class_info_index = 0;
- const int outer_class_info_index = 1;
-
JvmtiVMObjectAllocEventCollector oam;
// ofClass is a reference to a java_lang_Class object. The mirror object
// of an instanceKlass
@@ -1315,26 +1312,26 @@
}
instanceKlassHandle k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(ofClass)));
-
- if (k->inner_classes()->length() == 0) {
+ InnerClassesIterator iter(k);
+
+ if (iter.length() == 0) {
// Neither an inner nor outer class
oop result = oopFactory::new_objArray(SystemDictionary::Class_klass(), 0, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, result);
}
// find inner class info
- typeArrayHandle icls(thread, k->inner_classes());
constantPoolHandle cp(thread, k->constants());
- int length = icls->length();
+ int length = iter.length();
// Allocate temp. result array
objArrayOop r = oopFactory::new_objArray(SystemDictionary::Class_klass(), length/4, CHECK_NULL);
objArrayHandle result (THREAD, r);
int members = 0;
- for(int i = 0; i < length; i += 4) {
- int ioff = icls->ushort_at(i + inner_class_info_index);
- int ooff = icls->ushort_at(i + outer_class_info_index);
+ for (; !iter.done(); iter.next()) {
+ int ioff = iter.inner_class_info_index();
+ int ooff = iter.outer_class_info_index();
if (ioff != 0 && ooff != 0) {
// Check to see if the name matches the class we're looking for
@@ -1392,17 +1389,13 @@
bool* inner_is_member,
TRAPS) {
Thread* thread = THREAD;
- const int inner_class_info_index = inner_class_inner_class_info_offset;
- const int outer_class_info_index = inner_class_outer_class_info_offset;
-
- if (k->inner_classes()->length() == 0) {
+ InnerClassesIterator iter(k);
+ if (iter.length() == 0) {
// No inner class info => no declaring class
return NULL;
}
- typeArrayHandle i_icls(thread, k->inner_classes());
constantPoolHandle i_cp(thread, k->constants());
- int i_length = i_icls->length();
bool found = false;
klassOop ok;
@@ -1410,10 +1403,10 @@
*inner_is_member = false;
// Find inner_klass attribute
- for (int i = 0; i < i_length && !found; i += inner_class_next_offset) {
- int ioff = i_icls->ushort_at(i + inner_class_info_index);
- int ooff = i_icls->ushort_at(i + outer_class_info_index);
- int noff = i_icls->ushort_at(i + inner_class_inner_name_offset);
+ for (; !iter.done() && !found; iter.next()) {
+ int ioff = iter.inner_class_info_index();
+ int ooff = iter.outer_class_info_index();
+ int noff = iter.inner_name_index();
if (ioff != 0) {
// Check to see if the name matches the class we're looking for
// before attempting to find the class.
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -292,8 +292,8 @@
// Compute the number of entries in the InnerClasses attribute
u2 JvmtiClassFileReconstituter::inner_classes_attribute_length() {
- typeArrayOop inner_class_list = ikh()->inner_classes();
- return (inner_class_list == NULL) ? 0 : inner_class_list->length();
+ InnerClassesIterator iter(ikh());
+ return iter.length();
}
// Write an annotation attribute. The VM stores them in raw form, so all we need
@@ -324,26 +324,20 @@
// JVMSpec| } classes[number_of_classes];
// JVMSpec| }
void JvmtiClassFileReconstituter::write_inner_classes_attribute(int length) {
- typeArrayOop inner_class_list = ikh()->inner_classes();
- guarantee(inner_class_list != NULL && inner_class_list->length() == length,
+ InnerClassesIterator iter(ikh());
+ guarantee(iter.length() != 0 && iter.length() == length,
"caller must check");
- typeArrayHandle inner_class_list_h(thread(), inner_class_list);
- assert (length % instanceKlass::inner_class_next_offset == 0, "just checking");
u2 entry_count = length / instanceKlass::inner_class_next_offset;
u4 size = 2 + entry_count * (2+2+2+2);
write_attribute_name_index("InnerClasses");
write_u4(size);
write_u2(entry_count);
- for (int i = 0; i < length; i += instanceKlass::inner_class_next_offset) {
- write_u2(inner_class_list_h->ushort_at(
- i + instanceKlass::inner_class_inner_class_info_offset));
- write_u2(inner_class_list_h->ushort_at(
- i + instanceKlass::inner_class_outer_class_info_offset));
- write_u2(inner_class_list_h->ushort_at(
- i + instanceKlass::inner_class_inner_name_offset));
- write_u2(inner_class_list_h->ushort_at(
- i + instanceKlass::inner_class_access_flags_offset));
+ for (; !iter.done(); iter.next()) {
+ write_u2(iter.inner_class_info_index());
+ write_u2(iter.outer_class_info_index());
+ write_u2(iter.inner_name_index());
+ write_u2(iter.inner_access_flags());
}
}
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -2400,44 +2400,33 @@
// new constant indices as needed. The inner classes info is a
// quadruple:
// (inner_class_info, outer_class_info, inner_name, inner_access_flags)
- typeArrayOop inner_class_list = scratch_class->inner_classes();
- int icl_length = (inner_class_list == NULL) ? 0 : inner_class_list->length();
- if (icl_length > 0) {
- typeArrayHandle inner_class_list_h(THREAD, inner_class_list);
- for (int i = 0; i < icl_length;
- i += instanceKlass::inner_class_next_offset) {
- int cur_index = inner_class_list_h->ushort_at(i
- + instanceKlass::inner_class_inner_class_info_offset);
- if (cur_index == 0) {
- continue; // JVM spec. allows null inner class refs so skip it
- }
- int new_index = find_new_index(cur_index);
- if (new_index != 0) {
- RC_TRACE_WITH_THREAD(0x00080000, THREAD,
- ("inner_class_info change: %d to %d", cur_index, new_index));
- inner_class_list_h->ushort_at_put(i
- + instanceKlass::inner_class_inner_class_info_offset, new_index);
- }
- cur_index = inner_class_list_h->ushort_at(i
- + instanceKlass::inner_class_outer_class_info_offset);
- new_index = find_new_index(cur_index);
- if (new_index != 0) {
- RC_TRACE_WITH_THREAD(0x00080000, THREAD,
- ("outer_class_info change: %d to %d", cur_index, new_index));
- inner_class_list_h->ushort_at_put(i
- + instanceKlass::inner_class_outer_class_info_offset, new_index);
- }
- cur_index = inner_class_list_h->ushort_at(i
- + instanceKlass::inner_class_inner_name_offset);
- new_index = find_new_index(cur_index);
- if (new_index != 0) {
- RC_TRACE_WITH_THREAD(0x00080000, THREAD,
- ("inner_name change: %d to %d", cur_index, new_index));
- inner_class_list_h->ushort_at_put(i
- + instanceKlass::inner_class_inner_name_offset, new_index);
- }
- } // end for each inner class
- } // end if we have inner classes
+ InnerClassesIterator iter(scratch_class);
+ for (; !iter.done(); iter.next()) {
+ int cur_index = iter.inner_class_info_index();
+ if (cur_index == 0) {
+ continue; // JVM spec. allows null inner class refs so skip it
+ }
+ int new_index = find_new_index(cur_index);
+ if (new_index != 0) {
+ RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+ ("inner_class_info change: %d to %d", cur_index, new_index));
+ iter.set_inner_class_info_index(new_index);
+ }
+ cur_index = iter.outer_class_info_index();
+ new_index = find_new_index(cur_index);
+ if (new_index != 0) {
+ RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+ ("outer_class_info change: %d to %d", cur_index, new_index));
+ iter.set_outer_class_info_index(new_index);
+ }
+ cur_index = iter.inner_name_index();
+ new_index = find_new_index(cur_index);
+ if (new_index != 0) {
+ RC_TRACE_WITH_THREAD(0x00080000, THREAD,
+ ("inner_name change: %d to %d", cur_index, new_index));
+ iter.set_inner_name_index(new_index);
+ }
+ } // end for each inner class
// Attach each method in klass to the new constant pool and update
// to use new constant pool indices as needed:
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -816,8 +816,21 @@
return true;
}
- jio_fprintf(defaultStream::error_stream(),
- "Unrecognized VM option '%s'\n", argname);
+ // For locked flags, report a custom error message if available.
+ // Otherwise, report the standard unrecognized VM option.
+
+ Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true);
+ if (locked_flag != NULL) {
+ char locked_message_buf[BUFLEN];
+ locked_flag->get_locked_message(locked_message_buf, BUFLEN);
+ if (strlen(locked_message_buf) == 0) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Unrecognized VM option '%s'\n", argname);
+ } else {
+ jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf);
+ }
+ }
+
// allow for commandline "commenting out" options like -XX:#+Verbose
return arg[0] == '#';
}
@@ -2523,15 +2536,6 @@
// was arrived at by experimenting with specjbb.
FLAG_SET_CMDLINE(uintx, OldPLABSize, 8*K); // Note: this is in words
- // CompilationPolicyChoice=0 causes the server compiler to adopt
- // a more conservative which-method-do-I-compile policy when one
- // of the counters maintained by the interpreter trips. The
- // result is reduced startup time and improved specjbb and
- // alacrity performance. Zero is the default, but we set it
- // explicitly here in case the default changes.
- // See runtime/compilationPolicy.*.
- FLAG_SET_CMDLINE(intx, CompilationPolicyChoice, 0);
-
// Enable parallel GC and adaptive generation sizing
FLAG_SET_CMDLINE(bool, UseParallelGC, true);
FLAG_SET_DEFAULT(ParallelGCThreads,
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -81,6 +81,12 @@
}
}
+// Get custom message for this locked flag, or return NULL if
+// none is available.
+void Flag::get_locked_message(char* buf, int buflen) const {
+ get_locked_message_ext(buf, buflen);
+}
+
bool Flag::is_writeable() const {
return strcmp(kind, "{manageable}") == 0 ||
strcmp(kind, "{product rw}") == 0 ||
@@ -260,17 +266,22 @@
return strncmp(s, q, len) == 0;
}
-Flag* Flag::find_flag(char* name, size_t length) {
- for (Flag* current = &flagTable[0]; current->name; current++) {
+// Search the flag table for a named flag
+Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) {
+ for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
if (str_equal(current->name, name, length)) {
+ // Found a matching entry. Report locked flags only if allowed.
if (!(current->is_unlocked() || current->is_unlocker())) {
- // disable use of diagnostic or experimental flags until they
- // are explicitly unlocked
- return NULL;
+ if (!allow_locked) {
+ // disable use of locked flags, e.g. diagnostic, experimental,
+ // commercial... until they are explicitly unlocked
+ return NULL;
+ }
}
return current;
}
}
+ // Flag name is not in the flag table
return NULL;
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -222,7 +222,7 @@
// number of flags
static size_t numFlags;
- static Flag* find_flag(char* name, size_t length);
+ static Flag* find_flag(char* name, size_t length, bool allow_locked = false);
bool is_bool() const { return strcmp(type, "bool") == 0; }
bool get_bool() const { return *((bool*) addr); }
@@ -259,6 +259,9 @@
bool is_writeable_ext() const;
bool is_external_ext() const;
+ void get_locked_message(char*, int) const;
+ void get_locked_message_ext(char*, int) const;
+
void print_on(outputStream* st, bool withComments = false );
void print_as_flag(outputStream* st);
};
--- a/hotspot/src/share/vm/runtime/globals_ext.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals_ext.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,4 +61,9 @@
return false;
}
+inline void Flag::get_locked_message_ext(char* buf, int buflen) const {
+ assert(buf != NULL, "Buffer cannot be NULL");
+ buf[0] = '\0';
+}
+
#endif // SHARE_VM_RUNTIME_GLOBALS_EXT_HPP
--- a/hotspot/src/share/vm/runtime/reflection.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/runtime/reflection.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -591,14 +591,11 @@
// Caller is responsible for figuring out in advance which case must be true.
void Reflection::check_for_inner_class(instanceKlassHandle outer, instanceKlassHandle inner,
bool inner_is_member, TRAPS) {
- const int inner_class_info_index = 0;
- const int outer_class_info_index = 1;
-
- typeArrayHandle icls (THREAD, outer->inner_classes());
+ InnerClassesIterator iter(outer);
constantPoolHandle cp (THREAD, outer->constants());
- for(int i = 0; i < icls->length(); i += 4) {
- int ioff = icls->ushort_at(i + inner_class_info_index);
- int ooff = icls->ushort_at(i + outer_class_info_index);
+ for (; !iter.done(); iter.next()) {
+ int ioff = iter.inner_class_info_index();
+ int ooff = iter.outer_class_info_index();
if (inner_is_member && ioff != 0 && ooff != 0) {
klassOop o = cp->klass_at(ooff, CHECK);
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -198,8 +198,11 @@
return idx;
}
- void append_if_missing(const E& elem) {
- if (!contains(elem)) append(elem);
+ bool append_if_missing(const E& elem) {
+ // Returns TRUE if elem is added.
+ bool missed = !contains(elem);
+ if (missed) append(elem);
+ return missed;
}
E at(int i) const {
@@ -292,12 +295,22 @@
ShouldNotReachHere();
}
+ // The order is preserved.
void remove_at(int index) {
assert(0 <= index && index < _len, "illegal index");
for (int j = index + 1; j < _len; j++) _data[j-1] = _data[j];
_len--;
}
+ // The order is changed.
+ void delete_at(int index) {
+ assert(0 <= index && index < _len, "illegal index");
+ if (index < --_len) {
+ // Replace removed element with last one.
+ _data[index] = _data[_len];
+ }
+ }
+
// inserts the given element before the element at index i
void insert_before(const int idx, const E& elem) {
check_nesting();
--- a/hotspot/test/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/hotspot/test/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -26,6 +26,8 @@
# Makefile to run various jdk tests
#
+GETMIXEDPATH=echo
+
# Get OS/ARCH specifics
OSNAME = $(shell uname -s)
ifeq ($(OSNAME), SunOS)
@@ -60,7 +62,14 @@
ARCH = i586
endif
endif
-ifeq ($(OSNAME), Windows_NT)
+ifeq ($(PLATFORM),)
+ # detect wether we're running in MKS or cygwin
+ ifeq ($(OSNAME), Windows_NT) # MKS
+ GETMIXEDPATH=dosname -s
+ endif
+ ifeq ($(findstring CYGWIN,$(OSNAME)), CYGWIN)
+ GETMIXEDPATH=cygpath -m -s
+ endif
PLATFORM = windows
SLASH_JAVA = J:
ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64)
@@ -234,11 +243,11 @@
$(JTREG) -a -v:fail,error \
$(JTREG_KEY_OPTION) \
$(EXTRA_JTREG_OPTIONS) \
- -r:$(ABS_TEST_OUTPUT_DIR)/JTreport \
- -w:$(ABS_TEST_OUTPUT_DIR)/JTwork \
- -jdk:$(PRODUCT_HOME) \
+ -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \
+ -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \
+ -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \
$(JAVA_OPTIONS:%=-vmoption:%) \
- $(TEST_ROOT)/sanity \
+ $(shell $(GETMIXEDPATH) "$(TEST_ROOT)")/sanity \
|| $(BUNDLE_UP_FAILED)
$(BUNDLE_UP)
--- a/jaxp/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/jaxp/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
f3244c1f04864d35c41fa8d13669faf4f65b81e2 jdk8-b28
25099a745e1a43579b6af86b3e052b2e50958753 jdk8-b29
3be30c25a8255803652b5c466336055d36e2ba21 jdk8-b30
+94aabe098916440ae7911866311c9617d8481a36 jdk8-b31
+60960fbc75df8be4c1a2504aa69fc1428cc94f93 jdk8-b32
--- a/jaxws/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/jaxws/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
88b85470e72ce48515c802d2158f61cad198b935 jdk8-b28
4897d9d2d04838e3479745efa238a99bacd939c9 jdk8-b29
6882b10e85d6f6ba110dbb50926d6fe2222cc7ad jdk8-b30
+4c41c6d0e15de3b56919a5ba0a0f248a2d07f2b2 jdk8-b31
+017a7dbfaa92f5a8b144e6c890d1cebdaecaf681 jdk8-b32
--- a/jdk/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
1e1d41daaded291ab3a370ca6a27f7325701978e jdk8-b28
c5b882dce0fe27e05dc64debc92b1fb9ebf880ec jdk8-b29
cdbb33303ea344d5e9013e2dd642e7a6e7768db6 jdk8-b30
+27f0c08c427c65fcab6917edf646f59058e59524 jdk8-b31
+ddfe5562f61f54ed2121ac0c73b688b94f3e66b5 jdk8-b32
--- a/jdk/make/common/shared/Sanity.gmk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/make/common/shared/Sanity.gmk Thu Mar 29 21:22:07 2012 -0700
@@ -348,7 +348,13 @@
" Try setting LANG to 'C'. \n" \
"" >> $(WARNING_FILE) ; \
fi
+ifeq ($(PLATFORM), macosx)
+ @if [ "$(LANG)" = "" ]; then \
+ $(ECHO) "ERROR: LANG must be set on Mac OS X. Recommended value is \"C\"" >> $(ERROR_FILE) ; \
+ fi
endif
+endif
+
######################################################
# Check the Windows cygwin version
--- a/jdk/make/docs/CORE_PKGS.gmk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/make/docs/CORE_PKGS.gmk Thu Mar 29 21:22:07 2012 -0700
@@ -64,7 +64,7 @@
javax.management.* \
javax.script \
javax.sql.* \
- javax.tools \
+ javax.tools.* \
javax.xml.* \
org.w3c.* \
org.xml.sax
@@ -218,6 +218,7 @@
javax.swing.plaf.nimbus \
javax.swing.plaf.synth \
javax.tools \
+ javax.tools.annotation \
javax.transaction \
javax.transaction.xa \
javax.xml.parsers \
--- a/jdk/make/sun/security/ec/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/make/sun/security/ec/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -159,7 +159,9 @@
$(PKGDIR)/ECDSASignature.java \
$(PKGDIR)/ECKeyPairGenerator.java
- JAVAHFLAGS += -Xbootclasspath/p:$(CLASSDESTDIR)
+ JAVAHFLAGS = -bootclasspath \
+ "$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)"
+
#
# C and C++ files
--- a/jdk/make/sun/security/mscapi/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/make/sun/security/mscapi/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -149,7 +149,8 @@
# Rules
#
CLASSDESTDIR = $(TEMPDIR)/classes
-JAVAHFLAGS += -Xbootclasspath/p:$(CLASSDESTDIR)
+JAVAHFLAGS = -bootclasspath \
+ "$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)"
include $(BUILDDIR)/common/Mapfile-vers.gmk
--- a/jdk/make/sun/security/pkcs11/Makefile Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/make/sun/security/pkcs11/Makefile Thu Mar 29 21:22:07 2012 -0700
@@ -150,7 +150,8 @@
# Rules
#
CLASSDESTDIR = $(TEMPDIR)/classes
-JAVAHFLAGS = -bootclasspath "$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)"
+JAVAHFLAGS = -bootclasspath \
+ "$(CLASSDESTDIR)$(CLASSPATH_SEPARATOR)$(CLASSBINDIR)"
include $(BUILDDIR)/common/Mapfile-vers.gmk
--- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java Thu Mar 29 21:22:07 2012 -0700
@@ -522,11 +522,6 @@
postEvent(targetToAppContext(event.getSource()), event);
}
- /*
- * Returns true if the application (one of its windows) owns keyboard focus.
- */
- public abstract boolean isApplicationActive();
-
// use peer's back buffer to implement non-opaque windows.
@Override
public boolean needUpdateWindow() {
--- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java Thu Mar 29 21:22:07 2012 -0700
@@ -1067,11 +1067,7 @@
return false;
}
- // Cross-app activation requests are not allowed.
- if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
- !((LWToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
- {
- focusLog.fine("the app is inactive, so the request is rejected");
+ if (platformWindow.rejectFocusRequest(cause)) {
return false;
}
--- a/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/PlatformWindow.java Thu Mar 29 21:22:07 2012 -0700
@@ -27,6 +27,7 @@
import java.awt.*;
+import sun.awt.CausedFocusEvent;
import sun.java2d.SurfaceData;
// TODO Is it worth to generify this interface, like that:
@@ -117,6 +118,8 @@
public void updateFocusableWindowState();
+ public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
+
public boolean requestWindowFocus();
/*
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Thu Mar 29 21:22:07 2012 -0700
@@ -38,6 +38,8 @@
public class CEmbeddedFrame extends EmbeddedFrame {
private CPlatformResponder responder;
+ private boolean focused = true;
+ private boolean parentWindowActive = true;
public CEmbeddedFrame() {
show();
@@ -94,4 +96,31 @@
public void handleInputEvent(String text) {
new RuntimeException("Not implemented");
}
+
+ public void handleFocusEvent(boolean focused) {
+ this.focused = focused;
+ updateOverlayWindowActiveState();
+ }
+
+ public void handleWindowFocusEvent(boolean parentWindowActive) {
+ this.parentWindowActive = parentWindowActive;
+ updateOverlayWindowActiveState();
+ }
+
+ public boolean isParentWindowActive() {
+ return parentWindowActive;
+ }
+
+ /*
+ * May change appearance of contents of window, and generate a
+ * WINDOW_ACTIVATED event.
+ */
+ private void updateOverlayWindowActiveState() {
+ final boolean showAsFocused = parentWindowActive && focused;
+ dispatchEvent(
+ new FocusEvent(this, showAsFocused ?
+ FocusEvent.FOCUS_GAINED :
+ FocusEvent.FOCUS_LOST));
+ }
+
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java Thu Mar 29 21:22:07 2012 -0700
@@ -33,17 +33,23 @@
import sun.awt.CGraphicsConfig;
import sun.awt.CGraphicsDevice;
+import sun.awt.CausedFocusEvent;
import java.awt.*;
import java.awt.BufferCapabilities.FlipContents;
+import sun.util.logging.PlatformLogger;
+
/*
* Provides a lightweight implementation of the EmbeddedFrame.
*/
public class CPlatformEmbeddedFrame implements PlatformWindow {
+ private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
+
private CGLLayer windowLayer;
private LWWindowPeer peer;
+ private CEmbeddedFrame target;
private volatile int screenX = 0;
private volatile int screenY = 0;
@@ -52,6 +58,7 @@
public void initialize(Window target, final LWWindowPeer peer, PlatformWindow owner) {
this.peer = peer;
this.windowLayer = new CGLLayer(peer);
+ this.target = (CEmbeddedFrame)target;
}
@Override
@@ -149,6 +156,18 @@
public void updateFocusableWindowState() {}
@Override
+ public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+ // Cross-app activation requests are not allowed.
+ if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+ !target.isParentWindowActive())
+ {
+ focusLogger.fine("the embedder is inactive, so the request is rejected");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public boolean requestWindowFocus() {
return true;
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Mar 29 21:22:07 2012 -0700
@@ -65,6 +65,7 @@
// Loger to report issues happened during execution but that do not affect functionality
private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
+ private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformWindow");
// for client properties
public static final String WINDOW_BRUSH_METAL_LOOK = "apple.awt.brushMetalLook";
@@ -112,6 +113,7 @@
static final int MINIMIZABLE = 1 << 8;
static final int RESIZABLE = 1 << 9; // both a style bit and prop bit
+ static final int NONACTIVATING = 1 << 24;
static final int _STYLE_PROP_BITMASK = DECORATED | TEXTURED | UNIFIED | UTILITY | HUD | SHEET | CLOSEABLE | MINIMIZABLE | RESIZABLE;
@@ -127,9 +129,6 @@
static final int _METHOD_PROP_BITMASK = RESIZABLE | HAS_SHADOW | ZOOMABLE | ALWAYS_ON_TOP | HIDES_ON_DEACTIVATE | DRAGGABLE_BACKGROUND | DOCUMENT_MODIFIED | FULLSCREENABLE;
- // not sure
- static final int POPUP = 1 << 14;
-
// corresponds to callback-based properties
static final int SHOULD_BECOME_KEY = 1 << 12;
static final int SHOULD_BECOME_MAIN = 1 << 13;
@@ -264,10 +263,6 @@
// defaults style bits
int styleBits = DECORATED | HAS_SHADOW | CLOSEABLE | MINIMIZABLE | ZOOMABLE | RESIZABLE;
- if (target.getName() == "###overrideRedirect###") {
- styleBits = SET(styleBits, POPUP, true);
- }
-
if (isNativelyFocusableWindow()) {
styleBits = SET(styleBits, SHOULD_BECOME_KEY, true);
styleBits = SET(styleBits, SHOULD_BECOME_MAIN, true);
@@ -275,6 +270,7 @@
final boolean isFrame = (target instanceof Frame);
final boolean isDialog = (target instanceof Dialog);
+ final boolean isPopup = (target.getType() == Window.Type.POPUP);
if (isDialog) {
styleBits = SET(styleBits, MINIMIZABLE, false);
}
@@ -304,8 +300,10 @@
}
// If the target is a dialog, popup or tooltip we want it to ignore the brushed metal look.
- if (!isDialog && IS(styleBits, POPUP)) {
+ if (isPopup) {
styleBits = SET(styleBits, TEXTURED, true);
+ // Popups in applets don't activate applet's process
+ styleBits = SET(styleBits, NONACTIVATING, true);
}
if (target instanceof javax.swing.RootPaneContainer) {
@@ -498,11 +496,18 @@
// If it ain't blocked, or is being hidden, go regular way
if (visible) {
CWrapper.NSWindow.makeFirstResponder(nsWindowPtr, contentView.getAWTView());
+
+ boolean isPopup = (target.getType() == Window.Type.POPUP);
+ if (isPopup) {
+ // Popups in applets don't activate applet's process
+ CWrapper.NSWindow.orderFrontRegardless(nsWindowPtr);
+ } else {
+ CWrapper.NSWindow.orderFront(nsWindowPtr);
+ }
+
boolean isKeyWindow = CWrapper.NSWindow.isKeyWindow(nsWindowPtr);
if (!isKeyWindow) {
- CWrapper.NSWindow.makeKeyAndOrderFront(nsWindowPtr);
- } else {
- CWrapper.NSWindow.orderFront(nsWindowPtr);
+ CWrapper.NSWindow.makeKeyWindow(nsWindowPtr);
}
} else {
CWrapper.NSWindow.orderOut(nsWindowPtr);
@@ -600,7 +605,20 @@
}
@Override
+ public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+ // Cross-app activation requests are not allowed.
+ if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+ !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
+ {
+ focusLogger.fine("the app is inactive, so the request is rejected");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
public boolean requestWindowFocus() {
+
long ptr = getNSWindowPtr();
if (CWrapper.NSWindow.canBecomeMainWindow(ptr)) {
CWrapper.NSWindow.makeMainWindow(ptr);
@@ -751,6 +769,11 @@
* Callbacks from the AWTWindow and AWTView objc classes.
*************************************************************/
private void deliverWindowFocusEvent(boolean gained){
+ // Fix for 7150349: ingore "gained" notifications when the app is inactive.
+ if (gained && !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive()) {
+ focusLogger.fine("the app is inactive, so the notification is ignored");
+ return;
+ }
peer.notifyActivation(gained);
}
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CWrapper.java Thu Mar 29 21:22:07 2012 -0700
@@ -47,6 +47,7 @@
public static native void setLevel(long window, int level);
public static native void makeKeyAndOrderFront(long window);
+ public static native void makeKeyWindow(long window);
public static native void makeMainWindow(long window);
public static native boolean canBecomeMainWindow(long window);
public static native boolean isKeyWindow(long window);
--- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java Thu Mar 29 21:22:07 2012 -0700
@@ -686,7 +686,10 @@
return sunAwtDisableCALayers.booleanValue();
}
- @Override
+
+ /*
+ * Returns true if the application (one of its windows) owns keyboard focus.
+ */
public native boolean isApplicationActive();
/************************
--- a/jdk/src/macosx/native/sun/awt/AWTView.m Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTView.m Thu Mar 29 21:22:07 2012 -0700
@@ -812,7 +812,7 @@
// Unicode value.
NSUInteger utf8Length = [aString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
- if ([self hasMarkedText] || !fProcessingKeystroke || (utf8Length > 2)) {
+ if ([self hasMarkedText] || !fProcessingKeystroke || (utf8Length > 1)) {
JNIEnv *env = [ThreadUtilities getJNIEnv];
static JNF_MEMBER_CACHE(jm_selectPreviousGlyph, jc_CInputMethod, "selectPreviousGlyph", "()V");
--- a/jdk/src/macosx/native/sun/awt/AWTWindow.m Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m Thu Mar 29 21:22:07 2012 -0700
@@ -102,11 +102,12 @@
type |= NSBorderlessWindowMask;
}
- if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;
- if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;
- if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;
- if (IS(styleBits, HUD)) type |= NSHUDWindowMask;
- if (IS(styleBits, SHEET)) type |= NSDocModalWindowMask;
+ if (IS(styleBits, TEXTURED)) type |= NSTexturedBackgroundWindowMask;
+ if (IS(styleBits, UNIFIED)) type |= NSUnifiedTitleAndToolbarWindowMask;
+ if (IS(styleBits, UTILITY)) type |= NSUtilityWindowMask;
+ if (IS(styleBits, HUD)) type |= NSHUDWindowMask;
+ if (IS(styleBits, SHEET)) type |= NSDocModalWindowMask;
+ if (IS(styleBits, NONACTIVATING)) type |= NSNonactivatingPanelMask;
return type;
}
--- a/jdk/src/macosx/native/sun/awt/CWrapper.m Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/CWrapper.m Thu Mar 29 21:22:07 2012 -0700
@@ -76,6 +76,26 @@
/*
* Class: sun_lwawt_macosx_CWrapper$NSWindow
+ * Method: makeKeyWindow
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_lwawt_macosx_CWrapper_00024NSWindow_makeKeyWindow
+(JNIEnv *env, jclass cls, jlong windowPtr)
+{
+JNF_COCOA_ENTER(env);
+
+ NSWindow *window = (NSWindow *)jlong_to_ptr(windowPtr);
+ [JNFRunLoop performOnMainThread:@selector(makeKeyWindow)
+ on:window
+ withObject:nil
+ waitUntilDone:NO];
+
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class: sun_lwawt_macosx_CWrapper$NSWindow
* Method: makeMainWindow
* Signature: (J)V
*/
--- a/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/LWCToolkit.m Thu Mar 29 21:22:07 2012 -0700
@@ -401,18 +401,21 @@
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isApplicationActive
(JNIEnv *env, jclass clazz)
{
- __block jboolean active = JNI_FALSE;
+ __block jboolean active = JNI_FALSE;
-AWT_ASSERT_NOT_APPKIT_THREAD;
JNF_COCOA_ENTER(env);
+ if ([NSThread isMainThread]) {
+ active = (jboolean)[NSRunningApplication currentApplication].active;
+ } else {
[JNFRunLoop performOnMainThreadWaiting:YES withBlock:^() {
- active = (jboolean)[NSRunningApplication currentApplication].active;
+ active = (jboolean)[NSRunningApplication currentApplication].active;
}];
+ }
JNF_COCOA_EXIT(env);
- return active;
+ return active;
}
--- a/jdk/src/macosx/native/sun/awt/OSVersion.m Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/OSVersion.m Thu Mar 29 21:22:07 2012 -0700
@@ -31,33 +31,31 @@
#import <JavaRuntimeSupport/JavaRuntimeSupport.h>
-// returns 10.7 for Lion, 10.6 for SnowLeopard etc.
-double getOSXMajorVersion() {
- char *version = JRSCopyOSVersion();
-
- if (version == NULL) return 0.0;
-
- char temp[32];
- strlcpy(temp, version, sizeof(temp));
- free(version);
-
- if (strlen(temp) < 3) {
- return 0.0;
+// returns 107 for Lion, 106 for SnowLeopard etc.
+int getOSXMajorVersion() {
+ char *ver = JRSCopyOSVersion();
+ if (ver == NULL) {
+ return 0;
}
- if (temp[2] != '.') { // Third char must be a '.'
- return 0.0;
+ int len = strlen(ver);
+ int v = 0;
+
+ // Third char must be a '.'
+ if (len >= 3 && ver[2] == '.') {
+ int i;
+
+ v = (ver[0] - '0') * 10 + (ver[1] - '0');
+ for (i = 3; i < len && isdigit(ver[i]); ++i) {
+ v = v * 10 + (ver[i] - '0');
+ }
}
- char *ptr = strchr(temp+3, '.'); // remove the second . if one exists.
- if (ptr != NULL) {
- *ptr = 0;
- }
-
- return atof(temp);
+ free(ver);
+
+ return v;
}
-
BOOL isSnowLeopardOrLower() {
- return (getOSXMajorVersion() < 10.7);
+ return (getOSXMajorVersion() < 107);
}
--- a/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/com/sun/crypto/provider/DHKeyAgreement.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.security.ProviderException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.KeyAgreementSpi;
@@ -234,31 +235,14 @@
protected byte[] engineGenerateSecret()
throws IllegalStateException
{
- if (generateSecret == false) {
- throw new IllegalStateException
- ("Key agreement has not been completed yet");
+ int expectedLen = (init_p.bitLength() + 7) >>> 3;
+ byte[] result = new byte[expectedLen];
+ try {
+ engineGenerateSecret(result, 0);
+ } catch (ShortBufferException sbe) {
+ // should never happen since length are identical
}
-
- // Reset the key agreement here (in case anything goes wrong)
- generateSecret = false;
-
- // get the modulus
- BigInteger modulus = init_p;
-
- BigInteger tmpResult = y.modPow(x, modulus);
- byte[] secret = tmpResult.toByteArray();
-
- /*
- * BigInteger.toByteArray will sometimes put a sign byte up front, but
- * we NEVER want one.
- */
- if ((tmpResult.bitLength() % 8) == 0) {
- byte retval[] = new byte[secret.length - 1];
- System.arraycopy(secret, 1, retval, 0, retval.length);
- return retval;
- } else {
- return secret;
- }
+ return result;
}
/**
@@ -301,39 +285,51 @@
}
BigInteger modulus = init_p;
- byte[] secret = this.y.modPow(this.x, modulus).toByteArray();
-
- // BigInteger.toByteArray will sometimes put a sign byte up front,
- // but we NEVER want one.
- if ((secret.length << 3) != modulus.bitLength()) {
- if ((sharedSecret.length - offset) < (secret.length - 1)) {
- throw new ShortBufferException
+ int expectedLen = (modulus.bitLength() + 7) >>> 3;
+ if ((sharedSecret.length - offset) < expectedLen) {
+ throw new ShortBufferException
("Buffer too short for shared secret");
- }
- System.arraycopy(secret, 1, sharedSecret, offset,
- secret.length - 1);
+ }
- // Reset the key agreement here (not earlier!), so that people
- // can recover from ShortBufferException above without losing
- // internal state
- generateSecret = false;
+ // Reset the key agreement after checking for ShortBufferException
+ // above, so user can recover w/o losing internal state
+ generateSecret = false;
- return secret.length - 1;
-
+ /*
+ * NOTE: BigInteger.toByteArray() returns a byte array containing
+ * the two's-complement representation of this BigInteger with
+ * the most significant byte is in the zeroth element. This
+ * contains the minimum number of bytes required to represent
+ * this BigInteger, including at least one sign bit whose value
+ * is always 0.
+ *
+ * Keys are always positive, and the above sign bit isn't
+ * actually used when representing keys. (i.e. key = new
+ * BigInteger(1, byteArray)) To obtain an array containing
+ * exactly expectedLen bytes of magnitude, we strip any extra
+ * leading 0's, or pad with 0's in case of a "short" secret.
+ */
+ byte[] secret = this.y.modPow(this.x, modulus).toByteArray();
+ if (secret.length == expectedLen) {
+ System.arraycopy(secret, 0, sharedSecret, offset,
+ secret.length);
} else {
- if ((sharedSecret.length - offset) < secret.length) {
- throw new ShortBufferException
- ("Buffer too short to hold shared secret");
+ // Array too short, pad it w/ leading 0s
+ if (secret.length < expectedLen) {
+ System.arraycopy(secret, 0, sharedSecret,
+ offset + (expectedLen - secret.length),
+ secret.length);
+ } else {
+ // Array too long, check and trim off the excess
+ if ((secret.length == (expectedLen+1)) && secret[0] == 0) {
+ // ignore the leading sign byte
+ System.arraycopy(secret, 1, sharedSecret, offset, expectedLen);
+ } else {
+ throw new ProviderException("Generated secret is out-of-range");
+ }
}
- System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
-
- // Reset the key agreement here (not earlier!), so that people
- // can recover from ShortBufferException above without losing
- // internal state
- generateSecret = false;
-
- return secret.length;
}
+ return expectedLen;
}
/**
--- a/jdk/src/share/classes/java/lang/management/ManagementFactory.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/java/lang/management/ManagementFactory.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.TreeSet;
+import java.util.HashSet;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
@@ -787,7 +787,7 @@
getPlatformManagementInterfaces()
{
Set<Class<? extends PlatformManagedObject>> result =
- new TreeSet<>();
+ new HashSet<>();
for (PlatformComponent component: PlatformComponent.values()) {
result.add(component.getMXBeanInterface());
}
--- a/jdk/src/share/classes/java/net/InMemoryCookieStore.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/java/net/InMemoryCookieStore.java Thu Mar 29 21:22:07 2012 -0700
@@ -207,6 +207,9 @@
public boolean removeAll() {
lock.lock();
try {
+ if (cookieJar.isEmpty()) {
+ return false;
+ }
cookieJar.clear();
domainIndex.clear();
uriIndex.clear();
--- a/jdk/src/share/classes/java/util/Currency.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/java/util/Currency.java Thu Mar 29 21:22:07 2012 -0700
@@ -34,6 +34,8 @@
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -99,7 +101,7 @@
// class data: instance map
- private static HashMap<String, Currency> instances = new HashMap<String, Currency>(7);
+ private static ConcurrentMap<String, Currency> instances = new ConcurrentHashMap<>(7);
private static HashSet<Currency> available;
@@ -284,7 +286,6 @@
private static Currency getInstance(String currencyCode, int defaultFractionDigits,
int numericCode) {
- synchronized (instances) {
// Try to look up the currency code in the instances table.
// This does the null pointer check as a side effect.
// Also, if there already is an entry, the currencyCode must be valid.
@@ -322,10 +323,9 @@
}
}
- instance = new Currency(currencyCode, defaultFractionDigits, numericCode);
- instances.put(currencyCode, instance);
- return instance;
- }
+ instance = instances.putIfAbsent(currencyCode,
+ new Currency(currencyCode, defaultFractionDigits, numericCode));
+ return (instance != null ? instance : instances.get(currencyCode));
}
/**
--- a/jdk/src/share/classes/java/util/jar/Manifest.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/java/util/jar/Manifest.java Thu Mar 29 21:22:07 2012 -0700
@@ -400,6 +400,8 @@
public byte peek() throws IOException {
if (pos == count)
fill();
+ if (pos == count)
+ return -1; // nothing left in buffer
return buf[pos];
}
--- a/jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/javax/swing/DefaultListSelectionModel.java Thu Mar 29 21:22:07 2012 -0700
@@ -252,6 +252,10 @@
// Updates first and last change indices
private void markAsDirty(int r) {
+ if (r == -1) {
+ return;
+ }
+
firstAdjustedIndex = Math.min(firstAdjustedIndex, r);
lastAdjustedIndex = Math.max(lastAdjustedIndex, r);
}
@@ -358,16 +362,12 @@
private void updateLeadAnchorIndices(int anchorIndex, int leadIndex) {
if (leadAnchorNotificationEnabled) {
if (this.anchorIndex != anchorIndex) {
- if (this.anchorIndex != -1) { // The unassigned state.
- markAsDirty(this.anchorIndex);
- }
+ markAsDirty(this.anchorIndex);
markAsDirty(anchorIndex);
}
if (this.leadIndex != leadIndex) {
- if (this.leadIndex != -1) { // The unassigned state.
- markAsDirty(this.leadIndex);
- }
+ markAsDirty(this.leadIndex);
markAsDirty(leadIndex);
}
}
--- a/jdk/src/share/classes/sun/rmi/rmic/BatchEnvironment.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/rmi/rmic/BatchEnvironment.java Thu Mar 29 21:22:07 2012 -0700
@@ -160,7 +160,7 @@
}
/** list of generated source files created in this environment */
- private Vector generatedFiles = new Vector();
+ private Vector<File> generatedFiles = new Vector<>();
/**
* Remember a generated source file generated so that it
@@ -177,9 +177,9 @@
*/
public void deleteGeneratedFiles() {
synchronized(generatedFiles) {
- Enumeration enumeration = generatedFiles.elements();
+ Enumeration<File> enumeration = generatedFiles.elements();
while (enumeration.hasMoreElements()) {
- File file = (File) enumeration.nextElement();
+ File file = enumeration.nextElement();
file.delete();
}
generatedFiles.removeAllElements();
--- a/jdk/src/share/classes/sun/rmi/rmic/Main.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/rmi/rmic/Main.java Thu Mar 29 21:22:07 2012 -0700
@@ -73,14 +73,15 @@
File destDir;
int flags;
long tm;
- Vector classes;
+ Vector<String> classes;
boolean nowrite;
boolean nocompile;
boolean keepGenerated;
boolean status;
String[] generatorArgs;
- Vector generators;
- Class environmentClass = BatchEnvironment.class;
+ Vector<Generator> generators;
+ Class<? extends BatchEnvironment> environmentClass =
+ BatchEnvironment.class;
boolean iiopGeneration = false;
/**
@@ -183,7 +184,7 @@
destDir = null;
flags = F_WARNINGS;
tm = System.currentTimeMillis();
- classes = new Vector();
+ classes = new Vector<>();
nowrite = false;
nocompile = false;
keepGenerated = false;
@@ -191,7 +192,7 @@
if (generatorArgs == null) {
return false;
}
- generators = new Vector();
+ generators = new Vector<>();
// Pre-process command line for @file arguments
try {
@@ -411,7 +412,7 @@
// Get the environment required by this generator...
- Class envClass = BatchEnvironment.class;
+ Class<?> envClass = BatchEnvironment.class;
String env = getString("generator.env." + arg);
if (env != null) {
try {
@@ -423,7 +424,7 @@
// Yes, so switch to the new one...
- environmentClass = envClass;
+ environmentClass = envClass.asSubclass(BatchEnvironment.class);
} else {
@@ -495,8 +496,9 @@
try {
Class[] ctorArgTypes = {OutputStream.class,ClassPath.class,Main.class};
Object[] ctorArgs = {out,classPath,this};
- Constructor constructor = environmentClass.getConstructor(ctorArgTypes);
- result = (BatchEnvironment) constructor.newInstance(ctorArgs);
+ Constructor<? extends BatchEnvironment> constructor =
+ environmentClass.getConstructor(ctorArgTypes);
+ result = constructor.newInstance(ctorArgs);
result.reset();
}
catch (Exception e) {
@@ -530,7 +532,7 @@
*/
for (int i = classes.size()-1; i >= 0; i-- ) {
Identifier implClassName =
- Identifier.lookup((String)classes.elementAt(i));
+ Identifier.lookup(classes.elementAt(i));
/*
* Fix bugid 4049354: support using '.' as an inner class
@@ -558,7 +560,7 @@
try {
ClassDefinition def = decl.getClassDefinition(env);
for (int j = 0; j < generators.size(); j++) {
- Generator gen = (Generator)generators.elementAt(j);
+ Generator gen = generators.elementAt(j);
gen.generate(env, def, destDir);
}
} catch (ClassNotFound ex) {
@@ -673,7 +675,7 @@
do {
done = true;
- for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
+ for (Enumeration<?> e = env.getClasses() ; e.hasMoreElements() ; ) {
ClassDeclaration c = (ClassDeclaration)e.nextElement();
done = compileClass(c,buf,env);
}
@@ -682,7 +684,9 @@
/*
* Compile a single class.
+ * Fallthrough is intentional
*/
+ @SuppressWarnings("fallthrough")
public boolean compileClass (ClassDeclaration c,
ByteArrayOutputStream buf,
BatchEnvironment env)
@@ -879,6 +883,6 @@
args[1] = (arg1 != null ? arg1.toString() : "null");
args[2] = (arg2 != null ? arg2.toString() : "null");
- return java.text.MessageFormat.format(format, args);
+ return java.text.MessageFormat.format(format, (Object[]) args);
}
}
--- a/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/rmi/rmic/RMIGenerator.java Thu Mar 29 21:22:07 2012 -0700
@@ -61,7 +61,7 @@
*/
public class RMIGenerator implements RMIConstants, Generator {
- private static final Hashtable versionOptions = new Hashtable();
+ private static final Hashtable<String, Integer> versionOptions = new Hashtable<>();
static {
versionOptions.put("-v1.1", new Integer(STUB_VERSION_1_1));
versionOptions.put("-vcompat", new Integer(STUB_VERSION_FAT));
@@ -96,7 +96,7 @@
return false;
}
explicitVersion = arg;
- version = ((Integer) versionOptions.get(arg)).intValue();
+ version = versionOptions.get(arg);
argv[i] = null;
}
}
@@ -519,7 +519,7 @@
* follows a previous catch of it or of one of its superclasses.
* The following method invocation takes care of these details.
*/
- Vector catchList = computeUniqueCatchList(exceptions);
+ Vector<ClassDefinition> catchList = computeUniqueCatchList(exceptions);
/*
* If we need to catch any particular exceptions (i.e. this method
@@ -615,10 +615,10 @@
* UnexpectedException, and end the try block.
*/
if (catchList.size() > 0) {
- for (Enumeration enumeration = catchList.elements();
+ for (Enumeration<ClassDefinition> enumeration = catchList.elements();
enumeration.hasMoreElements();)
{
- ClassDefinition def = (ClassDefinition) enumeration.nextElement();
+ ClassDefinition def = enumeration.nextElement();
p.pOlnI("} catch (" + def.getName() + " e) {");
p.pln("throw e;");
}
@@ -650,8 +650,8 @@
* of its superclasses is in the throws clause of the method, indicating
* that no exceptions need to be caught.
*/
- private Vector computeUniqueCatchList(ClassDeclaration[] exceptions) {
- Vector uniqueList = new Vector(); // unique exceptions to catch
+ private Vector<ClassDefinition> computeUniqueCatchList(ClassDeclaration[] exceptions) {
+ Vector<ClassDefinition> uniqueList = new Vector<>(); // unique exceptions to catch
uniqueList.addElement(defRuntimeException);
uniqueList.addElement(defRemoteException);
@@ -682,8 +682,7 @@
* exceptions that need to be caught:
*/
for (int j = 0; j < uniqueList.size();) {
- ClassDefinition def =
- (ClassDefinition) uniqueList.elementAt(j);
+ ClassDefinition def = uniqueList.elementAt(j);
if (def.superClassOf(env, decl)) {
/*
* If a superclass of this exception is already on
--- a/jdk/src/share/classes/sun/rmi/rmic/newrmic/Main.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/rmi/rmic/newrmic/Main.java Thu Mar 29 21:22:07 2012 -0700
@@ -455,7 +455,7 @@
BatchEnvironment env;
try {
Constructor<? extends BatchEnvironment> cons =
- batch.envClass.getConstructor(new Class[] { RootDoc.class });
+ batch.envClass.getConstructor(new Class<?>[] { RootDoc.class });
env = cons.newInstance(rootDoc);
} catch (NoSuchMethodException e) {
throw new AssertionError(e);
--- a/jdk/src/share/classes/sun/rmi/rmic/newrmic/Resources.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/rmi/rmic/newrmic/Resources.java Thu Mar 29 21:22:07 2012 -0700
@@ -69,7 +69,7 @@
format = "missing resource key: key = \"" + key + "\", " +
"arguments = \"{0}\", \"{1}\", \"{2}\"";
}
- return MessageFormat.format(format, args);
+ return MessageFormat.format(format, (Object[]) args);
}
/**
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -198,8 +198,22 @@
token.p11.C_GetAttributeValue(session.id(), keyID, attributes);
byte[] secret = attributes[0].getByteArray();
token.p11.C_DestroyObject(session.id(), keyID);
- // trim leading 0x00 bytes per JCE convention
- return P11Util.trimZeroes(secret);
+ // Some vendors, e.g. NSS, trim off the leading 0x00 byte(s) from
+ // the generated secret. Thus, we need to check the secret length
+ // and trim/pad it so the returned value has the same length as
+ // the modulus size
+ if (secret.length == secretLen) {
+ return secret;
+ } else {
+ if (secret.length > secretLen) {
+ // Shouldn't happen; but check just in case
+ throw new ProviderException("generated secret is out-of-range");
+ }
+ byte[] newSecret = new byte[secretLen];
+ System.arraycopy(secret, 0, newSecret, secretLen - secret.length,
+ secret.length);
+ return newSecret;
+ }
} catch (PKCS11Exception e) {
throw new ProviderException("Could not derive key", e);
} finally {
--- a/jdk/src/solaris/native/java/util/TimeZone_md.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/java/util/TimeZone_md.c Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -96,9 +96,9 @@
/*
* Scans the specified directory and its subdirectories to find a
* zoneinfo file which has the same content as /etc/localtime on Linux
- * or /usr/share/lib/zoneinfo/localtime (most likely a symbolic link)
- * on Solaris given in 'buf'. Returns a zone ID if found, otherwise,
- * NULL is returned.
+ * or /usr/share/lib/zoneinfo/localtime on Solaris given in 'buf'.
+ * If file is symbolic link, then the contents it points to are in buf.
+ * Returns a zone ID if found, otherwise, NULL is returned.
*/
static char *
findZoneinfoFile(char *buf, size_t size, const char *dir)
@@ -280,21 +280,27 @@
tz = getZoneName(linkbuf);
if (tz != NULL) {
tz = strdup(tz);
+ return tz;
}
- return tz;
}
/*
* If it's a regular file, we need to find out the same zoneinfo file
* that has been copied as /etc/localtime.
+ * If initial symbolic link resolution failed, we should treat target
+ * file as a regular file.
*/
+ if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
+ return NULL;
+ }
+ if (fstat(fd, &statbuf) == -1) {
+ (void) close(fd);
+ return NULL;
+ }
size = (size_t) statbuf.st_size;
buf = (char *) malloc(size);
if (buf == NULL) {
- return NULL;
- }
- if ((fd = open(DEFAULT_ZONEINFO_FILE, O_RDONLY)) == -1) {
- free((void *) buf);
+ (void) close(fd);
return NULL;
}
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Thu Mar 29 21:22:07 2012 -0700
@@ -541,6 +541,8 @@
J2dRlsTraceLn1(J2D_TRACE_ERROR,
"X11SD_SetupSharedSegment shmget has failed: %s",
strerror(errno));
+ free((void *)shminfo);
+ XDestroyImage(img);
return NULL;
}
@@ -550,6 +552,8 @@
J2dRlsTraceLn1(J2D_TRACE_ERROR,
"X11SD_SetupSharedSegment shmat has failed: %s",
strerror(errno));
+ free((void *)shminfo);
+ XDestroyImage(img);
return NULL;
}
@@ -570,6 +574,9 @@
J2dRlsTraceLn1(J2D_TRACE_ERROR,
"X11SD_SetupSharedSegment XShmAttach has failed: %s",
strerror(errno));
+ shmdt(shminfo->shmaddr);
+ free((void *)shminfo);
+ XDestroyImage(img);
return NULL;
}
@@ -1345,13 +1352,10 @@
#ifdef MITSHM
if (image->obdata != NULL) {
X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata);
- } else {
- free(image->data);
+ image->obdata = NULL;
}
-#else
- free(image->data);
#endif /* MITSHM */
- XFree(image);
+ XDestroyImage(image);
}
}
--- a/jdk/src/solaris/native/sun/nio/ch/DatagramDispatcher.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/nio/ch/DatagramDispatcher.c Thu Mar 29 21:22:07 2012 -0700
@@ -36,6 +36,7 @@
#include <sys/socket.h>
#include "nio_util.h"
+#include <limits.h>
JNIEXPORT jint JNICALL
Java_sun_nio_ch_DatagramDispatcher_read0(JNIEnv *env, jclass clazz,
@@ -60,23 +61,14 @@
ssize_t result = 0;
struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
struct msghdr m;
- if (len > 16) {
- len = 16;
+ if (len > IOV_MAX) {
+ len = IOV_MAX;
}
- m.msg_name = NULL;
- m.msg_namelen = 0;
+ // initialize the message
+ memset(&m, 0, sizeof(m));
m.msg_iov = iov;
m.msg_iovlen = len;
-#ifdef __solaris__
- m.msg_accrights = NULL;
- m.msg_accrightslen = 0;
-#endif
-
-#if defined(__linux__) || defined(_ALLBSD_SOURCE)
- m.msg_control = NULL;
- m.msg_controllen = 0;
-#endif
result = recvmsg(fd, &m, 0);
if (result < 0 && errno == ECONNREFUSED) {
@@ -108,23 +100,14 @@
struct iovec *iov = (struct iovec *)jlong_to_ptr(address);
struct msghdr m;
ssize_t result = 0;
- if (len > 16) {
- len = 16;
+ if (len > IOV_MAX) {
+ len = IOV_MAX;
}
- m.msg_name = NULL;
- m.msg_namelen = 0;
+ // initialize the message
+ memset(&m, 0, sizeof(m));
m.msg_iov = iov;
m.msg_iovlen = len;
-#ifdef __solaris__
- m.msg_accrights = NULL;
- m.msg_accrightslen = 0;
-#endif
-
-#if defined(__linux__) || defined(_ALLBSD_SOURCE)
- m.msg_control = NULL;
- m.msg_controllen = 0;
-#endif
result = sendmsg(fd, &m, 0);
if (result < 0 && errno == ECONNREFUSED) {
--- a/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/nio/fs/GnomeFileTypeDetector.c Thu Mar 29 21:22:07 2012 -0700
@@ -30,9 +30,6 @@
#include <stdlib.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#ifdef __solaris__
#include <strings.h>
--- a/jdk/src/solaris/native/sun/security/jgss/wrapper/NativeFunc.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/security/jgss/wrapper/NativeFunc.c Thu Mar 29 21:22:07 2012 -0700
@@ -26,9 +26,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#include "NativeFunc.h"
/* standard GSS method names (ordering is from mapfile) */
--- a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c Thu Mar 29 21:22:07 2012 -0700
@@ -28,9 +28,6 @@
#include <string.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#include <jni_util.h>
--- a/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Thu Mar 29 21:22:07 2012 -0700
@@ -64,9 +64,6 @@
#include <assert.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#include <jni.h>
--- a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c Thu Mar 29 21:22:07 2012 -0700
@@ -29,9 +29,6 @@
#include <assert.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#include <winscard.h>
--- a/jdk/src/solaris/npt/npt_md.h Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/solaris/npt/npt_md.h Thu Mar 29 21:22:07 2012 -0700
@@ -32,9 +32,6 @@
#include <string.h>
#include <errno.h>
#include <dlfcn.h>
-#ifndef __APPLE__
-#include <link.h>
-#endif
#include <jvm_md.h>
#define NPT_LIBNAME "npt"
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Thu Mar 29 21:22:07 2012 -0700
@@ -302,6 +302,7 @@
delete m_childList;
DestroyDropTarget();
+ ReleaseDragCapture(0);
if (m_myControlID != 0) {
AwtComponent* parent = GetParent();
--- a/jdk/test/ProblemList.txt Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/ProblemList.txt Thu Mar 29 21:22:07 2012 -0700
@@ -212,7 +212,7 @@
# 7076644
java/io/File/Basic.java windows-all
-# Test needs AWT window server, does not work headless
+# 7145435 - Test needs AWT window server, does not work headless
java/io/Serializable/resolveClass/deserializeButton/run.sh macosx-all
############################################################################
@@ -225,9 +225,6 @@
# 7052549
java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all
-# 6963118
-java/nio/channels/Selector/Wakeup.java windows-all
-
# 7133499, 7133497
java/nio/channels/AsyncCloseAndInterrupt.java macosx-all
java/nio/channels/AsynchronousFileChannel/Lock.java macosx-all
@@ -259,9 +256,6 @@
# jdk_security
-# 7145024
-sun/security/ssl/com/sun/net/ssl/internal/ssl/GenSSLConfigs/main.java solaris-all
-
# 7147060
com/sun/org/apache/xml/internal/security/transforms/ClassLoaderTest.java generic-all
@@ -305,9 +299,6 @@
# 7079203 sun/security/tools/keytool/printssl.sh fails on solaris with timeout
sun/security/tools/keytool/printssl.sh solaris-all
-# 7081817
-sun/security/provider/certpath/X509CertPath/IllegalCertiticates.java generic-all
-
# 7041639, Solaris DSA keypair generation bug (Note: jdk_util also affected)
java/security/KeyPairGenerator/SolarisShortDSA.java solaris-all
sun/security/tools/jarsigner/onlymanifest.sh solaris-all
--- a/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 0000000
+ * @bug 7146728
* @summary DHKeyAgreement2
* @author Jan Luehe
*/
@@ -52,15 +52,12 @@
public class DHKeyAgreement2 {
+ private static final String SUNJCE = "SunJCE";
private DHKeyAgreement2() {}
public static void main(String argv[]) throws Exception {
String mode = "USE_SKIP_DH_PARAMS";
- // Add JCE to the list of providers
- SunJCE jce = new SunJCE();
- Security.addProvider(jce);
-
DHKeyAgreement2 keyAgree = new DHKeyAgreement2();
if (argv.length > 1) {
@@ -86,7 +83,7 @@
// Some central authority creates new DH parameters
System.err.println("Creating Diffie-Hellman parameters ...");
AlgorithmParameterGenerator paramGen
- = AlgorithmParameterGenerator.getInstance("DH");
+ = AlgorithmParameterGenerator.getInstance("DH", SUNJCE);
paramGen.init(512);
AlgorithmParameters params = paramGen.generateParameters();
dhSkipParamSpec = (DHParameterSpec)params.getParameterSpec
@@ -103,7 +100,7 @@
* above
*/
System.err.println("ALICE: Generate DH keypair ...");
- KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
+ KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH", SUNJCE);
aliceKpairGen.initialize(dhSkipParamSpec);
KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
System.out.println("Alice DH public key:\n" +
@@ -112,14 +109,14 @@
aliceKpair.getPrivate().toString());
DHParameterSpec dhParamSpec =
((DHPublicKey)aliceKpair.getPublic()).getParams();
- AlgorithmParameters algParams = AlgorithmParameters.getInstance("DH");
+ AlgorithmParameters algParams = AlgorithmParameters.getInstance("DH", SUNJCE);
algParams.init(dhParamSpec);
System.out.println("Alice DH parameters:\n"
+ algParams.toString());
// Alice executes Phase1 of her version of the DH protocol
System.err.println("ALICE: Execute PHASE1 ...");
- KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
+ KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH", SUNJCE);
aliceKeyAgree.init(aliceKpair.getPrivate());
// Alice encodes her public key, and sends it over to Bob.
@@ -130,7 +127,7 @@
* in encoded format.
* He instantiates a DH public key from the encoded key material.
*/
- KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
+ KeyFactory bobKeyFac = KeyFactory.getInstance("DH", SUNJCE);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec
(alicePubKeyEnc);
PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);
@@ -144,7 +141,7 @@
// Bob creates his own DH key pair
System.err.println("BOB: Generate DH keypair ...");
- KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
+ KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH", SUNJCE);
bobKpairGen.initialize(dhParamSpec);
KeyPair bobKpair = bobKpairGen.generateKeyPair();
System.out.println("Bob DH public key:\n" +
@@ -154,7 +151,7 @@
// Bob executes Phase1 of his version of the DH protocol
System.err.println("BOB: Execute PHASE1 ...");
- KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
+ KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH", SUNJCE);
bobKeyAgree.init(bobKpair.getPrivate());
// Bob encodes his public key, and sends it over to Alice.
@@ -166,7 +163,7 @@
* Before she can do so, she has to instanticate a DH public key
* from Bob's encoded key material.
*/
- KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");
+ KeyFactory aliceKeyFac = KeyFactory.getInstance("DH", SUNJCE);
x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);
System.err.println("ALICE: Execute PHASE2 ...");
@@ -187,49 +184,32 @@
byte[] aliceSharedSecret = aliceKeyAgree.generateSecret();
int aliceLen = aliceSharedSecret.length;
+ // check if alice's key agreement has been reset afterwards
+ try {
+ aliceKeyAgree.generateSecret();
+ throw new Exception("Error: alice's KeyAgreement not reset");
+ } catch (IllegalStateException e) {
+ System.out.println("EXPECTED: " + e.getMessage());
+ }
+
byte[] bobSharedSecret = new byte[aliceLen];
int bobLen;
try {
// provide output buffer that is too short
bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 1);
-
- /*
- * Gatekeeper's note:
- * We should not be getting here, but every so often, we
- * get a failure, either a "ShortBufferException" or
- * "Key agreement has not been completed yet" in the
- * generateSecret(bobSharedSecret, 0) below.
- *
- * This will help to figure out why we're dropping through
- * and not failing.
- */
- System.out.println("NIGHTLY: Should *NOT* be here!!!\n" +
- "aliceLen = " + aliceLen + "\n" +
- "Alice's shared secret");
-
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- hd.encodeBuffer(
- new ByteArrayInputStream(aliceSharedSecret), System.out);
- } catch (IOException e) { }
-
- System.out.println("bobLen = " + bobLen);
-
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- hd.encodeBuffer(
- new ByteArrayInputStream(bobSharedSecret), System.out);
- } catch (IOException e) { }
-
- throw new Exception("Shouldn't be succeeding.");
} catch (ShortBufferException e) {
System.out.println("EXPECTED: " + e.getMessage());
}
+ // retry w/ output buffer of required size
+ bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0);
- // provide output buffer of required size
- bobLen = bobKeyAgree.generateSecret(bobSharedSecret, 0);
+ // check if bob's key agreement has been reset afterwards
+ try {
+ bobKeyAgree.generateSecret(bobSharedSecret, 0);
+ throw new Exception("Error: bob's KeyAgreement not reset");
+ } catch (IllegalStateException e) {
+ System.out.println("EXPECTED: " + e.getMessage());
+ }
System.out.println("Alice secret: " + toHexString(aliceSharedSecret));
System.out.println("Bob secret: " + toHexString(bobSharedSecret));
--- a/jdk/test/com/sun/jdi/EarlyReturnTest.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/com/sun/jdi/EarlyReturnTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -292,7 +292,9 @@
private String[] excludes = {
"javax.*",
"sun.*",
- "com.sun.*"};
+ "com.sun.*",
+ "com.oracle.*",
+ "oracle.*"};
static VirtualMachineManager vmm ;
ClassType targetClass;
--- a/jdk/test/com/sun/jdi/MethodEntryExitEvents.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/com/sun/jdi/MethodEntryExitEvents.java Thu Mar 29 21:22:07 2012 -0700
@@ -114,7 +114,8 @@
* http://java.sun.com/javase/technologies/core/toolsapis/jpda/
*/
private String[] excludes = {"java.*", "javax.*", "sun.*",
- "com.sun.*"};
+ "com.sun.*", "com.oracle.*",
+ "oracle.*"};
MethodEntryExitEvents (String args[]) {
super(args);
--- a/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/com/sun/jdi/MethodExitReturnValuesTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -218,7 +218,9 @@
private String[] excludes = {
"javax.*",
"sun.*",
- "com.sun.*"};
+ "com.sun.*",
+ "com.oracle.*",
+ "oracle.*"};
static VirtualMachineManager vmm ;
ClassType targetClass;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/WindowDragTest/WindowDragTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7128738
+ @summary dragged dialog freezes system on dispose
+ @author Oleg Pekhovskiy: area=awt.toplevel
+ @library ../../regtesthelpers
+ @run main WindowDragTest
+*/
+
+import java.awt.Frame;
+import java.awt.event.InputEvent;
+import java.awt.AWTException;
+import test.java.awt.regtesthelpers.Util;
+import java.awt.Robot;
+import java.awt.Point;
+import java.awt.Dimension;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class WindowDragTest {
+
+ static boolean passed = false;
+
+ public static void main(String[] args) {
+ try {
+ Robot robot = new Robot();
+ robot.setAutoDelay(1000);
+
+ Frame frame1 = new Frame();
+ frame1.setBounds(50, 50, 300, 200);
+ frame1.setVisible(true);
+ frame1.toFront();
+ frame1.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ // Clicking frame1 succeeded - mouse is not captured
+ passed = true;
+ }
+ });
+ robot.delay(1000);
+
+ Frame frame2 = new Frame();
+ frame2.setBounds(100, 100, 300, 200);
+ frame2.setVisible(true);
+ frame2.toFront();
+ robot.delay(1000);
+
+ Point p = frame2.getLocationOnScreen();
+ Dimension d = frame2.getSize();
+
+ // Move cursor to frame2 title bar to drag
+ robot.mouseMove(p.x + (int)(d.getWidth() / 2), p.y + (int)frame2.getInsets().top / 2);
+ Util.waitForIdle(robot);
+
+ // Start window dragging
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(robot);
+
+ // Dispose window being dragged
+ frame2.dispose();
+ Util.waitForIdle(robot);
+
+ // Release mouse button to be able to get MOUSE_CLICKED event on Util.clickOnComp()
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(robot);
+
+ // Click frame1 to check whether mouse is not captured by frame2
+ Util.clickOnComp(frame1, robot);
+ Util.waitForIdle(robot);
+
+ frame1.dispose();
+ if (passed) {
+ System.out.println("Test passed.");
+ }
+ else {
+ System.out.println("Test failed.");
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ catch (AWTException e) {
+ throw new RuntimeException("AWTException occurred - problem creating robot!");
+ }
+ }
+}
--- a/jdk/test/java/io/File/isDirectory/Applet.html Thu Mar 29 21:16:58 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-<!---->
-<applet code=Applet.class width=100 height=100></applet>
--- a/jdk/test/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java Thu Mar 29 21:22:07 2012 -0700
@@ -22,7 +22,6 @@
*/
/* @test
- * @clean A B Container ReplacerObjectOutputStream
* @summary Verify that ClassCastException is thrown when deserializing
* an object and one of its object fields is incompatibly replaced
* by either replaceObject/resolveObject.
--- a/jdk/test/java/io/Serializable/replaceStringArray/ReplaceStringArray.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/io/Serializable/replaceStringArray/ReplaceStringArray.java Thu Mar 29 21:22:07 2012 -0700
@@ -22,7 +22,6 @@
*/
/* @test
- * @clean A SubstituteObjectOutputStream SubstituteObjectInputStream
* @bug 4099013
* @summary Enable substitution of String and Array by ObjectStreams.
*/
--- a/jdk/test/java/io/Serializable/replaceWithNull/ReplaceWithNull.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/io/Serializable/replaceWithNull/ReplaceWithNull.java Thu Mar 29 21:22:07 2012 -0700
@@ -23,7 +23,6 @@
/* @test
* @bug 4065313
- * @clean A ReplaceWithNull MyObjectOutputStream
* @summary Ensure that it is okay to replace an object with null.
*/
import java.io.*;
--- a/jdk/test/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java Thu Mar 29 21:22:07 2012 -0700
@@ -22,7 +22,6 @@
*/
/* @test
- * @clean A
* @bug 4146453
* @summary Test that regrow of object/handle table of ObjectOutputStream works.
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/management/ManagementFactory/GetPlatformManagementInterfaces.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7074616
+ * @summary Basic unit test of the
+ * ManagementFactory.getPlatformManagementInterfaces() method
+ * @author Frederic Parain
+ *
+ * @run main GetPlatformManagementInterfaces
+ */
+
+import java.lang.management.*;
+import java.io.IOException;
+import java.util.*;
+import javax.management.*;
+
+import static java.lang.management.ManagementFactory.*;
+
+public class GetPlatformManagementInterfaces {
+
+ private static enum ManagementInterfaces {
+ CLASS_LOADING_MXBEAN(ClassLoadingMXBean.class),
+ COMPILATION_MXBEAN(CompilationMXBean.class),
+ MEMORY_MXBEAN(MemoryMXBean.class),
+ OPERATING_SYSTEM_MXBEAN(OperatingSystemMXBean.class),
+ RUNTIME_MXBEAN(RuntimeMXBean.class),
+ THREAD_MXBEAN(ThreadMXBean.class),
+ GARBAGE_COLLECTOR_MXBEAN(GarbageCollectorMXBean.class),
+ MEMORY_MANAGER_MXBEAN(MemoryManagerMXBean.class),
+ MEMORY_POOL_MXBEAN(MemoryPoolMXBean.class);
+
+ private final Class<? extends PlatformManagedObject> managementInterface;
+ private ManagementInterfaces(Class<? extends PlatformManagedObject> minterface) {
+ managementInterface = minterface;
+ }
+ public Class<? extends PlatformManagedObject> getManagementInterface() {
+ return managementInterface;
+ }
+ };
+
+ public static void main(String[] args) {
+ Set<Class<? extends PlatformManagedObject>> interfaces =
+ ManagementFactory.getPlatformManagementInterfaces();
+ for(Class<? extends PlatformManagedObject> pom : interfaces) {
+ List<? extends PlatformManagedObject> list =
+ ManagementFactory.getPlatformMXBeans(pom);
+ }
+ for(ManagementInterfaces mi : ManagementInterfaces.values()) {
+ if(!interfaces.contains(mi.getManagementInterface())) {
+ throw new RuntimeException(mi.getManagementInterface() + " not in ManagementInterfaces set");
+ }
+ }
+ }
+}
--- a/jdk/test/java/net/CookieHandler/NullUriCookieTest.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/net/CookieHandler/NullUriCookieTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -23,8 +23,9 @@
/*
* @test
- * @bug 6953455
+ * @bug 6953455 7045655
* @summary CookieStore.add() cannot handle null URI parameter
+ * and An empty InMemoryCookieStore should not return true for removeAll
*/
import java.net.CookieManager;
@@ -44,6 +45,11 @@
static void checkCookieNullUri() throws Exception {
//get a cookie store implementation and add a cookie to the store with null URI
CookieStore cookieStore = (new CookieManager()).getCookieStore();
+ //Check if removeAll() retrurns false on an empty CookieStore
+ if (cookieStore.removeAll()) {
+ fail = true;
+ }
+ checkFail("removeAll on empty store should return false");
HttpCookie cookie = new HttpCookie("MY_COOKIE", "MY_COOKIE_VALUE");
cookie.setDomain("foo.com");
cookieStore.add(null, cookie);
--- a/jdk/test/java/net/Socks/SocksServer.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/net/Socks/SocksServer.java Thu Mar 29 21:22:07 2012 -0700
@@ -22,13 +22,14 @@
*/
import java.net.*;
import java.io.*;
+import java.util.HashMap;
public class SocksServer extends Thread {
// Some useful SOCKS constant
- static final int PROTO_VERS4 = 4;
+ static final int PROTO_VERS4 = 4;
static final int PROTO_VERS = 5;
- static final int DEFAULT_PORT = 1080;
+ static final int DEFAULT_PORT = 1080;
static final int NO_AUTH = 0;
static final int GSSAPI = 1;
@@ -36,28 +37,28 @@
static final int NO_METHODS = -1;
static final int CONNECT = 1;
- static final int BIND = 2;
+ static final int BIND = 2;
static final int UDP_ASSOC = 3;
- static final int IPV4 = 1;
- static final int DOMAIN_NAME = 3;
- static final int IPV6 = 4;
+ static final int IPV4 = 1;
+ static final int DOMAIN_NAME = 3;
+ static final int IPV6 = 4;
static final int REQUEST_OK = 0;
static final int GENERAL_FAILURE = 1;
- static final int NOT_ALLOWED = 2;
+ static final int NOT_ALLOWED = 2;
static final int NET_UNREACHABLE = 3;
static final int HOST_UNREACHABLE = 4;
- static final int CONN_REFUSED = 5;
- static final int TTL_EXPIRED = 6;
+ static final int CONN_REFUSED = 5;
+ static final int TTL_EXPIRED = 6;
static final int CMD_NOT_SUPPORTED = 7;
static final int ADDR_TYPE_NOT_SUP = 8;
private int port;
private ServerSocket server;
private boolean useV4 = false;
- private java.util.Hashtable users = new java.util.Hashtable();
- private boolean done = false;
+ private HashMap<String,String> users = new HashMap<>();
+ private volatile boolean done = false;
// Inner class to handle protocol with client
// This is the bulk of the work (protocol handler)
class ClientHandler extends Thread {
@@ -136,7 +137,7 @@
System.err.println("User: '" + uname);
System.err.println("PSWD: '" + password);
if (users.containsKey(uname)) {
- String p1 = (String) users.get(uname);
+ String p1 = users.get(uname);
System.err.println("p1 = " + p1);
if (p1.equals(password)) {
out.write(PROTO_VERS);
@@ -492,7 +493,12 @@
public SocksServer(int port) throws IOException {
this.port = port;
server = new ServerSocket();
- server.bind(new InetSocketAddress(port));
+ if (port == 0) {
+ server.bind(null);
+ this.port = server.getLocalPort();
+ } else {
+ server.bind(new InetSocketAddress(port));
+ }
}
public SocksServer() throws IOException {
@@ -503,8 +509,13 @@
users.put(user, passwd);
}
- public synchronized void terminate() {
+ public int getPort() {
+ return port;
+ }
+
+ public void terminate() {
done = true;
+ try { server.close(); } catch (IOException unused) {}
}
public void run() {
--- a/jdk/test/java/net/Socks/SocksV4Test.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/net/Socks/SocksV4Test.java Thu Mar 29 21:22:07 2012 -0700
@@ -26,23 +26,22 @@
* @bug 4727547
* @summary SocksSocketImpl throws NullPointerException
* @build SocksServer
+ * @run main SocksV4Test
*/
import java.net.*;
-import java.io.*;
public class SocksV4Test {
- public static void main(String[] args) throws IOException {
- // Create a SOCKS V4 proxy on port 8888
- SocksServer srvr = new SocksServer(8888, true);
+ public static void main(String[] args) throws Exception {
+ // Create a SOCKS V4 proxy
+ SocksServer srvr = new SocksServer(0, true);
srvr.start();
- System.setProperty("socksProxyHost", "localhost");
- System.setProperty("socksProxyPort", "8888");
+ Proxy sp = new Proxy(Proxy.Type.SOCKS,
+ new InetSocketAddress("localhost", srvr.getPort()));
// Let's create an unresolved address
InetSocketAddress ad = new InetSocketAddress("doesnt.exist.name", 1234);
- Socket s = new Socket();
- try {
- s.connect(ad,10000);
+ try (Socket s = new Socket(sp)) {
+ s.connect(ad, 10000);
} catch (UnknownHostException ex) {
// OK, that's what we expected
} catch (NullPointerException npe) {
@@ -50,7 +49,6 @@
throw new RuntimeException("Got a NUllPointerException");
} finally {
srvr.terminate();
- srvr.interrupt();
}
}
}
--- a/jdk/test/java/nio/file/Files/CustomOptions.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/nio/file/Files/CustomOptions.java Thu Mar 29 21:22:07 2012 -0700
@@ -28,6 +28,7 @@
* @author Brandon Passanisi
* @library ..
* @build CustomOptions PassThroughFileSystem
+ * @run main CustomOptions
*/
import java.io.IOException;
--- a/jdk/test/java/text/Bidi/Bug6850113.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/java/text/Bidi/Bug6850113.java Thu Mar 29 21:22:07 2012 -0700
@@ -25,6 +25,7 @@
* @bug 6850113
* @summary Verify the return value of digit() for some digits.
* @compile -XDignore.symbol.file=true Bug6850113.java
+ * @run main Bug6850113
*/
import sun.text.normalizer.UCharacter;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/jar/Manifest/CreateManifest.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7148584
+ * @summary Jar tools fails to generate manifest correctly when boundary condition hit
+ * @compile -XDignore.symbol.file=true CreateManifest.java
+ * @run main CreateManifest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.jar.*;
+
+public class CreateManifest {
+
+public static void main(String arg[]) throws Exception {
+
+ String jarFileName = "test.jar";
+ String ManifestName = "MANIFEST.MF";
+
+ // create the MANIFEST.MF file
+ Files.write(Paths.get(ManifestName), FILE_CONTENTS.getBytes());
+
+ String [] args = new String [] { "cvfm", jarFileName, ManifestName};
+ sun.tools.jar.Main jartool =
+ new sun.tools.jar.Main(System.out, System.err, "jar");
+ jartool.run(args);
+
+ try (JarFile jf = new JarFile(jarFileName)) {
+ Manifest m = jf.getManifest();
+ String result = m.getMainAttributes().getValue("Class-path");
+ if (result == null)
+ throw new RuntimeException("Failed to add Class-path attribute to manifest");
+ } finally {
+ Files.deleteIfExists(Paths.get(jarFileName));
+ Files.deleteIfExists(Paths.get(ManifestName));
+ }
+
+}
+
+private static final String FILE_CONTENTS =
+ "Class-path: \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-testconsole-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-testconsole-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-bmp-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-bmp-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-host-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-host-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agent-patching-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agent-patching-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-connector-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-connector-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-discovery-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gccompliance-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mos-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mos-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-security-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-security-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-topology-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-topology-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mext-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mext-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-discovery-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-discovery-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ecm-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ecm-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ecm-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-console-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-console-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-rules-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-rules-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gccompliance-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ip-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ip-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-probanalysis-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-probanalysis-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-swlib-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-installmediacomponent-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-uifwk-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-uifwk-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-discovery-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gccompliance-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-bmp-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-host-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agent-patching-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-connector-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mos-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-event-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-discovery-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gccompliance-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ip-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-probanalysis-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-testconsole-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-uifwk-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mext-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-security-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentpush-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentpush-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentpush-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-selfupdate-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-selfupdate-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-selfupdate-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentpush-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-groups-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-groups-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-groups-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-topology-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-jobs-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-jobs-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-jobs-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-templ-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-templ-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-templ-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metricalertserrors-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metricalertserrors-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metricalertserrors-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metrics-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metrics-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-metrics-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-tc-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-tc-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-tc-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentmgmt-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentmgmt-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentmgmt-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gcharvester-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gcharvester-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-gcharvester-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-patching-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-patching-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-patching-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohinv-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohinv-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohinv-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohagent-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohcoherence-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohjrockit-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-extensibility-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mpcustom-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-selfmonitor-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ocheck-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-udmmig-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-multioms-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-postupgrade-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-postupgrade-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-postupgrade-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ppc-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ppc-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ppc-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ppc-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ppc-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mextjmx-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mextjmx-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-mextjmx-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ocheck-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-services-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-services-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-services-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-eventmobile-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-uifwkmobile-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-logmgmt-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-omsproperties-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-ohel-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-agentupgrade-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-lm-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-lm-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-core-lm-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-regiontest-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-uipatterns-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-uipatterns-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-uipatterns-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-uielements-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-uielements-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-sandbox-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-sandbox-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-sdkcore-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-sdkcore-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-sdkcore-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-core-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-core-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-samples-core-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-adfext-bc-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-aslm-services-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-avail-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-charge-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-config-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-connect-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-db-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-discovery-public-entity.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-discovery-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-event-console-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-event-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-event-rules-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-extens-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-filebrowser-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-filebrowser-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-gccompliance-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-gccompliance-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-gccompliance-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ip-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-job-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-me-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-metric-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ecm-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ecm-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ecm-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ecm-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-paf-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-security-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-swlib-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-swlib-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-templ-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-uifwk-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-uifwk-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-uifwk-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-bmp-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-bmp-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-bmp-public-entity.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-agent-patching-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-agent-patching-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mext-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mext-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mext-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-testconsole-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-testconsole-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-testconsole-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mos-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mos-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-mos-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-topology-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-topology-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-regions-uimodel.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-regions-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-event-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-uifwk-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-adfext-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-agentpatching-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-avail-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-bmp-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-charge-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-config-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-connect-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-db-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-discovery-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ecm-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-extens-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-gccompliance-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ip-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-job-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-me-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-metric-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-paf-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-regions-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-security-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-swlib-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-templ-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-groups-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-groups-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-topology-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-resources-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-clonecomponents-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-clonecomponents-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-clonecomponents-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-clonecomponents-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-patching-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-patching-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ohinv-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ohinv-test.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ppc-public-pojo.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-ppc-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-agentpush-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-uifwkmobile-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-lm-public-model.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-lm-public-ui.jar \n" +
+ " /ade/dtsao_re/oracle/emcore//lib/em-sdkcore-lm-test.jar \n";
+}
--- a/jdk/test/javax/naming/spi/DirectoryManager/GetContDirCtx.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/javax/naming/spi/DirectoryManager/GetContDirCtx.java Thu Mar 29 21:22:07 2012 -0700
@@ -26,6 +26,7 @@
* @bug 4241676
* @summary getContinuationDirContext() should set CPE environment property.
* @build DummyObjectFactory DummyContext
+ * @run main/othervm GetContDirCtx
*/
import java.util.Hashtable;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JTable/7027139/bug7027139.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7027139
+ @summary getFirstIndex() does not return the first index that has changed
+ @author Pavel Porvatov
+*/
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+public class bug7027139 {
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ JTable orderTable = new JTable(new String[][]{
+ {"Item 1 1", "Item 1 2"},
+ {"Item 2 1", "Item 2 2"},
+ {"Item 3 1", "Item 3 2"},
+ {"Item 4 1", "Item 4 2"},
+ },
+ new String[]{"Col 1", "Col 2"});
+
+ ListSelectionModel selectionModel = orderTable.getSelectionModel();
+ selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ selectionModel.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent e) {
+ if (e.getValueIsAdjusting()) {
+ return;
+ }
+
+ if (e.getFirstIndex() < 0) {
+ throw new RuntimeException("Test bug7027139 failed");
+ }
+ }
+ });
+
+ orderTable.selectAll();
+ }
+ });
+
+ System.out.println("Test bug7027139 passed");
+ }
+}
--- a/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassLoadingTime.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/management/HotspotClassLoadingMBean/GetClassLoadingTime.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
* @summary Basic unit test of HotspotClassLoadingMBean.getClassLoadingTime()
* @author Steve Bohne
* @build ClassToLoad0
+ * @run main GetClassLoadingTime
*/
/*
@@ -71,10 +72,8 @@
}
long time2 = mbean.getClassLoadingTime();
- long count = mbean.getLoadedClassCount();
if (trace) {
- System.out.println("(new count is " + count + ")");
System.out.println("Class loading time2 (ms): " + time2);
}
@@ -93,8 +92,6 @@
// so we can avoid delegation and spend lots of time loading the
// same class over and over, to test the class loading timer.
class KlassLoader extends ClassLoader {
- static String klassDir="";
- static int index=0;
public KlassLoader() {
super(null);
@@ -102,14 +99,13 @@
protected synchronized Class findClass(String name)
throws ClassNotFoundException {
- String cname = klassDir
- + (klassDir == "" ? "" : "/")
- +name.replace('.', '/')
+ String cname =
+ name.replace('.', '/')
+".class";
FileInputStream in;
try {
- in=new FileInputStream(cname);
+ in = new FileInputStream(new File(System.getProperty("test.classes", "."), cname));
if (in == null) {
throw new ClassNotFoundException("getResourceAsStream("
+cname+")");
--- a/jdk/test/sun/misc/Cleaner/exitOnThrow.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/misc/Cleaner/exitOnThrow.sh Thu Mar 29 21:22:07 2012 -0700
@@ -29,6 +29,7 @@
# @summary Ensure that if a cleaner throws an exception then the VM exits
#
# @build ExitOnThrow
+# @run shell exitOnThrow.sh
# Command-line usage: sh exitOnThrow.sh /path/to/build
--- a/jdk/test/sun/nio/cs/OLD/TestIBMDB.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/nio/cs/OLD/TestIBMDB.java Thu Mar 29 21:22:07 2012 -0700
@@ -26,6 +26,7 @@
* @bug 6843578
* @summary Test IBM DB charsets
* @build IBM930_OLD IBM933_OLD IBM935_OLD IBM937_OLD IBM939_OLD IBM942_OLD IBM943_OLD IBM948_OLD IBM949_OLD IBM950_OLD IBM970_OLD IBM942C_OLD IBM943C_OLD IBM949C_OLD IBM1381_OLD IBM1383_OLD EUC_CN_OLD EUC_KR_OLD GBK_OLD Johab_OLD MS932_OLD MS936_OLD MS949_OLD MS950_OLD
+ * @run main TestIBMDB
*/
import java.nio.charset.*;
--- a/jdk/test/sun/nio/cs/OLD/TestX11CS.java Thu Mar 29 21:16:58 2012 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * 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 1234567
- * @summary Test updated X11 charsets
- * @build X11GB2312_OLD X11GBK_OLD X11KSC5601_OLD
- */
-
-import java.nio.charset.*;
-import java.nio.*;
-import java.util.*;
-
-public class TestX11CS {
-
- static char[] decode(byte[] bb, Charset cs)
- throws Exception {
- CharsetDecoder dec = cs.newDecoder();
- ByteBuffer bbf = ByteBuffer.wrap(bb);
- CharBuffer cbf = CharBuffer.allocate(bb.length);
- CoderResult cr = dec.decode(bbf, cbf, true);
- if (cr != CoderResult.UNDERFLOW) {
- System.out.println("DEC-----------------");
- int pos = bbf.position();
- System.out.printf(" cr=%s, bbf.pos=%d, bb[pos]=%x,%x,%x,%x%n",
- cr.toString(), pos,
- bb[pos++]&0xff, bb[pos++]&0xff,bb[pos++]&0xff, bb[pos++]&0xff);
- throw new RuntimeException("Decoding err: " + cs.name());
- }
- char[] cc = new char[cbf.position()];
- cbf.flip(); cbf.get(cc);
- return cc;
-
- }
-
- static byte[] encode(char[] cc, Charset cs)
- throws Exception {
- ByteBuffer bbf = ByteBuffer.allocate(cc.length * 4);
- CharBuffer cbf = CharBuffer.wrap(cc);
- CharsetEncoder enc = cs.newEncoder();
-
- CoderResult cr = enc.encode(cbf, bbf, true);
- if (cr != CoderResult.UNDERFLOW) {
- System.out.println("ENC-----------------");
- int pos = cbf.position();
- System.out.printf(" cr=%s, cbf.pos=%d, cc[pos]=%x%n",
- cr.toString(), pos, cc[pos]&0xffff);
- throw new RuntimeException("Encoding err: " + cs.name());
- }
- byte[] bb = new byte[bbf.position()];
- bbf.flip(); bbf.get(bb);
- return bb;
- }
-
- static char[] getChars(Charset newCS, Charset oldCS) {
- CharsetEncoder enc = oldCS.newEncoder();
- CharsetEncoder encNew = newCS.newEncoder();
- char[] cc = new char[0x10000];
- int pos = 0;
- int i = 0;
- while (i < 0x10000) {
- if (enc.canEncode((char)i) != encNew.canEncode((char)i)) {
- System.out.printf(" Err i=%x%n", i);
- //throw new RuntimeException("canEncode() err!");
- }
- if (enc.canEncode((char)i)) {
- cc[pos++] = (char)i;
- }
- i++;
- }
- return Arrays.copyOf(cc, pos);
- }
-
- static void compare(Charset newCS, Charset oldCS) throws Exception {
- System.out.printf(" Diff <%s> <%s>...%n", newCS.name(), oldCS.name());
- char[] cc = getChars(newCS, oldCS);
-
- byte[] bb1 = encode(cc, newCS);
- byte[] bb2 = encode(cc, oldCS);
-
- if (!Arrays.equals(bb1, bb2)) {
- System.out.printf(" encoding failed!%n");
- }
- char[] cc1 = decode(bb1, newCS);
- char[] cc2 = decode(bb1, oldCS);
- if (!Arrays.equals(cc1, cc2)) {
- for (int i = 0; i < cc1.length; i++) {
- if (cc1[i] != cc2[i]) {
- System.out.printf("i=%d, cc1=%x cc2=%x, bb=<%x%x>%n",
- i,
- cc1[i]&0xffff, cc2[i]&0xffff,
- bb1[i*2]&0xff, bb1[i*2+1]&0xff);
- }
-
- }
-
- System.out.printf(" decoding failed%n");
- }
- }
-
- public static void main(String[] args) throws Exception {
- compare(new sun.awt.motif.X11GBK(),
- new X11GBK_OLD());
-
- compare(new sun.awt.motif.X11GB2312(),
- new X11GB2312_OLD());
-
- compare(new sun.awt.motif.X11KSC5601(),
- new X11KSC5601_OLD());
-
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/Basic.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7152176
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file Basic.java
+ * @run main/othervm Basic
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// The basic krb5 test skeleton you can copy from
+public class Basic {
+
+ public static void main(String[] args) throws Exception {
+
+ new OneKDC(null).writeJAASConf();
+
+ Context c, s;
+ c = Context.fromJAAS("client");
+ s = Context.fromJAAS("server");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(c, s);
+
+ Context.transmit("i say high --", c, s);
+ Context.transmit(" you say low", s, c);
+
+ s.dispose();
+ c.dispose();
+ }
+}
--- a/jdk/test/sun/security/krb5/auto/Context.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/security/krb5/auto/Context.java Thu Mar 29 21:22:07 2012 -0700
@@ -96,6 +96,15 @@
}
/**
+ * No JAAS login at all, can be used to test JGSS without JAAS
+ */
+ public static Context fromThinAir() throws Exception {
+ Context out = new Context();
+ out.s = new Subject();
+ return out;
+ }
+
+ /**
* Logins with a JAAS login config entry name
*/
public static Context fromJAAS(final String name) throws Exception {
@@ -111,8 +120,10 @@
String user, char[] pass, boolean storeKey) throws Exception {
return fromUserPass(null, user, pass, storeKey);
}
+
/**
* Logins with a username and a password, using Krb5LoginModule directly
+ * @param s existing subject, test multiple princ & creds for single subj
* @param storeKey true if key should be saved, used on acceptor side
*/
public static Context fromUserPass(Subject s,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/GSS.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7152176
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file GSS.java
+ * @run main/othervm GSS
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// Testing JGSS without JAAS
+public class GSS {
+
+ public static void main(String[] args) throws Exception {
+
+ new OneKDC(null).writeJAASConf();
+
+ Context c, s;
+ c = Context.fromThinAir();
+ s = Context.fromThinAir();
+
+ // This is the only setting needed for JGSS without JAAS. The default
+ // JAAS config entries are already created by OneKDC.
+ System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(c, s);
+
+ Context.transmit("i say high --", c, s);
+ Context.transmit(" you say low", s, c);
+
+ s.dispose();
+ c.dispose();
+ }
+}
--- a/jdk/test/sun/security/krb5/auto/KDC.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/security/krb5/auto/KDC.java Thu Mar 29 21:22:07 2012 -0700
@@ -236,80 +236,82 @@
}
/**
- * Writes or appends KDC keys into a keytab. See doc for writeMultiKtab.
+ * Writes or appends keys into a keytab.
+ * <p>
+ * Attention: This is the most basic one of a series of methods below on
+ * keytab creation or modification. All these methods reference krb5.conf
+ * settings. If you need to modify krb5.conf or switch to another krb5.conf
+ * later, please call <code>Config.refresh()</code> again. For example:
+ * <pre>
+ * kdc.writeKtab("/etc/kdc/ktab", true); // Config is initialized,
+ * System.setProperty("java.security.krb5.conf", "/home/mykrb5.conf");
+ * Config.refresh();
+ * </pre>
+ * Inside this method there are 2 places krb5.conf is used:
+ * <ol>
+ * <li> (Fatal) Generating keys: EncryptionKey.acquireSecretKeys
+ * <li> (Has workaround) Creating PrincipalName
+ * </ol>
+ * @param tab the keytab file name
* @param append true if append, otherwise, overwrite.
+ * @param names the names to write into, write all if names is empty
*/
- private static void writeKtab0(String tab, boolean append, KDC... kdcs)
+ public void writeKtab(String tab, boolean append, String... names)
throws IOException, KrbException {
KeyTab ktab = append ? KeyTab.getInstance(tab) : KeyTab.create(tab);
- for (KDC kdc: kdcs) {
- for (String name : kdc.passwords.keySet()) {
- char[] pass = kdc.passwords.get(name);
- int kvno = 0;
- if (Character.isDigit(pass[pass.length-1])) {
- kvno = pass[pass.length-1] - '0';
- }
- ktab.addEntry(new PrincipalName(name,
- name.indexOf('/') < 0 ?
- PrincipalName.KRB_NT_UNKNOWN :
- PrincipalName.KRB_NT_SRV_HST),
- pass,
- kvno,
- true);
+ Iterable<String> entries =
+ (names.length != 0) ? Arrays.asList(names): passwords.keySet();
+ for (String name : entries) {
+ char[] pass = passwords.get(name);
+ int kvno = 0;
+ if (Character.isDigit(pass[pass.length-1])) {
+ kvno = pass[pass.length-1] - '0';
}
+ ktab.addEntry(new PrincipalName(name,
+ name.indexOf('/') < 0 ?
+ PrincipalName.KRB_NT_UNKNOWN :
+ PrincipalName.KRB_NT_SRV_HST),
+ pass,
+ kvno,
+ true);
}
ktab.save();
}
/**
* Writes all principals' keys from multiple KDCs into one keytab file.
- * Note that the keys for the krbtgt principals will not be written.
- * <p>
- * Attention: This method references krb5.conf settings. If you need to
- * setup krb5.conf later, please call <code>Config.refresh()</code> after
- * the new setting. For example:
- * <pre>
- * KDC.writeKtab("/etc/kdc/ktab", kdc); // Config is initialized,
- * System.setProperty("java.security.krb5.conf", "/home/mykrb5.conf");
- * Config.refresh();
- * </pre>
- *
- * Inside this method there are 2 places krb5.conf is used:
- * <ol>
- * <li> (Fatal) Generating keys: EncryptionKey.acquireSecretKeys
- * <li> (Has workaround) Creating PrincipalName
- * </ol>
- * @param tab The keytab filename to write to.
* @throws java.io.IOException for any file output error
* @throws sun.security.krb5.KrbException for any realm and/or principal
* name error.
*/
public static void writeMultiKtab(String tab, KDC... kdcs)
throws IOException, KrbException {
- writeKtab0(tab, false, kdcs);
+ KeyTab.create(tab).save(); // Empty the old keytab
+ appendMultiKtab(tab, kdcs);
}
/**
* Appends all principals' keys from multiple KDCs to one keytab file.
- * See writeMultiKtab for details.
*/
public static void appendMultiKtab(String tab, KDC... kdcs)
throws IOException, KrbException {
- writeKtab0(tab, true, kdcs);
+ for (KDC kdc: kdcs) {
+ kdc.writeKtab(tab, true);
+ }
}
/**
* Write a ktab for this KDC.
*/
public void writeKtab(String tab) throws IOException, KrbException {
- KDC.writeMultiKtab(tab, this);
+ writeKtab(tab, false);
}
/**
* Appends keys in this KDC to a ktab.
*/
public void appendKtab(String tab) throws IOException, KrbException {
- KDC.appendMultiKtab(tab, this);
+ writeKtab(tab, true);
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/TwoTab.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7152176
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file TwoTab.java
+ * @run main/othervm TwoTab
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.security.Security;
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+import sun.security.krb5.internal.ktab.KeyTab;
+
+// Two services using their own keytab.
+public class TwoTab {
+
+ public static void main(String[] args) throws Exception {
+
+ KDC k = new OneKDC(null);
+
+ // Write JAAS conf, two service using different keytabs
+ System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+ File f = new File(OneKDC.JAAS_CONF);
+ try (FileOutputStream fos = new FileOutputStream(f)) {
+ fos.write((
+ "server {\n" +
+ " com.sun.security.auth.module.Krb5LoginModule required\n" +
+ " principal=\"" + OneKDC.SERVER + "\"\n" +
+ " useKeyTab=true\n" +
+ " keyTab=server.keytab\n" +
+ " storeKey=true;\n};\n" +
+ "server2 {\n" +
+ " com.sun.security.auth.module.Krb5LoginModule required\n" +
+ " principal=\"" + OneKDC.BACKEND + "\"\n" +
+ " useKeyTab=true\n" +
+ " keyTab=backend.keytab\n" +
+ " storeKey=true;\n};\n"
+ ).getBytes());
+ }
+ f.deleteOnExit();
+
+ k.writeKtab("server.keytab", false, "server/host.rabbit.hole@RABBIT.HOLE");
+ k.writeKtab("backend.keytab", false, "backend/host.rabbit.hole@RABBIT.HOLE");
+
+ Context c, s, s2;
+ c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+ s = Context.fromJAAS("server");
+ s2 = Context.fromJAAS("server2");
+
+ c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+ s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(c, s);
+
+ Context.transmit("i say high --", c, s);
+ Context.transmit(" you say low", s, c);
+
+ s.dispose();
+ c.dispose();
+
+ c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+ c.startAsClient(OneKDC.BACKEND, GSSUtil.GSS_KRB5_MECH_OID);
+ s2.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+ Context.handshake(c, s2);
+
+ Context.transmit("i say high --", c, s2);
+ Context.transmit(" you say low", s2, c);
+
+ s2.dispose();
+ c.dispose();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/KeyAgreement/TestInterop.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7146728
+ * @summary Interop test for DH with secret that has a leading 0x00 byte
+ * @library ..
+ */
+import java.math.BigInteger;
+import java.util.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestInterop extends PKCS11Test {
+
+ private final static BigInteger p = new BigInteger
+ ("171718397966129586011229151993178480901904202533705695869569760169920539"
+ + "80807543778874708672297590042574075430109846864794139516459381007417046"
+ + "27996080624930219892858374168155487210358743785481212360509485282294161"
+ + "39585571568998066586304075565145536350296006867635076744949977849997684"
+ + "222020336013226588207303");
+
+ private final static BigInteger g = new BigInteger("2");
+
+ private final static BigInteger ya = new BigInteger
+ ("687709211571508809414670982463565909269384277848448625781941269577397703"
+ + "73675199968849153119146758339814638228795348558483510369322822476757204"
+ + "22158455966026517829008713407587339322132253724742557954802911059639161"
+ + "24827916158465757962384625410294483756242900146397201260757102085985457"
+ + "09397033481077351036224");
+
+ private final static BigInteger xa = new BigInteger
+ ("104917367119952955556289227181599819745346393858545449202252025137706135"
+ + "98100778613457655440586438263591136003106529323555991109623536177695714"
+ + "66884181531401472902830508361532232717792847436112280721439936797741371"
+ + "245140912614191507");
+
+ private final static BigInteger yb = new BigInteger
+ ("163887874871842952463100699681506173424091615364591742415764095471629919"
+ + "08421025296419917755446931473037086355546823601999684501737493240373415"
+ + "65608293667837249198973539289354492348897732633852665609611113031379864"
+ + "58514616034107537409230452318065341748503347627733368519091332060477528"
+ + "173423377887175351037810");
+
+ private final static BigInteger xb = new BigInteger
+ ("127757517533485947079959908591028646859165238853082197617179368337276371"
+ + "51601819447716934542027725311863797141734616730248519214531856941516613"
+ + "30313414180008978013330410484011186019824874948204261839391153650949864"
+ + "429505597086564709");
+
+ public void main(Provider prov) throws Exception {
+ if (prov.getService("KeyAgreement", "DH") == null) {
+ System.out.println("DH not supported, skipping");
+ return;
+ }
+ try {
+ System.out.println("testing generateSecret()");
+
+ DHPublicKeySpec publicSpec;
+ DHPrivateKeySpec privateSpec;
+ KeyFactory kf = KeyFactory.getInstance("DH");
+ KeyAgreement ka = KeyAgreement.getInstance("DH", prov);
+ KeyAgreement kbSunJCE = KeyAgreement.getInstance("DH", "SunJCE");
+ DHPrivateKeySpec privSpecA = new DHPrivateKeySpec(xa, p, g);
+ DHPublicKeySpec pubSpecA = new DHPublicKeySpec(ya, p, g);
+ PrivateKey privA = kf.generatePrivate(privSpecA);
+ PublicKey pubA = kf.generatePublic(pubSpecA);
+
+ DHPrivateKeySpec privSpecB = new DHPrivateKeySpec(xb, p, g);
+ DHPublicKeySpec pubSpecB = new DHPublicKeySpec(yb, p, g);
+ PrivateKey privB = kf.generatePrivate(privSpecB);
+ PublicKey pubB = kf.generatePublic(pubSpecB);
+
+ ka.init(privA);
+ ka.doPhase(pubB, true);
+ byte[] n1 = ka.generateSecret();
+
+ kbSunJCE.init(privB);
+ kbSunJCE.doPhase(pubA, true);
+ byte[] n2 = kbSunJCE.generateSecret();
+
+ if (Arrays.equals(n1, n2) == false) {
+ throw new Exception("values mismatch!");
+ } else {
+ System.out.println("values: same");
+ }
+
+ System.out.println("testing generateSecret(byte[], int)");
+ byte[] n3 = new byte[n1.length];
+ ka.init(privB);
+ ka.doPhase(pubA, true);
+ int n3Len = ka.generateSecret(n3, 0);
+ if (n3Len != n3.length) {
+ throw new Exception("PKCS11 Length mismatch!");
+ } else System.out.println("PKCS11 Length: ok");
+ byte[] n4 = new byte[n2.length];
+ kbSunJCE.init(privA);
+ kbSunJCE.doPhase(pubB, true);
+ int n4Len = kbSunJCE.generateSecret(n4, 0);
+ if (n4Len != n4.length) {
+ throw new Exception("SunJCE Length mismatch!");
+ } else System.out.println("SunJCE Length: ok");
+
+ if (Arrays.equals(n3, n4) == false) {
+ throw new Exception("values mismatch! ");
+ } else {
+ System.out.println("values: same");
+ }
+ } catch (Exception ex) {
+ System.out.println("Unexpected ex: " + ex);
+ ex.printStackTrace();
+ throw ex;
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new TestInterop());
+ }
+}
--- a/jdk/test/sun/security/pkcs11/KeyAgreement/TestShort.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/security/pkcs11/KeyAgreement/TestShort.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 4942494
+ * @bug 4942494 7146728
* @summary KAT test for DH (normal and with secret that has leading a 0x00 byte)
* @author Andreas Sterbenz
* @library ..
@@ -66,7 +66,7 @@
("433011588852527167500079509018272713204454720683");
private final static byte[] s2 = parse
- ("19:c7:f1:bb:2e:3d:93:fa:02:d2:e9:9f:75:32:b9:e6:7a:a0:4a:10:45:81:d4:2b:"
+ ("00:19:c7:f1:bb:2e:3d:93:fa:02:d2:e9:9f:75:32:b9:e6:7a:a0:4a:10:45:81:d4:2b:"
+ "e2:77:4c:70:41:39:7c:19:fa:65:64:47:49:8a:ad:0a:fa:9d:e9:62:68:97:c5:52"
+ ":b1:37:03:d9:cd:aa:e1:bd:7e:71:0c:fc:15:a1:95");
@@ -88,31 +88,36 @@
System.out.println("DH not supported, skipping");
return;
}
- DHPublicKeySpec publicSpec;
- DHPrivateKeySpec privateSpec;
- KeyFactory kf = KeyFactory.getInstance("DH", provider);
- KeyAgreement ka = KeyAgreement.getInstance("DH", provider);
-// KeyAgreement ka = KeyAgreement.getInstance("DH");
+ try {
+ DHPublicKeySpec publicSpec;
+ DHPrivateKeySpec privateSpec;
+ KeyFactory kf = KeyFactory.getInstance("DH", provider);
+ KeyAgreement ka = KeyAgreement.getInstance("DH", provider);
- PrivateKey pr1 = kf.generatePrivate(new DHPrivateKeySpec(x1, p, g));
- PublicKey pu2 = kf.generatePublic(new DHPublicKeySpec(y2, p, g));
- PublicKey pu3 = kf.generatePublic(new DHPublicKeySpec(y3, p, g));
+ PrivateKey pr1 = kf.generatePrivate(new DHPrivateKeySpec(x1, p, g));
+ PublicKey pu2 = kf.generatePublic(new DHPublicKeySpec(y2, p, g));
+ PublicKey pu3 = kf.generatePublic(new DHPublicKeySpec(y3, p, g));
- ka.init(pr1);
- ka.doPhase(pu2, true);
- byte[] n2 = ka.generateSecret();
- if (Arrays.equals(s2, n2) == false) {
- throw new Exception("mismatch 2");
- }
- System.out.println("short ok");
+ ka.init(pr1);
+ ka.doPhase(pu2, true);
+ byte[] n2 = ka.generateSecret();
+ if (Arrays.equals(s2, n2) == false) {
+ throw new Exception("mismatch 2");
+ }
+ System.out.println("short ok");
- ka.init(pr1);
- ka.doPhase(pu3, true);
- byte[] n3 = ka.generateSecret();
- if (Arrays.equals(s3, n3) == false) {
- throw new Exception("mismatch 3");
+ ka.init(pr1);
+ ka.doPhase(pu3, true);
+ byte[] n3 = ka.generateSecret();
+ if (Arrays.equals(s3, n3) == false) {
+ throw new Exception("mismatch 3");
+ }
+ System.out.println("normal ok");
+ } catch (Exception ex) {
+ System.out.println("Unexpected Exception: " + ex);
+ ex.printStackTrace();
+ throw ex;
}
- System.out.println("normal ok");
/*
KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", provider);
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ProviderTest.java Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/SSLSecurity/ProviderTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -27,6 +27,7 @@
* @compile JavaxSSLContextImpl.java ComSSLContextImpl.java
* JavaxTrustManagerFactoryImpl.java ComTrustManagerFactoryImpl.java
* JavaxKeyManagerFactoryImpl.java ComKeyManagerFactoryImpl.java
+ * @run main ProviderTest
* @summary brokenness in the com.sun.net.ssl.SSLSecurity wrappers
*/
--- a/jdk/test/sun/tools/jcmd/jcmd_Output1.awk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jcmd/jcmd_Output1.awk Thu Mar 29 21:22:07 2012 -0700
@@ -20,6 +20,11 @@
current=1;
}
+# or match an empty class name
+/^[0-9]+ $/ {
+ current=1;
+ }
+
{ totallines++; matched+=current; current=0; print $0 }
END {
--- a/jdk/test/sun/tools/jps/jps-l_Output1.awk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jps/jps-l_Output1.awk Thu Mar 29 21:22:07 2012 -0700
@@ -20,6 +20,11 @@
matched++;
}
+# or match an empty class name
+/^[0-9]+ $/ {
+ matched++;
+ }
+
{ totallines++; print $0 }
END {
--- a/jdk/test/sun/tools/jps/jps_Output1.awk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jps/jps_Output1.awk Thu Mar 29 21:22:07 2012 -0700
@@ -20,6 +20,11 @@
matched++;
}
+# or match an empty class name
+/^[0-9]+ $/ {
+ matched++;
+ }
+
{ totallines++; print $0 }
END {
--- a/jdk/test/sun/tools/jstat/jstatClassOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatClassOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -class 0 2>&1 | awk -f ${TESTSRC}/classOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -class 0 2>&1 | awk -f ${TESTSRC}/classOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatClassloadOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatClassloadOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -classload -J-Djstat.showUnsupported=true 0 2>&1 | awk -f ${TESTSRC}/classloadOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -classload -J-Djstat.showUnsupported=true 0 2>&1 | awk -f ${TESTSRC}/classloadOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatCompilerOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatCompilerOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -compiler 0 2>&1 | awk -f ${TESTSRC}/compilerOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -compiler 0 2>&1 | awk -f ${TESTSRC}/compilerOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatFileURITest1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatFileURITest1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -40,12 +40,12 @@
# characters into forward slash characters in an effort to convert
# TESTSRC into a canonical form useable as URI path.
cp ${TESTSRC}/hsperfdata_3433 .
- ${JSTAT} -J-XX:+UsePerfData -gcutil file:/`pwd`/hsperfdata_3433 2>&1 | awk -f ${TESTSRC}/fileURITest1.awk
+ ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil file:/`pwd`/hsperfdata_3433 2>&1 | awk -f ${TESTSRC}/fileURITest1.awk
RC=$?
rm -f hsperfdata_3433 2>&1 > /dev/null
;;
*)
- ${JSTAT} -J-XX:+UsePerfData -gcutil file:${TESTSRC}/hsperfdata_3433 2>&1 | awk -f ${TESTSRC}/fileURITest1.awk
+ ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil file:${TESTSRC}/hsperfdata_3433 2>&1 | awk -f ${TESTSRC}/fileURITest1.awk
RC=$?
;;
esac
--- a/jdk/test/sun/tools/jstat/jstatGcCapacityOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcCapacityOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcCauseOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcCauseOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -37,4 +37,4 @@
# class machine, ergonomics will automatically use UseParallelGC.
# The UseParallelGC collector does not currently update the gc cause counters.
-${JSTAT} -J-XX:+UsePerfData -J-XX:+UseSerialGC -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -J-XX:+UseSerialGC -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcNewCapacityOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcNewCapacityOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcNewOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcNewOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcOldCapacityOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcOldCapacityOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcOldOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcOldOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatGcPermCapacityOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatGcPermCapacityOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcpermcapacity 0 2>&1 | awk -f ${TESTSRC}/gcPermCapacityOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcpermcapacity 0 2>&1 | awk -f ${TESTSRC}/gcPermCapacityOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatLineCounts1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatLineCounts1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk
--- a/jdk/test/sun/tools/jstat/jstatLineCounts2.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatLineCounts2.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk
--- a/jdk/test/sun/tools/jstat/jstatLineCounts3.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatLineCounts3.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk
--- a/jdk/test/sun/tools/jstat/jstatLineCounts4.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatLineCounts4.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk
--- a/jdk/test/sun/tools/jstat/jstatOptions1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatOptions1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,8 +33,8 @@
JSTAT="${TESTJAVA}/bin/jstat"
rm -f jstat.out1 jstat.out2 2>/dev/null
-${JSTAT} -J-XX:+UsePerfData -options > jstat.out1 2>&1
-${JSTAT} -J-XX:+UsePerfData -options -J-Djstat.showUnsupported=true > jstat.out2 2>&1
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -options > jstat.out1 2>&1
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -options -J-Djstat.showUnsupported=true > jstat.out2 2>&1
diff -w jstat.out1 ${TESTSRC}/options1.out
diff -w jstat.out2 ${TESTSRC}/options2.out
--- a/jdk/test/sun/tools/jstat/jstatPrintCompilationOutput1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatPrintCompilationOutput1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -35,4 +35,4 @@
# run with -Xcomp as jstat may complete too quickly to assure
# that compilation occurs.
-${JSTAT} -J-XX:+UsePerfData -J-Xcomp -printcompilation 0 2>&1 | awk -f ${TESTSRC}/printCompilationOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -J-Xcomp -printcompilation 0 2>&1 | awk -f ${TESTSRC}/printCompilationOutput1.awk
--- a/jdk/test/sun/tools/jstat/jstatSnap1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatSnap1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -snap 0 2>&1 | awk -f ${TESTSRC}/snap1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -snap 0 2>&1 | awk -f ${TESTSRC}/snap1.awk
--- a/jdk/test/sun/tools/jstat/jstatSnap2.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatSnap2.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -J-Djstat.showUnsupported=true -snap 0 2>&1 | awk -f ${TESTSRC}/snap2.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -J-Djstat.showUnsupported=true -snap 0 2>&1 | awk -f ${TESTSRC}/snap2.awk
--- a/jdk/test/sun/tools/jstat/jstatTimeStamp1.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstat/jstatTimeStamp1.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,4 +33,4 @@
JSTAT="${TESTJAVA}/bin/jstat"
-${JSTAT} -J-XX:+UsePerfData -gcutil -t 0 2>&1 | awk -f ${TESTSRC}/timeStamp1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil -t 0 2>&1 | awk -f ${TESTSRC}/timeStamp1.awk
--- a/jdk/test/sun/tools/jstatd/jpsOutput1.awk Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstatd/jpsOutput1.awk Thu Mar 29 21:22:07 2012 -0700
@@ -11,6 +11,10 @@
matched++;
}
+/^[0-9]+ $/ {
+ matched++;
+ }
+
{ totallines++; print $0 }
END {
--- a/jdk/test/sun/tools/jstatd/jstatdDefaults.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstatd/jstatdDefaults.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@
exit 1
fi
-${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_PID}@${HOSTNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
RC=$?
if [ ${RC} -ne 0 ]
--- a/jdk/test/sun/tools/jstatd/jstatdExternalRegistry.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstatd/jstatdExternalRegistry.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
exit 1
fi
-${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
RC=$?
if [ ${RC} -ne 0 ]
--- a/jdk/test/sun/tools/jstatd/jstatdPort.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstatd/jstatdPort.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@
exit 1
fi
-${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_PID}@${HOSTNAME}:${PORT} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
RC=$?
if [ ${RC} -ne 0 ]
--- a/jdk/test/sun/tools/jstatd/jstatdServerName.sh Thu Mar 29 21:16:58 2012 -0700
+++ b/jdk/test/sun/tools/jstatd/jstatdServerName.sh Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -86,8 +86,8 @@
exit 1
fi
-echo "running: ${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5"
-${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
+echo "running: ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5"
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_1} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
RC=$?
if [ ${RC} -ne 0 ]
@@ -95,8 +95,8 @@
echo "jstat output differs from expected output"
fi
-echo "running: ${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5"
-${JSTAT} -J-XX:+UsePerfData -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
+echo "running: ${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5"
+${JSTAT} -J-XX:+UsePerfData -J-Duser.language=en -gcutil ${JSTATD_1_PID}@${HOSTNAME}:${PORT_2}/${SERVERNAME} 250 5 2>&1 | awk -f ${TESTSRC}/jstatGcutilOutput1.awk
RC=$?
if [ ${RC} -ne 0 ]
--- a/langtools/.hgtags Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/.hgtags Thu Mar 29 21:22:07 2012 -0700
@@ -152,3 +152,5 @@
5bed623b0c773aa8a8d5f8d4004ce9d3974143cc jdk8-b28
e974e82abe51ef66dc32bb6ab5d0733753d3c7d7 jdk8-b29
08a3425f39f829502ca0ddbfb2d051c31710cb19 jdk8-b30
+b28cfbe7e8b196da954bed9a22bfd790e55333aa jdk8-b31
+be069d72dde2bfe6f996c46325a320961ca854c2 jdk8-b32
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -126,6 +126,7 @@
public final Type cloneableType;
public final Type serializableType;
public final Type methodHandleType;
+ public final Type nativeHeaderType;
public final Type polymorphicSignatureType;
public final Type throwableType;
public final Type errorType;
@@ -477,6 +478,7 @@
List.of(exceptionType), methodClass),
autoCloseableType.tsym);
trustMeType = enterClass("java.lang.SafeVarargs");
+ nativeHeaderType = enterClass("javax.tools.annotation.GenerateNativeHeader");
synthesizeEmptyInterfaceIfMissing(autoCloseableType);
synthesizeEmptyInterfaceIfMissing(cloneableType);
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -648,7 +648,8 @@
new SimpleLocationHandler(StandardLocation.SOURCE_PATH, Option.SOURCEPATH),
new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, Option.PROCESSORPATH),
new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), Option.D),
- new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S)
+ new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), Option.S),
+ new OutputLocationHandler((StandardLocation.NATIVE_HEADER_OUTPUT), Option.H)
};
for (LocationHandler h: handlers) {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,11 +69,11 @@
*/
private boolean verbose;
- /** Switch: scrable private names.
+ /** Switch: scramble private names.
*/
private boolean scramble;
- /** Switch: scrable private names.
+ /** Switch: scramble private names.
*/
private boolean scrambleAll;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/JNIWriter.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,856 @@
+/*
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.StringTokenizer;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.Name;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.NoType;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.type.TypeVisitor;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleTypeVisitor8;
+import javax.lang.model.util.Types;
+
+import javax.tools.FileObject;
+import javax.tools.JavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.tools.javac.code.Attribute;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+
+import static com.sun.tools.javac.main.Option.*;
+
+/** This class provides operations to write native header files for classes.
+ *
+ * <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 JNIWriter {
+ protected static final Context.Key<JNIWriter> jniWriterKey =
+ new Context.Key<JNIWriter>();
+
+ /** Access to files. */
+ private final JavaFileManager fileManager;
+
+ JavacElements elements;
+ JavacTypes types;
+
+ /** The log to use for verbose output.
+ */
+ private final Log log;
+
+ /** Switch: verbose output.
+ */
+ private boolean verbose;
+
+ /** Switch: check all nested classes of top level class
+ */
+ private boolean checkAll;
+
+ private Mangle mangler;
+
+ private Context context;
+
+ private Symtab syms;
+
+ private String lineSep;
+
+ private final boolean isWindows =
+ System.getProperty("os.name").startsWith("Windows");
+
+ /** Get the ClassWriter instance for this context. */
+ public static JNIWriter instance(Context context) {
+ JNIWriter instance = context.get(jniWriterKey);
+ if (instance == null)
+ instance = new JNIWriter(context);
+ return instance;
+ }
+
+ /** Construct a class writer, given an options table.
+ */
+ private JNIWriter(Context context) {
+ context.put(jniWriterKey, this);
+ fileManager = context.get(JavaFileManager.class);
+ log = Log.instance(context);
+
+ Options options = Options.instance(context);
+ verbose = options.isSet(VERBOSE);
+ checkAll = options.isSet("javah:full");
+
+ this.context = context; // for lazyInit()
+ syms = Symtab.instance(context);
+
+ lineSep = System.getProperty("line.separator");
+ }
+
+ private void lazyInit() {
+ if (mangler == null) {
+ elements = JavacElements.instance(context);
+ types = JavacTypes.instance(context);
+ mangler = new Mangle(elements, types);
+ }
+ }
+
+ public boolean needsHeader(ClassSymbol c) {
+ if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+ return false;
+
+ if (checkAll)
+ return needsHeader(c.outermostClass(), true);
+ else
+ return needsHeader(c, false);
+ }
+
+ private boolean needsHeader(ClassSymbol c, boolean checkNestedClasses) {
+ if (c.isLocal() || (c.flags() & Flags.SYNTHETIC) != 0)
+ return false;
+
+ for (Attribute.Compound a: c.attributes_field) {
+ if (a.type.tsym == syms.nativeHeaderType.tsym)
+ return true;
+ }
+ for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
+ if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
+ return true;
+ }
+ if (checkNestedClasses) {
+ for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
+ if ((i.sym.kind == Kinds.TYP) && needsHeader(((ClassSymbol) i.sym), true))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Emit a class file for a given class.
+ * @param c The class from which a class file is generated.
+ */
+ public FileObject write(ClassSymbol c)
+ throws IOException
+ {
+ String className = c.flatName().toString();
+ FileObject outFile
+ = fileManager.getFileForOutput(StandardLocation.NATIVE_HEADER_OUTPUT,
+ "", className.replaceAll("[.$]", "_") + ".h", null);
+ Writer out = outFile.openWriter();
+ try {
+ write(out, c);
+ if (verbose)
+ log.printVerbose("wrote.file", outFile);
+ out.close();
+ out = null;
+ } finally {
+ if (out != null) {
+ // if we are propogating an exception, delete the file
+ out.close();
+ outFile.delete();
+ outFile = null;
+ }
+ }
+ return outFile; // may be null if write failed
+ }
+
+ public void write(Writer out, ClassSymbol sym)
+ throws IOException {
+ lazyInit();
+ try {
+ String cname = mangler.mangle(sym.fullname, Mangle.Type.CLASS);
+ println(out, fileTop());
+ println(out, includes());
+ println(out, guardBegin(cname));
+ println(out, cppGuardBegin());
+
+ writeStatics(out, sym);
+ writeMethods(out, sym, cname);
+
+ println(out, cppGuardEnd());
+ println(out, guardEnd(cname));
+ } catch (TypeSignature.SignatureException e) {
+ throw new IOException(e);
+ }
+ }
+
+ protected void writeStatics(Writer out, ClassSymbol sym) throws IOException {
+ List<VariableElement> classfields = getAllFields(sym);
+
+ for (VariableElement v: classfields) {
+ if (!v.getModifiers().contains(Modifier.STATIC))
+ continue;
+ String s = null;
+ s = defineForStatic(sym, v);
+ if (s != null) {
+ println(out, s);
+ }
+ }
+ }
+
+ /**
+ * Including super class fields.
+ */
+ List<VariableElement> getAllFields(TypeElement subclazz) {
+ List<VariableElement> fields = new ArrayList<VariableElement>();
+ TypeElement cd = null;
+ Stack<TypeElement> s = new Stack<TypeElement>();
+
+ cd = subclazz;
+ while (true) {
+ s.push(cd);
+ TypeElement c = (TypeElement) (types.asElement(cd.getSuperclass()));
+ if (c == null)
+ break;
+ cd = c;
+ }
+
+ while (!s.empty()) {
+ cd = s.pop();
+ fields.addAll(ElementFilter.fieldsIn(cd.getEnclosedElements()));
+ }
+
+ return fields;
+ }
+
+ protected String defineForStatic(TypeElement c, VariableElement f) {
+ CharSequence cnamedoc = c.getQualifiedName();
+ CharSequence fnamedoc = f.getSimpleName();
+
+ String cname = mangler.mangle(cnamedoc, Mangle.Type.CLASS);
+ String fname = mangler.mangle(fnamedoc, Mangle.Type.FIELDSTUB);
+
+ Assert.check(f.getModifiers().contains(Modifier.STATIC));
+
+ if (f.getModifiers().contains(Modifier.FINAL)) {
+ Object value = null;
+
+ value = f.getConstantValue();
+
+ if (value != null) { /* so it is a ConstantExpression */
+ String constString = null;
+ if ((value instanceof Integer)
+ || (value instanceof Byte)
+ || (value instanceof Short)) {
+ /* covers byte, short, int */
+ constString = value.toString() + "L";
+ } else if (value instanceof Boolean) {
+ constString = ((Boolean) value) ? "1L" : "0L";
+ } else if (value instanceof Character) {
+ Character ch = (Character) value;
+ constString = String.valueOf(((int) ch) & 0xffff) + "L";
+ } else if (value instanceof Long) {
+ // Visual C++ supports the i64 suffix, not LL.
+ if (isWindows)
+ constString = value.toString() + "i64";
+ else
+ constString = value.toString() + "LL";
+ } else if (value instanceof Float) {
+ /* bug for bug */
+ float fv = ((Float)value).floatValue();
+ if (Float.isInfinite(fv))
+ constString = ((fv < 0) ? "-" : "") + "Inff";
+ else
+ constString = value.toString() + "f";
+ } else if (value instanceof Double) {
+ /* bug for bug */
+ double d = ((Double)value).doubleValue();
+ if (Double.isInfinite(d))
+ constString = ((d < 0) ? "-" : "") + "InfD";
+ else
+ constString = value.toString();
+ }
+
+ if (constString != null) {
+ StringBuilder s = new StringBuilder("#undef ");
+ s.append(cname); s.append("_"); s.append(fname); s.append(lineSep);
+ s.append("#define "); s.append(cname); s.append("_");
+ s.append(fname); s.append(" "); s.append(constString);
+ return s.toString();
+ }
+
+ }
+ }
+
+ return null;
+ }
+
+
+ protected void writeMethods(Writer out, ClassSymbol sym, String cname)
+ throws IOException, TypeSignature.SignatureException {
+ List<ExecutableElement> classmethods = ElementFilter.methodsIn(sym.getEnclosedElements());
+ for (ExecutableElement md: classmethods) {
+ if(md.getModifiers().contains(Modifier.NATIVE)){
+ TypeMirror mtr = types.erasure(md.getReturnType());
+ String sig = signature(md);
+ TypeSignature newtypesig = new TypeSignature(elements);
+ CharSequence methodName = md.getSimpleName();
+ boolean longName = false;
+ for (ExecutableElement md2: classmethods) {
+ if ((md2 != md)
+ && (methodName.equals(md2.getSimpleName()))
+ && (md2.getModifiers().contains(Modifier.NATIVE)))
+ longName = true;
+
+ }
+ println(out, "/*");
+ println(out, " * Class: " + cname);
+ println(out, " * Method: " +
+ mangler.mangle(methodName, Mangle.Type.FIELDSTUB));
+ println(out, " * Signature: " + newtypesig.getTypeSignature(sig, mtr));
+ println(out, " */");
+ println(out, "JNIEXPORT " + jniType(mtr) +
+ " JNICALL " +
+ mangler.mangleMethod(md, sym,
+ (longName) ?
+ Mangle.Type.METHOD_JNI_LONG :
+ Mangle.Type.METHOD_JNI_SHORT));
+ print(out, " (JNIEnv *, ");
+ List<? extends VariableElement> paramargs = md.getParameters();
+ List<TypeMirror> args = new ArrayList<TypeMirror>();
+ for (VariableElement p: paramargs) {
+ args.add(types.erasure(p.asType()));
+ }
+ if (md.getModifiers().contains(Modifier.STATIC))
+ print(out, "jclass");
+ else
+ print(out, "jobject");
+
+ for (TypeMirror arg: args) {
+ print(out, ", ");
+ print(out, jniType(arg));
+ }
+ println(out, ");"
+ + lineSep);
+ }
+ }
+ }
+
+ // c.f. MethodDoc.signature
+ String signature(ExecutableElement e) {
+ StringBuilder sb = new StringBuilder("(");
+ String sep = "";
+ for (VariableElement p: e.getParameters()) {
+ sb.append(sep);
+ sb.append(types.erasure(p.asType()).toString());
+ sep = ",";
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ protected final String jniType(TypeMirror t) {
+ TypeElement throwable = elements.getTypeElement("java.lang.Throwable");
+ TypeElement jClass = elements.getTypeElement("java.lang.Class");
+ TypeElement jString = elements.getTypeElement("java.lang.String");
+ Element tclassDoc = types.asElement(t);
+
+
+ switch (t.getKind()) {
+ case ARRAY: {
+ TypeMirror ct = ((ArrayType) t).getComponentType();
+ switch (ct.getKind()) {
+ case BOOLEAN: return "jbooleanArray";
+ case BYTE: return "jbyteArray";
+ case CHAR: return "jcharArray";
+ case SHORT: return "jshortArray";
+ case INT: return "jintArray";
+ case LONG: return "jlongArray";
+ case FLOAT: return "jfloatArray";
+ case DOUBLE: return "jdoubleArray";
+ case ARRAY:
+ case DECLARED: return "jobjectArray";
+ default: throw new Error(ct.toString());
+ }
+ }
+
+ case VOID: return "void";
+ case BOOLEAN: return "jboolean";
+ case BYTE: return "jbyte";
+ case CHAR: return "jchar";
+ case SHORT: return "jshort";
+ case INT: return "jint";
+ case LONG: return "jlong";
+ case FLOAT: return "jfloat";
+ case DOUBLE: return "jdouble";
+
+ case DECLARED: {
+ if (tclassDoc.equals(jString))
+ return "jstring";
+ else if (types.isAssignable(t, throwable.asType()))
+ return "jthrowable";
+ else if (types.isAssignable(t, jClass.asType()))
+ return "jclass";
+ else
+ return "jobject";
+ }
+ }
+
+ Assert.check(false, "jni unknown type");
+ return null; /* dead code. */
+ }
+
+ protected String fileTop() {
+ return "/* DO NOT EDIT THIS FILE - it is machine generated */";
+ }
+
+ protected String includes() {
+ return "#include <jni.h>";
+ }
+
+ /*
+ * Deal with the C pre-processor.
+ */
+ protected String cppGuardBegin() {
+ return "#ifdef __cplusplus" + lineSep
+ + "extern \"C\" {" + lineSep
+ + "#endif";
+ }
+
+ protected String cppGuardEnd() {
+ return "#ifdef __cplusplus" + lineSep
+ + "}" + lineSep
+ + "#endif";
+ }
+
+ protected String guardBegin(String cname) {
+ return "/* Header for class " + cname + " */" + lineSep
+ + lineSep
+ + "#ifndef _Included_" + cname + lineSep
+ + "#define _Included_" + cname;
+ }
+
+ protected String guardEnd(String cname) {
+ return "#endif";
+ }
+
+ protected void print(Writer out, String text) throws IOException {
+ out.write(text);
+ }
+
+ protected void println(Writer out, String text) throws IOException {
+ out.write(text);
+ out.write(lineSep);
+ }
+
+
+ private static class Mangle {
+
+ public static class Type {
+ public static final int CLASS = 1;
+ public static final int FIELDSTUB = 2;
+ public static final int FIELD = 3;
+ public static final int JNI = 4;
+ public static final int SIGNATURE = 5;
+ public static final int METHOD_JDK_1 = 6;
+ public static final int METHOD_JNI_SHORT = 7;
+ public static final int METHOD_JNI_LONG = 8;
+ };
+
+ private Elements elems;
+ private Types types;
+
+ Mangle(Elements elems, Types types) {
+ this.elems = elems;
+ this.types = types;
+ }
+
+ public final String mangle(CharSequence name, int mtype) {
+ StringBuilder result = new StringBuilder(100);
+ int length = name.length();
+
+ for (int i = 0; i < length; i++) {
+ char ch = name.charAt(i);
+ if (isalnum(ch)) {
+ result.append(ch);
+ } else if ((ch == '.') &&
+ mtype == Mangle.Type.CLASS) {
+ result.append('_');
+ } else if (( ch == '$') &&
+ mtype == Mangle.Type.CLASS) {
+ result.append('_');
+ result.append('_');
+ } else if (ch == '_' && mtype == Mangle.Type.FIELDSTUB) {
+ result.append('_');
+ } else if (ch == '_' && mtype == Mangle.Type.CLASS) {
+ result.append('_');
+ } else if (mtype == Mangle.Type.JNI) {
+ String esc = null;
+ if (ch == '_')
+ esc = "_1";
+ else if (ch == '.')
+ esc = "_";
+ else if (ch == ';')
+ esc = "_2";
+ else if (ch == '[')
+ esc = "_3";
+ if (esc != null) {
+ result.append(esc);
+ } else {
+ result.append(mangleChar(ch));
+ }
+ } else if (mtype == Mangle.Type.SIGNATURE) {
+ if (isprint(ch)) {
+ result.append(ch);
+ } else {
+ result.append(mangleChar(ch));
+ }
+ } else {
+ result.append(mangleChar(ch));
+ }
+ }
+
+ return result.toString();
+ }
+
+ public String mangleMethod(ExecutableElement method, TypeElement clazz,
+ int mtype) throws TypeSignature.SignatureException {
+ StringBuilder result = new StringBuilder(100);
+ result.append("Java_");
+
+ if (mtype == Mangle.Type.METHOD_JDK_1) {
+ result.append(mangle(clazz.getQualifiedName(), Mangle.Type.CLASS));
+ result.append('_');
+ result.append(mangle(method.getSimpleName(),
+ Mangle.Type.FIELD));
+ result.append("_stub");
+ return result.toString();
+ }
+
+ /* JNI */
+ result.append(mangle(getInnerQualifiedName(clazz), Mangle.Type.JNI));
+ result.append('_');
+ result.append(mangle(method.getSimpleName(),
+ Mangle.Type.JNI));
+ if (mtype == Mangle.Type.METHOD_JNI_LONG) {
+ result.append("__");
+ String typesig = signature(method);
+ TypeSignature newTypeSig = new TypeSignature(elems);
+ String sig = newTypeSig.getTypeSignature(typesig, method.getReturnType());
+ sig = sig.substring(1);
+ sig = sig.substring(0, sig.lastIndexOf(')'));
+ sig = sig.replace('/', '.');
+ result.append(mangle(sig, Mangle.Type.JNI));
+ }
+
+ return result.toString();
+ }
+ //where
+ private String getInnerQualifiedName(TypeElement clazz) {
+ return elems.getBinaryName(clazz).toString();
+ }
+
+ public final String mangleChar(char ch) {
+ String s = Integer.toHexString(ch);
+ int nzeros = 5 - s.length();
+ char[] result = new char[6];
+ result[0] = '_';
+ for (int i = 1; i <= nzeros; i++)
+ result[i] = '0';
+ for (int i = nzeros+1, j = 0; i < 6; i++, j++)
+ result[i] = s.charAt(j);
+ return new String(result);
+ }
+
+ // Warning: duplicated in Gen
+ private String signature(ExecutableElement e) {
+ StringBuilder sb = new StringBuilder();
+ String sep = "(";
+ for (VariableElement p: e.getParameters()) {
+ sb.append(sep);
+ sb.append(types.erasure(p.asType()).toString());
+ sep = ",";
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ /* Warning: Intentional ASCII operation. */
+ private static boolean isalnum(char ch) {
+ return ch <= 0x7f && /* quick test */
+ ((ch >= 'A' && ch <= 'Z') ||
+ (ch >= 'a' && ch <= 'z') ||
+ (ch >= '0' && ch <= '9'));
+ }
+
+ /* Warning: Intentional ASCII operation. */
+ private static boolean isprint(char ch) {
+ return ch >= 32 && ch <= 126;
+ }
+ }
+
+ private static class TypeSignature {
+ static class SignatureException extends Exception {
+ private static final long serialVersionUID = 1L;
+ SignatureException(String reason) {
+ super(reason);
+ }
+ }
+
+ Elements elems;
+
+ /* Signature Characters */
+
+ private static final String SIG_VOID = "V";
+ private static final String SIG_BOOLEAN = "Z";
+ private static final String SIG_BYTE = "B";
+ private static final String SIG_CHAR = "C";
+ private static final String SIG_SHORT = "S";
+ private static final String SIG_INT = "I";
+ private static final String SIG_LONG = "J";
+ private static final String SIG_FLOAT = "F";
+ private static final String SIG_DOUBLE = "D";
+ private static final String SIG_ARRAY = "[";
+ private static final String SIG_CLASS = "L";
+
+
+
+ public TypeSignature(Elements elems){
+ this.elems = elems;
+ }
+
+ /*
+ * Returns the type signature of a field according to JVM specs
+ */
+ public String getTypeSignature(String javasignature) throws SignatureException {
+ return getParamJVMSignature(javasignature);
+ }
+
+ /*
+ * Returns the type signature of a method according to JVM specs
+ */
+ public String getTypeSignature(String javasignature, TypeMirror returnType)
+ throws SignatureException {
+ String signature = null; //Java type signature.
+ String typeSignature = null; //Internal type signature.
+ List<String> params = new ArrayList<String>(); //List of parameters.
+ String paramsig = null; //Java parameter signature.
+ String paramJVMSig = null; //Internal parameter signature.
+ String returnSig = null; //Java return type signature.
+ String returnJVMType = null; //Internal return type signature.
+ int dimensions = 0; //Array dimension.
+
+ int startIndex = -1;
+ int endIndex = -1;
+ StringTokenizer st = null;
+ int i = 0;
+
+ // Gets the actual java signature without parentheses.
+ if (javasignature != null) {
+ startIndex = javasignature.indexOf("(");
+ endIndex = javasignature.indexOf(")");
+ }
+
+ if (((startIndex != -1) && (endIndex != -1))
+ &&(startIndex+1 < javasignature.length())
+ &&(endIndex < javasignature.length())) {
+ signature = javasignature.substring(startIndex+1, endIndex);
+ }
+
+ // Separates parameters.
+ if (signature != null) {
+ if (signature.indexOf(",") != -1) {
+ st = new StringTokenizer(signature, ",");
+ if (st != null) {
+ while (st.hasMoreTokens()) {
+ params.add(st.nextToken());
+ }
+ }
+ } else {
+ params.add(signature);
+ }
+ }
+
+ /* JVM type signature. */
+ typeSignature = "(";
+
+ // Gets indivisual internal parameter signature.
+ while (params.isEmpty() != true) {
+ paramsig = params.remove(i).trim();
+ paramJVMSig = getParamJVMSignature(paramsig);
+ if (paramJVMSig != null) {
+ typeSignature += paramJVMSig;
+ }
+ }
+
+ typeSignature += ")";
+
+ // Get internal return type signature.
+
+ returnJVMType = "";
+ if (returnType != null) {
+ dimensions = dimensions(returnType);
+ }
+
+ //Gets array dimension of return type.
+ while (dimensions-- > 0) {
+ returnJVMType += "[";
+ }
+ if (returnType != null) {
+ returnSig = qualifiedTypeName(returnType);
+ returnJVMType += getComponentType(returnSig);
+ } else {
+ System.out.println("Invalid return type.");
+ }
+
+ typeSignature += returnJVMType;
+
+ return typeSignature;
+ }
+
+ /*
+ * Returns internal signature of a parameter.
+ */
+ private String getParamJVMSignature(String paramsig) throws SignatureException {
+ String paramJVMSig = "";
+ String componentType ="";
+
+ if(paramsig != null){
+
+ if(paramsig.indexOf("[]") != -1) {
+ // Gets array dimension.
+ int endindex = paramsig.indexOf("[]");
+ componentType = paramsig.substring(0, endindex);
+ String dimensionString = paramsig.substring(endindex);
+ if(dimensionString != null){
+ while(dimensionString.indexOf("[]") != -1){
+ paramJVMSig += "[";
+ int beginindex = dimensionString.indexOf("]") + 1;
+ if(beginindex < dimensionString.length()){
+ dimensionString = dimensionString.substring(beginindex);
+ }else
+ dimensionString = "";
+ }
+ }
+ } else componentType = paramsig;
+
+ paramJVMSig += getComponentType(componentType);
+ }
+ return paramJVMSig;
+ }
+
+ /*
+ * Returns internal signature of a component.
+ */
+ private String getComponentType(String componentType) throws SignatureException {
+
+ String JVMSig = "";
+
+ if(componentType != null){
+ if(componentType.equals("void")) JVMSig += SIG_VOID ;
+ else if(componentType.equals("boolean")) JVMSig += SIG_BOOLEAN ;
+ else if(componentType.equals("byte")) JVMSig += SIG_BYTE ;
+ else if(componentType.equals("char")) JVMSig += SIG_CHAR ;
+ else if(componentType.equals("short")) JVMSig += SIG_SHORT ;
+ else if(componentType.equals("int")) JVMSig += SIG_INT ;
+ else if(componentType.equals("long")) JVMSig += SIG_LONG ;
+ else if(componentType.equals("float")) JVMSig += SIG_FLOAT ;
+ else if(componentType.equals("double")) JVMSig += SIG_DOUBLE ;
+ else {
+ if(!componentType.equals("")){
+ TypeElement classNameDoc = elems.getTypeElement(componentType);
+
+ if(classNameDoc == null){
+ throw new SignatureException(componentType);
+ }else {
+ String classname = classNameDoc.getQualifiedName().toString();
+ String newclassname = classname.replace('.', '/');
+ JVMSig += "L";
+ JVMSig += newclassname;
+ JVMSig += ";";
+ }
+ }
+ }
+ }
+ return JVMSig;
+ }
+
+ int dimensions(TypeMirror t) {
+ if (t.getKind() != TypeKind.ARRAY)
+ return 0;
+ return 1 + dimensions(((ArrayType) t).getComponentType());
+ }
+
+
+ String qualifiedTypeName(TypeMirror type) {
+ TypeVisitor<Name, Void> v = new SimpleTypeVisitor8<Name, Void>() {
+ @Override
+ public Name visitArray(ArrayType t, Void p) {
+ return t.getComponentType().accept(this, p);
+ }
+
+ @Override
+ public Name visitDeclared(DeclaredType t, Void p) {
+ return ((TypeElement) t.asElement()).getQualifiedName();
+ }
+
+ @Override
+ public Name visitPrimitive(PrimitiveType t, Void p) {
+ return elems.getName(t.toString());
+ }
+
+ @Override
+ public Name visitNoType(NoType t, Void p) {
+ if (t.getKind() == TypeKind.VOID)
+ return elems.getName("void");
+ return defaultAction(t, p);
+ }
+
+ @Override
+ public Name visitTypeVariable(TypeVariable t, Void p) {
+ return t.getUpperBound().accept(this, p);
+ }
+ };
+ return v.visit(type).toString();
+ }
+ }
+
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Mar 29 21:22:07 2012 -0700
@@ -44,6 +44,8 @@
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
import static javax.tools.StandardLocation.CLASS_OUTPUT;
import com.sun.source.util.TaskEvent;
@@ -60,6 +62,7 @@
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.Log.WriterKind;
+
import static com.sun.tools.javac.main.Option.*;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
import static com.sun.tools.javac.util.ListBuffer.lb;
@@ -227,6 +230,10 @@
*/
protected ClassWriter writer;
+ /** The native header writer.
+ */
+ protected JNIWriter jniWriter;
+
/** The module for the symbol table entry phases.
*/
protected Enter enter;
@@ -330,6 +337,7 @@
reader = ClassReader.instance(context);
make = TreeMaker.instance(context);
writer = ClassWriter.instance(context);
+ jniWriter = JNIWriter.instance(context);
enter = Enter.instance(context);
todo = Todo.instance(context);
@@ -1450,8 +1458,13 @@
JavaFileObject file;
if (usePrintSource)
file = printSource(env, cdef);
- else
+ else {
+ if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
+ && jniWriter.needsHeader(cdef.sym)) {
+ jniWriter.write(cdef.sym);
+ }
file = genCode(env, cdef);
+ }
if (results != null && file != null)
results.add(file);
} catch (IOException ex) {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Option.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Option.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -160,6 +160,8 @@
S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
+ H("-h", "opt.arg.directory", "opt.headerDest", STANDARD, FILEMANAGER),
+
IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"),
ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) {
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,8 @@
Specify where to place generated class files
javac.opt.sourceDest=\
Specify where to place generated source files
+javac.opt.headerDest=\
+ Specify where to place generated native header files
javac.opt.J=\
Pass <flag> directly to the runtime system
javac.opt.encoding=\
--- a/langtools/src/share/classes/javax/tools/StandardLocation.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/src/share/classes/javax/tools/StandardLocation.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -66,7 +66,13 @@
* Location to search for platform classes. Sometimes called
* the boot class path.
*/
- PLATFORM_CLASS_PATH;
+ PLATFORM_CLASS_PATH,
+
+ /**
+ * Location of new native header files.
+ * @since 1.8
+ */
+ NATIVE_HEADER_OUTPUT;
/**
* Gets a location object with the given name. The following
@@ -97,6 +103,13 @@
public String getName() { return name(); }
public boolean isOutputLocation() {
- return this == CLASS_OUTPUT || this == SOURCE_OUTPUT;
+ switch (this) {
+ case CLASS_OUTPUT:
+ case SOURCE_OUTPUT:
+ case NATIVE_HEADER_OUTPUT:
+ return true;
+ default:
+ return false;
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/javax/tools/annotation/GenerateNativeHeader.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.tools.annotation;
+
+import java.lang.annotation.*;
+import static java.lang.annotation.RetentionPolicy.*;
+import static java.lang.annotation.ElementType.*;
+
+/**
+ * An annotation used to indicate that a native header file
+ * should be generated for this class.
+ *
+ * Normally, the presence of native methods is a sufficient
+ * indication of the need for a native header file. However,
+ * in some cases, a class may contain constants of interest to
+ * native code, without containing any native methods.
+ *
+ * @since 1.8
+ */
+@Documented
+@Target(TYPE)
+@Retention(SOURCE)
+public @interface GenerateNativeHeader {
+}
--- a/langtools/test/tools/javac/api/7086261/T7086261.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/test/tools/javac/api/7086261/T7086261.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 20011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Thu Mar 29 21:16:58 2012 -0700
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Thu Mar 29 21:22:07 2012 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -259,6 +259,7 @@
"application.home", // in Paths.java
"env.class.path",
"line.separator",
+ "os.name",
"user.dir",
// file names
"ct.sym",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nativeHeaders/NativeHeaderTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7150368
+ * @summary javac should include basic ability to generate native headers
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.JavacTool;
+
+public class NativeHeaderTest {
+ public static void main(String... args) throws Exception {
+ new NativeHeaderTest().run();
+ }
+
+ /** How to invoke javac. */
+ enum RunKind {
+ /** Use the command line entry point. */
+ CMD,
+ /** Use the JavaCompiler API. */
+ API
+ };
+
+ /** Which classes for which to generate headers. */
+ enum GenKind {
+ /** Just classes with native methods or the marker annotation. */
+ SIMPLE,
+ /** All appropriate classes within the top level class. */
+ FULL
+ };
+
+ // ---------- Test cases, invoked reflectively via run. ----------
+
+ @Test
+ void simpleTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "class C { native void m(); }"));
+
+ Set<String> expect = createSet("C.h");
+
+ test(rk, gk, files, expect);
+ }
+
+ @Test
+ void nestedClassTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "class C { static class Inner { native void m(); } }"));
+
+ Set<String> expect = createSet("C_Inner.h");
+ if (gk == GenKind.FULL) expect.add("C.h");
+
+ test(rk, gk, files, expect);
+ }
+
+ @Test
+ void localClassTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "class C { native void m(); void m2() { class Local { } } }"));
+
+ Set<String> expect = createSet("C.h");
+
+ test(rk, gk, files, expect);
+ }
+
+ @Test
+ void syntheticClassTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "class C {\n"
+ + " private C() { }\n"
+ + " class Inner extends C { native void m(); }\n"
+ + "}"));
+
+ Set<String> expect = createSet("C_Inner.h");
+ if (gk == GenKind.FULL) expect.add("C.h");
+
+ test(rk, gk, files, expect);
+
+ // double check the synthetic class was generated
+ checkEqual("generatedClasses",
+ createSet("C.class", "C$1.class", "C$Inner.class"),
+ createSet(classesDir.list()));
+ }
+
+ @Test
+ void annoTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "@javax.tools.annotation.GenerateNativeHeader class C { }"));
+
+ Set<String> expect = createSet("C.h");
+
+ test(rk, gk, files, expect);
+ }
+
+ @Test
+ void annoNestedClassTest(RunKind rk, GenKind gk) throws Exception {
+ List<File> files = new ArrayList<File>();
+ files.add(createFile("p/C.java",
+ "class C { @javax.tools.annotation.GenerateNativeHeader class Inner { } }"));
+
+ Set<String> expect = createSet("C_Inner.h");
+ if (gk == GenKind.FULL) expect.add("C.h");
+
+ test(rk, gk, files, expect);
+ }
+
+ /**
+ * The worker method for each test case.
+ * Compile the files and verify that exactly the expected set of header files
+ * is generated.
+ */
+ void test(RunKind rk, GenKind gk, List<File> files, Set<String> expect) throws Exception {
+ List<String> args = new ArrayList<String>();
+ if (gk == GenKind.FULL)
+ args.add("-XDjavah:full");
+
+ switch (rk) {
+ case CMD:
+ args.add("-d");
+ args.add(classesDir.getPath());
+ args.add("-h");
+ args.add(headersDir.getPath());
+ for (File f: files)
+ args.add(f.getPath());
+ int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]));
+ if (rc != 0)
+ throw new Exception("compilation failed, rc=" + rc);
+ break;
+
+ case API:
+ fm.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(srcDir));
+ fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(classesDir));
+ fm.setLocation(StandardLocation.NATIVE_HEADER_OUTPUT, Arrays.asList(headersDir));
+ JavacTask task = javac.getTask(null, fm, null, args, null,
+ fm.getJavaFileObjectsFromFiles(files));
+ if (!task.call())
+ throw new Exception("compilation failed");
+ break;
+ }
+
+ Set<String> found = createSet(headersDir.list());
+ checkEqual("header files", expect, found);
+ }
+
+ /** Marker annotation for test cases. */
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Test { }
+
+ /** Combo test to run all test cases in all modes. */
+ void run() throws Exception {
+ javac = JavacTool.create();
+ fm = javac.getStandardFileManager(null, null, null);
+
+ for (RunKind rk: RunKind.values()) {
+ for (GenKind gk: GenKind.values()) {
+ for (Method m: getClass().getDeclaredMethods()) {
+ Annotation a = m.getAnnotation(Test.class);
+ if (a != null) {
+ init(rk, gk, m.getName());
+ try {
+ m.invoke(this, new Object[] { rk, gk });
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ throw (cause instanceof Exception) ? ((Exception) cause) : e;
+ }
+ System.err.println();
+ }
+ }
+ }
+ }
+ System.err.println(testCount + " tests" + ((errorCount == 0) ? "" : ", " + errorCount + " errors"));
+ if (errorCount > 0)
+ throw new Exception(errorCount + " errors found");
+ }
+
+ /**
+ * Init directories for a test case.
+ */
+ void init(RunKind rk, GenKind gk, String name) throws IOException {
+ System.err.println("Test " + rk + " " + gk + " " + name);
+ testCount++;
+
+ testDir = new File(rk.toString().toLowerCase() + "_" + gk.toString().toLowerCase() + "-" + name);
+ srcDir = new File(testDir, "src");
+ srcDir.mkdirs();
+ classesDir = new File(testDir, "classes");
+ classesDir.mkdirs();
+ headersDir = new File(testDir, "headers");
+ headersDir.mkdirs();
+ }
+
+ /** Create a source file with given body text. */
+ File createFile(String path, final String body) throws IOException {
+ File f = new File(srcDir, path);
+ f.getParentFile().mkdirs();
+ try (FileWriter out = new FileWriter(f)) {
+ out.write(body);
+ }
+ return f;
+ }
+
+ /** Convenience method to create a set of items. */
+ <T> Set<T> createSet(T... items) {
+ return new HashSet<T>(Arrays.asList(items));
+ }
+
+ /** Convenience method to check two values are equal, and report an error if not. */
+ <T> void checkEqual(String label, T expect, T found) {
+ if ((found == null) ? (expect == null) : found.equals(expect))
+ return;
+ System.err.println("Error: mismatch");
+ System.err.println(" expected: " + expect);
+ System.err.println(" found: " + found);
+ errorCount++;
+ }
+
+ // Shared across API test cases
+ JavacTool javac;
+ StandardJavaFileManager fm;
+
+ // Directories set up by init
+ File testDir;
+ File srcDir;
+ File classesDir;
+ File headersDir;
+
+ // Statistics
+ int testCount;
+ int errorCount;
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/CompareTest.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2007,2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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 7150368
+ * @summary javac should include basic ability to generate native headers
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class CompareTest {
+ public static void main(String... args) throws Exception {
+ new CompareTest().run();
+ }
+
+ void run() throws Exception {
+ File srcDir = new File(System.getProperty("test.src"));
+ File classesDir = new File("classes");
+ classesDir.mkdirs();
+ File javacHeaders = new File("headers.javac");
+ javacHeaders.mkdirs();
+ File javahHeaders = new File("headers.javah");
+ javahHeaders.mkdirs();
+
+ List<String> javacArgs = new ArrayList<String>();
+ javacArgs.add("-d");
+ javacArgs.add(classesDir.getPath());
+ javacArgs.add("-h");
+ javacArgs.add(javacHeaders.getPath());
+ javacArgs.add("-XDjavah:full");
+
+ for (File f: srcDir.listFiles()) {
+ if (f.getName().matches("TestClass[0-9]+\\.java")) {
+ sourceFileCount++;
+ javacArgs.add(f.getPath());
+ }
+ }
+
+ int rc = com.sun.tools.javac.Main.compile(javacArgs.toArray(new String[javacArgs.size()]));
+ if (rc != 0)
+ throw new Exception("javac failed; rc=" + rc);
+
+ List<String> javahArgs = new ArrayList<String>();
+ javahArgs.add("-d");
+ javahArgs.add(javahHeaders.getPath());
+
+ for (File f: classesDir.listFiles()) {
+ if (f.getName().endsWith(".class")) {
+ javahArgs.add(inferBinaryName(f));
+ }
+ }
+
+ PrintWriter pw = new PrintWriter(System.out, true);
+ rc = com.sun.tools.javah.Main.run(javahArgs.toArray(new String[javahArgs.size()]), pw);
+ if (rc != 0)
+ throw new Exception("javah failed; rc=" + rc);
+
+ compare(javahHeaders, javacHeaders);
+
+ int javahHeaderCount = javahHeaders.list().length;
+ int javacHeaderCount = javacHeaders.list().length;
+
+ System.out.println(sourceFileCount + " .java files found");
+ System.out.println(javacHeaderCount + " .h files generated by javac");
+ System.out.println(javahHeaderCount + " .h files generated by javah");
+ System.out.println(compareCount + " header files compared");
+
+ if (javacHeaderCount != javahHeaderCount || javacHeaderCount != compareCount)
+ error("inconsistent counts");
+
+ if (errors > 0)
+ throw new Exception(errors + " errors occurred");
+ }
+
+ String inferBinaryName(File file) {
+ String name = file.getName();
+ return name.substring(0, name.length() - ".class".length()).replace("$", ".");
+ }
+
+ /** Compare two directories.
+ * @param f1 The golden directory
+ * @param f2 The directory to be compared
+ */
+ void compare(File f1, File f2) {
+ compare(f1, f2, null);
+ }
+
+ /** Compare two files or directories
+ * @param f1 The golden directory
+ * @param f2 The directory to be compared
+ * @param p An optional path identifying a file within the two directories
+ */
+ void compare(File f1, File f2, String p) {
+ File f1p = (p == null ? f1 : new File(f1, p));
+ File f2p = (p == null ? f2 : new File(f2, p));
+ if (f1p.isDirectory() && f2p.isDirectory()) {
+ Set<String> children = new HashSet<String>();
+ children.addAll(Arrays.asList(f1p.list()));
+ children.addAll(Arrays.asList(f2p.list()));
+ for (String c: children) {
+ compare(f1, f2, new File(p, c).getPath()); // null-safe for p
+ }
+ }
+ else if (f1p.isFile() && f2p.isFile()) {
+ System.out.println("checking " + p);
+ compareCount++;
+ String s1 = read(f1p);
+ String s2 = read(f2p);
+ if (!s1.equals(s2)) {
+ System.out.println("File: " + f1p + "\n" + s1);
+ System.out.println("File: " + f2p + "\n" + s2);
+ error("Files differ: " + f1p + " " + f2p);
+ }
+ }
+ else if (f1p.exists() && !f2p.exists())
+ error("Only in " + f1 + ": " + p);
+ else if (f2p.exists() && !f1p.exists())
+ error("Only in " + f2 + ": " + p);
+ else
+ error("Files differ: " + f1p + " " + f2p);
+ }
+
+ private String read(File f) {
+ try {
+ return new String(Files.readAllBytes(f.toPath()));
+ } catch (IOException e) {
+ error("error reading " + f + ": " + e);
+ return "";
+ }
+ }
+
+ private void error(String msg) {
+ System.out.println(msg);
+ errors++;
+ }
+
+ private int errors;
+ private int compareCount;
+ private int sourceFileCount;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass1.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.List;
+
+public class TestClass1 {
+ // simple types
+ byte b;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ Object o;
+ String t;
+ List<String> g;
+
+ // constants
+ static final byte bc = 0;
+ static final short sc = 0;
+ static final int ic = 0;
+ static final long lc = 0;
+ static final float fc = 0;
+ static final double dc = 0;
+ static final Object oc = null;
+ static final String tc = "";
+ static final List<String> gc = null;
+
+ // simple arrays
+ byte[] ba;
+ short[] sa; // not handled corrected by javah v6
+ int[] ia;
+ long[] la;
+ float[] fa;
+ double[] da;
+ Object[] oa;
+ String[] ta;
+ List<String>[] ga;
+
+ // multidimensional arrays
+ byte[][] baa;
+ short[][] saa;
+ int[][] iaa;
+ long[][] laa;
+ float[][] faa;
+ double[][] daa;
+ Object[][] oaa;
+ String[][] taa;
+ List<String>[] gaa;
+
+ // simple Java methods
+ byte bm() { return 0; }
+ short sm() { return 0; }
+ int im() { return 0; }
+ long lm() { return 0; }
+ float fm() { return 0; }
+ double dm() { return 0; }
+ Object om() { return null; }
+ String tm() { return ""; }
+ List<String> gm() { return null; }
+ void vm() { }
+ byte[] bam() { return null; }
+ short[] sam() { return null; }
+ int[] iam() { return null; }
+ long[] lam() { return null; }
+ float[] fam() { return null; }
+ double[] dam() { return null; }
+ Object[] oam() { return null; }
+ String[] tam() { return null; }
+ List<String>[] gam() { return null; }
+ byte[][] baam() { return null; }
+ short[][] saam() { return null; }
+ int[][] iaam() { return null; }
+ long[][] laam() { return null; }
+ float[][] faam() { return null; }
+ double[][] daam() { return null; }
+ Object[][] oaam() { return null; }
+ String[][] taam() { return null; }
+ List<String>[] gaam() { return null; }
+
+ // simple native methods
+ native byte bmn();
+ native short smn();
+ native int imn();
+ native long lmn();
+ native float fmn();
+ native double dmn();
+ native Object omn();
+ native String tmn();
+ native List<String> gmn();
+ native void vmn();
+ native byte[] bamn();
+ native short[] samn();
+ native int[] iamn();
+ native long[] lamn();
+ native float[] famn();
+ native double[] damn();
+ native Object[] oamn();
+ native String[] tamn();
+ native List<String>[] gamn();
+ native byte[][] baamn();
+ native short[][] saamn();
+ native int[][] iaamn();
+ native long[][] laamn();
+ native float[][] faamn();
+ native double[][] daamn();
+ native Object[][] oaamn();
+ native String[][] taamn();
+ native List<String>[] gaamn();
+
+ // overloaded Java methods
+ byte bm1() { return 0; }
+ short sm1() { return 0; }
+ int im1() { return 0; }
+ long lm1() { return 0; }
+ float fm1() { return 0; }
+ double dm1() { return 0; }
+ Object om1() { return null; }
+ String tm1() { return ""; }
+ List<String> gm1() { return null; }
+ void vm1() { }
+
+ byte bm2(int i) { return 0; }
+ short sm2(int i) { return 0; }
+ int im2(int i) { return 0; }
+ long lm2(int i) { return 0; }
+ float fm2(int i) { return 0; }
+ double dm2(int i) { return 0; }
+ Object om2(int i) { return null; }
+ String tm2(int i) { return ""; }
+ List<String> gm2(int i) { return null; }
+ void vm2(int i) { }
+
+ // overloaded native methods
+ native byte bmn1();
+ native short smn1();
+ native int imn1();
+ native long lmn1();
+ native float fmn1();
+ native double dmn1();
+ native Object omn1();
+ native String tmn1();
+ native List<String> gmn1();
+ native void vmn1();
+
+ native byte bmn2(int i);
+ native short smn2(int i);
+ native int imn2(int i);
+ native long lmn2(int i);
+ native float fmn2(int i);
+ native double dmn2(int i);
+ native Object omn2(int i);
+ native String tmn2(int i);
+ native List<String> gmn2(int i);
+ native void vmn2(int i);
+
+ // arg types for Java methods
+ void mb(byte b) { }
+ void ms(short s) { }
+ void mi(int i) { }
+ void ml(long l) { }
+ void mf(float f) { }
+ void md(double d) { }
+ void mo(Object o) { }
+ void mt(String t) { }
+ void mg(List<String> g) { }
+
+ // arg types for native methods
+ native void mbn(byte b);
+ native void msn(short s);
+ native void min(int i);
+ native void mln(long l);
+ native void mfn(float f);
+ native void mdn(double d);
+ native void mon(Object o);
+ native void mtn(String t);
+ native void mgn(List<String> g);
+
+ static class Inner1 {
+ // simple types
+ byte b;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ Object o;
+ String t;
+ List<String> g;
+
+ // constants
+ static final byte bc = 0;
+ static final short sc = 0;
+ static final int ic = 0;
+ static final long lc = 0;
+ static final float fc = 0;
+ static final double dc = 0;
+ static final Object oc = null;
+ static final String tc = "";
+ static final List<String> gc = null;
+
+ // simple arrays
+ byte[] ba;
+ // short[] sa; // not handled corrected by javah v6
+ int[] ia;
+ long[] la;
+ float[] fa;
+ double[] da;
+ Object[] oa;
+ String[] ta;
+ List<String>[] ga;
+
+ // multidimensional arrays
+ byte[][] baa;
+ short[][] saa;
+ int[][] iaa;
+ long[][] laa;
+ float[][] faa;
+ double[][] daa;
+ Object[][] oaa;
+ String[][] taa;
+ List<String>[] gaa;
+
+ // simple Java methods
+ byte bm() { return 0; }
+ short sm() { return 0; }
+ int im() { return 0; }
+ long lm() { return 0; }
+ float fm() { return 0; }
+ double dm() { return 0; }
+ Object om() { return null; }
+ String tm() { return ""; }
+ List<String> gm() { return null; }
+ void vm() { }
+
+ // simple native methods
+ native byte bmn();
+ native short smn();
+ native int imn();
+ native long lmn();
+ native float fmn();
+ native double dmn();
+ native Object omn();
+ native String tmn();
+ native List<String> gmn();
+ native void vmn();
+
+ // overloaded Java methods
+ byte bm1() { return 0; }
+ short sm1() { return 0; }
+ int im1() { return 0; }
+ long lm1() { return 0; }
+ float fm1() { return 0; }
+ double dm1() { return 0; }
+ Object om1() { return null; }
+ String tm1() { return ""; }
+ List<String> gm1() { return null; }
+ void vm1() { }
+
+ byte bm2(int i) { return 0; }
+ short sm2(int i) { return 0; }
+ int im2(int i) { return 0; }
+ long lm2(int i) { return 0; }
+ float fm2(int i) { return 0; }
+ double dm2(int i) { return 0; }
+ Object om2(int i) { return null; }
+ String tm2(int i) { return ""; }
+ List<String> gm2(int i) { return null; }
+ void vm2(int i) { }
+
+ // overloaded native methods
+ native byte bmn1();
+ native short smn1();
+ native int imn1();
+ native long lmn1();
+ native float fmn1();
+ native double dmn1();
+ native Object omn1();
+ native String tmn1();
+ native List<String> gmn1();
+ native void vmn1();
+
+ native byte bmn2(int i);
+ native short smn2(int i);
+ native int imn2(int i);
+ native long lmn2(int i);
+ native float fmn2(int i);
+ native double dmn2(int i);
+ native Object omn2(int i);
+ native String tmn2(int i);
+ native List<String> gmn2(int i);
+ native void vmn2(int i);
+
+ // arg types for Java methods
+ void mb(byte b) { }
+ void ms(short s) { }
+ void mi(int i) { }
+ void ml(long l) { }
+ void mf(float f) { }
+ void md(double d) { }
+ void mo(Object o) { }
+ void mt(String t) { }
+ void mg(List<String> g) { }
+
+ // arg types for native methods
+ native void mbn(byte b);
+ native void msn(short s);
+ native void min(int i);
+ native void mln(long l);
+ native void mfn(float f);
+ native void mdn(double d);
+ native void mon(Object o);
+ native void mtn(String t);
+ native void mgn(List<String> g);
+ }
+
+ class Inner2 {
+ // simple types
+ byte b;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ Object o;
+ String t;
+ List<String> g;
+
+ // constants
+ static final byte bc = 0;
+ static final short sc = 0;
+ static final int ic = 0;
+ static final long lc = 0;
+ static final float fc = 0;
+ static final double dc = 0;
+ //static final Object oc = null;
+ static final String tc = "";
+ //static final List<String> gc = null;
+
+ // simple arrays
+ byte[] ba;
+ // short[] sa; // not handled corrected by javah v6
+ int[] ia;
+ long[] la;
+ float[] fa;
+ double[] da;
+ Object[] oa;
+ String[] ta;
+ List<String>[] ga;
+
+ // multidimensional arrays
+ byte[][] baa;
+ short[][] saa;
+ int[][] iaa;
+ long[][] laa;
+ float[][] faa;
+ double[][] daa;
+ Object[][] oaa;
+ String[][] taa;
+ List<String>[] gaa;
+
+ // simple Java methods
+ byte bm() { return 0; }
+ short sm() { return 0; }
+ int im() { return 0; }
+ long lm() { return 0; }
+ float fm() { return 0; }
+ double dm() { return 0; }
+ Object om() { return null; }
+ String tm() { return ""; }
+ List<String> gm() { return null; }
+ void vm() { }
+
+ // simple native methods
+ native byte bmn();
+ native short smn();
+ native int imn();
+ native long lmn();
+ native float fmn();
+ native double dmn();
+ native Object omn();
+ native String tmn();
+ native List<String> gmn();
+ native void vmn();
+
+ // overloaded Java methods
+ byte bm1() { return 0; }
+ short sm1() { return 0; }
+ int im1() { return 0; }
+ long lm1() { return 0; }
+ float fm1() { return 0; }
+ double dm1() { return 0; }
+ Object om1() { return null; }
+ String tm1() { return ""; }
+ List<String> gm1() { return null; }
+ void vm1() { }
+
+ byte bm2(int i) { return 0; }
+ short sm2(int i) { return 0; }
+ int im2(int i) { return 0; }
+ long lm2(int i) { return 0; }
+ float fm2(int i) { return 0; }
+ double dm2(int i) { return 0; }
+ Object om2(int i) { return null; }
+ String tm2(int i) { return ""; }
+ List<String> gm2(int i) { return null; }
+ void vm2(int i) { }
+
+ // overloaded native methods
+ native byte bmn1();
+ native short smn1();
+ native int imn1();
+ native long lmn1();
+ native float fmn1();
+ native double dmn1();
+ native Object omn1();
+ native String tmn1();
+ native List<String> gmn1();
+ native void vmn1();
+
+ native byte bmn2(int i);
+ native short smn2(int i);
+ native int imn2(int i);
+ native long lmn2(int i);
+ native float fmn2(int i);
+ native double dmn2(int i);
+ native Object omn2(int i);
+ native String tmn2(int i);
+ native List<String> gmn2(int i);
+ native void vmn2(int i);
+
+ // arg types for Java methods
+ void mb(byte b) { }
+ void ms(short s) { }
+ void mi(int i) { }
+ void ml(long l) { }
+ void mf(float f) { }
+ void md(double d) { }
+ void mo(Object o) { }
+ void mt(String t) { }
+ void mg(List<String> g) { }
+
+ // arg types for native methods
+ native void mbn(byte b);
+ native void msn(short s);
+ native void min(int i);
+ native void mln(long l);
+ native void mfn(float f);
+ native void mdn(double d);
+ native void mon(Object o);
+ native void mtn(String t);
+ native void mgn(List<String> g);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass2.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.tools.annotation.GenerateNativeHeader;
+
+@GenerateNativeHeader
+public class TestClass2 {
+ byte b;
+ short s;
+ int i;
+ long l;
+ float f;
+ double d;
+ Object o;
+ String t;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/nativeHeaders/javahComparison/TestClass3.java Thu Mar 29 21:22:07 2012 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * 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.tools.annotation.GenerateNativeHeader;
+
+@GenerateNativeHeader
+public class TestClass3 {
+ public int tc3;
+
+ public class Inner1 {
+ public int tc3i1;
+
+ public class Inner1A {
+ public int tc3i1i1a;
+ }
+
+ public class Inner1B {
+ public int tc3i1i1b;
+ }
+ }
+
+ public class Inner2 {
+ public int tc321;
+
+ public class Inner2A {
+ public int tc3i2i2a;
+ }
+
+ public class Inner2B {
+ public int tc3i2i2b;
+ }
+ }
+}
+